Added upstream from http://ftp.icm.edu.pl/pub/loglan/
[loglan.git] / examples / simulati / bank22.log
1 program bank22;
2 begin
3 pref IIUWGraph BLOCK
4 (* SYMULACJA PRACY BANKU *)
5 (* dolaczone funkcje graficzne *)
6
7 (****************************************************************************)
8
9 unit kasa:procedure(nr:integer);
10 var i:integer;
11 begin
12 i:=71+(nr-1)*56;
13 call move(10,i);
14 call draw(10,i+36);
15 call draw(56,i+36);
16 call draw(56,i);
17 call draw(10,i);
18 (*call vfill(i+36);
19 call hfill(46);
20 call move(10,i+36);
21 call hfill(46);
22 call move(46,i);
23 call vfill(i+36);*)
24 call move(13,i+7);
25 call outstring("Desk");
26 call move(13,i+21);
27 call outstring("No");
28 call move(38,i+18);
29 (* call hascii(0); *)
30  call hascii(nr+48);
31 end kasa;
32
33 (****************************************************************************)
34
35 unit klient:procedure(nr,kasa:integer;inout kl:integer);
36 var i,j,k,p:integer;
37 begin
38 kl:=kl+1;
39 j:=85+(kasa-1)*56;
40 i:=54+(nr-1)*26;
41 call move(i,j-4);
42 call hfill(i+24);
43 call vfill(j+12);
44 call move(i,j+12);
45 call hfill(i+24);
46 call move(i+24,j-4);
47 call vfill(j+12);
48 call move(i+4,j);
49 k:=kl div 10; p:=kl mod 10;
50 if k>0 then
51 (* call hascii(0); *)
52  call hascii(k+48);
53 call move(i+12,j);
54 (* call hascii(0); *) 
55 call hascii(p+48);
56 else
57 call move(i+8,j);
58 (* call hascii(0); *)
59 call hascii(p+48);
60 fi;
61 end klient;
62
63 (****************************************************************************)
64
65 unit obsluzony:procedure(nr,kasa:integer);
66 var j:integer,pom:arrayof integer;
67 begin
68 j:=85+(kasa-1)*56;
69 call move(80,j-5);
70 pom:=getmap(199,j+14);
71 call xormap(pom);
72 call move(54,j-5);
73 call putmap(pom);
74 kill(pom);
75 end obsluzony;
76
77
78 (****************************************************************************)
79
80 unit ramka:procedure;
81 var i:integer;
82 begin
83 call move(0,0);
84 call vfill(347);
85 call hfill(719);
86 call move(719,0);
87 call vfill(347);
88 call move(0,347);
89 call hfill(719);
90 call move(0,63);
91 call hfill(719);
92 call move(200,63);
93 call vfill(347);
94 call move(200,337);
95 call hfill(719);
96 call move(195,4);
97 call outstring("       SIMULATION PROGRAM  - BANK        ");
98 call move(0,14);
99 call hfill(719);
100 for i:=1 to 5 do
101    call kasa(i) od ;
102 call move(5,19);
103 call outstring("This program simulates a bank department with 5 desks ");
104  call outstring("served by 5 cashiers "); 
105 call move(5,29);
106
107 call outstring("Customers arrive at random. The service time is also random ");
108
109 call move(5,39);
110 call outstring("as well as its account and the sum to be paid ");
111 call move(5,49);
112 end ramka;
113
114 (****************************************************************************)
115
116 unit zwieksz:procedure(inout linia:integer);
117 var pom:arrayof integer;
118 begin
119 linia:=linia+10;
120 if linia>=326 then
121 call move(205,65);
122 pom:=getmap(718,325);
123 call xormap(pom);
124 linia:=66;
125 fi;
126 kill(pom);
127 end zwieksz;
128
129 (****************************************************************************)
130
131 unit piszczas:procedure(t:real);
132 var d,p,i:integer,r,x:real;
133 begin
134 x:=inxpos+16;
135 p:=entier(t);
136 for i:=1 to 3 do
137 d:=p mod 10;
138 call move(x,inypos);
139 call hascii(0);call hascii(d+48);
140 x:=x-8;
141 p:=p div 10;
142 if p=0 then exit fi;
143 od;
144 x:=x+(i+1)*8;
145 call move(x,inypos);
146 call hascii(0);call hascii(ord('.'));
147 r:=t*1000;
148 r:=r-(p*1000);
149 p:=entier(r);
150 x:=x+24;
151 call move(x,inypos);
152 for i:=1 to 3 do
153 d:=p mod 10;
154 call move(x,inypos);
155 call hascii(0); call hascii(d+48);
156 x:=x-8;
157 p:=p div 10;
158 od;
159 call move(x+32,inypos);
160 end piszczas;
161
162 (****************************************************************************)
163
164
165 UNIT PRIORITYQUEUE: CLASS;
166   (* HEAP AS BINARY LINKED TREE WITH FATHER LINK*)
167
168
169
170      UNIT QUEUEHEAD: CLASS;
171         (* HEAP ACCESING MODULE *)
172              VAR LAST,ROOT:NODE;
173
174              UNIT MIN: FUNCTION: ELEM;
175                   BEGIN
176                 IF ROOT=/= NONE THEN RESULT:=ROOT.EL FI;
177                  END MIN;
178
179              UNIT INSERT: PROCEDURE(R:ELEM);
180                (* INSERTION INTO HEAP *)
181                    VAR X,Z:NODE;
182                  BEGIN
183                        X:= R.LAB;
184                        IF LAST=NONE THEN
185                          ROOT:=X;
186                          ROOT.LEFT,ROOT.RIGHT,LAST:=ROOT
187                        ELSE
188                          IF LAST.NS=0 THEN
189                            LAST.NS:=1;
190                            Z:=LAST.LEFT;
191                            LAST.LEFT:=X;
192                            X.UP:=LAST;
193                            X.LEFT:=Z;
194                            Z.RIGHT:=X;
195                          ELSE
196                            LAST.NS:=2;
197                            Z:=LAST.RIGHT;
198                            LAST.RIGHT:=X;
199                            X.RIGHT:=Z;
200                            X.UP:=LAST;
201                            Z.LEFT:=X;
202                            LAST.LEFT.RIGHT:=X;
203                            X.LEFT:=LAST.LEFT;
204                            LAST:=Z;
205                          FI
206                        FI;
207                        CALL CORRECT(R,FALSE)
208                        END INSERT;
209
210 UNIT DELETE: PROCEDURE(R: ELEM);
211      VAR X,Y,Z:NODE;
212      BEGIN
213      X:=R.LAB;
214      Z:=LAST.LEFT;
215      IF LAST.NS =0 THEN
216            Y:= Z.UP;
217            Y.RIGHT:= LAST;
218            LAST.LEFT:=Y;
219            LAST:=Y;
220                    ELSE
221            Y:= Z.LEFT;
222            Y.RIGHT:= LAST;
223             LAST.LEFT:= Y;
224                     FI;
225        Z.EL.LAB:=X;
226        X.EL:= Z.EL;
227        LAST.NS:= LAST.NS-1;
228        R.LAB:=Z;
229        Z.EL:=R;
230        IF X.LESS(X.UP) THEN CALL CORRECT(X.EL,FALSE)
231                        ELSE CALL CORRECT(X.EL,TRUE) FI;
232      END DELETE;
233
234 UNIT CORRECT: PROCEDURE(R:ELEM,DOWN:BOOLEAN);
235    (* CORRECTION OF THE HEAP WITH STRUCTURE BROKEN BY R *)
236      VAR X,Z:NODE,T:ELEM,FIN,LOG:BOOLEAN;
237      BEGIN
238      Z:=R.LAB;
239      IF DOWN THEN
240           WHILE NOT FIN DO
241                  IF Z.NS =0 THEN FIN:=TRUE ELSE
242                       IF Z.NS=1 THEN X:=Z.LEFT ELSE
243                       IF Z.LEFT.LESS(Z.RIGHT) THEN X:=Z.LEFT ELSE X:=Z.RIGHT
244                        FI; FI;
245                       IF Z.LESS(X) THEN FIN:=TRUE ELSE
246                             T:=X.EL;
247                             X.EL:=Z.EL;
248                             Z.EL:=T;
249                             Z.EL.LAB:=Z;
250                            X.EL.LAB:=X
251                       FI; FI;
252                  Z:=X;
253                        OD
254               ELSE
255     X:=Z.UP;
256     IF X=NONE THEN LOG:=TRUE ELSE LOG:=X.LESS(Z); FI;
257     WHILE NOT LOG DO
258           T:=Z.EL;
259           Z.EL:=X.EL;
260            X.EL:=T;
261           X.EL.LAB:=X;
262           Z.EL.LAB:=Z;
263           Z:=X;
264           X:=Z.UP;
265            IF X=NONE THEN LOG:=TRUE ELSE LOG:=X.LESS(Z);
266             FI;
267                 OD
268      FI;
269  END CORRECT;
270
271 END QUEUEHEAD;
272
273
274 UNIT NODE: CLASS (EL:ELEM);
275   (* ELEMENT OF THE HEAP *)
276       VAR LEFT,RIGHT,UP: NODE, NS:INTEGER;
277       UNIT LESS: FUNCTION(X:NODE): BOOLEAN;
278           BEGIN
279           IF X= NONE THEN RESULT:=FALSE
280                     ELSE RESULT:=EL.LESS(X.EL) FI;
281           END LESS;
282      END NODE;
283
284  
285 UNIT ELEM: CLASS(PRIOR:REAL);
286   (* PREFIX OF INFORMATION TO BE STORED IN NODE *)
287    VAR LAB: NODE;
288    UNIT VIRTUAL LESS: FUNCTION(X:ELEM):BOOLEAN;
289             BEGIN
290             IF X=NONE THEN RESULT:= FALSE ELSE
291                            RESULT:= PRIOR< X.PRIOR FI;
292             END LESS;
293     BEGIN
294     LAB:= NEW NODE(THIS ELEM);
295     END ELEM;
296
297
298 END PRIORITYQUEUE;
299
300
301  
302 UNIT SIMULATION: PRIORITYQUEUE CLASS;
303 (* THE LANGUAGE FOR SIMULATION PURPOSES *)
304  
305   VAR CURR: SIMPROCESS,  (*ACTIVE PROCESS *)
306       PQ:QUEUEHEAD,  (* THE TIME AXIS *)
307        MAINPR: MAINPROGRAM;
308
309
310       UNIT SIMPROCESS: COROUTINE;
311         (* USER PROCESS PREFIX *)
312              VAR EVENT,  (* ACTIVATION MOMENT NOTICE *)
313                  EVENTAUX: EVENTNOTICE,
314                  (* THIS IS FOR AVOIDING MANY NEW CALLS AS AN RESULT OF *)
315                  (* SUBSEQUENT PASSIVATIONS AND ACTIVATIONS             *)
316                  FINISH: BOOLEAN;
317  
318              UNIT IDLE: FUNCTION: BOOLEAN;
319                    BEGIN
320                    RESULT:= EVENT= NONE;
321                    END IDLE;
322
323              UNIT TERMINATED: FUNCTION :BOOLEAN;
324                    BEGIN
325                   RESULT:= FINISH;
326                    END TERMINATED;
327
328              UNIT EVTIME: FUNCTION: REAL;
329              (* TIME OF ACTIVATION *)
330                   BEGIN
331                   IF IDLE THEN CALL ERROR1;
332                                            FI;
333                   RESULT:= EVENT.EVENTTIME;
334                   END EVTIME;
335
336     UNIT ERROR1:PROCEDURE;
337                 BEGIN
338                 ATTACH(MAIN);
339                 call groff;
340                 WRITELN(" AN ATTEMPT TO ACCESS AN IDLE PROCESS TIME");
341                 END ERROR1;
342
343      UNIT ERROR2:PROCEDURE;
344                  BEGIN
345                  ATTACH(MAIN);
346                  call groff;
347                  WRITELN(" AN ATTEMPT TO ACCESS A TERMINATED PROCESS TIME");
348                  END ERROR2;
349              BEGIN
350
351              RETURN;
352              INNER;
353              FINISH:=TRUE;
354               CALL PASSIVATE;
355              CALL ERROR2;
356           END SIMPROCESS;
357
358
359 UNIT EVENTNOTICE: ELEM CLASS;
360   (* A PROCESS ACTIVATION NOTICE TO BE PLACED ONTO THE TIME AXIS PQ *)
361       VAR EVENTTIME: REAL, PROC: SIMPROCESS;
362
363       UNIT VIRTUAL LESS: FUNCTION(X: EVENTNOTICE):BOOLEAN;
364        (* OVERWRITE THE FORMER VERSION CONSIDERING EVENTTIME *)
365                   BEGIN
366                   IF X=NONE THEN RESULT:= FALSE ELSE
367                   RESULT:= EVENTTIME< X.EVENTTIME OR
368                   (EVENTTIME=X.EVENTTIME AND PRIOR< X.PRIOR); FI;
369
370                END LESS;
371     END EVENTNOTICE;
372  
373
374 UNIT MAINPROGRAM: SIMPROCESS CLASS;
375  (* IMPLEMENTING MASTER PROGRAM AS A PROCESS *)
376       BEGIN
377       DO ATTACH(MAIN) OD;
378       END MAINPROGRAM;
379  
380 UNIT TIME:FUNCTION:REAL;
381  (* CURRENT VALUE OF SIMULATION TIME *)
382      BEGIN
383      RESULT:=CURRENT.EVTIME
384      END TIME;
385
386 UNIT CURRENT: FUNCTION: SIMPROCESS;
387    (* THE FIRST PROCESS ON THE TIME AXIS *)
388      BEGIN
389      RESULT:=CURR;
390      END CURRENT;
391  
392 UNIT SCHEDULE: PROCEDURE(P:SIMPROCESS,T:REAL);
393  (* ACTIVATION OF PROCESS P AT TIME T AND DEFINITION OF "PRIOR"- PRIORITY *)
394  (* WITHIN TIME MOMENT T                                                  *)
395       BEGIN
396       IF T<TIME THEN T:= TIME FI;
397       IF P=CURRENT THEN CALL HOLD(T-TIME) ELSE
398       IF P.IDLE AND P.EVENTAUX=NONE THEN (* HAS NOT BEEN SCHEDULED YET*)
399                 P.EVENT,P.EVENTAUX:= NEW EVENTNOTICE(RANDOM);
400                 P.EVENT.PROC:= P;
401                                       ELSE
402        IF P.IDLE (* P HAS ALREADY BEEN SCHEDULED *) THEN
403                P.EVENT:= P.EVENTAUX;
404                P.EVENT.PRIOR:=RANDOM;
405                                           ELSE
406    (* NEW SCHEDULING *)
407                P.EVENT.PRIOR:=RANDOM;
408                CALL PQ.DELETE(P.EVENT)
409                                 FI; FI;
410       P.EVENT.EVENTTIME:= T;
411       CALL PQ.INSERT(P.EVENT) FI;
412 END SCHEDULE;
413
414 UNIT HOLD:PROCEDURE(T:REAL);
415  (* MOVE THE ACTIVE PROCESS T MINUTES BACK ALONG PQ *)
416  (* REDEFINE PRIOR                                  *)
417      BEGIN
418      CALL PQ.DELETE(CURRENT.EVENT);
419      CURRENT.EVENT.PRIOR:=RANDOM;
420      IF T<0 THEN T:=0; FI;
421       CURRENT.EVENT.EVENTTIME:=TIME+T;
422      CALL PQ.INSERT(CURRENT.EVENT);
423      CALL CHOICEPROCESS;
424      END HOLD;
425  
426 UNIT PASSIVATE: PROCEDURE;
427   (* REMOVE THE ACTVE PROCESS FROM PQ AND ACTIVATE THE NEXT ONE *)
428      BEGIN
429       CALL PQ.DELETE(CURRENT.EVENT);
430       CURRENT.EVENT:=NONE;
431       CALL CHOICEPROCESS
432      END PASSIVATE;
433
434 UNIT RUN: PROCEDURE(P:SIMPROCESS);
435  (* ACTIVATE P IMMEDIATELY AND DELAY THE FORMER FIRST PROCESS BY REDEFINING*)
436  (* PRIOR                                                              *)
437      BEGIN
438      CURRENT.EVENT.PRIOR:=RANDOM;
439      IF NOT P.IDLE THEN
440             P.EVENT.PRIOR:=0;
441             P.EVENT.EVENTTIME:=TIME;
442             CALL PQ.CORRECT(P.EVENT,FALSE)
443                     ELSE
444       IF P.EVENTAUX=NONE THEN
445             P.EVENT,P.EVENTAUX:=NEW EVENTNOTICE(0);
446             P.EVENT.EVENTTIME:=TIME;
447             P.EVENT.PROC:=P;
448             CALL PQ.INSERT(P.EVENT)
449                         ELSE
450              P.EVENT:=P.EVENTAUX;
451              P.EVENT.PRIOR:=0;
452              P.EVENT.EVENTTIME:=TIME;
453              P.EVENT.PROC:=P;
454              CALL PQ.INSERT(P.EVENT);
455                           FI;FI;
456       CALL CHOICEPROCESS;
457 END RUN;
458
459 UNIT CANCEL:PROCEDURE(P: SIMPROCESS);
460  (* REMOVE PROCESS P FROM PQ AND CONTINUE SIMULATION *)
461    BEGIN
462    IF P= CURRENT THEN CALL PASSIVATE ELSE
463     CALL PQ.DELETE(P.EVENT);
464     P.EVENT:=NONE;  FI;
465  END CANCEL;
466
467 UNIT CHOICEPROCESS:PROCEDURE;
468  (* CHOOSE THE FIRST PROCESS FROM PQ TO BE ACTIVATED *)
469    VAR P:SIMPROCESS;
470    BEGIN
471    P:=CURR;
472    CURR:= PQ.MIN QUA EVENTNOTICE.PROC;
473     IF CURR=NONE THEN
474     call groff;
475      WRITE(" ERROR IN THE HEAP"); WRITELN;
476                       ATTACH(MAIN);
477                  ELSE ATTACH(CURR); FI;
478 END CHOICEPROCESS;
479
480 BEGIN
481   PQ:=NEW QUEUEHEAD;  (* SIMULATION TIME AXIS*)
482   CURR,MAINPR:=NEW MAINPROGRAM;
483   MAINPR.EVENT,MAINPR.EVENTAUX:=NEW EVENTNOTICE(0);
484   MAINPR.EVENT.EVENTTIME:=0;
485   MAINPR.EVENT.PROC:=MAINPR;
486   CALL PQ.INSERT(MAINPR.EVENT);
487   (* THE FIRST PROCESS TO BE ACTIVATED IS MAIN PROGRAM *)
488   INNER;
489   PQ:=NONE;
490 END SIMULATION;
491
492
493  
494 UNIT LISTS:SIMULATION CLASS;
495  (* WE WISH TO USE LISTS FOR QUEUEING PROCESSES DURING SIMULATION*)
496
497            UNIT LINKAGE:CLASS;
498             (*WE WILL USE TWO WAY LISTS *)
499                 VAR SUC1,PRED1:LINKAGE;
500                           END LINKAGE;
501             UNIT HEAD:LINKAGE CLASS;
502             (* EACH LIST WILL HAVE ONE ELEMENT ESTABLISHED *)
503                       UNIT FIRST:FUNCTION:LINK;
504                                  BEGIN
505                              IF SUC1 IN LINK THEN RESULT:=SUC1
506                                              ELSE RESULT:=NONE FI;
507                                  END;
508                       UNIT EMPTY:FUNCTION:BOOLEAN;
509                                  BEGIN
510                                  RESULT:=SUC1=THIS LINKAGE;
511                                  END EMPTY;
512                    BEGIN
513                    SUC1,PRED1:=THIS LINKAGE;
514                      END HEAD;
515
516           UNIT LINK:LINKAGE CLASS;
517            (* ORDINARY LIST ELEMENT PREFIX *)
518                      UNIT OUT:PROCEDURE;
519                               BEGIN
520                               IF SUC1=/=NONE THEN
521                                     SUC1.PRED1:=PRED1;
522                                     PRED1.SUC1:=SUC1;
523                                     SUC1,PRED1:=NONE FI;
524                                END OUT;
525                      UNIT INTO:PROCEDURE(S:HEAD);
526                                BEGIN
527
528                                CALL OUT;
529                                IF S=/= NONE THEN
530                                     IF S.SUC1=/=NONE THEN
531                                             SUC1:=S;
532                                             PRED1:=S.PRED1;
533                                             PRED1.SUC1:=THIS LINKAGE;
534                                             S.PRED1:=THIS LINKAGE;
535                                                  FI FI;
536                                   END INTO;
537                   END LINK;
538
539      UNIT ELEM:LINK CLASS(SPROCESS:SIMPROCESS);
540      (* USER DEFINED  PROCESS WILL BE JOINED INTO LISTS  *)
541                     END ELEM;
542
543     END LISTS;
544
545  
546
547
548
549   (*poczatek symulacji pracy banku*)
550
551
552   UNIT OFFICE:LISTS CLASS; (*AN OFFICE*)
553
554      UNIT TILL:SIMPROCESS CLASS(QUEUE:HEAD);
555      (* TELLER WITH CUSTOMERS QUEUEING UP *)
556             UNIT VIRTUAL SERVICE:PROCEDURE;
557              (* SERVICE OF THIS TELLER WILL BE PRECISED LATER *)
558                                  END SERVICE;
559               VAR CSTM:CUSTOMER,  (*THE CUSTOMER BEING SERVED*)
560                   REST,PAUSE:REAL;
561
562               BEGIN
563               PAUSE:=TIME;
564               DO
565               REST:=REST+TIME-PAUSE;
566               WHILE NOT QUEUE.EMPTY DO
567                (* SERVE ALL QUEUE *)
568                        CSTM:=QUEUE.FIRST QUA ELEM.SPROCESS;
569                        CALL SERVICE;
570                        CALL SCHEDULE(CSTM,TIME);
571                                        OD;
572               PAUSE:=TIME;
573               CALL PASSIVATE
574               OD;
575      END TILL;
576
577    UNIT CUSTOMER:SIMPROCESS CLASS;
578
579               VAR ELLIST:ELEM, K:INTEGER;
580               UNIT ARRIVAL:PROCEDURE(S:TILL);
581               (* ATTACHING TELLER S *)
582                         BEGIN
583                         IF S=/=NONE THEN
584                           ELLIST:=NEW ELEM(THIS CUSTOMER);
585                           CALL ELLIST.INTO(S.QUEUE);
586                           IF S.IDLE THEN CALL SCHEDULE(S,TIME) FI;
587                           CALL PASSIVATE; FI;
588                         END ARRIVAL;
589        END CUSTOMER;
590
591  END OFFICE;
592
593
594
595 UNIT BANKDEPARTMENT:OFFICE CLASS;
596
597
598     UNIT COUNTER:TILL CLASS;
599               VAR PAYTIME:REAL; (*RANDOM SERVICE TIME*)
600               UNIT VIRTUAL SERVICE:PROCEDURE;
601                  BEGIN
602                  call move(205,linia);
603                  call outstring(" Customer No"); 
604                  p1:=cstm.k div 10; p2:=cstm.k mod 10;
605                  if p1>0 then
606                  call hascii(0); call hascii(p1+48);
607                  call hascii(0);call hascii(p2+48);
608                  else
609                   call hascii(0);call hascii(p2+48);
610                  fi;
611                  call outstring(" has payed at the desk at time: ");
612                  call piszczas(time);
613                  call zwieksz(linia);
614                  CALL CSTM.ELLIST.OUT;
615                  PAYTIME:=RANDOM*2+2;
616                  CALL HOLD(PAYTIME);
617                  END SERVICE;
618     END COUNTER;
619
620
621     UNIT TELLER:TILL CLASS(NUMBER:INTEGER);
622               VAR SERVICETIME:REAL;
623               UNIT VIRTUAL SERVICE:PROCEDURE;
624                  VAR N:INTEGER;
625                  BEGIN
626                  call move(205,linia);
627                  call outstring(" Cashier No ");
628                  call hascii(0); call hascii(number+48);
629                  call outstring(" was waiting a customer during  ");
630                  call piszczas(REST);
631                  call zwieksz(linia);
632                  CALL CSTM.ELLIST.OUT;
633                  N:=CSTM QUA BANKCUSTOMER.NO;
634                  call move(205,linia);
635                  call outstring(" Customer No ");
636                  p1:=cstm.k div 10; p2:=cstm.k mod 10;
637                  if p1>0 then
638                  call hascii(0); call hascii(p1+48);
639                  call hascii(0);call hascii(p2+48);
640                  else
641                    call hascii(0);call hascii(p2+48);
642                   fi;
643                   call outstring(" becomes to be served by cashier No ");
644                   call hascii(0); call hascii(number+48);
645                   call zwieksz(linia);
646                   call move(205,linia);
647                   call outstring(" at time ");
648                   call piszczas(TIME);
649                   call zwieksz(linia);
650                   ACCOUNT(N):=ACCOUNT(N)+CSTM QUA BANKCUSTOMER.AMOUNT;
651                   IF ACCOUNT(N)<0 THEN CALL CSTM.ARRIVAL(CONTROL);FI;
652                   SERVICETIME:=RANDOM*7+3;
653                   CALL HOLD(SERVICETIME);
654
655                  END SERVICE;
656           END TELLER;
657
658
659     UNIT BANKCUSTOMER:CUSTOMER CLASS(NO:INTEGER,AMOUNT:REAL);
660     (* BANK CUSTOMER. AMOUNT- THE MONEY TO BE PAID AT THE BANK *)
661             VAR ARRIVALTIME,STAYTIME:REAL,CHOOSETELLER:INTEGER;
662                BEGIN
663                I:=I+1;
664                K:=I;
665                ARRIVALTIME:=TIME;
666                call move(205,linia);
667                call outstring(" Customer No ");
668                p1:=k div 10; p2:=k mod 10;
669                if p1>0 then
670                call hascii(0); call hascii(p1+48);
671                call hascii(0);call hascii(p2+48);
672                else
673                 call hascii(0);call hascii(p2+48);
674                fi;
675                call outstring(" arrived at time ");
676                call piszczas(TIME);
677                call zwieksz(linia);
678                CHOOSETELLER:=RANDOM*5+1;
679                kasa(chooseteller):=kasa(chooseteller)+1;
680                call klient(kasa(chooseteller),chooseteller,kl);
681                CALL ARRIVAL(TELLERS(CHOOSETELLER));
682                IF AMOUNT<0 THEN CALL ARRIVAL(CTR); FI;
683                STAYTIME:=TIME-ARRIVALTIME;
684                call move(205,linia);
685                call outstring(" Customer No ");
686                p1:=k div 10; p2:=k mod 10;
687                if p1>0 then
688                call hascii(0); call hascii(p1+48);
689                call hascii(0);call hascii(p2+48);
690                else
691                 call hascii(0);call hascii(p2+48);
692                fi;
693                call outstring(" left bank after ");
694                call piszczas(STAYTIME); (*STAN KONTA ",ACCOUNT(NO):10:4); *)
695                call zwieksz(linia);
696                call obsluzony(kasa(chooseteller),chooseteller);
697                kasa(chooseteller):=kasa(chooseteller)-1
698             END BANKCUSTOMER;
699
700   VAR TELLERS:ARRAYOF TELLER,ACCOUNT:ARRAYOF REAL;
701   VAR CTR:COUNTER, CONTROL:TILL,I:INTEGER;
702   var linia,p1,p2,kl:integer;
703   var kasa:arrayof integer;
704
705     BEGIN   (* NEW BANK DEPARTMENT GENERATION *)
706     linia:=66;
707     array kasa dim(1:5);
708     CTR:=NEW COUNTER(NEW HEAD);
709     ARRAY TELLERS DIM(1:5);  (* WE DEAL WITH 5 TELLES *)
710     FOR I:=1 TO 5 DO  TELLERS(I):=NEW TELLER(NEW HEAD,I); OD;
711     ARRAY ACCOUNT DIM(1:100);
712     (* WE DEAL WITH 100 ACOUNTS IN THIS BANK DEPARTMENT *)
713     FOR I:=1 TO 100 DO  ACCOUNT(I):=RANDOM*901+100; OD;
714                   (* AN ACCOUNT VALUE CAN FLUCTUATE FROM 100 TO 1000$ *)
715     I:=0;
716  END BANKDEPARTMENT;
717
718
719
720  BEGIN (* OF PROGRAM *)
721    PREF BANKDEPARTMENT BLOCK
722         UNIT GENERATOR:SIMPROCESS CLASS;
723          (* CUSTOMERS GENERATION *)
724               BEGIN
725               DO
726               CALL SCHEDULE(NEW BANKCUSTOMER(RANDOM*100+1,
727                               RANDOM*9996+5),TIME);
728               CALL HOLD(RANDOM*3);
729               CALL SCHEDULE(NEW BANKCUSTOMER(RANDOM*100+1,
730                           -(RANDOM*900+5)),TIME);
731               CALL HOLD(RANDOM*2);
732               OD
733               END GENERATOR;
734       BEGIN
735       call hpage(1,0,0);
736       call hpage(1,720,347); 
737
738       call gron(1);
739       call ramka;
740       call move(300,339);
741       call outstring("Click the mouse in order to start simulation");
742     (*  call track(719,349); *)
743       CALL SCHEDULE(NEW GENERATOR,TIME);
744       CALL HOLD (135);
745       call move(300,339);
746       call outstring(" Click the mouse in order to finish   ");
747       (* call track(719,349); *)
748       call groff
749        END
750 END
751 end
752 (****************************************************************************)