elevator  0.7
Симулятор пассажирского лифта
Файл main.cpp

Основной файл программы elevator. Подробнее...

#include <cmath>
#include <iostream>
#include <list>
#include <map>
#include "Control.h"
Граф включаемых заголовочных файлов для main.cpp:

См. исходные тексты.

Классы

struct  myParams
 Структура, содержащая пользовательские параметры Подробнее...
 

Функции

void CONTROLSYSTEM (Control &control, myParams &params)
 Основная функция системы управления Подробнее...
 
int main (int argc, char **argv)
 

Переменные

const size_t numberOfElevators = 2
 Число лифтов Подробнее...
 
const size_t elevatorCapacity = 8
 
const size_t maxFloor = 11
 
const size_t numberOfFloors = maxFloor + 1
 Общее число этажей Подробнее...
 
const size_t maxTime = 26000
 

Подробное описание

Основной файл программы elevator.

Автор
Марчевский Илья Константинович
Версия
0.7
Дата
20 февраля 2022 г.

См. определение в файле main.cpp

Функции

void CONTROLSYSTEM ( Control control,
myParams params 
)

Основная функция системы управления

Именно эту функцию нужно модифицировав, реализовав здесь оптимизированный алгорим работы пассажирского лифта.

Другие функции "трогать" запрещается.

Данная функция вызывается на каждом шаге (каждую секунду) работы лифта.

Внутри можно пользоваться структурой params, сохраняя в нее при необходимости нужные сведения, которые, соответственно, будут доступны при следующем вызове функции CONTROLSYSTEM

Cобственно, для активного управления лифтами есть всего две команды:

  • control.setElevatorDestination(elevatorNumber, newDestination);
  • control.setElevatorIndicator(elevatorNumber, newIndicator)

Прежде, чем отдавать команду лифту по итогам анализа его текущего состояния - надо решить, имеет ли смысл делать это прямо сейчас

К примеру, если лифт едет куда-то на вызов (скажем, на 10-й этаж), и в этот момент кто-то в подвале (0-й этаж) нажал на кнопку вызова, то если поступить формально и в этот момент изменить назначение лифта путем исполнения команды

  • control.setElevatorDestination(elev, newDestination),

то он затормозит по пути (возможно, даже между этажами), и потом начнет разгоняться и поедет в обратном направлении (вниз); если лифт прибыл на этаж, начал тормозить, и в этот момент ему установить новое назначение, то он затормозит, двери не откроет, и тут же поедет по новому назначению!

Будьте аккуратны. Наш лифт очень "исполнительный"!

Поэтому нужно тщательно обдумывать, в какой момент отдавать команду на изменение направления и в какой команд отдавать команду на изменение индикатора

  • control.setElevatorIndicator(elev, newIndicator)

(пассажиры садятся только в тот лифт, который едет в нужную им сторону, судя по индикатору, который они видят, хотя иногда попадаются и те, кто садятся не туда, при этом зайдя в лифт, они "жмут" кнопку, куда надо им — это тоже надо как-то обрабатывать!!!)

Аргументы
[in,out]controlссылка на основной класс-симулятор лифта
[in,out]paramsссылка на набор пользовательских параметров

См. определение в файле main.cpp строка 194

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 }
стрелочки в обоих направлениях
bool isElevatorAchievedDestination(size_t elevatorNumber) const
Проверка того, что лифт завершил выполнение текущего назначения
Definition: Control.h:167
ElevatorIndicator
Состояния лампочки (индикатора направления движения) кабины лифта
Definition: Elevator.h:36
bool started
Признак того, что лифт выполняет работу
Definition: main.cpp:47
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
size_t getCurrentTime() const
Функция запроса текущего времени
Definition: Control.h:110
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 getElevatorDestination(size_t elevatorNumber) const
Функция запроса текущего назначения
Definition: Control.h:140
const size_t maxFloor
Definition: main.cpp:64
bool isElevatorGoingUniformly(size_t elevatorNumber) const
Проверка того, что кабина лифта движется равномерно
Definition: Control.h:250
стрелочка вниз

Граф вызовов:

Граф вызова функции:

int main ( int  argc,
char **  argv 
)

См. определение в файле main.cpp строка 120

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 }
const size_t numberOfFloors
Общее число этажей
Definition: main.cpp:67
void CONTROLSYSTEM(Control &control, myParams &params)
Основная функция системы управления
Definition: main.cpp:194
Структура, содержащая пользовательские параметры
Definition: main.cpp:41
const size_t numberOfElevators
Число лифтов
Definition: main.cpp:56
const size_t maxTime
Definition: main.cpp:71
Основной класс — симулятор пассажирского лифта
Definition: Control.h:25
const size_t elevatorCapacity
Definition: main.cpp:60

Граф вызовов:

Переменные

const size_t elevatorCapacity = 8

Вместимость лифта

Предупреждения
Тренироваться проще с меньшей вместимостью, в реальной задаче будет не менее 6 человек

См. определение в файле main.cpp строка 60

const size_t maxFloor = 11

Максимальный номер этажа (не считая подвала, который имеет номер 0). Пассажиры иногда ездят в подвал и из подвала

См. определение в файле main.cpp строка 64

const size_t maxTime = 26000

Время моделирования в секундах

Предупреждения
Cейчас для тестирования задано 26000 секунд, в реальной задаче может быть, скажем, 54000 секунд: от 7:00 утра до 22:00 вечера

См. определение в файле main.cpp строка 71

const size_t numberOfElevators = 2

Число лифтов

См. определение в файле main.cpp строка 56

const size_t numberOfFloors = maxFloor + 1

Общее число этажей

См. определение в файле main.cpp строка 67