main.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import datetime
  2. import plotly.figure_factory as ff
  3. class ShipTraffic:
  4. def parse_reqs(self, reqs): # функция перебора заявок
  5. reqs = list(map(lambda x: self.make_datetime(x), reqs))
  6. resp = list(map(lambda x: self.processing_req(x),
  7. sorted(reqs, key=lambda x: (x[6], x[7]))))
  8. self.made_gant(resp)
  9. h = 0
  10. while not all(list(map(lambda x: True if x[0] != 403 else False, resp))):
  11. if h > 20:
  12. break
  13. not_allowed = list(filter(lambda x: x[0] == 403, resp))
  14. not_reqs = []
  15. for i in not_allowed:
  16. start_id = i[1][-1][1]
  17. req = list(filter(lambda x: x[6] == start_id, reqs))
  18. reqs[reqs.index(req[0])][6] -= datetime.timedelta(days=1)
  19. i[1][-1][1] -= datetime.timedelta(days=1)
  20. resp = list(map(lambda x: self.processing_req(x),
  21. sorted(reqs, key=lambda x: (x[6], x[7]))))
  22. h += 1
  23. if h < 20:
  24. self.made_gant(resp)
  25. def processing_req(self, req): # функция обработки заявки
  26. time_interval = self.ship_graph_time(req)
  27. route = self.can_swim(time_interval, req)
  28. return route
  29. def ship_graph_time(self, req): # функция определения временного интервала для ребра: [rebro, time_start, time_end]
  30. from data import routes
  31. rout1, rout2 = routes[req[4] + req[5]]
  32. time_rout1, time_rout2 = self.time_route_maker(rout1, req), self.time_route_maker(rout2, req)
  33. return [time_rout1, time_rout2]
  34. def can_swim(self, time_interval, req): # функция определения плотности льда на пути транспортного судна
  35. swim_route_1, swim_route_2 = self.ice_density(time_interval[0], req[2]), self.ice_density(time_interval[1],
  36. req[2])
  37. if swim_route_1 != 403 and swim_route_2 != 403:
  38. optimal = sorted([swim_route_1, swim_route_2], key=lambda x: x[-1][2])[0]
  39. elif swim_route_1 != 403 or swim_route_2 != 403:
  40. optimal = swim_route_1 if swim_route_1 != 403 else swim_route_2
  41. else:
  42. optimal = [403, sorted([time_interval[0], time_interval[1]], key=lambda x: x[-1][2])[0]]
  43. return optimal
  44. @staticmethod
  45. def ice_density(time_rout, req): # функция определяет плотность льда и возможность прохождения в n-день
  46. resp = [] # [rebro, time_start, time_end, status]
  47. from data import class_can, ice_can, day_ice
  48. for i in time_rout:
  49. if i[1].date() == i[2].date():
  50. weather = day_ice[i[0] - 1][i[1].day - 1 if i[1].day - 1 <= 29 else i[1].day - 2]
  51. if ice_can[int(weather)][class_can[req]] == '3':
  52. return 403
  53. resp.append([i[0], i[1], i[2], ice_can[int(weather)][class_can[req]]])
  54. elif i[1].date() + datetime.timedelta(days=1) == i[2].date():
  55. weather = max([day_ice[i[0] - 1][i[1].day - 1 if i[1].day - 1 <= 29 else i[1].day - 2],
  56. day_ice[i[0] - 1][i[2].day - 1 if i[2].day - 1 <= 29 else i[2].day - 2]])
  57. if ice_can[int(weather)][class_can[req]] == '3':
  58. return 403
  59. resp.append([i[0], i[1], i[2], ice_can[int(weather)][class_can[req]]])
  60. elif i[1].date() + datetime.timedelta(days=2) == i[2].date():
  61. weather = max([day_ice[i[0] - 1][i[1].day - 1 if i[1].day - 1 <= 29 else i[1].day - 2],
  62. day_ice[i[0] - 1][i[2].day - 1 if i[2].day - 1 <= 29 else i[2].day - 2],
  63. day_ice[i[0] - 1][i[2].day - 1]])
  64. if ice_can[int(weather)][class_can[req]] == '3':
  65. return 403
  66. resp.append([i[0], i[1], i[2], ice_can[int(weather)][class_can[req]]])
  67. return resp[::-1]
  68. @staticmethod
  69. def make_datetime(req):
  70. req[6] = datetime.datetime.strptime(req[6], '%d.%m.%Y %H:%M')
  71. req[7] = datetime.datetime.strptime(req[7], '%d.%m.%Y %H:%M')
  72. return req
  73. @staticmethod
  74. def time_route_maker(rout, req):
  75. from data import edges
  76. time_route = []
  77. for i in rout:
  78. time_rout = [i]
  79. time_rout.append(req[6] if rout.index(i) == 0 else time_route[-1][2])
  80. time_swim = round((edges[i] / (int(req[3]) * 1.852)) * 60)
  81. time_swim = datetime.timedelta(hours=time_swim // 60, minutes=time_swim - 60 * (time_swim // 60))
  82. time_rout.append(time_rout[1] + time_swim)
  83. time_route.append(time_rout)
  84. return time_route[::-1]
  85. @staticmethod
  86. def made_gant(data):
  87. from data import skip_status
  88. gant_data = []
  89. h = 1
  90. for i in data:
  91. if i[0] == 403:
  92. for j in i[1]:
  93. gant_data.append(dict(Task=f'Заявка №{str(h)}', Start=j[1], Finish=j[2], Resource=skip_status[3]))
  94. else:
  95. for j in i:
  96. gant_data.append(
  97. dict(Task=f'Заявка №{str(h)}', Start=j[1], Finish=j[2], Resource=skip_status[int(j[-1])]))
  98. h += 1
  99. colors = {'Проход невозможен': 'rgb(220, 0, 0)',
  100. 'Нужна проводка': (1, 0.9, 0.16),
  101. 'Самостоятельно': 'rgb(0, 255, 100)'}
  102. fig = ff.create_gantt(gant_data, colors=colors, index_col='Resource', show_colorbar=True,
  103. group_tasks=True)
  104. fig.show()
  105. def main():
  106. from data import icebreakers_requests
  107. sd = ShipTraffic()
  108. sd.parse_reqs(icebreakers_requests)
  109. if __name__ == "__main__":
  110. main()