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()