Advertisement
Guest User

Untitled

a guest
Jul 17th, 2019
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.26 KB | None | 0 0
  1. import argparse
  2. import requests
  3. from retrying import retry
  4. import pandas as pd
  5. import contextlib
  6. import warnings
  7. from functools import partialmethod
  8. from copy import deepcopy
  9.  
  10. TIMEOUT = 60
  11. MVRP_LOG_URLS = [
  12.     'https://courier.common.yandex.ru/vrs/api/v1/log/{}/{}',
  13.     'https://routing-solver-dev.common.yandex.net/api/v1/log/{}/{}'
  14. ]
  15.  
  16.  
  17. @contextlib.contextmanager
  18. def no_ssl_verification():
  19.     old_request = requests.Session.request
  20.     requests.Session.request = partialmethod(old_request, verify=False)
  21.     warnings.filterwarnings('ignore', 'Unverified HTTPS request')
  22.     warnings.filterwarnings('ignore', category=ResourceWarning, message='unclosed*<ssl.SSLSocket.*>')
  23.     warnings.simplefilter('ignore', ResourceWarning)
  24.     yield
  25.     warnings.resetwarnings()
  26.     requests.Session.request = old_request
  27.  
  28.  
  29. @retry(retry_on_exception=lambda x: isinstance(x, (requests.exceptions.Timeout,
  30.                                                    requests.exceptions.ConnectionError)),
  31.        stop_max_attempt_number=3
  32.        )
  33. def get_json_by_mvrp_id(req_resp, solution_id):
  34.     r = None
  35.     for url in MVRP_LOG_URLS:
  36.         with no_ssl_verification():
  37.             r = requests.get(
  38.                 url.format(req_resp, solution_id),
  39.                 timeout=TIMEOUT,
  40.                 verify=False
  41.             )
  42.             if r.status_code == requests.codes.ok:
  43.                 break
  44.             else:
  45.                 continue
  46.  
  47.     if r.status_code != 200:
  48.         print('Bad response from MVRP API {} {}'.format(r.status_code, r.text))
  49.     r.raise_for_status()
  50.     return r.json()
  51.  
  52.  
  53. def get_mvrp_solution(solution_id):
  54.     return get_json_by_mvrp_id('response', solution_id)['result']
  55.  
  56.  
  57. def get_mvrp_request(solution_id):
  58.     return get_json_by_mvrp_id('request', solution_id)
  59.  
  60.  
  61. def parse_request(request):
  62.     optional_location_params = [
  63.         'ref', 'hard_window', 'type', 'shared_service_duration_s', 'delivery_to', 'service_duration_s',
  64.         'depot_duration_s'
  65.     ]
  66.  
  67.     orders = []
  68.     for l in request['locations']:
  69.         order = {
  70.             'point.lat': l['point']['lat'],
  71.             'point.lon': l['point']['lon'],
  72.             'time_window': l['time_window']
  73.         }
  74.  
  75.         for param in optional_location_params:
  76.             if param in l:
  77.                 order[param] = l[param]
  78.  
  79.         for param in ('load_types', 'required_tags'):
  80.             if param in l:
  81.                 order[param] = ','.join(l[param])
  82.  
  83.         if 'shipment_size' in l:
  84.             for param in ('units', 'weight_kg'):
  85.                 if param in l['shipment_size']:
  86.                     order['shipment_size.' + param] = l['shipment_size'][param]
  87.  
  88.             if 'volume' in l['shipment_size']:
  89.                 for param in ('width_m', 'depth_m', 'height_m'):
  90.                     order['shipment_size.volume.' + param] = l['shipment_size']['volume'][param]
  91.  
  92.         if 'penalty' in l:
  93.             if 'drop' in l['penalty']:
  94.                 order['penalty.drop'] = l['penalty']['drop']
  95.  
  96.             if 'out_of_time' in l['penalty']:
  97.                 if 'minute' in l['penalty']['out_of_time']:
  98.                     order['penalty.out_of_time.minute'] = l['penalty']['out_of_time']['minute']
  99.  
  100.                 if 'fixed' in l['penalty']['out_of_time']:
  101.                     order['penalty.out_of_time.fixed'] = l['penalty']['out_of_time']['fixed']
  102.  
  103.         orders.append(order)
  104.  
  105.     optional_depot_params = [
  106.         'ref', 'hard_window', 'finish_service_duration_s', 'service_duration_s', 'flexible_start_time'
  107.     ]
  108.  
  109.     d = request['depot']
  110.     depot = {
  111.         'point.lat': d['point']['lat'],
  112.         'point.lon': d['point']['lon'],
  113.         'time_window': d['time_window']
  114.     }
  115.  
  116.     for param in optional_depot_params:
  117.         if param in d:
  118.             depot[param] = d[param]
  119.  
  120.     if 'penalty' in d:
  121.         if 'out_of_time' in d['penalty']:
  122.             for param in ('minute', 'fixed'):
  123.                 if param in d['penalty']['out_of_time']:
  124.                     depot['penalty.out_of_time.' + param] = d['penalty']['out_of_time'][param]
  125.  
  126.         if 'throughput' in d['penalty']:
  127.             for param in ('fixed', 'kg', 'unit'):
  128.                 if param in d['penalty']['throughput']:
  129.                     depot['penalty.throughput.' + param] = d['penalty']['throughput'][param]
  130.  
  131.     if 'throughput' in d:
  132.         for param in ('kg_per_hour', 'units_per_hour'):
  133.             if param in d['throughput']:
  134.                 depot['throughput.' + param] = d['throughput'][param]
  135.  
  136.     optional_vehicle_params = [
  137.         'return_to_depot', 'max_runs', 'priority', 'travel_time_multiplier', 'company_name', 'ref'
  138.     ]
  139.  
  140.     vehicles = []
  141.     for v in request.get('vehicles') or [request['vehicle']]:
  142.         vehicle = {}
  143.  
  144.         for param in optional_vehicle_params:
  145.             if param in v:
  146.                 vehicle[param] = v[param]
  147.  
  148.         if 'tags' in v:
  149.             vehicle['tags'] = ','.join(v['tags'])
  150.  
  151.         if 'excluded_tags' in v:
  152.             vehicle['excluded_tags'] = ','.join(v['excluded_tags'])
  153.  
  154.         if 'capacity' in v:
  155.             for param in ('units', 'weight_kg'):
  156.                 if param in v['capacity']:
  157.                     vehicle['capacity.' + param] = v['capacity'][param]
  158.  
  159.             if 'volume' in v['capacity']:
  160.                 for param in ('width_m', 'depth_m', 'height_m'):
  161.                     vehicle['capacity.volume.' + param] = v['capacity']['volume'][param]
  162.  
  163.             if 'limits' in v['capacity']:
  164.                 for param in ('weight_perc', 'units_perc', 'volume_perc'):
  165.                     if param in v['capacity']['limits']:
  166.                         vehicle['capacity.limits.' + param] = v['capacity']['limits'][param]
  167.  
  168.         if 'cost' in v:
  169.             for param in ('fixed', 'km', 'hour', 'location', 'run'):
  170.                 if param in v['cost']:
  171.                     vehicle['cost.' + param] = v['cost'][param]
  172.  
  173.         if 'shifts' in v:
  174.             for i, shift in enumerate(v['shifts']):
  175.                 for param in ('time_window', 'service_duration_s', 'hard_window', 'max_duration_s'):
  176.                     if param in shift:
  177.                         vehicle['shifts.{}.{}'.format(i, param)] = shift[param]
  178.  
  179.                 if 'penalty' in shift:
  180.                     if 'out_of_time' in shift['penalty']:
  181.                         for param in ('fixed', 'minute'):
  182.                             if param in shift['penalty']['out_of_time']:
  183.                                 vehicle['shifts.{}.penalty.out_of_time.{}'.format(i, param)] = \
  184.                                     shift['penalty']['out_of_time'][param]
  185.  
  186.         vehicles.append(vehicle)
  187.  
  188.     optional_options_params = [
  189.         'time_zone', 'thread_count', 'minimize_lateness_risk', 'quality', 'routing_mode', 'weighted_drop_penalty',
  190.         'temperature', 'critical_lateness_risk_probability', 'eta_model_sigma', 'proximity_factor', 'absolute_time',
  191.         'default_speed_km_h', 'rand_seed', 'task_count', 'date', 'restart_on_drop', 'merge_multiorders',
  192.         'solver_time_limit_s', 'minimize', 'matrix_router'
  193.     ]
  194.  
  195.     options = {}
  196.     for param in optional_options_params:
  197.         if param in request['options']:
  198.             options[param] = request['options'][param]
  199.  
  200.     # todo: incompatible load types & visited locations
  201.     # todo: recursive parsing
  202.     return orders, vehicles, depot, options
  203.  
  204.  
  205. def save2xlsx(orders, vehicles, depot, options, f_name):
  206.     writer = pd.ExcelWriter(f_name)
  207.     pd.DataFrame(orders).to_excel(writer, 'Orders')
  208.     pd.DataFrame(vehicles).to_excel(writer, 'Vehicles')
  209.     pd.DataFrame([depot]).to_excel(writer, 'Depot')
  210.     pd.DataFrame([options]).to_excel(writer, 'Options')
  211.     writer.save()
  212.  
  213.  
  214. def parse_args():
  215.     parser = argparse.ArgumentParser()
  216.     parser.add_argument('-t', '--task-id', required=True, help='Solver task ID')
  217.     parser.add_argument('-o', '--output', help='Output .xlsx file name')
  218.  
  219.     return parser.parse_args()
  220.  
  221.  
  222. def main():
  223.     args = parse_args()
  224.  
  225.     request = get_mvrp_request(args.task_id)
  226.  
  227.     f_name = args.output or '{}.xlsx'.format(args.task_id)
  228.     save2xlsx(*parse_request(request), f_name=args.output or '{}.xlsx'.format(args.task_id))
  229.     print('Request was saved to file {}'.format(f_name))
  230.  
  231.  
  232. if __name__ == '__main__':
  233.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement