#!/usr/bin/env python3 ''' plan_gen main functions ''' import time import numpy as np import lxml.etree as etree # constants # ------------------ MIN_DEPARTURE_TIME = '08:00:00' MAX_DEPARTURE_TIME = '09:00:00' WORK_DURATION = '04:00:00' # utils # ------------------ def parse_value(string): ''' convert string to int, float or string ''' try: return int(string) except ValueError: try: return float(string) except ValueError: return string def parse_params(param_str): ''' parse a param string to a dict ''' dict_params = {} if param_str: for key_value_str in param_str.split(','): key, value = key_value_str.split('=') if key in ['hc', 'wc']: dict_params[key] = [file for file in value.split(':')] else: dict_params[key] = parse_value(value) return dict_params def get_seconds(time_str): ''' returns seconds from a time string ''' h, m, s = time_str.split(':') return int(h) * 3600 + int(m) * 60 + int(s) # main functions # ------------------ def rand_time(low, high): ''' returns a random time between low and high bounds ''' low_s = get_seconds(low) high_s = get_seconds(high) delta = np.random.randint(high_s - low_s) return time.strftime('%H:%M:%S', time.gmtime(low_s + delta)) def rand_node_xy(nodes, clusters): ''' returns a random node coordinates from a list of nodes ''' used_nodes = nodes if any(clusters): cluster = np.random.randint(len(clusters)) used_nodes = clusters[cluster] node = used_nodes[np.random.randint(len(used_nodes))] return (node.get('x'), node.get('y')) def rand_person(nodes, home_clusters, work_clusters): ''' returns a person as a dictionnary of random parameters ''' home_xy = rand_node_xy(nodes, home_clusters) work_xy = rand_node_xy(nodes, work_clusters) home_departure = rand_time(MIN_DEPARTURE_TIME, MAX_DEPARTURE_TIME) return {'home': home_xy, 'work': work_xy, 'home_departure': home_departure} def create_child(parent_node, child_name, child_attrs=None): ''' creates an xml child element and set its attributes ''' child = etree.SubElement(parent_node, child_name) if child_attrs is None: return child for attr, value in child_attrs.items(): child.set(attr, value) return child def make_plans(persons): ''' makes xml tree of plans based on persons list ''' plans = etree.Element('plans') for n, p in enumerate(persons): person = create_child(plans, 'person', {'id': str(n+1)}) plan = create_child(person, 'plan') # plan create_child(plan, 'act', {'type': 'h', 'x': p['home'][0], 'y': p['home'][1], 'end_time': p['home_departure']}) create_child(plan, 'leg', {'mode': 'car'}) create_child(plan, 'act', {'type': 'w', 'x': p['work'][0], 'y': p['work'][1], 'dur': WORK_DURATION}) create_child(plan, 'leg', {'mode': 'car'}) create_child(plan, 'act', {'type': 'h', 'x': p['home'][0], 'y': p['home'][1]}) return plans def read_nodes(input_network): ''' returns all network nodes as a list ''' if not input_network: return None tree = etree.parse(input_network) return [node for node in tree.xpath("/network/nodes/node")]