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