|
|
@@ -0,0 +1,125 @@
|
|
|
+import datetime
|
|
|
+import plotly.figure_factory as ff
|
|
|
+
|
|
|
+
|
|
|
+class ShipTraffic:
|
|
|
+ def parse_reqs(self, reqs): # функция перебора заявок
|
|
|
+ reqs = list(map(lambda x: self.make_datetime(x), reqs))
|
|
|
+ resp = list(map(lambda x: self.processing_req(x),
|
|
|
+ sorted(reqs, key=lambda x: (x[6], x[7]))))
|
|
|
+ self.made_gant(resp)
|
|
|
+ h = 0
|
|
|
+ while not all(list(map(lambda x: True if x[0] != 403 else False, resp))):
|
|
|
+ if h > 20:
|
|
|
+ break
|
|
|
+ not_allowed = list(filter(lambda x: x[0] == 403, resp))
|
|
|
+ not_reqs = []
|
|
|
+ for i in not_allowed:
|
|
|
+ start_id = i[1][-1][1]
|
|
|
+ req = list(filter(lambda x: x[6] == start_id, reqs))
|
|
|
+ reqs[reqs.index(req[0])][6] -= datetime.timedelta(days=1)
|
|
|
+ i[1][-1][1] -= datetime.timedelta(days=1)
|
|
|
+ resp = list(map(lambda x: self.processing_req(x),
|
|
|
+ sorted(reqs, key=lambda x: (x[6], x[7]))))
|
|
|
+ h += 1
|
|
|
+ if h < 20:
|
|
|
+ self.made_gant(resp)
|
|
|
+
|
|
|
+ def processing_req(self, req): # функция обработки заявки
|
|
|
+ time_interval = self.ship_graph_time(req)
|
|
|
+ route = self.can_swim(time_interval, req)
|
|
|
+ return route
|
|
|
+
|
|
|
+ def ship_graph_time(self, req): # функция определения временного интервала для ребра: [rebro, time_start, time_end]
|
|
|
+ from data import routes
|
|
|
+ rout1, rout2 = routes[req[4] + req[5]]
|
|
|
+ time_rout1, time_rout2 = self.time_route_maker(rout1, req), self.time_route_maker(rout2, req)
|
|
|
+ return [time_rout1, time_rout2]
|
|
|
+
|
|
|
+ def can_swim(self, time_interval, req): # функция определения плотности льда на пути транспортного судна
|
|
|
+ swim_route_1, swim_route_2 = self.ice_density(time_interval[0], req[2]), self.ice_density(time_interval[1],
|
|
|
+ req[2])
|
|
|
+ if swim_route_1 != 403 and swim_route_2 != 403:
|
|
|
+ optimal = sorted([swim_route_1, swim_route_2], key=lambda x: x[-1][2])[0]
|
|
|
+ elif swim_route_1 != 403 or swim_route_2 != 403:
|
|
|
+ optimal = swim_route_1 if swim_route_1 != 403 else swim_route_2
|
|
|
+ else:
|
|
|
+ optimal = [403, sorted([time_interval[0], time_interval[1]], key=lambda x: x[-1][2])[0]]
|
|
|
+ return optimal
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def ice_density(time_rout, req): # функция определяет плотность льда и возможность прохождения в n-день
|
|
|
+ resp = [] # [rebro, time_start, time_end, status]
|
|
|
+ from data import class_can, ice_can, day_ice
|
|
|
+ for i in time_rout:
|
|
|
+ if i[1].date() == i[2].date():
|
|
|
+ weather = day_ice[i[0] - 1][i[1].day - 1 if i[1].day - 1 <= 29 else i[1].day - 2]
|
|
|
+ if ice_can[int(weather)][class_can[req]] == '3':
|
|
|
+ return 403
|
|
|
+ resp.append([i[0], i[1], i[2], ice_can[int(weather)][class_can[req]]])
|
|
|
+ elif i[1].date() + datetime.timedelta(days=1) == i[2].date():
|
|
|
+ weather = max([day_ice[i[0] - 1][i[1].day - 1 if i[1].day - 1 <= 29 else i[1].day - 2],
|
|
|
+ day_ice[i[0] - 1][i[2].day - 1 if i[2].day - 1 <= 29 else i[2].day - 2]])
|
|
|
+ if ice_can[int(weather)][class_can[req]] == '3':
|
|
|
+ return 403
|
|
|
+ resp.append([i[0], i[1], i[2], ice_can[int(weather)][class_can[req]]])
|
|
|
+ elif i[1].date() + datetime.timedelta(days=2) == i[2].date():
|
|
|
+ weather = max([day_ice[i[0] - 1][i[1].day - 1 if i[1].day - 1 <= 29 else i[1].day - 2],
|
|
|
+ day_ice[i[0] - 1][i[2].day - 1 if i[2].day - 1 <= 29 else i[2].day - 2],
|
|
|
+ day_ice[i[0] - 1][i[2].day - 1]])
|
|
|
+ if ice_can[int(weather)][class_can[req]] == '3':
|
|
|
+ return 403
|
|
|
+ resp.append([i[0], i[1], i[2], ice_can[int(weather)][class_can[req]]])
|
|
|
+ return resp[::-1]
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def make_datetime(req):
|
|
|
+ req[6] = datetime.datetime.strptime(req[6], '%d.%m.%Y %H:%M')
|
|
|
+ req[7] = datetime.datetime.strptime(req[7], '%d.%m.%Y %H:%M')
|
|
|
+ return req
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def time_route_maker(rout, req):
|
|
|
+ from data import edges
|
|
|
+ time_route = []
|
|
|
+ for i in rout:
|
|
|
+ time_rout = [i]
|
|
|
+ time_rout.append(req[6] if rout.index(i) == 0 else time_route[-1][2])
|
|
|
+ time_swim = round((edges[i] / (int(req[3]) * 1.852)) * 60)
|
|
|
+ time_swim = datetime.timedelta(hours=time_swim // 60, minutes=time_swim - 60 * (time_swim // 60))
|
|
|
+ time_rout.append(time_rout[1] + time_swim)
|
|
|
+ time_route.append(time_rout)
|
|
|
+ return time_route[::-1]
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def made_gant(data):
|
|
|
+ from data import skip_status
|
|
|
+ gant_data = []
|
|
|
+ h = 1
|
|
|
+ for i in data:
|
|
|
+ if i[0] == 403:
|
|
|
+ for j in i[1]:
|
|
|
+ gant_data.append(dict(Task=f'Заявка №{str(h)}', Start=j[1], Finish=j[2], Resource=skip_status[3]))
|
|
|
+ else:
|
|
|
+ for j in i:
|
|
|
+ gant_data.append(
|
|
|
+ dict(Task=f'Заявка №{str(h)}', Start=j[1], Finish=j[2], Resource=skip_status[int(j[-1])]))
|
|
|
+ h += 1
|
|
|
+ colors = {'Проход невозможен': 'rgb(220, 0, 0)',
|
|
|
+ 'Нужна проводка': (1, 0.9, 0.16),
|
|
|
+ 'Самостоятельно': 'rgb(0, 255, 100)'}
|
|
|
+
|
|
|
+ fig = ff.create_gantt(gant_data, colors=colors, index_col='Resource', show_colorbar=True,
|
|
|
+ group_tasks=True)
|
|
|
+ fig.show()
|
|
|
+
|
|
|
+
|
|
|
+def main():
|
|
|
+ from data import icebreakers_requests
|
|
|
+
|
|
|
+ sd = ShipTraffic()
|
|
|
+ sd.parse_reqs(icebreakers_requests)
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|