Asansör simülasyonunu başlatın. Simülasyona bağlanan, bağlantı kurulunca konsola bir mesaj (ör. Connected to the elevator!) yazan ve bağlantıyı kapatıp biten bir program yazın.
Sonra simülasyonu kapatıp programı tekrar çalıştırın: ne oluyor?
Her programın ilk işi simülasyona bağlanmaktır. sim_connect() 0 döndürmezse simülasyon çalışmıyordur; program bir şey yapmadan biter (kütüphane de Start the simulation first mesajını yazar). Bağlantı kurulduysa mesaj yazılır ve sim_disconnect() ile bağlantı kapatılır. Bu iskeleti bundan sonraki bütün görevlerde kullanacaksınız.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1; // simulation is not running
printf("Connected to the elevator!\n");
sim_disconnect();
return 0;
}
from elevator import *
if sim_connect() != 0: # simulation is not running
exit(1)
print("Connected to the elevator!")
sim_disconnect()
Kabin Düğmeleri panelindeki ekranda sırayla 1, 2 ve 3 sayılarını gösterin. Her sayı ekranda 1 saniye kalsın. Program bittiğinde ekranda 3 yazmalıdır.
Program komutları yukarıdan aşağıya sırayla çalıştırır. Bekleme olmasaydı üç komut bir anda çalışır ve gözünüz yalnızca 3'ü görürdü. Her cabin_display() komutundan sonra 1 saniye bekleyerek her sayıyı görünür kılıyoruz. Son sayıdan sonra beklemeye gerek yok; ekran, değeri siz değiştirene kadar korur.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
cabin_display(1);
Sleep(1000); // 1000 ms = 1 second
cabin_display(2);
Sleep(1000);
cabin_display(3);
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
cabin_display(1)
time.sleep(1) # 1 second
cabin_display(2)
time.sleep(1)
cabin_display(3)
sim_disconnect()
Kabin Düğmeleri panelindeki 1, 2 ve 3 düğmelerinin ışıklarını yakın (düğmeler turuncu olur), 3 saniye bekleyin ve üçünü de söndürün.
Üç ışık art arda yakılır; komutlar çok hızlı çalıştığı için aynı anda yanmış gibi görünürler. 3 saniye beklendikten sonra aynı fonksiyon 0 değeriyle çağrılarak söndürülür. Işık düğmeye basılınca kendiliğinden yanmaz; onu yalnızca programınız yakar.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
cabin_button_light(1, 1); // on
cabin_button_light(2, 1);
cabin_button_light(3, 1);
Sleep(3000);
cabin_button_light(1, 0); // off
cabin_button_light(2, 0);
cabin_button_light(3, 0);
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
cabin_button_light(1, 1) # on
cabin_button_light(2, 1)
cabin_button_light(3, 1)
time.sleep(3)
cabin_button_light(1, 0) # off
cabin_button_light(2, 0)
cabin_button_light(3, 0)
sim_disconnect()
Gerçek bir binada anlamlı olan çağırma düğmelerinin ışıklarını yakın: 1. katta ▲, 2. katta ▲ ve ▼, 3. katta ▼. 3 saniye sonra hepsini söndürün. (1. katın ▼ ve 3. katın ▲ düğmesi sönük kalmalı.)
Kat düğmesi ışığı üç bilgi ister: hangi kat, hangi yön ve açık mı kapalı mı. 1. kattan aşağı, 3. kattan yukarı gidilemeyeceği için o iki düğmeye dokunmuyoruz. DIR_UP ve DIR_DOWN kütüphanedeki sabitlerdir (1 ve 0); sayı yerine isim kullanmak kodu okunur yapar.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
floor_button_light(1, DIR_UP, 1);
floor_button_light(2, DIR_UP, 1);
floor_button_light(2, DIR_DOWN, 1);
floor_button_light(3, DIR_DOWN, 1);
Sleep(3000);
floor_button_light(1, DIR_UP, 0);
floor_button_light(2, DIR_UP, 0);
floor_button_light(2, DIR_DOWN, 0);
floor_button_light(3, DIR_DOWN, 0);
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
floor_button_light(1, DIR_UP, 1)
floor_button_light(2, DIR_UP, 1)
floor_button_light(2, DIR_DOWN, 1)
floor_button_light(3, DIR_DOWN, 1)
time.sleep(3)
floor_button_light(1, DIR_UP, 0)
floor_button_light(2, DIR_UP, 0)
floor_button_light(2, DIR_DOWN, 0)
floor_button_light(3, DIR_DOWN, 0)
sim_disconnect()
Önce menüden Yenile'ye basın (kabin 3. kata gelir). Kabini 2 saniye aşağı indirin ve durdurun. 1 saniye bekleyin, sonra 1 saniye yukarı çıkarın ve tekrar durdurun. Kabin 3. ile 2. kat arasında bir yerde durmalıdır.
cabin_motor(CABIN_DOWN) motoru çalıştırır ve hemen geri döner; kabinin ne kadar ilerleyeceğini bekleme süresi belirler. 2 saniyede kabin iki kat arasındaki yolun yarısından biraz azını gider, bu yüzden 2. kata ulaşmaz. Yukarı yalnızca 1 saniye gittiği için 3. katı geçme (hata) tehlikesi yoktur. CABIN_STOP unutulursa kabin en alta kadar iner ve orada hata verir.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
cabin_motor(CABIN_DOWN);
Sleep(2000);
cabin_motor(CABIN_STOP);
Sleep(1000);
cabin_motor(CABIN_UP);
Sleep(1000);
cabin_motor(CABIN_STOP); // never leave the motor running
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
cabin_motor(CABIN_DOWN)
time.sleep(2)
cabin_motor(CABIN_STOP)
time.sleep(1)
cabin_motor(CABIN_UP)
time.sleep(1)
cabin_motor(CABIN_STOP) # never leave the motor running
sim_disconnect()
Yenile'ye basın. 3. kat kapısını 0,3 saniye açın ve motorunu durdurun (kapı yarıya kadar açılır). 2 saniye bekleyin, sonra kapıyı 0,3 saniye kapatın ve motoru durdurun.
Kapının tam kapanıp kapanmadığına ve menü çubuğunda HATA yazısının görünüp görünmediğine dikkat edin. Birkaç kez çalıştırın (her seferinde önce Yenile).
Kapı motoru da kabin motoru gibi siz durdurana kadar çalışır. Açma ve kapama süreleri aynı olduğu için kapının tam kapanması beklenir, ama bilgisayardaki beklemeler milisaniye düzeyinde kesin değildir: kapı bazen bir parça aralık kalır, bazen kapandıktan sonra kapanmaya devam ettiği için kısa bir HATA görülür. Süreyle kontrol, kesin bir sonuç vermez. Görev 19'da aynı işi sensörlerle hatasız yapacaksınız.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
door(3, DOOR_OPEN);
Sleep(300);
door(3, DOOR_STOP);
Sleep(2000);
door(3, DOOR_CLOSE);
Sleep(300);
door(3, DOOR_STOP);
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
door(3, DOOR_OPEN)
time.sleep(0.3)
door(3, DOOR_STOP)
time.sleep(2)
door(3, DOOR_CLOSE)
time.sleep(0.3)
door(3, DOOR_STOP)
sim_disconnect()
Üç kat sensörünü okuyup her birini ayrı bir değişkende saklayın ve üç değeri konsola yazdırın (ör. Floor 1: 0, Floor 2: 0, Floor 3: 1).
Yenile'den sonra çalıştırın. Sonra Elle Kontrol panelinde kabini Aşağı ile indirip iki katın arasında Dur'a basın ve programı yeniden çalıştırın. Ne görüyorsunuz?
Değişken, bir değeri adıyla saklayan kutudur. Her sensörü bir kez okuyup değişkende tutuyoruz. Kabin bir kattayken o katın sensörü 1, diğerleri 0'dır. Kabin iki katın arasındayken üç sensör de 0 olur: sensör, kabin tam kat hizasındayken 1 verir. Elle tam kat hizasında durdurmak çok zordur; programlar bu işi sensörü sürekli okuyarak yapar.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int s1 = cabin_sensor_read(1);
int s2 = cabin_sensor_read(2);
int s3 = cabin_sensor_read(3);
printf("Floor 1: %d\n", s1);
printf("Floor 2: %d\n", s2);
printf("Floor 3: %d\n", s3);
sim_disconnect();
return 0;
}
from elevator import *
if sim_connect() != 0:
exit(1)
s1 = cabin_sensor_read(1)
s2 = cabin_sensor_read(2)
s3 = cabin_sensor_read(3)
print("Floor 1:", s1)
print("Floor 2:", s2)
print("Floor 3:", s3)
sim_disconnect()
Kabinin hangi katta olduğunu bulun. Kabin bir kattaysa kat numarasını kabin ekranında gösterin ve konsola yazın. Kabin katların arasındaysa ekranda 0 gösterin ve konsola kabinin katlar arasında olduğunu yazın.
floor değişkeni 0 ile başlar. if / else if zinciri sensörleri sırayla dener ve 1 olanı bulunca kat numarasını değişkene yazar. Ardından tek bir if / else ile iki durum ayrılır: kat bulunduysa numarası, bulunamadıysa 0 gösterilir. Bu 'kabin hangi katta?' sorusunu ileride çok kullanacaksınız.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int floor = 0; // 0 = between floors
if (cabin_sensor_read(1) == 1) floor = 1;
else if (cabin_sensor_read(2) == 1) floor = 2;
else if (cabin_sensor_read(3) == 1) floor = 3;
if (floor != 0)
printf("The cabin is at floor %d\n", floor);
else
printf("The cabin is between floors\n");
cabin_display(floor);
sim_disconnect();
return 0;
}
from elevator import *
if sim_connect() != 0:
exit(1)
floor = 0 # 0 = between floors
if cabin_sensor_read(1) == 1:
floor = 1
elif cabin_sensor_read(2) == 1:
floor = 2
elif cabin_sensor_read(3) == 1:
floor = 3
if floor != 0:
print("The cabin is at floor", floor)
else:
print("The cabin is between floors")
cabin_display(floor)
sim_disconnect()
3. kat kapısının durumunu konsola yazın: tam kapalı, tam açık ya da aralık.
Deneyin: Yenile'den sonra (kapalı) ve Elle Kontrol'de 3. kat için Aç'a basıp kapı yarıdayken Dur'a bastıktan sonra (aralık). Kapıyı elle tam sınırında durdurmak çok zordur (geç kalırsanız HATA görünür); tam açık durumunu Görev 19'da programla göreceksiniz.
Tek bir sensör üç durumu ayırt edemez. Önce kapalı mı diye bakarız (door_sensor_read 0). Kapalı değilse tam açık mı diye bakarız (door_open_read 1). İkisi de değilse kapı aradadır. else if sırası önemlidir: ilk doğru olan koşul çalışır, diğerlerine bakılmaz.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int notClosed = door_sensor_read(3); // 1 = not fully closed
int fullyOpen = door_open_read(3); // 1 = fully open
if (notClosed == 0)
printf("Door 3 is fully closed\n");
else if (fullyOpen == 1)
printf("Door 3 is fully open\n");
else
printf("Door 3 is partly open\n");
sim_disconnect();
return 0;
}
from elevator import *
if sim_connect() != 0:
exit(1)
not_closed = door_sensor_read(3) # 1 = not fully closed
fully_open = door_open_read(3) # 1 = fully open
if not_closed == 0:
print("Door 3 is fully closed")
elif fully_open == 1:
print("Door 3 is fully open")
else:
print("Door 3 is partly open")
sim_disconnect()
Program önce konsola bir uyarı yazsın, sonra 5 saniye beklesin. Bu sürede Kabin Düğmeleri panelindeki 2 düğmesine basın ve basılı tutun. 5 saniye dolunca program düğmeyi okusun: basılıysa 2 düğmesinin ışığını 2 saniye yaksın ve basıldığını yazsın; değilse basılmadığını yazsın.
Bir kez de düğmeye basıp 5 saniye dolmadan bırakın. Sonuç ne oluyor, neden?
Düğme, yalnızca basılı tutulduğu anlarda 1 okunur; bırakınca hemen 0 olur. Program düğmeyi yalnızca bir kez, 5 saniyenin sonunda okuduğu için, erken bırakılan bir basış hiç görülmez. Bir basışı kaçırmamak için düğmeyi sürekli okumak gerekir; bunu Seviye 3'te döngülerle yapacaksınız.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
printf("Press and HOLD cabin button 2 ...\n");
Sleep(5000);
if (cabin_button_read(2) == 1)
{
printf("Button 2 is pressed\n");
cabin_button_light(2, 1);
Sleep(2000);
cabin_button_light(2, 0);
}
else
{
printf("Button 2 is not pressed\n");
}
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
print("Press and HOLD cabin button 2 ...")
time.sleep(5)
if cabin_button_read(2) == 1:
print("Button 2 is pressed")
cabin_button_light(2, 1)
time.sleep(2)
cabin_button_light(2, 0)
else:
print("Button 2 is not pressed")
sim_disconnect()
Yenile'ye basın; 3. kat kapısı kapalıdır. Bilerek bir hata yapın: kapalı kapıyı 0,1 saniye kapatmaya çalışın. Motoru durdurmadan hemen önce hata bayrağını okuyun, sonra motoru durdurun ve sonucu yazın. 1 saniye bekleyip bayrağı tekrar okuyun ve yazın.
Menü çubuğundaki HATA yazısını izleyin. Bittikten sonra Yenile'ye basın.
Kapalı bir kapıyı kapatmaya devam etmek, kapıyı sınırının ötesine itmek demektir; simülasyon bunu hata olarak işaretler ve kapıyı biraz geri sektirir. Motor çalıştığı sürece hata tekrar tekrar oluştuğu için ilk okuma 1 verir. Motor durunca bayrak kısa sürede kendiliğinden 0 olur, bu yüzden 1 saniye sonraki okuma 0 verir. Kapı geri sektiği için bir parça aralık kalabilir; bu yüzden en sonda Yenile'ye basıyoruz.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
door(3, DOOR_CLOSE); // the door is already closed: a mistake on purpose
Sleep(100);
int err = get_error();
door(3, DOOR_STOP);
if (err == 1)
printf("Error flag is 1: a limit was exceeded!\n");
else
printf("No error\n");
Sleep(1000);
printf("One second later the flag is %d\n", get_error());
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
door(3, DOOR_CLOSE) # the door is already closed: a mistake on purpose
time.sleep(0.1)
err = get_error()
door(3, DOOR_STOP)
if err == 1:
print("Error flag is 1: a limit was exceeded!")
else:
print("No error")
time.sleep(1)
print("One second later the flag is", get_error())
sim_disconnect()
Yenile'ye basın. Kabini aşağı yönde çalıştırın, 0,5 saniye sonra kabin motorunun durumunu okuyun ve anlamını yazın (stopped, up veya down). Sonra motoru durdurun ve durumu bir kez daha okuyup sayı olarak yazın.
Okunan değer, motora son verilen komuttur (Elle Kontrol'den verilen komut da buna dahildir). Değeri CABIN_STOP, CABIN_UP ve CABIN_DOWN ile karşılaştırarak sayıyı anlamlı bir kelimeye çeviriyoruz. Durdurduktan sonra okunan değer 0 olur. Benzer şekilde door_motion_read(kat) kapı motorunun durumunu verir.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
cabin_motor(CABIN_DOWN);
Sleep(500);
int m = cabin_motion_read();
if (m == CABIN_STOP) printf("Motor: stopped\n");
else if (m == CABIN_UP) printf("Motor: up\n");
else if (m == CABIN_DOWN) printf("Motor: down\n");
cabin_motor(CABIN_STOP);
printf("After stop the value is %d\n", cabin_motion_read());
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
cabin_motor(CABIN_DOWN)
time.sleep(0.5)
m = cabin_motion_read()
if m == CABIN_STOP:
print("Motor: stopped")
elif m == CABIN_UP:
print("Motor: up")
elif m == CABIN_DOWN:
print("Motor: down")
cabin_motor(CABIN_STOP)
print("After stop the value is", cabin_motion_read())
sim_disconnect()
Asansör yalnızca kabin bir kattaysa VE o katın kapısı tam kapalıysa yola çıkmaya hazırdır. Program bu iki koşulu kontrol etsin: ikisi de doğruysa hazır olduğunu ve katı konsola yazsın, katı ekranda göstersin; değilse hazır olmadığını yazsın.
Yenile'den sonra, sonra da Elle Kontrol ile 3. kat kapısını biraz açıp (Aç, sonra Dur) deneyin.
&& (ve) ile yazılan koşul, iki taraf da doğruysa doğrudur. Sıra önemlidir: önce floor != 0 kontrol edilir; yanlışsa ikinci kısım hiç çalıştırılmaz, böylece geçersiz bir 0. kat kapısı okunmaz. Bu kontrol, ileride kabini hareket ettirmeden önce yapacağımız güvenlik kontrolünün ilk hâlidir.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int floor = 0;
if (cabin_sensor_read(1) == 1) floor = 1;
else if (cabin_sensor_read(2) == 1) floor = 2;
else if (cabin_sensor_read(3) == 1) floor = 3;
if (floor != 0 && door_sensor_read(floor) == 0)
{
printf("Ready at floor %d\n", floor);
cabin_display(floor);
}
else
{
printf("Not ready\n");
}
sim_disconnect();
return 0;
}
from elevator import *
if sim_connect() != 0:
exit(1)
floor = 0
if cabin_sensor_read(1) == 1:
floor = 1
elif cabin_sensor_read(2) == 1:
floor = 2
elif cabin_sensor_read(3) == 1:
floor = 3
if floor != 0 and door_sensor_read(floor) == 0:
print("Ready at floor", floor)
cabin_display(floor)
else:
print("Not ready")
sim_disconnect()
Kabin ekranında 1'den 9'a kadar sayın; her sayı 0,5 saniye görünsün. Bu sefer 9 ayrı komut yazmak yerine bir döngü kullanın.
for döngüsü aynı komutları bir sayaçla tekrar tekrar çalıştırır. i her turda bir artar ve ekrana yazılır. Python'daki range(1, 10) 1'den başlar, 10'dan önce durur. Döngü sayesinde 1'den 99'a saymak da aynı uzunlukta bir programla yapılır.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
for (int i = 1; i <= 9; i++)
{
cabin_display(i);
Sleep(500);
}
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
for i in range(1, 10):
cabin_display(i)
time.sleep(0.5)
sim_disconnect()
Sürekli çalışan bir program yazın: kabin bir kata geldiğinde o katın numarasını ekranda göstersin ve konsola bir kez yazsın. Kabin katlar arasındayken ekran son katı göstermeye devam etsin. Aynı kat için konsola tekrar tekrar yazmasın.
Program çalışırken kabini Elle Kontrol panelinden (Yukarı / Dur / Aşağı) hareket ettirin. Programı Ctrl+C ile durdurun.
Kabin Düğmeleri panelindeki 2 düğmesi basılı tutulduğu sürece ışığı yansın, bırakılınca sönsün. Işık komutunu yalnızca düğmenin durumu değiştiğinde gönderin ve konsola pressed / released yazın. Ctrl+C ile durdurun.
Her turda düğme okunur ve old ile karşılaştırılır. Fark yoksa hiçbir şey yapılmaz. Fark varsa düğmenin yeni değeri doğrudan ışığa yazılır (1 yanar, 0 söner) ve old güncellenir. Bu 'yalnızca değişince işlem yap' kalıbı kontrol programlarında çok kullanılır: gereksiz komutları ve konsol kalabalığını önler.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int old = 0; // value in the previous round
while (1)
{
int b = cabin_button_read(2);
if (b != old)
{
cabin_button_light(2, b);
if (b == 1) printf("pressed\n");
else printf("released\n");
old = b;
}
Sleep(10);
}
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
old = 0 # value in the previous round
while True:
b = cabin_button_read(2)
if b != old:
cabin_button_light(2, b)
if b == 1:
print("pressed")
else:
print("released")
old = b
time.sleep(0.01)
Kabin düğmelerinden (1, 2, 3) birine kısa basılınca ışığı yansın ve yanık kalsın. Kabin o kata ulaştığında ışık sönsün. Her istek ve her ulaşma için konsola bir satır yazın.
Program çalışırken düğmelere basın ve kabini Elle Kontrol ile katlar arasında gezdirin. Ctrl+C ile durdurun.
Düğme yalnızca basılıyken 1 olduğu için isteği programın hatırlaması gerekir; bunu lit dizisi yapar. Dizinin 4 elemanı var, 0. elemanı kullanmayıp kat numarasını doğrudan indeks olarak kullanıyoruz. Düğme basılı ve ışık sönükse istek kaydedilir; ışık yanıkken kabin o kattaysa istek silinir. lit[f] == 0 kontrolü sayesinde basılı tutulan düğme her turda yeniden kaydedilmez. Kabin zaten 3. kattayken 3'e basarsanız ışık yanıp hemen söner: istek anında karşılanmıştır.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int lit[4] = {0, 0, 0, 0}; // lit[1..3]: request stored?
while (1)
{
for (int f = 1; f <= 3; f++)
{
if (cabin_button_read(f) == 1 && lit[f] == 0)
{
lit[f] = 1;
cabin_button_light(f, 1);
printf("Request: floor %d\n", f);
}
if (lit[f] == 1 && cabin_sensor_read(f) == 1)
{
lit[f] = 0;
cabin_button_light(f, 0);
printf("Reached floor %d\n", f);
}
}
Sleep(10);
}
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
lit = [0, 0, 0, 0] # lit[1..3]: request stored?
while True:
for f in (1, 2, 3):
if cabin_button_read(f) == 1 and lit[f] == 0:
lit[f] = 1
cabin_button_light(f, 1)
print("Request: floor", f)
if lit[f] == 1 and cabin_sensor_read(f) == 1:
lit[f] = 0
cabin_button_light(f, 0)
print("Reached floor", f)
time.sleep(0.01)
Yenile'ye basın (kabin 3. katta). Kabini aşağı gönderin ve 2. kat sensörü 1 olana kadar bekleyin; o anda motoru durdurun. Ekranda 2 gösterin ve konsola 2. kata gelindiğini yazın. Kabin tam kat hizasında durmalı ve HATA görünmemelidir.
Görev 18'den sonra kabin 2. kattadır. Program önce kabinin 2. katta olduğunu kontrol etsin; değilse bir mesaj yazıp bitsin. Kabin oradaysa: 2. kat kapısını tam açılana kadar açın ve durdurun, 3 saniye açık bekletin, sonra tam kapanana kadar kapatın ve durdurun. HATA hiç görünmemeli (Görev 6 ile karşılaştırın).
Süre yerine sensörü beklediğimiz için kapı her seferinde tam sınırında durur: tam açık sensörü 1 olduğu anda ya da kapı sensörü 0 olduğu anda motor kesilir. Kapı motoru sınırda yalnızca bir simülasyon adımı (yaklaşık 16 ms) içinde durdurulmazsa hata oluşur; boş döngü bu hızı sağlar. 3 saniyelik bekleme sırasında hiçbir motor çalışmadığı için orada Sleep kullanmak doğrudur. Baştaki kontrol, kabin başka bir kattayken kapının boşluğa açılmasını önler.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
if (cabin_sensor_read(2) == 0)
{
printf("The cabin is not at floor 2 (run Task 18 first)\n");
sim_disconnect();
return 0;
}
door(2, DOOR_OPEN);
while (door_open_read(2) == 0) { } // wait: fully open
door(2, DOOR_STOP);
printf("Door 2 is open\n");
Sleep(3000); // no motor runs: Sleep is fine
door(2, DOOR_CLOSE);
while (door_sensor_read(2) == 1) { } // wait: fully closed
door(2, DOOR_STOP);
printf("Door 2 is closed\n");
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
if cabin_sensor_read(2) == 0:
print("The cabin is not at floor 2 (run Task 18 first)")
sim_disconnect()
exit(0)
door(2, DOOR_OPEN)
while door_open_read(2) == 0: # wait: fully open
pass
door(2, DOOR_STOP)
print("Door 2 is open")
time.sleep(3) # no motor runs: sleep is fine
door(2, DOOR_CLOSE)
while door_sensor_read(2) == 1: # wait: fully closed
pass
door(2, DOOR_STOP)
print("Door 2 is closed")
sim_disconnect()
Kabin nerede olursa olsun (3. katta, 2. katta ya da katların arasında) onu 1. kata indirip tam hizada durdurun ve ekranda 1 gösterin. Kabin zaten 1. kattaysa motoru hiç çalıştırmayın, yalnızca bunu konsola yazın.
Kabini Elle Kontrol ile farklı yerlere götürüp birkaç kez deneyin.
Kabin bir kattayken çalıştırın (katlar arasındaysa program bir mesaj yazıp bitsin). Program bir kabin düğmesine (1, 2 veya 3) basılmasını beklesin. Basılan düğmenin ışığını yakın, kabini doğru yöne göndererek o katta durdurun, ışığı söndürün, ekranda katı gösterin ve konsola yazın. Basılan kat zaten bulunulan katsa kabin hareket etmemelidir.
Program önceki görevlerin parçalarını birleştirir. İlk döngü bir düğme basılana kadar döner; burada Sleep(10) kullanmak sorun değildir çünkü motor çalışmıyor ve insan bir düğmeyi 10 ms'den çok daha uzun basılı tutar. Yön, hedef kat bulunulan kattan büyükse yukarı, küçükse aşağıdır; eşitse motor hiç çalıştırılmaz ve bekleme döngüsü hemen biter, çünkü o katın sensörü zaten 1'dir.
#include "elevator.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int floor = 0;
for (int f = 1; f <= 3; f++)
if (cabin_sensor_read(f) == 1) floor = f;
if (floor == 0)
{
printf("Bring the cabin to a floor first\n");
sim_disconnect();
return 0;
}
printf("Press a cabin button (1, 2 or 3)\n");
int target = 0;
while (target == 0)
{
for (int f = 1; f <= 3; f++)
if (cabin_button_read(f) == 1) target = f;
Sleep(10);
}
cabin_button_light(target, 1);
if (target > floor) cabin_motor(CABIN_UP);
else if (target < floor) cabin_motor(CABIN_DOWN);
while (cabin_sensor_read(target) == 0) { }
cabin_motor(CABIN_STOP);
cabin_button_light(target, 0);
cabin_display(target);
printf("Arrived at floor %d\n", target);
sim_disconnect();
return 0;
}
from elevator import *
import time
if sim_connect() != 0:
exit(1)
floor = 0
for f in (1, 2, 3):
if cabin_sensor_read(f) == 1:
floor = f
if floor == 0:
print("Bring the cabin to a floor first")
sim_disconnect()
exit(0)
print("Press a cabin button (1, 2 or 3)")
target = 0
while target == 0:
for f in (1, 2, 3):
if cabin_button_read(f) == 1:
target = f
time.sleep(0.01)
cabin_button_light(target, 1)
if target > floor:
cabin_motor(CABIN_UP)
elif target < floor:
cabin_motor(CABIN_DOWN)
while cabin_sensor_read(target) == 0:
pass
cabin_motor(CABIN_STOP)
cabin_button_light(target, 0)
cabin_display(target)
print("Arrived at floor", target)
sim_disconnect()
İki fonksiyon yazın: current_floor() kabinin bulunduğu katı (katlar arasındaysa 0) döndürsün; go_to_floor(hedef) kabini hedef kata götürüp durdursun, ekranda katı göstersin ve konsola yazsın. Kabin katlar arasındaysa go_to_floor önce aşağıdaki kata insin, sonra hedefe gitsin.
Bu fonksiyonlarla şu turu yapın: 1. kata git, 2 saniye bekle, 3. kata git, 2 saniye bekle, 2. kata git.
current_floor() sensörleri sırayla dener ve 1 olan ilk katı return ile geri verir; hiçbiri 1 değilse 0 döner. go_to_floor() bu bilgiyle yönü seçer. Katlar arasındayken yön belli olmadığı için önce aşağı inip bir kata oturuyoruz (Görev 20'deki gibi, aşağı yön her zaman bir kata ulaşır). Artık ana program çok kısa ve okunaklıdır: ne yapıldığını söyler, nasıl yapıldığı fonksiyonların içindedir.
#include "elevator.h"
// Floor where the cabin is (1..3), or 0 between floors
int current_floor(void)
{
for (int f = 1; f <= 3; f++)
if (cabin_sensor_read(f) == 1) return f;
return 0;
}
// Takes the cabin to the target floor and stops it there
void go_to_floor(int target)
{
if (current_floor() == 0) // between floors: go down to a floor
{
cabin_motor(CABIN_DOWN);
while (current_floor() == 0) { }
cabin_motor(CABIN_STOP);
}
int now = current_floor();
if (target > now) cabin_motor(CABIN_UP);
else if (target < now) cabin_motor(CABIN_DOWN);
while (cabin_sensor_read(target) == 0) { }
cabin_motor(CABIN_STOP);
cabin_display(target);
printf("At floor %d\n", target);
}
int main(void)
{
if (sim_connect() != 0) return 1;
go_to_floor(1);
Sleep(2000);
go_to_floor(3);
Sleep(2000);
go_to_floor(2);
sim_disconnect();
return 0;
}
from elevator import *
import time
def current_floor():
"""Floor where the cabin is (1..3), or 0 between floors."""
for f in (1, 2, 3):
if cabin_sensor_read(f) == 1:
return f
return 0
def go_to_floor(target):
"""Takes the cabin to the target floor and stops it there."""
if current_floor() == 0: # between floors: go down to a floor
cabin_motor(CABIN_DOWN)
while current_floor() == 0:
pass
cabin_motor(CABIN_STOP)
now = current_floor()
if target > now:
cabin_motor(CABIN_UP)
elif target < now:
cabin_motor(CABIN_DOWN)
while cabin_sensor_read(target) == 0:
pass
cabin_motor(CABIN_STOP)
cabin_display(target)
print("At floor", target)
if sim_connect() != 0:
exit(1)
go_to_floor(1)
time.sleep(2)
go_to_floor(3)
time.sleep(2)
go_to_floor(2)
sim_disconnect()
Görev 22'deki fonksiyonlara iki tane daha ekleyin: open_door(kat) kapıyı tam açılana kadar açıp durdursun, close_door(kat) tam kapanana kadar kapatıp durdursun. Kapı zaten tam açıksa (ya da tam kapalıysa) fonksiyon motoru hiç çalıştırmasın.
Şu turu yapın: sırayla 1., 2. ve 3. kata gidin; her katta kapıyı açın, 2 saniye açık tutun ve kapatın.
Gerçek bir asansör, herhangi bir kat kapısı açıkken asla hareket etmez. Görev 23'teki go_to_floor fonksiyonunu değiştirin: kabini hareket ettirmeden önce üç kapıyı da kontrol etsin; açık (tam kapalı olmayan) kapı varsa konsola bir uyarı yazıp önce o kapıyı kapatsın.
Ana program: 1. kata git, 1 saniye bekle, 3. kata git. Test: çalıştırmadan önce Elle Kontrol'de 2. kat kapısı için Aç'a, kapı yarıdayken Dur'a basın.
Simülasyon kapı açıkken kabinin hareket etmesine izin verir; güvenliği programın sağlaması gerekir. Kontrolü go_to_floor fonksiyonunun içine koyduğumuz için kabini hareket ettiren her çağrı otomatik olarak güvenlidir; ana programda unutulması mümkün değildir. C'de close_door artık go_to_floor içinde kullanıldığı için ondan önce tanımlanmıştır.
#include "elevator.h"
int current_floor(void)
{
for (int f = 1; f <= 3; f++)
if (cabin_sensor_read(f) == 1) return f;
return 0;
}
void open_door(int f)
{
if (door_open_read(f) == 1) return;
door(f, DOOR_OPEN);
while (door_open_read(f) == 0) { }
door(f, DOOR_STOP);
}
void close_door(int f)
{
if (door_sensor_read(f) == 0) return;
door(f, DOOR_CLOSE);
while (door_sensor_read(f) == 1) { }
door(f, DOOR_STOP);
}
void go_to_floor(int target)
{
for (int f = 1; f <= 3; f++) // safety: all doors closed
{
if (door_sensor_read(f) == 1)
{
printf("Warning: door %d is open, closing it first\n", f);
close_door(f);
}
}
if (current_floor() == 0)
{
cabin_motor(CABIN_DOWN);
while (current_floor() == 0) { }
cabin_motor(CABIN_STOP);
}
int now = current_floor();
if (target > now) cabin_motor(CABIN_UP);
else if (target < now) cabin_motor(CABIN_DOWN);
while (cabin_sensor_read(target) == 0) { }
cabin_motor(CABIN_STOP);
cabin_display(target);
printf("At floor %d\n", target);
}
int main(void)
{
if (sim_connect() != 0) return 1;
go_to_floor(1);
Sleep(1000);
go_to_floor(3);
sim_disconnect();
return 0;
}
from elevator import *
import time
def current_floor():
for f in (1, 2, 3):
if cabin_sensor_read(f) == 1:
return f
return 0
def open_door(f):
if door_open_read(f) == 1:
return
door(f, DOOR_OPEN)
while door_open_read(f) == 0:
pass
door(f, DOOR_STOP)
def close_door(f):
if door_sensor_read(f) == 0:
return
door(f, DOOR_CLOSE)
while door_sensor_read(f) == 1:
pass
door(f, DOOR_STOP)
def go_to_floor(target):
for f in (1, 2, 3): # safety: all doors closed
if door_sensor_read(f) == 1:
print("Warning: door", f, "is open, closing it first")
close_door(f)
if current_floor() == 0:
cabin_motor(CABIN_DOWN)
while current_floor() == 0:
pass
cabin_motor(CABIN_STOP)
now = current_floor()
if target > now:
cabin_motor(CABIN_UP)
elif target < now:
cabin_motor(CABIN_DOWN)
while cabin_sensor_read(target) == 0:
pass
cabin_motor(CABIN_STOP)
cabin_display(target)
print("At floor", target)
if sim_connect() != 0:
exit(1)
go_to_floor(1)
time.sleep(1)
go_to_floor(3)
sim_disconnect()
Sürekli çalışan bir asansör yazın. Bir kabin düğmesine ya da bir kat çağırma düğmesine (▲ veya ▼) basılınca o düğmenin ışığını yakın, kabini o kata götürün, kapıyı açın, 3 saniye açık tutun, kapatın ve o katın bütün düğme ışıklarını söndürün. Sonra yeni bir çağrı bekleyin. Görev 24'teki fonksiyonları kullanın. Ctrl+C ile durdurun.
Görev 25'teki asansörü geliştirin: birden fazla çağrı birikebilsin. Her düğmenin isteğini bir dizide saklayın (kabin düğmeleri, ▲ düğmeleri, ▼ düğmeleri için üç dizi); ışık, isteğin saklandığını göstersin. Asansör boşta olduğunda bekleyen çağrılardan bulunduğu kata EN YAKIN olana gitsin, kapıyı açınca o katın isteklerini ve ışıklarını silsin, 3 saniye sonra kapıyı kapatsın.
Test: asansör boştayken hızlıca 1 ve 2 düğmelerine basın (kabin 3. kattayken önce 2'ye gitmeli). Kabin hareket ederken basılan düğmelere ne oluyor?
Diziler, her düğmenin isteğini ve dolayısıyla ışığını hatırlar; bir düğme basılı tutulsa da ışık komutu yalnızca bir kez gönderilir. nearest_call() bütün katları dolaşır, isteği olan katlar arasında uzaklığı en küçük olanı seçer (uzaklık, büyük kat numarasından küçüğü çıkararak bulunur; C'deki koşul ? a : b yazımı kısa bir if/else'tir, Python'da abs() mutlak değeri verir). İstekler kapı açılır açılmaz silinir. Kabin hareket ederken ya da kapı açıkken program bekleme döngülerinin içinde olduğu için o sırada yapılan basışlar hâlâ kaçırılıyor; Görev 27 bunu düzeltecek.
#include "elevator.h"
int cab_req[4], up_req[4], dn_req[4]; // index 1..3
int current_floor(void)
{
for (int f = 1; f <= 3; f++)
if (cabin_sensor_read(f) == 1) return f;
return 0;
}
void open_door(int f)
{
if (door_open_read(f) == 1) return;
door(f, DOOR_OPEN);
while (door_open_read(f) == 0) { }
door(f, DOOR_STOP);
}
void close_door(int f)
{
if (door_sensor_read(f) == 0) return;
door(f, DOOR_CLOSE);
while (door_sensor_read(f) == 1) { }
door(f, DOOR_STOP);
}
void go_to_floor(int target)
{
for (int f = 1; f <= 3; f++)
if (door_sensor_read(f) == 1) close_door(f);
if (current_floor() == 0)
{
cabin_motor(CABIN_DOWN);
while (current_floor() == 0) { }
cabin_motor(CABIN_STOP);
}
int now = current_floor();
if (target > now) cabin_motor(CABIN_UP);
else if (target < now) cabin_motor(CABIN_DOWN);
while (cabin_sensor_read(target) == 0) { }
cabin_motor(CABIN_STOP);
cabin_display(target);
}
// Stores new presses and turns their lights on
void scan_buttons(void)
{
for (int f = 1; f <= 3; f++)
{
if (cabin_button_read(f) == 1 && cab_req[f] == 0)
{
cab_req[f] = 1;
cabin_button_light(f, 1);
}
if (floor_button_read(f, DIR_UP) == 1 && up_req[f] == 0)
{
up_req[f] = 1;
floor_button_light(f, DIR_UP, 1);
}
if (floor_button_read(f, DIR_DOWN) == 1 && dn_req[f] == 0)
{
dn_req[f] = 1;
floor_button_light(f, DIR_DOWN, 1);
}
}
}
int has_call(int f)
{
return cab_req[f] == 1 || up_req[f] == 1 || dn_req[f] == 1;
}
void clear_calls(int f)
{
if (cab_req[f] == 1) { cab_req[f] = 0; cabin_button_light(f, 0); }
if (up_req[f] == 1) { up_req[f] = 0; floor_button_light(f, DIR_UP, 0); }
if (dn_req[f] == 1) { dn_req[f] = 0; floor_button_light(f, DIR_DOWN, 0); }
}
// Floor with a call nearest to 'from', or 0 if there is no call
int nearest_call(int from)
{
int best = 0, best_dist = 99;
for (int f = 1; f <= 3; f++)
{
if (has_call(f))
{
int dist = (f > from) ? f - from : from - f;
if (dist < best_dist) { best = f; best_dist = dist; }
}
}
return best;
}
int main(void)
{
if (sim_connect() != 0) return 1;
printf("Waiting for calls. Ctrl+C to stop.\n");
while (1)
{
scan_buttons();
int target = nearest_call(current_floor());
if (target != 0)
{
printf("Going to floor %d\n", target);
go_to_floor(target);
open_door(target);
clear_calls(target);
Sleep(3000);
close_door(target);
}
Sleep(10);
}
sim_disconnect();
return 0;
}
from elevator import *
import time
cab_req = [0, 0, 0, 0] # index 1..3
up_req = [0, 0, 0, 0]
dn_req = [0, 0, 0, 0]
def current_floor():
for f in (1, 2, 3):
if cabin_sensor_read(f) == 1:
return f
return 0
def open_door(f):
if door_open_read(f) == 1:
return
door(f, DOOR_OPEN)
while door_open_read(f) == 0:
pass
door(f, DOOR_STOP)
def close_door(f):
if door_sensor_read(f) == 0:
return
door(f, DOOR_CLOSE)
while door_sensor_read(f) == 1:
pass
door(f, DOOR_STOP)
def go_to_floor(target):
for f in (1, 2, 3):
if door_sensor_read(f) == 1:
close_door(f)
if current_floor() == 0:
cabin_motor(CABIN_DOWN)
while current_floor() == 0:
pass
cabin_motor(CABIN_STOP)
now = current_floor()
if target > now:
cabin_motor(CABIN_UP)
elif target < now:
cabin_motor(CABIN_DOWN)
while cabin_sensor_read(target) == 0:
pass
cabin_motor(CABIN_STOP)
cabin_display(target)
def scan_buttons():
"""Stores new presses and turns their lights on."""
for f in (1, 2, 3):
if cabin_button_read(f) == 1 and cab_req[f] == 0:
cab_req[f] = 1
cabin_button_light(f, 1)
if floor_button_read(f, DIR_UP) == 1 and up_req[f] == 0:
up_req[f] = 1
floor_button_light(f, DIR_UP, 1)
if floor_button_read(f, DIR_DOWN) == 1 and dn_req[f] == 0:
dn_req[f] = 1
floor_button_light(f, DIR_DOWN, 1)
def has_call(f):
return cab_req[f] == 1 or up_req[f] == 1 or dn_req[f] == 1
def clear_calls(f):
if cab_req[f] == 1:
cab_req[f] = 0
cabin_button_light(f, 0)
if up_req[f] == 1:
up_req[f] = 0
floor_button_light(f, DIR_UP, 0)
if dn_req[f] == 1:
dn_req[f] = 0
floor_button_light(f, DIR_DOWN, 0)
def nearest_call(start):
"""Floor with a call nearest to 'start', or 0 if there is no call."""
best = 0
best_dist = 99
for f in (1, 2, 3):
if has_call(f):
dist = abs(f - start)
if dist < best_dist:
best = f
best_dist = dist
return best
if sim_connect() != 0:
exit(1)
print("Waiting for calls. Ctrl+C to stop.")
while True:
scan_buttons()
target = nearest_call(current_floor())
if target != 0:
print("Going to floor", target)
go_to_floor(target)
open_door(target)
clear_calls(target)
time.sleep(3)
close_door(target)
time.sleep(0.01)
Görev 26'daki asansörde kabin hareket ederken ya da kapı açıkken yapılan basışlar kayboluyordu. Programı öyle değiştirin ki her bekleme sırasında da düğmeler okunsun: basılan düğmenin ışığı hemen yansın ve istek, sırası gelince karşılansın.
Test: kabin 3. kattan 1. kata giderken 2'ye ve 3. kat ▼ düğmesine basın; ikisinin de ışığı hemen yanmalı ve sonra karşılanmalı.
Her katta, kabinin hangi yöne gittiğini gösteren yukarı ve aşağı ok ışıkları vardır. Kütüphanede bunlar için hazır bir fonksiyon yok; adresleri ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3 (yukarı) ve ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3 (aşağı) sabitleridir ve write_mem(adres, değer) ile yazılır.
show_arrows(yön) fonksiyonunu yazın: yön CABIN_UP ise üç kattaki yukarı okları, CABIN_DOWN ise aşağı okları yaksın, CABIN_STOP ise hepsini söndürsün. Görev 27'deki go_to_floor içinde, kabin hareket ederken doğru oklar yansın ve kabin durunca sönsün.
write_mem kütüphanenin en alt düzey fonksiyonudur: paylaşılan bellekteki bir adrese doğrudan değer yazar; diğer bütün fonksiyonlar da aslında bunu yapar. Adresleri dizilere koyunca üç katı tek bir for döngüsüyle güncelleyebiliyoruz. Karşılaştırmanın sonucu doğruysa 1, yanlışsa 0 olduğu için yukarı giderken yukarı oklar yanar, aşağı oklar söner. Python'da True / False değerini int() ile 1 / 0'a çeviriyoruz.
#include "elevator.h"
int cab_req[4], up_req[4], dn_req[4]; // index 1..3
int up_arrow[4] = {0, ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3};
int dn_arrow[4] = {0, ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3};
// CABIN_UP: up arrows on, CABIN_DOWN: down arrows on, CABIN_STOP: all off
void show_arrows(int dir)
{
for (int f = 1; f <= 3; f++)
{
write_mem(up_arrow[f], dir == CABIN_UP);
write_mem(dn_arrow[f], dir == CABIN_DOWN);
}
}
void scan_buttons(void)
{
for (int f = 1; f <= 3; f++)
{
if (cabin_button_read(f) == 1 && cab_req[f] == 0)
{
cab_req[f] = 1;
cabin_button_light(f, 1);
}
if (floor_button_read(f, DIR_UP) == 1 && up_req[f] == 0)
{
up_req[f] = 1;
floor_button_light(f, DIR_UP, 1);
}
if (floor_button_read(f, DIR_DOWN) == 1 && dn_req[f] == 0)
{
dn_req[f] = 1;
floor_button_light(f, DIR_DOWN, 1);
}
}
}
int has_call(int f)
{
return cab_req[f] == 1 || up_req[f] == 1 || dn_req[f] == 1;
}
void clear_calls(int f)
{
if (cab_req[f] == 1) { cab_req[f] = 0; cabin_button_light(f, 0); }
if (up_req[f] == 1) { up_req[f] = 0; floor_button_light(f, DIR_UP, 0); }
if (dn_req[f] == 1) { dn_req[f] = 0; floor_button_light(f, DIR_DOWN, 0); }
}
int nearest_call(int from)
{
int best = 0, best_dist = 99;
for (int f = 1; f <= 3; f++)
{
if (has_call(f))
{
int dist = (f > from) ? f - from : from - f;
if (dist < best_dist) { best = f; best_dist = dist; }
}
}
return best;
}
void wait_ms(int ms)
{
DWORD start = GetTickCount(); // clock in milliseconds
while (GetTickCount() - start < (DWORD)ms)
{
scan_buttons();
Sleep(10);
}
}
int current_floor(void)
{
for (int f = 1; f <= 3; f++)
if (cabin_sensor_read(f) == 1) return f;
return 0;
}
void open_door(int f)
{
if (door_open_read(f) == 1) return;
door(f, DOOR_OPEN);
while (door_open_read(f) == 0) scan_buttons();
door(f, DOOR_STOP);
}
void close_door(int f)
{
if (door_sensor_read(f) == 0) return;
door(f, DOOR_CLOSE);
while (door_sensor_read(f) == 1) scan_buttons();
door(f, DOOR_STOP);
}
void go_to_floor(int target)
{
for (int f = 1; f <= 3; f++)
if (door_sensor_read(f) == 1) close_door(f);
if (current_floor() == 0)
{
show_arrows(CABIN_DOWN);
cabin_motor(CABIN_DOWN);
while (current_floor() == 0) scan_buttons();
cabin_motor(CABIN_STOP);
}
int now = current_floor();
if (target > now)
{
show_arrows(CABIN_UP);
cabin_motor(CABIN_UP);
}
else if (target < now)
{
show_arrows(CABIN_DOWN);
cabin_motor(CABIN_DOWN);
}
while (cabin_sensor_read(target) == 0) scan_buttons();
cabin_motor(CABIN_STOP);
show_arrows(CABIN_STOP);
cabin_display(target);
}
int main(void)
{
if (sim_connect() != 0) return 1;
show_arrows(CABIN_STOP);
printf("Waiting for calls. Ctrl+C to stop.\n");
while (1)
{
scan_buttons();
int target = nearest_call(current_floor());
if (target != 0)
{
printf("Going to floor %d\n", target);
go_to_floor(target);
open_door(target);
clear_calls(target);
wait_ms(3000);
close_door(target);
}
Sleep(10);
}
sim_disconnect();
return 0;
}
from elevator import *
import time
cab_req = [0, 0, 0, 0] # index 1..3
up_req = [0, 0, 0, 0]
dn_req = [0, 0, 0, 0]
up_arrow = [0, ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3]
dn_arrow = [0, ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3]
def show_arrows(direction):
"""CABIN_UP: up arrows on, CABIN_DOWN: down arrows on, CABIN_STOP: all off."""
for f in (1, 2, 3):
write_mem(up_arrow[f], int(direction == CABIN_UP))
write_mem(dn_arrow[f], int(direction == CABIN_DOWN))
def scan_buttons():
for f in (1, 2, 3):
if cabin_button_read(f) == 1 and cab_req[f] == 0:
cab_req[f] = 1
cabin_button_light(f, 1)
if floor_button_read(f, DIR_UP) == 1 and up_req[f] == 0:
up_req[f] = 1
floor_button_light(f, DIR_UP, 1)
if floor_button_read(f, DIR_DOWN) == 1 and dn_req[f] == 0:
dn_req[f] = 1
floor_button_light(f, DIR_DOWN, 1)
def has_call(f):
return cab_req[f] == 1 or up_req[f] == 1 or dn_req[f] == 1
def clear_calls(f):
if cab_req[f] == 1:
cab_req[f] = 0
cabin_button_light(f, 0)
if up_req[f] == 1:
up_req[f] = 0
floor_button_light(f, DIR_UP, 0)
if dn_req[f] == 1:
dn_req[f] = 0
floor_button_light(f, DIR_DOWN, 0)
def nearest_call(start):
best = 0
best_dist = 99
for f in (1, 2, 3):
if has_call(f):
dist = abs(f - start)
if dist < best_dist:
best = f
best_dist = dist
return best
def wait_ms(ms):
start = time.monotonic() # clock in seconds
while time.monotonic() - start < ms / 1000:
scan_buttons()
time.sleep(0.01)
def current_floor():
for f in (1, 2, 3):
if cabin_sensor_read(f) == 1:
return f
return 0
def open_door(f):
if door_open_read(f) == 1:
return
door(f, DOOR_OPEN)
while door_open_read(f) == 0:
scan_buttons()
door(f, DOOR_STOP)
def close_door(f):
if door_sensor_read(f) == 0:
return
door(f, DOOR_CLOSE)
while door_sensor_read(f) == 1:
scan_buttons()
door(f, DOOR_STOP)
def go_to_floor(target):
for f in (1, 2, 3):
if door_sensor_read(f) == 1:
close_door(f)
if current_floor() == 0:
show_arrows(CABIN_DOWN)
cabin_motor(CABIN_DOWN)
while current_floor() == 0:
scan_buttons()
cabin_motor(CABIN_STOP)
now = current_floor()
if target > now:
show_arrows(CABIN_UP)
cabin_motor(CABIN_UP)
elif target < now:
show_arrows(CABIN_DOWN)
cabin_motor(CABIN_DOWN)
while cabin_sensor_read(target) == 0:
scan_buttons()
cabin_motor(CABIN_STOP)
show_arrows(CABIN_STOP)
cabin_display(target)
if sim_connect() != 0:
exit(1)
show_arrows(CABIN_STOP)
print("Waiting for calls. Ctrl+C to stop.")
while True:
scan_buttons()
target = nearest_call(current_floor())
if target != 0:
print("Going to floor", target)
go_to_floor(target)
open_door(target)
clear_calls(target)
wait_ms(3000)
close_door(target)
time.sleep(0.01)
Görev 28'deki asansörü bekleme döngüsü olmadan, tek bir ana döngü ve bir durum değişkeniyle yeniden yazın. Durumlar: IDLE (boşta), MOVING (hareket), OPENING (kapı açılıyor), OPEN (kapı açık), CLOSING (kapı kapanıyor). Ana döngü her turda düğmeleri okusun ve yalnızca o anki durumun işini yapsın. Kapının 3 saniye açık kalma süresini Sleep ile değil saat okuyarak ölçün.
Davranış Görev 28 ile aynı olmalı: en yakın çağrıya git, kapıyı aç, istekleri sil, 3 saniye bekle, kapat; hareket sırasında oklar ve ekran doğru olsun. Başlangıçta önce bütün kapıları kapatın ve kabin katlar arasındaysa aşağıdaki kata indirin.
Durum makinesinde program hiçbir yerde takılıp beklemez; her turda 'şu anki durumda ne yapmalıyım, bir sonraki duruma geçmeli miyim?' sorusunu sorar. Bu sayede düğme okuma, sensör izleme ve zaman ölçme aynı döngüde birlikte yürür ve yeni bir özellik eklemek kolaylaşır. opened_at kapının açıldığı anı saklar; geçen süre şimdiki saatle farkıdır. Döngü yalnızca IDLE ve OPEN durumlarında 10 ms uyur; hareket ve kapı durumlarında sensörleri durmadan izler. MOVING durumunda geçilen her katta ekran güncellenir.
#include "elevator.h"
#define IDLE 0
#define MOVING 1
#define OPENING 2
#define OPEN 3
#define CLOSING 4
int cab_req[4], up_req[4], dn_req[4]; // index 1..3
int up_arrow[4] = {0, ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3};
int dn_arrow[4] = {0, ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3};
void show_arrows(int dir)
{
for (int f = 1; f <= 3; f++)
{
write_mem(up_arrow[f], dir == CABIN_UP);
write_mem(dn_arrow[f], dir == CABIN_DOWN);
}
}
void scan_buttons(void)
{
for (int f = 1; f <= 3; f++)
{
if (cabin_button_read(f) == 1 && cab_req[f] == 0)
{
cab_req[f] = 1;
cabin_button_light(f, 1);
}
if (floor_button_read(f, DIR_UP) == 1 && up_req[f] == 0)
{
up_req[f] = 1;
floor_button_light(f, DIR_UP, 1);
}
if (floor_button_read(f, DIR_DOWN) == 1 && dn_req[f] == 0)
{
dn_req[f] = 1;
floor_button_light(f, DIR_DOWN, 1);
}
}
}
int has_call(int f)
{
return cab_req[f] == 1 || up_req[f] == 1 || dn_req[f] == 1;
}
void clear_calls(int f)
{
if (cab_req[f] == 1) { cab_req[f] = 0; cabin_button_light(f, 0); }
if (up_req[f] == 1) { up_req[f] = 0; floor_button_light(f, DIR_UP, 0); }
if (dn_req[f] == 1) { dn_req[f] = 0; floor_button_light(f, DIR_DOWN, 0); }
}
int nearest_call(int from)
{
int best = 0, best_dist = 99;
for (int f = 1; f <= 3; f++)
{
if (has_call(f))
{
int dist = (f > from) ? f - from : from - f;
if (dist < best_dist) { best = f; best_dist = dist; }
}
}
return best;
}
int current_floor(void)
{
for (int f = 1; f <= 3; f++)
if (cabin_sensor_read(f) == 1) return f;
return 0;
}
void close_door(int f) // used only at start-up
{
if (door_sensor_read(f) == 0) return;
door(f, DOOR_CLOSE);
while (door_sensor_read(f) == 1) { }
door(f, DOOR_STOP);
}
int main(void)
{
if (sim_connect() != 0) return 1;
// Safe start: doors closed, cabin at a floor
cabin_motor(CABIN_STOP);
for (int f = 1; f <= 3; f++) close_door(f);
while (current_floor() == 0) cabin_motor(CABIN_DOWN);
cabin_motor(CABIN_STOP);
show_arrows(CABIN_STOP);
int floor = current_floor();
int target = 0;
int state = IDLE;
DWORD opened_at = 0;
cabin_display(floor);
printf("Running. Ctrl+C to stop.\n");
while (1)
{
scan_buttons();
if (state == IDLE)
{
target = nearest_call(floor);
if (target == floor)
{
door(floor, DOOR_OPEN);
state = OPENING;
}
else if (target > floor)
{
show_arrows(CABIN_UP);
cabin_motor(CABIN_UP);
state = MOVING;
}
else if (target != 0 && target < floor)
{
show_arrows(CABIN_DOWN);
cabin_motor(CABIN_DOWN);
state = MOVING;
}
}
else if (state == MOVING)
{
int f = current_floor();
if (f != 0 && f != floor) // reached a new floor
{
floor = f;
cabin_display(floor);
}
if (floor == target)
{
cabin_motor(CABIN_STOP);
show_arrows(CABIN_STOP);
door(floor, DOOR_OPEN);
state = OPENING;
}
}
else if (state == OPENING)
{
if (door_open_read(floor) == 1)
{
door(floor, DOOR_STOP);
clear_calls(floor);
opened_at = GetTickCount();
state = OPEN;
}
}
else if (state == OPEN)
{
if (GetTickCount() - opened_at >= 3000)
{
door(floor, DOOR_CLOSE);
state = CLOSING;
}
}
else if (state == CLOSING)
{
if (door_sensor_read(floor) == 0)
{
door(floor, DOOR_STOP);
state = IDLE;
}
}
if (state == IDLE || state == OPEN) Sleep(10); // no motor to stop
}
sim_disconnect();
return 0;
}
from elevator import *
import time
IDLE, MOVING, OPENING, OPEN, CLOSING = 0, 1, 2, 3, 4
cab_req = [0, 0, 0, 0] # index 1..3
up_req = [0, 0, 0, 0]
dn_req = [0, 0, 0, 0]
up_arrow = [0, ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3]
dn_arrow = [0, ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3]
def show_arrows(direction):
for f in (1, 2, 3):
write_mem(up_arrow[f], int(direction == CABIN_UP))
write_mem(dn_arrow[f], int(direction == CABIN_DOWN))
def scan_buttons():
for f in (1, 2, 3):
if cabin_button_read(f) == 1 and cab_req[f] == 0:
cab_req[f] = 1
cabin_button_light(f, 1)
if floor_button_read(f, DIR_UP) == 1 and up_req[f] == 0:
up_req[f] = 1
floor_button_light(f, DIR_UP, 1)
if floor_button_read(f, DIR_DOWN) == 1 and dn_req[f] == 0:
dn_req[f] = 1
floor_button_light(f, DIR_DOWN, 1)
def has_call(f):
return cab_req[f] == 1 or up_req[f] == 1 or dn_req[f] == 1
def clear_calls(f):
if cab_req[f] == 1:
cab_req[f] = 0
cabin_button_light(f, 0)
if up_req[f] == 1:
up_req[f] = 0
floor_button_light(f, DIR_UP, 0)
if dn_req[f] == 1:
dn_req[f] = 0
floor_button_light(f, DIR_DOWN, 0)
def nearest_call(start):
best = 0
best_dist = 99
for f in (1, 2, 3):
if has_call(f):
dist = abs(f - start)
if dist < best_dist:
best = f
best_dist = dist
return best
def current_floor():
for f in (1, 2, 3):
if cabin_sensor_read(f) == 1:
return f
return 0
def close_door(f): # used only at start-up
if door_sensor_read(f) == 0:
return
door(f, DOOR_CLOSE)
while door_sensor_read(f) == 1:
pass
door(f, DOOR_STOP)
if sim_connect() != 0:
exit(1)
# Safe start: doors closed, cabin at a floor
cabin_motor(CABIN_STOP)
for f in (1, 2, 3):
close_door(f)
while current_floor() == 0:
cabin_motor(CABIN_DOWN)
cabin_motor(CABIN_STOP)
show_arrows(CABIN_STOP)
floor = current_floor()
target = 0
state = IDLE
opened_at = 0.0
cabin_display(floor)
print("Running. Ctrl+C to stop.")
while True:
scan_buttons()
if state == IDLE:
target = nearest_call(floor)
if target == floor:
door(floor, DOOR_OPEN)
state = OPENING
elif target > floor:
show_arrows(CABIN_UP)
cabin_motor(CABIN_UP)
state = MOVING
elif target != 0 and target < floor:
show_arrows(CABIN_DOWN)
cabin_motor(CABIN_DOWN)
state = MOVING
elif state == MOVING:
f = current_floor()
if f != 0 and f != floor: # reached a new floor
floor = f
cabin_display(floor)
if floor == target:
cabin_motor(CABIN_STOP)
show_arrows(CABIN_STOP)
door(floor, DOOR_OPEN)
state = OPENING
elif state == OPENING:
if door_open_read(floor) == 1:
door(floor, DOOR_STOP)
clear_calls(floor)
opened_at = time.monotonic()
state = OPEN
elif state == OPEN:
if time.monotonic() - opened_at >= 3.0:
door(floor, DOOR_CLOSE)
state = CLOSING
elif state == CLOSING:
if door_sensor_read(floor) == 0:
door(floor, DOOR_STOP)
state = IDLE
if state == IDLE or state == OPEN: # no motor to stop
time.sleep(0.01)
Görev 29'daki durum makinesini gerçek asansörler gibi çalışacak hâle getirin:
• Asansör bir yöne gidiyorsa, o yönde bekleyen çağrı kaldığı sürece yönünü değiştirmesin; o yönde çağrı kalmayınca diğer yöne dönsün.
• Yol üzerinde, çağrısı olan bir kattan geçerken orada dursun (ör. 1. kattan 3. kata giderken 2. katta çağrı varsa önce 2. katta dursun).
• Her durakta kapıyı açsın, o katın isteklerini silsin, 3 saniye sonra kapatsın. Ekran ve oklar her zaman doğru olsun; kabin hiçbir zaman kapı açıkken hareket etmesin.
Test: kabin 1. kattayken kabin 3'e basın; kabin 2. kata yaklaşmadan 2. kattaki ▼ düğmesine basın. Kabin önce 2. katta, sonra 3. katta durmalı.
Bu, gerçek asansörlerde kullanılan toplayıcı (collective) kontrolün sade bir hâlidir. choose_direction() önce eski yönde çağrı var mı diye bakar; böylece asansör yolcuları ileri geri gezdirmez. MOVING durumunda her yeni katta karar verilir: o katta çağrı varsa ya da kat 1 veya 3 ise (daha ötesi yok) kabin durur ve IDLE durumuna geçer. IDLE, bulunduğu katta çağrı varsa kapıyı açar; yoksa yeni yönü seçer. Kapı yalnızca kabin dururken açılır ve kabin yalnızca IDLE durumunda, yani kapı tam kapalıyken hareket eder; güvenlik durum makinesinin yapısından gelir.
#include "elevator.h"
#define IDLE 0
#define MOVING 1
#define OPENING 2
#define OPEN 3
#define CLOSING 4
int cab_req[4], up_req[4], dn_req[4]; // index 1..3
int up_arrow[4] = {0, ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3};
int dn_arrow[4] = {0, ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3};
void show_arrows(int dir)
{
for (int f = 1; f <= 3; f++)
{
write_mem(up_arrow[f], dir == CABIN_UP);
write_mem(dn_arrow[f], dir == CABIN_DOWN);
}
}
void scan_buttons(void)
{
for (int f = 1; f <= 3; f++)
{
if (cabin_button_read(f) == 1 && cab_req[f] == 0)
{
cab_req[f] = 1;
cabin_button_light(f, 1);
}
if (floor_button_read(f, DIR_UP) == 1 && up_req[f] == 0)
{
up_req[f] = 1;
floor_button_light(f, DIR_UP, 1);
}
if (floor_button_read(f, DIR_DOWN) == 1 && dn_req[f] == 0)
{
dn_req[f] = 1;
floor_button_light(f, DIR_DOWN, 1);
}
}
}
int has_call(int f)
{
return cab_req[f] == 1 || up_req[f] == 1 || dn_req[f] == 1;
}
void clear_calls(int f)
{
if (cab_req[f] == 1) { cab_req[f] = 0; cabin_button_light(f, 0); }
if (up_req[f] == 1) { up_req[f] = 0; floor_button_light(f, DIR_UP, 0); }
if (dn_req[f] == 1) { dn_req[f] = 0; floor_button_light(f, DIR_DOWN, 0); }
}
int calls_above(int floor)
{
for (int f = floor + 1; f <= 3; f++)
if (has_call(f)) return 1;
return 0;
}
int calls_below(int floor)
{
for (int f = floor - 1; f >= 1; f--)
if (has_call(f)) return 1;
return 0;
}
// Keep the old direction while it has calls, else turn, else stop
int choose_direction(int floor, int old_dir)
{
if (old_dir == CABIN_UP && calls_above(floor)) return CABIN_UP;
if (old_dir == CABIN_DOWN && calls_below(floor)) return CABIN_DOWN;
if (calls_above(floor)) return CABIN_UP;
if (calls_below(floor)) return CABIN_DOWN;
return CABIN_STOP;
}
int current_floor(void)
{
for (int f = 1; f <= 3; f++)
if (cabin_sensor_read(f) == 1) return f;
return 0;
}
void close_door(int f) // used only at start-up
{
if (door_sensor_read(f) == 0) return;
door(f, DOOR_CLOSE);
while (door_sensor_read(f) == 1) { }
door(f, DOOR_STOP);
}
int main(void)
{
if (sim_connect() != 0) return 1;
cabin_motor(CABIN_STOP);
for (int f = 1; f <= 3; f++) close_door(f);
while (current_floor() == 0) cabin_motor(CABIN_DOWN);
cabin_motor(CABIN_STOP);
show_arrows(CABIN_STOP);
int floor = current_floor();
int dir = CABIN_STOP; // last travel direction
int state = IDLE;
DWORD opened_at = 0;
cabin_display(floor);
printf("Elevator running. Ctrl+C to stop.\n");
while (1)
{
scan_buttons();
if (state == IDLE)
{
if (has_call(floor))
{
door(floor, DOOR_OPEN);
state = OPENING;
}
else
{
dir = choose_direction(floor, dir);
if (dir != CABIN_STOP)
{
show_arrows(dir);
cabin_motor(dir);
state = MOVING;
}
}
}
else if (state == MOVING)
{
int f = current_floor();
if (f != 0 && f != floor) // reached a new floor
{
floor = f;
cabin_display(floor);
if (has_call(floor) || floor == 1 || floor == 3)
{
cabin_motor(CABIN_STOP);
show_arrows(CABIN_STOP);
state = IDLE; // IDLE opens the door if needed
}
}
}
else if (state == OPENING)
{
if (door_open_read(floor) == 1)
{
door(floor, DOOR_STOP);
clear_calls(floor);
opened_at = GetTickCount();
state = OPEN;
}
}
else if (state == OPEN)
{
if (GetTickCount() - opened_at >= 3000)
{
door(floor, DOOR_CLOSE);
state = CLOSING;
}
}
else if (state == CLOSING)
{
if (door_sensor_read(floor) == 0)
{
door(floor, DOOR_STOP);
state = IDLE;
}
}
if (state == IDLE || state == OPEN) Sleep(10);
}
sim_disconnect();
return 0;
}
from elevator import *
import time
IDLE, MOVING, OPENING, OPEN, CLOSING = 0, 1, 2, 3, 4
cab_req = [0, 0, 0, 0] # index 1..3
up_req = [0, 0, 0, 0]
dn_req = [0, 0, 0, 0]
up_arrow = [0, ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3]
dn_arrow = [0, ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3]
def show_arrows(direction):
for f in (1, 2, 3):
write_mem(up_arrow[f], int(direction == CABIN_UP))
write_mem(dn_arrow[f], int(direction == CABIN_DOWN))
def scan_buttons():
for f in (1, 2, 3):
if cabin_button_read(f) == 1 and cab_req[f] == 0:
cab_req[f] = 1
cabin_button_light(f, 1)
if floor_button_read(f, DIR_UP) == 1 and up_req[f] == 0:
up_req[f] = 1
floor_button_light(f, DIR_UP, 1)
if floor_button_read(f, DIR_DOWN) == 1 and dn_req[f] == 0:
dn_req[f] = 1
floor_button_light(f, DIR_DOWN, 1)
def has_call(f):
return cab_req[f] == 1 or up_req[f] == 1 or dn_req[f] == 1
def clear_calls(f):
if cab_req[f] == 1:
cab_req[f] = 0
cabin_button_light(f, 0)
if up_req[f] == 1:
up_req[f] = 0
floor_button_light(f, DIR_UP, 0)
if dn_req[f] == 1:
dn_req[f] = 0
floor_button_light(f, DIR_DOWN, 0)
def calls_above(floor):
for f in range(floor + 1, 4):
if has_call(f):
return True
return False
def calls_below(floor):
for f in range(floor - 1, 0, -1):
if has_call(f):
return True
return False
def choose_direction(floor, old_dir):
"""Keep the old direction while it has calls, else turn, else stop."""
if old_dir == CABIN_UP and calls_above(floor):
return CABIN_UP
if old_dir == CABIN_DOWN and calls_below(floor):
return CABIN_DOWN
if calls_above(floor):
return CABIN_UP
if calls_below(floor):
return CABIN_DOWN
return CABIN_STOP
def current_floor():
for f in (1, 2, 3):
if cabin_sensor_read(f) == 1:
return f
return 0
def close_door(f): # used only at start-up
if door_sensor_read(f) == 0:
return
door(f, DOOR_CLOSE)
while door_sensor_read(f) == 1:
pass
door(f, DOOR_STOP)
if sim_connect() != 0:
exit(1)
cabin_motor(CABIN_STOP)
for f in (1, 2, 3):
close_door(f)
while current_floor() == 0:
cabin_motor(CABIN_DOWN)
cabin_motor(CABIN_STOP)
show_arrows(CABIN_STOP)
floor = current_floor()
direction = CABIN_STOP # last travel direction
state = IDLE
opened_at = 0.0
cabin_display(floor)
print("Elevator running. Ctrl+C to stop.")
while True:
scan_buttons()
if state == IDLE:
if has_call(floor):
door(floor, DOOR_OPEN)
state = OPENING
else:
direction = choose_direction(floor, direction)
if direction != CABIN_STOP:
show_arrows(direction)
cabin_motor(direction)
state = MOVING
elif state == MOVING:
f = current_floor()
if f != 0 and f != floor: # reached a new floor
floor = f
cabin_display(floor)
if has_call(floor) or floor == 1 or floor == 3:
cabin_motor(CABIN_STOP)
show_arrows(CABIN_STOP)
state = IDLE # IDLE opens the door if needed
elif state == OPENING:
if door_open_read(floor) == 1:
door(floor, DOOR_STOP)
clear_calls(floor)
opened_at = time.monotonic()
state = OPEN
elif state == OPEN:
if time.monotonic() - opened_at >= 3.0:
door(floor, DOOR_CLOSE)
state = CLOSING
elif state == CLOSING:
if door_sensor_read(floor) == 0:
door(floor, DOOR_STOP)
state = IDLE
if state == IDLE or state == OPEN:
time.sleep(0.01)
Gerçek asansörlerde kapı kapanırken birisi aynı katın düğmesine basarsa kapı yeniden açılır. Görev 30'daki denetleyiciye şunu ekleyin:
• Kapı açıkken (OPEN) bulunulan katın bir düğmesine basılırsa istek hemen silinsin ve 3 saniyelik süre baştan başlasın.
• Kapı kapanırken (CLOSING) bulunulan katın bir düğmesine basılırsa kapı hemen yeniden açılmaya başlasın.
Test: kabin bir katta kapısını kapatırken o katın ▲ düğmesine ya da kabin içinde o katın düğmesine basın.
Binaya gelenlerin çoğu giriş katından (1. kat) biner. Görev 30'daki denetleyiciye şunu ekleyin: asansör 10 saniye boyunca hiç çağrı almadan boşta (IDLE) kalırsa ve 1. katta değilse, kapısını açmadan 1. kata insin ve orada beklesin. Bu sırada bir çağrı gelirse her zamanki gibi karşılansın.
Test: Yenile'den sonra programı başlatın ve hiçbir şeye basmayın; yaklaşık 10 saniye sonra kabin 1. kata inmeli.
Güvenli bir denetleyici, bir şeylerin ters gittiğini fark edip her şeyi durdurabilmelidir. Görev 30'daki denetleyiciye şunları ekleyin:
• Başlangıçta, varsa eski hata bayrağı temizlenene kadar bekleyin.
• Ana döngünün her turunda get_error() 1 ise acil durdurma yapın.
• Kabin hareket ederken 7 saniye boyunca yeni bir kata ulaşamazsa (normalde iki kat arası yaklaşık 4,7 saniyedir) bunu da arıza sayıp acil durdurma yapın.
Acil durdurma: kabin motorunu ve üç kapı motorunu durdurun, okları söndürün, ekranda 0 gösterin, nedeni konsola yazın ve programı bitirin.
Test 1: kabin hareket ederken Elle Kontrol'de kabin motoru için Dur'a basın (7 saniye sonra zaman aşımı). Test 2: program çalışırken Elle Kontrol'de kabinin bulunmadığı bir katın kapısı için Aç'a basıp bekleyin (kapı tam açılıp devam edince hata).
Bir asansörün ne kadar iyi çalıştığını ölçmek için Görev 30'daki denetleyiciye istatistik ekleyin:
• Kaç durakta kapı açıldığını (hizmet sayısı),
• Kabinin toplam kaç kat yol gittiğini,
• Her kat için ilk düğmeye basılmasından o katta kapının tam açılmasına kadar geçen bekleme süresini ölçüp ortalamasını tutun.
5 hizmetten sonra, kapı kapanıp asansör boşta kalınca bu üç bilgiyi konsola yazın (ortalama bekleme süresi saniye cinsinden, bir ondalıkla), okları söndürüp programı düzgünce bitirin.