elevator  0.7
Симулятор пассажирского лифта
Control.cpp
См. документацию.
1 // Проект elevator
2 // (c) И.К. Марчевский, 2021-2022
3 
12 #include <algorithm>
13 #include <fstream>
14 #include <iostream>
15 #include <iterator>
16 
17 
18 #include "Control.h"
19 #include "Queue.h"
20 
21 
22 Control::Control(size_t numberOfFloors, size_t numberOfElevators, size_t capacityOfElevator)
23  : floorButtons(new FloorButtons(numberOfFloors)), queue(new Queue(numberOfFloors)), time(0)
24 {
25  for (size_t id = 0; id < numberOfElevators; ++id)
26  elevators.emplace_back(new Elevator(numberOfFloors, capacityOfElevator, id));
27 }//Control(...)
28 
29 
31 {
32 }//~Control()
33 
34 
35 void Control::TimeIncrement()
36 {
37  ++time;
38 }//TimeIncrement()
39 
40 
41 void Control::FindAppearingPassengers()
42 {
43  auto newEnd = std::partition(queue->passengers.begin(), queue->passengers.end(), \
44  [=](const Passenger& p) {return p.getTimeInit() != getCurrentTime(); });
45 
46  for (auto it = newEnd; it != queue->passengers.end(); ++it)
47  {
48  queue->passOnFloor[it->getFloorDeparture()].push_back(*it);
49  passStatBuffer.push_back("time = " + std::to_string(getCurrentTime()) \
50  + "\tPassenger #" + std::to_string(it->id) \
51  + "\tappeared on floor #" + std::to_string(it->getFloorDeparture()) \
52  + ", goes to floor #" + std::to_string(it->getFloorDestination()));
53  }//for it
54 
55  queue->passengers.erase(newEnd, queue->passengers.end());
56 }//FindAppearingPassengers()
57 
58 
59 void Control::PressingFloorButtons()
60 {
61  for (size_t floor = 0; floor < queue->passOnFloor.size(); ++floor)
62  {
63  for (auto& p : queue->passOnFloor[floor])
64  if (!isElevatorOnFloor(floor))
65  {
66  if (p.getFloorDestination() > p.getFloorDeparture())
67  floorButtons->setUpButton(p.getFloorDeparture());
68  else
69  floorButtons->setDnButton(p.getFloorDeparture());
70  }//if !isElevatorOnFloor
71  }//for floor
72 }//PressingFloorButtons()
73 
74 
75 void Control::LeavingFloors()
76 {
77  for (size_t floor = 0; floor < queue->passOnFloor.size(); ++floor)
78  {
79  std::vector<Passenger> continueWaiting;
80 
81  for (auto& p : queue->passOnFloor[floor])
82  {
83  if (getCurrentTime() - p.getTimeInit() < p.properties.criticalWaitTime)
84  continueWaiting.push_back(p);
85  else
86  {
87  p.status = PassengerStatus::leaved;
88  queue->finished.push_back(p);
89  passStatBuffer.push_back(\
90  "time = " + std::to_string(getCurrentTime()) \
91  + "\tPassenger #" + std::to_string(p.id) \
92  + "\tfrom floor #" + std::to_string(p.getFloorDeparture()) \
93  + " to floor #" + std::to_string(p.getFloorDestination()) \
94  + "\tleaved the floor (waiting time = " + std::to_string(getCurrentTime() - p.getTimeInit()) + ")");
95  }
96  }
97  queue->passOnFloor[floor] = std::move(continueWaiting);
98 
99  }//for floor
100 }
101 
103 {
104  passStatBuffer.resize(0);
105 
106  TimeIncrement();
107 
108  //Проверка появления пассажиров на этажах и их передача
109  //в соответствующие списки ожидающих на этажах
110  FindAppearingPassengers();
111 
112  //Нажатие появившимися пассажирами кнопок на этажах
113  PressingFloorButtons();
114 
115  //Пассажиры, ждавшие слишком долго, уходят с этажей, и за это начисляется большой штраф
116  LeavingFloors();
117 
118  //Посадка пассажиров в лифты на этажах
119  //цикл по этажам:
120  for (size_t pos = 0; pos < floorButtons->dnButtons.size(); ++pos)
121  {
122  //std::vector<ElevatorIndicator> ind = { ElevatorIndicator::up, ElevatorIndicator::down };
123 
124  //for (auto& indValue : ind)
125  //{
126  std::vector<Elevator*> elevOnFloor;
127  for (auto& e : elevators)
128  {
129  if ((e->position / 100 == pos) && (e->doorsStatus == ElevatorDoorsStatus::openedLoading))
130  if (e->getNumberOfPassengers() < e->capacity)
131  elevOnFloor.push_back(e.get());
132  else
133  {
134  if (e->timeToSelfProgramme == 0)
135  {
136  e->timeToSelfProgramme = waitingTime;
137  e->doorsStatus = ElevatorDoorsStatus::waiting;
138  }
139  }
140  }
141 
142  if (elevOnFloor.size() > 1)
143  for (auto& pe : elevOnFloor)
144  pe->timeToSelfProgramme = elevOnFloor[0]->timeToSelfProgramme;
145 
146  if (elevOnFloor.size() > 0)
147  if (elevOnFloor[0]->timeToSelfProgramme == 0)
148  {
149  auto& pass = queue->passOnFloor[pos];
150 
151  size_t passToUp = 0, passToDn = 0;
152  for (auto& p : pass)
153  {
154  if (p.getFloorDestination() > pos)
155  ++passToUp;
156  else
157  ++passToDn;
158  }
159 
160  if (passToUp == 0)
161  for (auto& e : elevOnFloor)
162  if (e->getIndicator() == ElevatorIndicator::up)
163  {
164  e->timeToSelfProgramme = waitingTime;
165  e->doorsStatus = ElevatorDoorsStatus::waiting;
166  };
167 
168  if (passToDn == 0)
169  for (auto& e : elevOnFloor)
170  if (e->getIndicator() == ElevatorIndicator::down)
171  {
172  e->timeToSelfProgramme = waitingTime;
173  e->doorsStatus = ElevatorDoorsStatus::waiting;
174  };
175 
176  if ((passToUp == 0) && (passToDn == 0))
177  for (auto& e : elevOnFloor)
178  if (e->getIndicator() == ElevatorIndicator::both)
179  {
180  e->timeToSelfProgramme = waitingTime;
181  e->doorsStatus = ElevatorDoorsStatus::waiting;
182  };
183 
184 
185  std::vector<Passenger> stillWaiting;
186 
187  for (auto& p : pass)
188  {
189 
190  std::vector<Elevator*> elevAppropriate;
191  bool inverseWay = false;
192 
193  bool inv = p.PerformInverseProbability(getCurrentTime());
194 
195  for (auto& e : elevOnFloor)
196  {
197  if ((p.getFloorDestination() > pos) && (e->timeToSelfProgramme == 0) && (e->doorsStatus == ElevatorDoorsStatus::openedLoading) && (e->indicator == ElevatorIndicator::up || e->indicator == ElevatorIndicator::both))
198  {
199  e->lastChechedPassenger = std::max(p.id, e->lastChechedPassenger);
200 
201  if (e->getNumberOfPassengers() < e->capacity)
202  elevAppropriate.push_back(e);
203  else
204  {
205  e->timeToSelfProgramme = waitingTime;
206  e->doorsStatus = ElevatorDoorsStatus::waiting;
207  }
208  }
209 
210  if ((p.getFloorDestination() < pos) && (e->timeToSelfProgramme == 0) && (e->doorsStatus == ElevatorDoorsStatus::openedLoading) && (e->indicator == ElevatorIndicator::down || e->indicator == ElevatorIndicator::both))
211  {
212  e->lastChechedPassenger = std::max(p.id, e->lastChechedPassenger);
213 
214  if (e->getNumberOfPassengers() < e->capacity)
215  elevAppropriate.push_back(e);
216  else
217  {
218  e->timeToSelfProgramme = waitingTime;
219  e->doorsStatus = ElevatorDoorsStatus::waiting;
220  }
221  }
222  }
223 
224  //Если человек готов сесть не туда
225  if ((elevAppropriate.size() == 0) && (inv))
226  {
227 
228  for (auto& e : elevOnFloor)
229  {
230  if ((e->timeToSelfProgramme == 0) && (e->doorsStatus == ElevatorDoorsStatus::openedLoading))
231  {
232  e->lastChechedPassenger = std::max(p.id, e->lastChechedPassenger);
233 
234  if (e->lastChechedPassenger <= p.id)
235  {
236  if (e->getNumberOfPassengers() < e->capacity)
237  {
238  elevAppropriate.push_back(e);
239  inverseWay = true;
240  }
241  else
242  {
243  e->timeToSelfProgramme = waitingTime;
244  e->doorsStatus = ElevatorDoorsStatus::waiting;
245  }
246  }
247  }
248  }
249  }
250 
251 
252  if (elevAppropriate.size() > 0)
253  {
254  size_t elevWithSmallestPass = 0;
255  size_t smallestPass = elevAppropriate[0]->getNumberOfPassengers();
256 
257  for (size_t numb = 1; numb < elevAppropriate.size(); ++numb)
258  if (elevAppropriate[numb]->getNumberOfPassengers() < smallestPass)
259  {
260  elevWithSmallestPass = numb;
261  smallestPass = elevAppropriate[numb]->getNumberOfPassengers();
262  }
263 
264 
265  Elevator* e = elevAppropriate[elevWithSmallestPass];
266 
267  e->passengers.push_back(p);
268  e->passengers.back().status = PassengerStatus::going;
269  e->passengers.back().timeStart = getCurrentTime();
270  passStatBuffer.push_back("time = " + std::to_string(getCurrentTime()) \
271  + "\tPassenger #" + std::to_string(e->passengers.back().id) \
272  + "\tfrom floor #" + std::to_string(e->passengers.back().getFloorDeparture()) \
273  + " to floor #" + std::to_string(e->passengers.back().getFloorDestination()) \
274  + (inverseWay ? "*" : "") \
275  + "\tentered the elevator #" + std::to_string(e->myid));
276  e->timeToSelfProgramme = timeEntering;
277  e->buttons[e->passengers.back().getFloorDestination()] = true;
278  if (e->indicator == ElevatorIndicator::both)
279  {
280  if (e->passengers.back().properties.floorDestination > pos)
281  e->indicator = ElevatorIndicator::up;
282  else
283  e->indicator = ElevatorIndicator::down;
284  }
285 
286  }
287  else
288  stillWaiting.push_back(p);
289 
290  }//for p
291 
292  pass.clear();
293  pass = std::move(stillWaiting);
294 
295  }
296  //}//for indValue
297  }//for pos
298 
299 
300  //Обработка нажатия кнопки "Ход"
301  for (auto& e : elevators)
302  {
303  if (e->doorsStatus == ElevatorDoorsStatus::waiting)
304  if (e->isGoingButtonPressed() && (e->timeToSelfProgramme > 1))
305  {
306  e->timeToSelfProgramme = 1;
307  }
308  }
309 
310  //Обработка движения лифта
311  for (auto& e : elevators)
312  {
313  if (e->timeToSelfProgramme == 0)
314  {
315  auto pos = e->position / 100;
316  auto& pass = queue->passOnFloor[pos];
317 
318  switch (e->status)
319  {
321  {
322  //3.1. Обрабатываем стоящий лифт
323  switch (e->doorsStatus)
324  {
326  {
327  e->timeToSelfProgramme = timeLeaving - 1;
328  auto it = std::find_if(e->passengers.begin(), e->passengers.end(), \
329  [=](const Passenger& p) {return p.getFloorDestination() == pos; });
330  if (it != e->passengers.end())
331  {
332  it->status = PassengerStatus::arrived;
333  it->timeFinish = getCurrentTime();
334  queue->finished.push_back(*it);
335  passStatBuffer.push_back("time = " + std::to_string(getCurrentTime()) \
336  + "\tPassenger #" + std::to_string(it->id) \
337  + "\tfrom floor #" + std::to_string(it->getFloorDeparture()) \
338  + " to floor #" + std::to_string(it->getFloorDestination()) \
339  + "\tgot off the elevator #" + std::to_string(e->myid) \
340  + " (appeared t = " + std::to_string(it->properties.timeInit) \
341  + ", in elevator t = " + std::to_string(it->timeStart) + ")");
342  e->passengers.erase(it);
343  break;
344  }// if it!=
345 
346  e->doorsStatus = ElevatorDoorsStatus::openedLoading;
347  e->lastChechedPassenger = 0;
348 
349  break;
350  }//case ElevatorDoorsStatus::openedUnloading:
351 
353  {
354  e->doorsStatus = ElevatorDoorsStatus::closing;
355  e->timeToSelfProgramme = timeClosing - 1;
356  break;
357  }//case ElevatorDoorsStatus::waiting:
358 
360  {
361  //Только что закрывший двери лифт - делаем двери закрытыми
362  e->doorsStatus = ElevatorDoorsStatus::closed;
363  break;
364  }//case ElevatorDoorsStatus::closing:
365 
367  {
368  //Если лифт стоит на этаже и появляется человек снаружи //29.05.2021
369  if ( ((e->position % 100) == 0 ) && (e->isEmpty()) )
370  {
371  if (queue->passOnFloor[e->position / 100].size() > 0)
372  {
373  bool isPassUp = false, isPassDn = false;
374  for (auto& p : queue->passOnFloor[e->position / 100])
375  {
376  if (p.getFloorDestination() > pos)
377  isPassUp = true;
378  if (p.getFloorDestination() < pos)
379  isPassDn = true;
380  }
381 
382  if ((e->indicator == ElevatorIndicator::both)
383  || (e->indicator == ElevatorIndicator::up && isPassUp)
384  || (e->indicator == ElevatorIndicator::down && isPassDn))
385  {
386  e->doorsStatus = ElevatorDoorsStatus::opening;
387  e->buttons[pos] = false;
388  e->timeToSelfProgramme = timeOpening - 1;
389  break;
390  }
391 
392  }
393  }
394 
395  //Если есть назначение для стоящего лифта с закрытыми дверьми - разгоняем
396 
397  //вверх
398  if ((e->position / 100) < e->destinationFloor)
399  {
400  e->status = ElevatorStatus::movingUp;
401  e->acceleration = ElevatorAcceleration::accelerating;
402  e->timeToSelfProgramme = timeAccelerating - 1;
403  }//if ((e->position...
404 
405  //вниз
406  if (((e->position + 99) / 100) > e->destinationFloor)
407  {
408  e->status = ElevatorStatus::movingDn;
409  e->acceleration = ElevatorAcceleration::accelerating;
410  e->timeToSelfProgramme = timeAccelerating - 1;
411  }//if (((e->position...
412 
413  //3.1.4. Если лифт прибыл в пункт назначения - открываем двери
414  if (((e->position / 100) == e->destinationFloor) &&
415  ((e->position % 100) == 0))
416  {
417  //но открываем двери только если либо он непустой, либо снаружи нажата кнопка:
418  if ((e->getNumberOfPassengers() > 0) ||
419  (floorButtons->getDnButton(e->destinationFloor)) ||
420  (floorButtons->getUpButton(e->destinationFloor)))
421  {
422  e->doorsStatus = ElevatorDoorsStatus::opening;
423  e->buttons[pos] = false;
424  e->timeToSelfProgramme = timeOpening - 1;
425 
426  if ((floorButtons->getDnButton(e->destinationFloor)) &&
427  (e->indicator == ElevatorIndicator::down || e->indicator == ElevatorIndicator::both))
428  floorButtons->unsetDnButton(e->destinationFloor);
429 
430  if ((floorButtons->getUpButton(e->destinationFloor)) &&
431  (e->indicator == ElevatorIndicator::up || e->indicator == ElevatorIndicator::both))
432  floorButtons->unsetUpButton(e->destinationFloor);
433  }//if ((e->getNumberOfPassengers() > 0) ||...
434  }//if (((e->position...
435  break;
436  }//case ElevatorDoorsStatus::closed:
437 
439  {
440  //Только что открывший двери лифт - делаем двери открытыми
441  if (e->isEmpty()) //29.05.2021
442  e->doorsStatus = ElevatorDoorsStatus::openedLoading;
443  else
444  e->doorsStatus = ElevatorDoorsStatus::openedUnloading;
445  break;
446  }
447 
448  }//switch (e->doorsStatus)
449 
450  break;
451  }// case ElevatorStatus::staying
452 
453 
456  {
457  switch (e->acceleration)
458  {
460  {
461  e->acceleration = ElevatorAcceleration::uniform;
462  e->status = ElevatorStatus::staying;
463  break;
464  }//case ElevatorAcceleration::breaking:
465 
467  {
468  int sign = (e->status == ElevatorStatus::movingUp) ? 1 : -1;
469  e->position += sign * (int)(100*veloUniform);
470  e->acceleration = ElevatorAcceleration::uniform;
471  break;
472  }//case ElevatorAcceleration::accelerating:
473 
475  {
476  int sign = (e->status == ElevatorStatus::movingUp) ? 1 : -1;
477 
478  bool critDir = ((100 * (int)e->destinationFloor - (int)e->position) * sign) > 0;
479  if (critDir)
480  {
481  if (abs((int)((e->position - 100 * e->destinationFloor))) != (int)(100 * veloUniform))
482 
483  e->position += sign * (int)(100 * veloUniform);
484  else
485  {
486  e->acceleration = ElevatorAcceleration::breaking;
487  e->position += sign * 12;
488  e->timeToSelfProgramme = timeBreaking - 1;
489  }//else
490  }
491  else
492  {
493  e->acceleration = ElevatorAcceleration::breaking;
494  e->position += sign * 12;
495  e->timeToSelfProgramme = timeBreaking - 1;
496  }
497  }//case ElevatorAcceleration::uniform:
498 
499  }//switch (e->acceleration)
500 
501  break;
502  }//case ElevatorStatus::movingUp:
503  //case ElevatorStatus::movingDn:
504  }
505 
506 
507  }//if (e->timeToSelfProgramme == 0)
508  else // если продолжается предыдущая операция
509  {
510  if ((e->status == ElevatorStatus::movingUp) ||
511  (e->status == ElevatorStatus::movingDn))
512  {
513  int sign = (e->status == ElevatorStatus::movingUp) ? 1 : -1;
514 
515  if (e->acceleration == ElevatorAcceleration::accelerating)
516  {
517  switch (e->timeToSelfProgramme)
518  {
519  case 3:
520  e->position += sign * 5;
521  break;
522 
523  case 2:
524  e->position += sign * 8;
525  break;
526 
527  case 1:
528  e->position += sign * 12;
529  break;
530  }//switch (e->timeToSelfProgramme)
531  }//if (e->acceleration == ElevatorAcceleration::accelerating)
532 
533  if (e->acceleration == ElevatorAcceleration::breaking)
534  {
535  switch (e->timeToSelfProgramme)
536  {
537  case 2:
538  e->position += sign * 8;
539  break;
540 
541  case 1:
542  e->position += sign * 5;
543  break;
544  }//switch (e->timeToSelfProgramme)
545  }//if (e->acceleration == ElevatorAcceleration::breaking)
546  }//if ((e->status == ElevatorStatus::movingUp) || (e->status == ElevatorStatus::movingDn))
547 
548  --(e->timeToSelfProgramme);
549  }//else
550  }//for e : elevators
551 }//MakeStep()
552 
553 
555 {
556  queue->addPassenger(passProp_);
557 }//AddPassengerToQueue(...)
558 
559 void Control::ReadTimeTable(const std::string& fileName_)
560 {
561  std::ifstream fi(fileName_);
562 
563  char str[255];
564  fi.getline(str, 100, '\n');
565 
566  PassengerProperties passProp;
567  int N;
568 
569  while (!fi.eof())
570  {
571  fi >> N;
572  fi.get();
573  fi >> passProp.timeInit;
574  fi.get();
575  fi >> passProp.floorDeparture;
576  fi.get();
577  fi >> passProp.floorDestination;
578  fi.get();
579  fi >> passProp.criticalWaitTime;
580  fi.get();
581  fi >> passProp.pInverseStartWaiting;
582  fi.get();
583  fi >> passProp.pInverseStopWaiting;
584  fi.get();
585  fi >> passProp.pStartGoing;
586 
587  queue->addPassenger(passProp);
588  }
589 
590  fi.close();
591  fi.clear();
592 }
593 
594 
595 void Control::PrintElevatorState(size_t i, const std::string& fname) const
596 {
597  std::ofstream fout;
598  if (fname != "")
599  {
600  if (getCurrentTime() <= 1)
601  fout.open(fname);
602  else
603  fout.open(fname, std::ios_base::app);
604  }//if (fname != "")
605 
606  std::ostream& str = (fname == "") ? std::cout : fout;
607 
608 /*str << "time = " << getCurrentTime() << ", \telev[" << i << "]: " \
609  << elevators[i]->getStateString() << std::endl;*/
610 
611  printf("\033[01;37m");
612  str << "time = " << getCurrentTime() << ", \telev[";
613  switch (i) {
614  case 0: printf("\033[01;34m"); break;
615  case 1: printf("\033[01;32m"); break;
616  case 2: printf("\033[22;31m"); break;
617  case 3: printf("\033[01;35m"); break;
618  default: printf("\033[22;33m");
619  }
620  str << i;
621  printf("\033[01;37m");
622  str << "]: ";
623 
624  //begin
625  //std::string strState;
626 
627  //std::string strStatus;
628 
629  str << "level = ";
630  str << std::to_string(elevators[i]->position / 100);
631  str << ".";
632  if ((elevators[i]->position % 100) < 10)
633  str << "0";
634  str << std::to_string(elevators[i]->position % 100);
635 
636  str << ", dir. = ";
637 
638  switch (elevators[i]->status)
639  {
641  printf("\033[01;32m");
642  str << "up, ";
643  break;
645  printf("\033[01;34m");
646  str << "dn, ";
647  break;
649  printf("\033[01;33m");
650  str << "stay,";
651  break;
652  }//switch (status)
653 
654  printf("\033[01;37m");
655  str << " ind. = ";
656 
657  //std::string strIndicator;
658  switch (elevators[i]->indicator)
659  {
661  printf("\033[01;32m");
662  str << "up, ";
663  break;
665  printf("\033[01;34m");
666  str << "down,";
667  break;
669  printf("\033[01;33m");
670  str << "both,";
671  break;
672  }// switch (indicator)
673 
674  printf("\033[01;37m");
675  str << " acceler. = ";
676 
677  //std::string strAccel;
678  switch (elevators[i]->acceleration)
679  {
681  printf("\033[22;32m");
682  str << "acceler.,";
683  break;
685  printf("\033[22;31m");
686  str << "breaking,";
687  break;
689  printf("\033[22;33m");
690  str << "uniform, ";
691  break;
692  }//switch (acceleration)
693 
694  printf("\033[01;37m");
695  str << " doors = ";
696 
697  //std::string strDoors;
698  switch (elevators[i]->doorsStatus)
699  {
701  printf("\033[01;31m");
702  str << "unloading...";
703  break;
705  printf("\033[01;31m");
706  str << "loading... ";
707  break;
709  printf("\033[01;33m");
710  str << "opening... ";
711  break;
713  printf("\033[01;33m");
714  str << "closing... ";
715  break;
717  printf("\033[22;36m");
718  str << "closed ";
719  break;
721  printf("\033[01;31m");
722  str << "waiting... ";
723  break;
724  }//switch (doorsStatus)
725 
726  printf("\033[01;37m");
727  str << " (pass.: ";
728  for (auto& p : elevators[i]->passengers)
729  {
730  str << std::to_string(p.id);
731  str << ", ";
732  }//for p
733  str << ")" << std::endl;
734  //end
735 
736 
737  if (fname != "")
738  fout.close();
739 }//PrintElevatorState(...)
740 
741 
742 void Control::PrintButtonsState(const std::string& fname) const
743 {
744  std::ofstream fout;
745  if (fname != "")
746  {
747  if (getCurrentTime() <= 1)
748  fout.open(fname);
749  else
750  fout.open(fname, std::ios_base::app);
751  }//if (fname != "")
752 
753  std::ostream& str = (fname == "") ? std::cout : fout;
754 
755  str << "time = " << getCurrentTime() << ": " << std::endl;
756  for (auto& e : elevators)
757  {
758  str << " in elevator #" << e->myid << ": ";
759  for (size_t i = 0; i < e->buttons.size(); ++i)
760  if (e->getButton(i))
761  str << i << " ";
762  str << std::endl;
763  }//for e
764  str << " on floors: ";
765  for (size_t i = 0; i < floorButtons->upButtons.size(); ++i)
766  {
767  if (floorButtons->getUpButton(i) || floorButtons->getDnButton(i))
768  {
769  str << "#" << i << "(";
770  if (floorButtons->getUpButton(i)) {
771  printf("\033[01;32m");
772  str << "up ";
773  }
774  if (floorButtons->getDnButton(i)) {
775  printf("\033[01;34m");
776  str << "dn";
777  }
778  printf("\033[01;37m");
779  str << ") ";
780  }//if (floorButtons->...
781  }//for i
782  str << std::endl << std::endl;
783 
784  if (fname != "")
785  fout.close();
786 }//PrintButtonsState(...)
787 
788 
789 void Control::PrintPassengerState(const std::string& fname) const
790 {
791  std::ofstream fout;
792  if (fname != "")
793  {
794  if (getCurrentTime() <= 1)
795  fout.open(fname);
796  else
797  fout.open(fname, std::ios_base::app);
798  }//if (fname != "")
799 
800  std::ostream& str = (fname == "") ? std::cout : fout;
801  printf("\033[01;33m");
802  if (passStatBuffer.size() > 0)
803  for (auto& st : passStatBuffer)
804  str << st << std::endl;
805 
806  if (fname != "")
807  fout.close();
808  printf("\033[01;37m");
809 }//PrintPassengerState(...)
810 
811 
812 bool Control::isElevatorOnFloor(size_t stage) const
813 {
814  for (auto& e : elevators)
815  if ((e->position / 100.0 == stage) && (e->position % 100 == 0))
816  return true;
817  return false;
818 }//isElevatorOnFloor(...)
819 
820 
821 void Control::PrintStatistics(bool passengersDetails, const std::string& fname) const
822 {
823  std::ofstream fout;
824  if (fname != "")
825  fout.open(fname);
826 
827  std::ostream& str = (fname == "") ? std::cout : fout;
828 
829  std::vector<Passenger> allPass(queue->passengers);
830  for (auto& pf : queue->passOnFloor)
831  std::copy(pf.begin(), pf.end(), std::back_inserter(allPass));
832  for (auto& e : elevators)
833  std::copy(e->passengers.begin(), e->passengers.end(), std::back_inserter(allPass));
834  std::copy(queue->finished.begin(), queue->finished.end(), std::back_inserter(allPass));
835 
836  std::sort(allPass.begin(), allPass.end());
837 
838  size_t numInElevetor = 0, numOnFloors = 0, numLeaved = 0;
839  size_t penaltyFinished = 0, penaltyInElevetor = 0, penaltyOnFloors = 0, penaltyLeaved = 0;
840 
841  if (passengersDetails)
842  str << "Passangers:" << std::endl;
843 
844  for (auto& p : allPass)
845  {
846  switch (p.status)
847  {
849  {
850  penaltyFinished += p.timeFinish - p.getTimeInit();
851  if (passengersDetails)
852  str << "#" << p.id << ", penalty = " << p.timeFinish - p.getTimeInit() \
853  << " (init = " << p.getTimeInit() << ", started = " << p.timeStart << ", finished = " << p.timeFinish << ")" \
854  << std::endl;
855  break;
856  }//case PassengerStatus::arrived:
857 
859  {
860  ++numInElevetor;
861  penaltyInElevetor += getCurrentTime() - p.getTimeInit();
862  if (passengersDetails)
863  str << "#" << p.id << ", penalty = " << getCurrentTime() - p.getTimeInit() \
864  << " (init = " << p.getTimeInit() << ", started = " << p.timeStart << ", STILL IN ELEVATOR!!!" << ")" \
865  << std::endl;
866  break;
867  }//case PassengerStatus::going:
868 
870  {
871  ++numOnFloors;
872  penaltyOnFloors += getCurrentTime() - p.getTimeInit();
873  if (passengersDetails)
874  str << "#" << p.id << ", penalty = " << getCurrentTime() - p.getTimeInit() \
875  << " (init = " << p.getTimeInit() << ", STILL WAITING FOR ELEVATOR!!!" << ")" \
876  << std::endl;
877  break;
878  }//case PassengerStatus::waiting:
879 
881  {
882  ++numLeaved;
883  penaltyLeaved += p.properties.criticalWaitTime * 5;
884  if (passengersDetails)
885  str << "#" << p.id << ", penalty = " << p.properties.criticalWaitTime * 5 \
886  << " (init = " << p.getTimeInit() << ", LEAVED THE FLOOR!!!" << ")" \
887  << std::endl;
888  break;
889  }//case PassengerStatus::leaved:
890  }//switch (p.status)
891  }//for p
892 
893  if (passengersDetails)
894  str << std::endl;
895 
896  size_t waitingTime = 0, goingTime = 0, totalTime = 0;
897  size_t num_finished_notLeaved = 0;
898  for (auto& p : queue->finished)
899  {
900  if (p.status != PassengerStatus::leaved)
901  {
902  ++num_finished_notLeaved;
903  waitingTime += p.timeStart - p.getTimeInit();
904  goingTime += p.timeFinish - p.timeStart;
905  totalTime += p.timeFinish - p.getTimeInit();
906  }
907  //else
908  //{
909  // waitingTime += p.properties.criticalWaitTime;
910  // totalTime += p.properties.criticalWaitTime;
911  //}
912  }//for p
913 
914  str << "Number of passengers, that have finished the trip: " << num_finished_notLeaved << std::endl;
915  if (num_finished_notLeaved > 0)
916  {
917  str << " average waiting time = " << 1.0 * waitingTime / num_finished_notLeaved << std::endl;
918  str << " average going time = " << 1.0 * goingTime / num_finished_notLeaved << std::endl;
919  str << " average total time = " << 1.0 * totalTime / num_finished_notLeaved << std::endl;
920  }
921  str << "Penalty for them = " << penaltyFinished << std::endl;
922  str << std::endl;
923 
924 
925  str << "Still waiting on floors = " << numOnFloors << std::endl;
926  str << "Penalty for them = " << penaltyOnFloors << std::endl;
927  str << std::endl;
928 
929  str << "Still in elevator = " << numInElevetor << std::endl;
930  str << "Penalty for them = " << penaltyInElevetor << std::endl;
931  str << std::endl;
932 
933  str << "Leaved the floors, because of too large waiting time = " << numLeaved << std::endl;
934  str << "Penalty for them = " << penaltyLeaved << std::endl;
935  str << std::endl;
936 
937  str << "TOTAL PENALTY = " << penaltyFinished + penaltyInElevetor + penaltyOnFloors + penaltyLeaved << std::endl;
938 
939  if (fname != "")
940  fout.close();
941 }//PrintStatistics(...)
942 
стрелочки в обоих направлениях
Класс — кабина лифта
Definition: Elevator.h:79
double pStartGoing
Вероятность нажать кнопку "ход", не дожидаясь закрытия дверей
Definition: Passenger.h:48
const double veloUniform
Скорость равномерно движения лифта (в долях этажа)
Definition: Control.h:86
const size_t timeLeaving
Время между выходами двух пассажиров в лифт
Definition: Control.h:71
const size_t numberOfFloors
Общее число этажей
Definition: main.cpp:67
void PrintPassengerState(const std::string &fname="") const
Функция печати в файл или на экран событий, произошедших с пассажирами за последний шаг (последнюю се...
Definition: Control.cpp:789
Пассажир не дождался лифта и ушел
size_t timeInit
Время появления пассажира на этаже
Definition: Passenger.h:30
движется вниз
движется равномерно или стоит
Пассажир ждет лифта на этаже отправления
движется вверх
стрелочка вверх
const size_t waitingTime
Время ожидания до закрытия дверей (если только кто-то не нажмет кнопку "ход" раньше) ...
Definition: Control.h:65
void AddPassengerToQueue(const PassengerProperties &passProp_)
Функция добавления пассажира в очередь
Definition: Control.cpp:554
const size_t timeOpening
Время открывания дверей
Definition: Control.h:74
size_t criticalWaitTime
Время ожидания, после которого пассажир уходит
Definition: Passenger.h:39
const size_t timeBreaking
Время торможения лифта
Definition: Control.h:83
size_t floorDestination
Этаж, на который пассажир едет
Definition: Passenger.h:36
size_t getCurrentTime() const
Функция запроса текущего времени
Definition: Control.h:110
const size_t numberOfElevators
Число лифтов
Definition: main.cpp:56
Заголовочный файл с описанием класса Queue.
Пассажир успешно прибыл на нужный этаж
size_t floorDeparture
Этаж, с которого пассажир отправляется
Definition: Passenger.h:33
Класс — пассажир
Definition: Passenger.h:54
const size_t timeAccelerating
Время разгона лифта
Definition: Control.h:80
открыты (идет посадка пассажиров)
~Control()
Деструктор
Definition: Control.cpp:30
Параметры пассажиров
Definition: Passenger.h:27
открыты (лифт ожидает отправления)
double pInverseStopWaiting
Вероятность сесть в лифт, едущий в неверном направлении в конце ожидания
Definition: Passenger.h:45
const size_t timeClosing
Время закрывания дверей
Definition: Control.h:77
открыты (идет высадка пассажиров)
стоит (не движется)
открываются
double pInverseStartWaiting
Вероятность сесть в лифт, едущий в неверном направлении в начале ожидания
Definition: Passenger.h:42
void PrintElevatorState(size_t elevatorNumber, const std::string &fname="") const
Функция печати в файл или на экран состояния лифта в текущий момент времени
Definition: Control.cpp:595
const size_t timeEntering
Время между входами двух пассажиров в лифт
Definition: Control.h:68
Control(size_t numberOfFloors, size_t numberOfElevators, size_t capacityOfElevator)
Инициализирующий конструктор
Definition: Control.cpp:22
Класс — очередь пассажиров
Definition: Queue.h:21
void PrintButtonsState(const std::string &fname="") const
Функция печати в файл или на экран состояния кнопок в кабинах и на этажах в текущий момент времени ...
Definition: Control.cpp:742
Заголовочный файл с описанием основного класса Control.
Пассажир нажодится в лифте
закрываются
замедляется (тормозит)
void MakeStep()
Функция выполнения шага моделирования по времени
Definition: Control.cpp:102
void PrintStatistics(bool passengersDetails, const std::string &fname="") const
Функция печати в файл или на экран итоговой статистики, включая итоговый "рейтинг" (чем меньше - тем ...
Definition: Control.cpp:821
ускоряется (разгоняется)
Класс — кнопки на этажах
Definition: FloorButtons.h:19
стрелочка вниз
void ReadTimeTable(const std::string &fileName_)
Функция чтения расписания появления пассажиров на этажах
Definition: Control.cpp:559