ORIGIN '~beta/basiclib/systemenv'; INCLUDE '~beta/basiclib/random' --- program: descriptor --- (* Liftszimulator *) SystemEnv(# emeletszam :@integer; (* az emeletek szama *) utasperemelet :@integer;(* hany utas lehet max egy emeleten *) maxutas :@integer; (* hany utas lehet max *) maradekutas :@integer; (* hany utas van meg hatra *) liftido: @integer; (* a lift haladasi ideje ket emelet kozott *) utas:(# azonosito :@integer; (* az utas azonositoja *) helyzet:@integer; (* az utas helyzete *) cel:@integer (* az utas celja, amelyik emeletre utazni szeretne *) enter (azonosito,helyzet,cel) #); (* az emeletet megvalosito osztalyminta *) emelet:(# azonosito:@integer; (* az emelet szama *) utasok: [utasperemelet] ^utas; (* az emeleten tartozkodo utasok *) utasszam: @integer; (* hany utas van eppen az emeleten *) (* betesz az emeletre egy uj utast es belerakja az igenysoraba a helyet es celjat *) betesz:(# ujutas:^utas; vegrehajtas:@boolean; enter ujutas[] do (if (utasszam < utasperemelet) and (ujutas.cel <> azonosito) then ujutas[] -> utasok[utasszam+1][]; utasszam + 1 -> utasszam; (* belerakja az igenysorba az uj utas helyet vagy annak negaltjat, attol fuggoen, hogy lefele vagy folfele akar-e menni az uj utas *) (if azonosito < ujutas.cel then azonosito -> iranyito.ujigeny; else -1*azonosito -> iranyito.ujigeny; if); 'Ujutas az ' -> puttext; azonosito -> putint; '.emeleten! Azonosito: ' -> puttext; utasok[utasszam].azonosito -> putint; ' Cel: ' -> puttext; ujutas.cel -> putint; putline; true -> vegrehajtas; else false -> vegrehajtas; if); exit vegrehajtas #); (* kivesz az emeletrol egy utast *) kivesz:(# melyik:@integer; regiutas:^utas; enter melyik do regiutas[] = NONE; (if (utasszam >= 1) and (melyik <= utasszam) then utasok[melyik][] ->regiutas[]; (for i:(utasszam - melyik) repeat utasok[melyik+i][] -> utasok[melyik+i-1][] for); utasszam - 1 -> utasszam; if); exit regiutas[] #); (* kiveszi az emeletrol a sorban a legelso olyan utast, amelyik a megadott cel iranyaba vagy azon tul szeretne utazni. Ha a cel 0, akkor egy tetszoleges utast vesz ki *) vanutas:(# hova:@integer; joutas: ^utas; enter hova do (* a megadott iranyba utazni kivano utasok kozul visszadja az elsot *) (for i:utasszam repeat (if (((hova >= azonosito) and (utasok[i].cel>azonosito)) or ((hova <= azonosito) and (utasok[i].cel < azonosito)) or (hova = 0)) then i -> kivesz -> joutas[]; leave vanutas; if) for); exit joutas[] #); (* ha nem fer be minden utas a liftbe, akkor hivodik meg ez a fuggveny. Megnezi, hogy van-e a megadott cel iranyaba utazo utas, es ha igen, akkor ujbol berakja az igenysorba magat a megfelelo elojellel *) jelzes:(# hova:@integer enter hova do ' Uj jelzes' -> putline; (for i:utasszam repeat (if true //((hova >= azonosito) and (utasok[i].cel>azonosito)) then azonosito -> iranyito.ujigeny; leave jelzes; // ((hova <= azonosito) and (utasok[i].cel < azonosito)) then -1*azonosito -> iranyito.ujigeny; leave jelzes; if) for); #); enter azonosito do 0 -> utasszam; utasperemelet -> utasok.extend; #); emeletek: [0]^emelet; (* a liftet megvalosito osztalyminta *) lift:@|System(# ferohely: @integer; (* hanyan fernek el a liftben *) helyzet : @integer; (* melyik emeleten van eppen a lift *) utasszam: @integer; (* hany utas tartozkodik eppen a liftben *) utasok: [0]^utas; (* a liftben levo utasokat tartalmazo sor *) aktcel: @integer; (* a lift aktualis celja, erteke 0, ha eppen nincs cel *) (* betesz egy utast a liftbe es celjat bejegyzi a jelzesek koze*) betesz : (# ujutas: ^utas; enter ujutas[] do (if utasszam < ferohely then ujutas[] -> utasok[utasszam+1][]; utasszam + 1 -> utasszam; if) #); (* kivesz egy olyan utast a liftbol, amelyik a megadott emeletre akar utazni *) kivesz :(# regiutas: ^utas; melyiket :@integer; cel :@integer; enter cel do (* megkeresi a kiszallni akaro utasok kozul az elsonek az indexet az utasok sorban *) -1 -> melyiket; ciklus:(for i:utasszam repeat (if utasok[utasszam - i + 1].cel = cel then utasszam - i + 1 -> melyiket; leave ciklus; if) for); (if melyiket = -1 then NONE -> regiutas[]; leave kivesz; if); (* kiveszi a megtalalt indexu utast sorbol *) utasok[melyiket][] -> regiutas[]; (for i:(utasszam-melyiket) repeat utasok[melyiket+i][] -> utasok[melyiket+i-1][] for); (* csokkenti a liftben levo utasok szamat es az osszes utas szamat *) utasszam - 1 -> utasszam; maradekutas - 1 -> maradekutas; 'Maradek utasok szama: ' -> puttext; maradekutas -> putint; putline; exit regiutas[] #); (* atviszi a liftet a megadott emeletre *) halad : (# hova :@integer; ciklusvaltozo :@integer; irany :@integer; segedutas :^utas; do (if aktcel = 0 then iranyito.igenyad -> aktcel; if); (if true // (aktcel = helyzet) or (aktcel = 0) then (* jo emeleten van lift vagy nincs celja *) 1 -> ciklusvaltozo; 0 -> irany; // aktcel > helyzet then (* felfele kell menni *) aktcel-helyzet -> ciklusvaltozo; 1 -> irany; // aktcel < helyzet then (* lefele kell menni *) helyzet-aktcel -> ciklusvaltozo; -1 -> irany; if); (* elmegy a megadott celemeletre emeletenkent lepkedve az eredeti emeletrol indulva *) (for ciklusvaltozo repeat (* leptetjuk egy emelettel a liftet *) (if irany <> 0 then helyzet + irany -> helyzet; 'Lift a(z) ' -> puttext; helyzet -> putint; '.emeleten van ' -> putline; if); liftido -> sleep; (* ha az aktcel az adott emelet, akkor atallitja azt 0-ra *) (if aktcel = helyzet then 0 -> aktcel; if); (* megnezi, van-e a kiszallo utas az adott emeleten es ha van, kiszedi oket *) ciklus:(# do helyzet -> kivesz -> segedutas[]; (if segedutas[] = NONE then leave ciklus; if); 'Utas kiszall a liftbol a(z) ' -> puttext; helyzet -> putint; '.emeleten! Azonosito: ' -> puttext; segedutas.azonosito -> putint; ' Cel: ' -> puttext; segedutas.cel -> putint; putline; restart ciklus; #); (* ha nem marad utas a liftben, es nincs celja a liftnek, akkor ker egy uj celt az iranyitotol *) (* (if (aktcel = 0) and (utasszam = 0) then iranyito.igenyad -> aktcel; if); *) (* megnezi, van-e beszallo utas az adott emeleten *) ciklus: (# do NONE -> segedutas[]; (if utasszam < ferohely then aktcel -> emeletek[helyzet].vanutas ->segedutas[]; if); (* ha nincs tobb utas, akkor kilep es torli az adott emeletre szolo bejegyzest az iranyitobol *) (if segedutas[] = NONE then (if true //(aktcel <> 0) and (aktcel>helyzet) then helyzet -> iranyito.igenykivesz; //(aktcel <> 0) and (aktcel iranyito.igenykivesz; if); (* ha mar nem fer be tobb utas a liftbe, a kint maradoknak ujbol jelezniuk kell a megfelelo iranyba *) (if utasszam = ferohely then aktcel -> emeletek[helyzet].jelzes; if); leave ciklus; if); (* beteszi az uj utast a liftbe *) segedutas[] -> betesz; (* ha nincs celja a liftnek, akkor a beszallo utas celja lesz a lift uj celja *) (if aktcel = 0 then segedutas.cel -> aktcel; if); (* ha az uj utas celja tovabbvisz a lift eredeti celjan, akkor az uj cel az uj utas celja lesz *) (if ((helyzet > aktcel) and (aktcel > segedutas.cel)) or ((helyzet < aktcel) and (aktcel < segedutas.cel)) then segedutas.cel -> aktcel if); 'Utas beszall a liftbe a(z) ' -> puttext; helyzet -> putint; '.emeleten! Azonosito: ' -> puttext; segedutas.azonosito -> putint; ' Cel: ' -> puttext; segedutas.cel -> putint; putline; restart ciklus; #); for); #) do putline; 10 -> ferohely; 0 -> utasszam; ferohely -> utasok.extend; 1 -> helyzet; 0 -> aktcel; ciklus:cycle(# do halad; (if maradekutas = 0 then leave ciklus; if) #) #); (* iranyitja a lift mukodeset *) iranyito:@(# igenyek:[0]@integer; (* igenyeket tartalmazo sor *) igenyszam:@integer; (* az igenysorban eppen szereplo igenyek szama *) in,out: @integer; (* beteszi a megkapott igenyt az igenysor vegere, ha az meg nem szerepel a sorban *) ujigeny: (# hova:@integer; enter hova do (for i:igenyszam repeat (if igenyek[i] = hova then leave ujigeny; if) for); igenyszam + 1 -> igenyszam; hova -> igenyek[igenyszam]; #); (* visszaadja az igenysorban elol levo igenynek megfelelo iranyba a maximalis helyre szolo igenyt a hivonak. Ha nincs igeny az igenysorban, akkor 0-t ad vissza *) igenyad: (# hova:@integer; max:@integer; do (if igenyszam = 0 then 0 -> hova else igenyek[1] -> max; (for i:igenyszam repeat (if true //(0 > igenyek[1]) and (max > igenyek[i]) then igenyek[i] -> max; //(0 < igenyek[1]) and (max < igenyek[i]) then igenyek[i] -> max; if) for); max -> abs -> hova if) exit hova #); (* kiveszi a megkapott erteknek megfelelo igenyt az igenysorbol *) igenykivesz: (# melyik:@integer; leptetes :@integer; enter melyik do 0 -> leptetes; (for i:igenyszam repeat (if (igenyek[i] = melyik) and (leptetes <> 1) then 1 -> leptetes; igenyszam - 1 -> igenyszam; if); (if (leptetes = 1) and (i+1 <= igenyek.range) then igenyek[i+1] -> igenyek[i]; if) for); #); do (* kiterjeszti az igenyek tombot az emelet szamanak ketszeresere *) 2*emeletszam -> igenyek.extend; (* kezdetben 0 igeny van *) 0 -> igenyszam; (* inicializalja az igenyeket tartalmazo tombot *) (for i:igenyek.range repeat -1 -> igenyek[i]; for); #); (* uj utasokat hoz letre tetszoleges cellal es beteszi oket egy tetszoleges emeletre *) utasgeneralo:@|System(# tesztutas :^utas; hol :@integer; hova :@integer; do (for i:maxutas repeat &utas[] -> tesztutas[]; ignlgi; (* egy tetszolegesen kivalasztott emeletre rakja az uj utast *) (1, emeletszam) -> ignuin -> hol; (* egy tetszolegesen celt ad az uj utasnak *) (1,emeletszam) -> ignuin -> hova; (if hol = hova then ((hova + 1) mod emeletszam) -> hova; if); (i,hol,hova) -> tesztutas; tesztutas[] -> emeletek[hol].betesz; (* majd tetszolges ideig varakozik *) (0,5) -> ignuin -> sleep; for); #); OK:@ boolean; beker :@getint (# syntaxError:: (# do 'Hibas adatot adott meg' -> msg.putline; #) #); do (* adatok bekerese *) true -> OK; bekeres: (# do (* emeletszam bekerese *) 0 -> emeletszam; ciklus: cycle (# do 'Kerem az emeletek szamat !' -> putline; beker -> emeletszam; (if emeletszam > 0 then leave ciklus; if); #); (* utasok szamanak bekerese *) 'Kerem az utasok szamat !' -> putline; beker -> maxutas; (* lift sebessegenek bekeresese *) ciklus: cycle (# do 'Kerem a lift sebesseget (1..10)!' -> putline; beker -> liftido; (if (liftido >= 1) and (liftido <= 10) then leave ciklus; if) #); #); 11 - liftido -> liftido; (* globalis valtozok inicializalasa *) maxutas -> maradekutas; 10 -> utasperemelet; (* emeletek letrehozasa es inicializalasa *) emeletszam -> emeletek.extend; (for i:emeletszam repeat &emelet[] -> emeletek[i][]; i -> emeletek[i]; for); (* iranyito meghivasa *) iranyito; (* szalak elinditasa *) conc(# do utasgeneralo[]->start; lift[]->start #); #)