const n = 10; n5 = 6; n6 = 3; nT = 50; function f1: integer; begin f1 := random(4) + 2; end; function f2: integer; begin f2 := random(10); end; (***** TClient *****) type PTClient = ^TClient; TClient = object constructor create(value: integer); function get_id: integer; private ID: integer; end; constructor TClient.create(value: integer); begin ID := value; end; function TClient.get_id: integer; begin get_id := ID; end; type T = PTClient; PTQueueItem = ^TQueueItem; TQueueItem = object item: T; next: PTQueueItem; constructor create(value: T); end; TQueue = object constructor create; destructor destroy; procedure get(var value: T); procedure put(const value: T); function is_empty: boolean; private front, back: PTQueueItem; end; constructor TQueueItem.create(value: T); begin item := value; next := nil; end; constructor TQueue.create; begin front := nil; back := nil; end; destructor TQueue.destroy; var value: T; begin while not is_empty do get(value); end; procedure TQueue.get(var value: T); var pt: PTQueueItem; begin if is_empty then begin writeln('Trying to Get from the empty queue !'); halt(101) end; pt := front; front := front^.next; value := pt^.item; dispose(pt); end; procedure TQueue.put(const value: T); var pt: PTQueueItem; begin pt := new(PTQueueItem, create(value)); if is_empty then begin front := pt; back := pt; end else begin back^.next := pt; back := pt; end; end; function TQueue.is_empty: boolean; begin is_empty := (front = nil) end; (* template class TQueue { public: TQueue() { front = back = 0; } ~TQueue(); T get(); void put(const T&); int is_empty() { return((!front) ? 1 : 0); } private: class TQueueItem { public: TQueueItem(T value): item(value), next(0) { } T item; TQueueItem *next; }; TQueueItem *front, *back; }; template TQueue :: ~TQueue() { while(!is_empty()) (void)get(); } template void TQueue :: put(const T &value) { TQueueItem *pt = new TQueueItem(value); if(is_empty()) { front = back = pt; } else { back -> next = pt; back = pt; } } template T TQueue :: get() { if(is_empty()) { cout << "Trying to Get from the empty queue !\n"; exit(-1); } TQueueItem *pt = front; front = front -> next; T value = pt -> item; delete pt; return value; } *) type status = ( _busy = 0, _waiting, _vacation ); PTCasher = ^TCasher; TCasher = object state: status; work_time, ID: integer; { *** const *** } working_time, this_client: integer; public constructor create(_id, _work: integer); function handle(var changed: integer): status; procedure next; end; constructor TCasher.create(_id, _work: integer); begin ID := _id; work_time := _work; state := _waiting; working_time := work_time; end; function TCasher.handle(var changed: integer): status; begin changed := 0; if state = _busy then begin dec(this_client); dec(working_time); if this_client = 0 then begin state := _waiting; changed := 1; end; end; if state = _vacation then begin inc(working_time); if working_time > 0 then begin state := _waiting; working_time := work_time; changed := 1; end; end; if state = _waiting then begin if changed = 0 then dec(working_time); if working_time <= 0 then begin state := _vacation; working_time := -n6; changed := 1; end; end; handle := state; end; procedure TCasher.next; begin state := _busy; this_client := f2; end; type TManager = object queue: TQueue; cash_workers: array[0 .. pred(n)] of PTCasher; current_time, after_prev_enter: integer; public constructor create; destructor destroy; procedure run; end; constructor TManager.create; var i: integer; begin current_time := 0; after_prev_enter := 0; for i := 0 to pred(n) do cash_workers[i] := new(PTCasher, create(i + 1, n5)); end; destructor TManager.destroy; var i: integer; begin for i := 0 to pred(n) do dispose(cash_workers[i]); end; procedure TManager.run; const client_entered: integer = 0; var i: integer; status_changed: integer; curr_status: status; client: PTClient; begin while (current_time <= nT) or (not queue.is_empty) do begin for i := 0 to pred(n) do begin status_changed := 0; curr_status := cash_workers[i]^.Handle(status_changed); if status_changed <> 0 then { statistics } case curr_status of _vacation: writeln('casher #', i, ' goes to rest at:: ', current_time); _waiting: writeln('casher #', i, ' awaiting at:: ', current_time); end; if curr_status = _waiting then if not queue.is_empty then begin queue.get(client); writeln('client #', client^.get_id, ' sent to casher #', i, ' at:: ', current_time); cash_workers[i]^.next; dispose(client); end; end; if current_time <= nT then begin inc(after_prev_enter); if after_prev_enter > f1 then begin after_prev_enter := 0; inc(client_entered); client := new(PTClient, create(client_entered)); queue.put(client); end; end; inc(current_time); end; writeln(client_entered); end; var bank: TManager; begin bank.create; bank.run; bank.destroy; end.