elevator  0.7
Симулятор пассажирского лифта
main.cpp
См. документацию.
1 // Проект elevator
2 // (c) И.К. Марчевский, 2021-2022
3 
27 #include <cmath>
28 #include <iostream>
29 #include <list>
30 #include <map>
31 
32 #include "Control.h"
33 
41 struct myParams
42 {
44  size_t arbitraryParam = 0;
45 
47  bool started = false;
48 
49  //можно добавить любое число параметров любого типа
50 };
51 
52 
53 //Задание условия задачи
54 
56 const size_t numberOfElevators = 2;
57 
60 const size_t elevatorCapacity = 8;
61 
64 const size_t maxFloor = 11;
65 
67 const size_t numberOfFloors = maxFloor + 1;
68 
71 const size_t maxTime = 26000;
72 
73 
117 void CONTROLSYSTEM(Control& control, myParams& params);
118 
119 
120 int main(int argc, char** argv)
121 {
122  //Задание конфигурации лифтового хозяйства
124 
125  //Для загрузки расписания появления пассажиров из файла
126  control.ReadTimeTable("TimeTable/timetable500a.csv");
127 
128  //Для тестирования вместо чтения из файла (строка выше)
129  //можно вводить появляющихся пассажиров вручную
130  //параметры в фиг. скобках
131  //{
132  // 1) время появления пассажира (от начала моделирования)
133  // 2) этаж, где появляется пассажир
134  // 3) этаж, куда направляется пассажир
135  // 4) время, которое пассажир ждет и после которого, не вырерживая, уходит (начисляется штраф)
136  // 5) вероятность сесть в лифт, идущий в обратном направлении, в начале ожидания
137  // 6) вероятность сесть в лифт, идущий в обратном направлении, в конце ожидания
138  // 7) вероятеность того, что пассажир, войдя в лифт, нажмет "ход" и лифт не будет стоять
139  // }
140  /*
141  control.AddPassengerToQueue({ 5, 5, 3, 300, 0.01, 0.20, 0.50 });
142  control.AddPassengerToQueue({ 6, 5, 10, 300, 0.01, 0.20, 0.50 });
143  control.AddPassengerToQueue({ 7, 5, 2, 300, 0.01, 0.20, 0.50 });
144  control.AddPassengerToQueue({ 8, 5, 8, 300, 0.01, 0.20, 0.50 });
145  control.AddPassengerToQueue({ 9, 5, 10, 300, 0.01, 0.20, 0.50 });
146  control.AddPassengerToQueue({ 10, 5, 6, 300, 0.01, 0.20, 0.50 });
147  control.AddPassengerToQueue({ 11, 5, 9, 300, 0.01, 0.20, 0.50 });
148  control.AddPassengerToQueue({ 12, 5, 8, 300, 0.01, 0.20, 0.50 });
149  control.AddPassengerToQueue({ 13, 5, 11, 300, 0.01, 0.20, 0.50 });
150  control.AddPassengerToQueue({ 14, 5, 10, 300, 0.01, 0.20, 0.50 });
151  */
152 
153  myParams params;
154 
155  do
156  {
157  //Выполнение одного шага (= 1 секунда) моделирования работы лифта
158  control.MakeStep();
159 
160  //Вызов функции системы управления --- в ней можно "отдать команду" лифту,
161  //исходя из его текущего состояния и состояния кнопок в лифте и на этажах
162  CONTROLSYSTEM(control, params);
163 
164  //Вывод состояния лифта
165  //control.PrintElevatorState(0); //Вывод состояния лифта #0 на экран
166  //control.PrintElevatorState(1); //Вывод состояния лифта #1 на экран
167 
168  control.PrintElevatorState(0, "fileElev0.txt"); //Вывод состояния лифта #0 в файл
169  control.PrintElevatorState(1, "fileElev1.txt"); //Вывод состояния лифта #1 в файл
170 
171  //Вывод состояния кнопок в лифте и на этажах
172  //control.PrintButtonsState(); //Вывод состояния кнопок на экран
173  control.PrintButtonsState("fileButtons.txt"); //Вывод состояния кнопок в файл
174 
175  //Вывод событий появлений пассажиров, их входа в лифт, выхода из лифта, ухода с этажа
176  //control.PrintPassengerState(); //Вывод статистики пассажиров на экран
177  control.PrintPassengerState("filePassengers.txt"); //Вывод статистики пассажиров в файл
178 
179  } while (control.getCurrentTime() <= maxTime);
180 
181  //Печать итоговой статистики в конце работы симулятора
182  control.PrintStatistics(true, "Statistics.txt");
183 
184  return 0;
185 }
186 
187 
188 // Здесь пример системы управления --- именно эту функцию надо модифицировать.
189 // Другие функции "трогать" запрещается
190 // Данная функция вызывается на каждом шаге (каждую секунду) работы лифта
191 //
192 // Внутри можно пользоваться структурой params, сохраняя в нее при необходимости нужные сведения,
193 // которые, соответственно, будут доступны при следующем вызове функции CONTROLSYSTEM
194 void CONTROLSYSTEM(Control& control, myParams& params)
195 {
196  // Прежде, чем отдавать команду лифту по итогам анализа его текущего состояния - надо решить,
197  // имеет ли смысл делать это прямо сейчас
198  //
199  // К примеру, если лифт едет куда-то на вызов (скажем, на 10-й этаж), и в этот момент кто-то
200  // в подвале (0-й этаж) нажал на кнопку вызова,
201  // то если поступить формально и в этот момент изменить назначение лифта путем исполнения команды
202  //
203  // control.setElevatorDestination(elev, newDestination),
204  //
205  // то он затормозит по пути (возможно, даже между этажами), и потом начнет разгоняться
206  // и поедет в обратном направлении (вниз);
207  // если лифт прибыл на этаж, начал тормозить, и в этот момент ему установить новое назначение,
208  // то он затормозит, двери не откроет, и тут же поедет по новому назначению!
209  // Будьте аккуратны. Наш лифт очень "исполнительный"!
210  //
211  // Поэтому нужно тщательно обдумывать, в какой момент отдавать команду на изменение направления
212  // и в какой команд отдавать команду на изменение индикатора
213  //
214  // control.setElevatorIndicator(elev, newIndicator)
215  //
216  // (пассажиры садятся только в тот лифт, который едет в нужную им сторону,
217  // судя по индикатору, который они видят, хотя иногда попадаются и те, кто садятся не туда,
218  // при этом зайдя в лифт, они "жмут" кнопку, куда надо им --- это тоже надо как-то обрабатывать!!!)
219  //
220  // ПРИМЕЧАНИЕ: собственно, для активного управления лифтами есть всего две команды:
221  // control.setElevatorDestination(elev, newDestination);
222  // control.setElevatorIndicator(elev, newIndicator)
223  //
224 
225 
226  // Для получения текущего времени можно пользоваться командой
227  // control.getCurrentTime()
228 
229 
230  // Следующие команды носят характер опроса текущего состояния лифта
231  //
232  // - текущее назначение лифта:
233  // control.getElevatorDestination(elev);
234  //
235  // - текущее начение индикатора:
236  // control.getElevatorIndicator(elev);
237  //
238  // - текущее положение лифта (дробное число, когда лифт между этажами;
239  // даже если оно целое - лифт не обязательно с открытыми дверьми, он может начинать разгоняться
240  // или тормозить и т.п.)
241  // control.getElevatorPosition(elev);
242  //
243  // - признак того, что лифт движется вверх
244  // control.isElevatorGoingUp(elev)
245  //
246  // - признак того, что лифт движется вниз
247  // control.isElevatorGoingDn(elev)
248  //
249  // - признак того, что лифт стоит на месте
250  // control.isElevatorStaying(elev)
251  //
252  // - признак того, что лифт движется равномерно
253  // control.isElevatorGoingUniformly(elev);
254  //
255  // - признак того, что лифт движется с ускорением (разгоняется)
256  // control.isElevatorAccelerating(elev);
257  //
258  // - признак того, что лифт движется с замедлением (тормозит)
259  // control.isElevatorBreaking(elev);
260  //
261  // - признак того, что лифт стоит на месте (на этаже) с закрытыми дверьми
262  // control.isElevatorStayingDoorsClosed(elev);
263  //
264  // - признак того, что в текущий сомент происходит закрывание дверей
265  // control.isElevatorDoorsClosing(elev);
266  //
267  // - признак того, что в текущий сомент происходит открывание дверей
268  // control.isElevatorDoorsOpening(elev);
269  //
270  // - признак того, что в текущий момент двери открыты
271  // control.isElevatorDoorsOpened(elev);
272  //
273  // - признак того, что лифт пустой (в нем нет ни одного пассажира)
274  // control.isElevatorEmpty(elev);
275  //
276  // - признак того, что в данный момент завершилась высадка пассажиров, и лифт оказался пустым (см. ниже)
277  // control.isElevatorEmptyAfterUnloading(elev);
278  //
279  // - признак того, что лифт достиг точки назначения
280  // точка назначения считается достигнутой, когда
281  // 1) лифт приехал на тот этаж, куда его послали, остановился, и
282  // 2) выполнено одно из трех условий:
283  // а) в нем есть хотя бы 1 пассажир - тогда открылись двери
284  // б) он пустой, а на этаже, на который он прибыл, нажата хотя бы одна
285  // кнопка - тогда тоже открылись двери
286  // в) он пустой, а на этаже, на который он прибыл, не нажато ни одной
287  // кнопки - тогда двери не открываются
288  // control.isElevatorAchievedDestination(elev)
289  //
290  //
291  // Может быть полезной команда
292  //
293  // control.isElevatorEmptyAfterUnloading(elev)
294  //
295  // которая возвращает true, если лифт стоит на этаже, и после выхода очередного пассажира
296  // лифт оказался пустым --- возможно, при этом имеет смысл "включить" индикатор в оба направления,
297  // чтобы в любом случае зашел пассажир, стоящий первым в очереди.
298  // Но это не обязательно - у Вас может быть своя логика!
299  //
300  // Если индикатор лифта "горит" в состоянии both (он пустой или нет - не важно),
301  // и в лифт входит пассажир, то индикатор автоматически переключается в то направление,
302  // какую кнопку он нажал, входя в лифт.
303  // Будьте осторожны, "зажигайте" состояние индикатора both аккуратно, но и без него обойтись будет трудно!
304  //
305 
306  // Следующие 4 команды позволяют узнать состояние "нажатости" кнопок на этажах
307  // const std::vector<bool>& getFloorUpButtons() const
308  //
309  // При этом когда лифт приезжает на какой-либо этаж, то в момент открывания дверей на этаже
310  // автоматически гаснет та кнопка, какой индикатор в этот момент установлен у лифта
311  // (если индикатор both - гаснут обе кнопки)
312  // Если пассажиры, оставшиеся на этаже, видят, что нужная им кнопка погасла, они
313  // нажмут ее снова, как только лифт тронется
314  //
315  // - возвращает вектор (массив) состояний нажатия кнопок вверх
316  // control.floorButtons->getUpButtons();
317  //
318  // - возвращает вектор (массив) состояний нажатия кнопок вниз
319  // control.floorButtons->getUpButtons();
320  //
321  // - возвращает состояние нажатия кнопки вверх на i-м этаже
322  // control.floorButtons->getUpButton(i);
323  //
324  // - возвращает состояние нажатия кнопки вниз на i-м этаже
325  // control.floorButtons->getDnButton(i);
326  //
327  // При необходимости можно использовать команды принудительного выключения кнопок на соответствующих этажах:
328  // control.unsetUpButton(floor);
329  // control.unsetDnButton(floor);
330 
331 
332  // Наконец, еще 2 команды позволяют оценить состояние кнопок в кабине лифта
333  // Человек, входящий в лифт, нажимает кнопку этажа назначения
334  // Кнопка, нажатая внутри лифта, гаснет, когда лифт прибывает на этаж и начинает открывать двери
335  //
336  // - возвращает вектор состояния нажатости кнопок в кабине лифта
337  // control.getElevatorButtons(elev)
338  //
339  // - возвращает вектор состояния нажатости кнопки i-го этажа в кабине лифта
340  // control.getElevatorButton(elev, i)
341 
342 
344  // ПРИМЕР примитивной системы управления, при которой первоначально лифт #0 стоит
345  // в подвале, а лифту #1 отдается команда уехать на самый верхний этаж.
346  // Потом они оба ждут до момента появления первого пассажира на каком-либо этаже,
347  // после чего начинают кататься вверх-вниз, останавливаясь на каждом этаже
348  // т.е. вообще не реагируя на кнопки!
350 
351  if (control.getCurrentTime() == 1)
352  {
353  control.SetElevatorDestination(1, maxFloor);
355  }
356 
357  if (!params.started)
358  {
359  size_t nUp = std::count(control.getFloorUpButtons().begin(), control.getFloorUpButtons().end(), true);
360  size_t nDn = std::count(control.getFloorDnButtons().begin(), control.getFloorDnButtons().end(), true);
361 
362  //Если хоть одна кнопка вверх или вниз на этажах нажата - запускаем лифт!
363  if (nUp + nDn > 0)
364  {
365  params.started = true;
366  }
367  }
368 
369  for (size_t elv = 0; elv < 2; ++elv)
370  {
371  // В данном примере новая команда (назначение) не отдается,
372  // пока не выполнена предыдущая
373  if ((params.started) && (control.isElevatorAchievedDestination(elv)))
374  {
375  // считываем этаж, на который лифт прибыл
376  size_t curDest = control.getElevatorDestination(elv);
377 
378  // прибывая на этаж назначения лифт открывает двери, если либо он непустой,
379  // либо на этом этаже нажата кнопка вызова хотя бы в какую-то сторону,
380  // в противном случае прибывает на этаж и стоит, не открывая двери
381 
382  // считываем текущее положение лифта
383  size_t nextDest = (size_t)(control.getElevatorPosition(elv));
384 
385  switch (control.getElevatorIndicator(elv))
386  {
389  ++nextDest;
390  break;
391 
393  --nextDest;
394  break;
395  }
396 
397  control.SetElevatorDestination(elv, nextDest);
398  }
399 
400  //Теперь устанавливаем индикатор
401  if (control.isElevatorGoingUniformly(elv))
402  {
403  // считываем текущий индикатор движения (лифт изначально инициализирован в both)
404  ElevatorIndicator curInd = control.getElevatorIndicator(elv);
405 
406  // индикатор, который будет установлен дальше, инициализируем его в текущим индикатором
407  ElevatorIndicator nextInd = curInd;
408 
409  // поменяем его, если он установлен в both
410  if (curInd == ElevatorIndicator::both)
411  nextInd = ElevatorIndicator::up;
412 
413  // при прибытии на максимальный этаж - переключаем индикатор "вниз"
414  if ((control.getElevatorDestination(elv) == maxFloor) && (control.getElevatorPosition(elv) > maxFloor - 1))
415  nextInd = ElevatorIndicator::down;
416 
417  // при прибытии на миниимальный этаж (в подвал) - переключаем индикатор "вверх"
418  if ((control.getElevatorDestination(elv) == 0) && (control.getElevatorPosition(elv) < 1))
419  nextInd = ElevatorIndicator::up;
420 
421  // собственно, установка значения индикатора
422  control.SetElevatorIndicator(elv, nextInd);
423  }//if (control.isElevatorGoingUniformly(elv))
424  }
425 
426  /*
427  if (control.getCurrentTime() < 5)
428  control.SetElevatorDestination(1, 2);
429  else
430  control.SetElevatorDestination(1, 0);
431  */
432 }
стрелочки в обоих направлениях
const size_t numberOfFloors
Общее число этажей
Definition: main.cpp:67
void PrintPassengerState(const std::string &fname="") const
Функция печати в файл или на экран событий, произошедших с пассажирами за последний шаг (последнюю се...
Definition: Control.cpp:789
bool isElevatorAchievedDestination(size_t elevatorNumber) const
Проверка того, что лифт завершил выполнение текущего назначения
Definition: Control.h:167
ElevatorIndicator
Состояния лампочки (индикатора направления движения) кабины лифта
Definition: Elevator.h:36
bool started
Признак того, что лифт выполняет работу
Definition: main.cpp:47
int main(int argc, char **argv)
Definition: main.cpp:120
void CONTROLSYSTEM(Control &control, myParams &params)
Основная функция системы управления
Definition: main.cpp:194
void SetElevatorDestination(size_t elevatorNumber, size_t destination)
Функция задания назначения лифту
Definition: Control.h:120
const std::vector< bool > & getFloorDnButtons() const
Функция запроса состояний кнопок "вниз" на этажах
Definition: Control.h:350
стрелочка вверх
double getElevatorPosition(size_t elevatorNumber) const
Функция запроса текущего положения лифта
Definition: Control.h:332
Структура, содержащая пользовательские параметры
Definition: main.cpp:41
size_t getCurrentTime() const
Функция запроса текущего времени
Definition: Control.h:110
const size_t numberOfElevators
Число лифтов
Definition: main.cpp:56
const size_t maxTime
Definition: main.cpp:71
ElevatorIndicator getElevatorIndicator(size_t elevatorNumber) const
Функция запроса текущего состояния индикатора
Definition: Control.h:150
const std::vector< bool > & getFloorUpButtons() const
Функция запроса состояний кнопок "вверх" на этажах
Definition: Control.h:341
void SetElevatorIndicator(size_t elevatorNumber, ElevatorIndicator indicator)
Функция задания состояния индикатора лифта (лампочка со стрелочкой, которую видят пассажиры) ...
Definition: Control.h:130
size_t arbitraryParam
Некоторый произвольный параметр, инициализированный значением "0".
Definition: main.cpp:44
size_t getElevatorDestination(size_t elevatorNumber) const
Функция запроса текущего назначения
Definition: Control.h:140
Основной класс — симулятор пассажирского лифта
Definition: Control.h:25
void PrintElevatorState(size_t elevatorNumber, const std::string &fname="") const
Функция печати в файл или на экран состояния лифта в текущий момент времени
Definition: Control.cpp:595
const size_t maxFloor
Definition: main.cpp:64
void PrintButtonsState(const std::string &fname="") const
Функция печати в файл или на экран состояния кнопок в кабинах и на этажах в текущий момент времени ...
Definition: Control.cpp:742
const size_t elevatorCapacity
Definition: main.cpp:60
Заголовочный файл с описанием основного класса Control.
bool isElevatorGoingUniformly(size_t elevatorNumber) const
Проверка того, что кабина лифта движется равномерно
Definition: Control.h:250
void MakeStep()
Функция выполнения шага моделирования по времени
Definition: Control.cpp:102
void PrintStatistics(bool passengersDetails, const std::string &fname="") const
Функция печати в файл или на экран итоговой статистики, включая итоговый "рейтинг" (чем меньше - тем ...
Definition: Control.cpp:821
стрелочка вниз
void ReadTimeTable(const std::string &fileName_)
Функция чтения расписания появления пассажиров на этажах
Definition: Control.cpp:559