<commit_before># flake8: noqa
import sys
import os
import flow.config as config

SITEPACKAGES = os.path.join(config.AIMSUN_SITEPACKAGES,
                            "lib/python2.7/site-packages")
sys.path.append(SITEPACKAGES)

sys.path.append(os.path.join(config.AIMSUN_NEXT_PATH,
                             'programming/Aimsun Next API/AAPIPython/Micro'))

from flow.core.params import InFlows
from flow.core.params import TrafficLightParams

from copy import deepcopy
import json
import numpy as np


# Load an empty template
gui = GKGUISystem.getGUISystem().getActiveGui()
gui.newDoc(os.path.join(config.PROJECT_PATH,
                        "flow/utils/aimsun/Aimsun_Flow.ang"),
           "EPSG:32601")
model = gui.getActiveModel()


def generate_net(nodes, edges, connections, inflows, veh_types, traffic_lights):
    inflows = inflows.get()
    lane_width = 3.6  # TODO additional params??
    type_section = model.getType("GKSection")
    type_node = model.getType("GKNode")
    type_turn = model.getType("GKTurning")
    type_traffic_state = model.getType("GKTrafficState")
    type_vehicle = model.getType("GKVehicle")
    type_demand = model.getType("GKTrafficDemand")

    # draw edges
    for edge in edges:
        points = GKPoints()
        if "shape" in edge:
            for p in edge["shape"]:  # TODO add x, y offset (radius)
                new_point = GKPoint()
                new_point.set(p[0], p[1], 0)
                points.append(new_point)

            cmd = model.createNewCmd(model.getType("GKSection"))
            cmd.setPoints(edge["numLanes"], lane_width, points)
            model.getCommander().addCommand(cmd)
            section = cmd.createdObject()
            section.setName(edge["id"])
            edge_aimsun = model.getCatalog().findByName(
                edge["id"], type_section)
            edge_aimsun.setSpeed(edge["speed"] * 3.6)
        else:
            first_node, last_node = get_edge_nodes(edge, nodes)
            theta = get_edge_angle(first_node, last_node)
            first_node_offset = [0, 0]  # x, and y offset
            last_node_offset = [0, 0]  # x, and y offset

            # offset edge ends if there is a radius in the node
            if "radius" in first_node:
                first_node_offset[0] = first_node["radius"] * \
                    np.cos(theta*np.pi/180)
                first_node_offset[1] = first_node["radius"] * \
                    np.sin(theta*np.pi/180)
            if "radius" in last_node:
                last_node_offset[0] = - last_node["radius"] * \
                    np.cos(theta*np.pi/180)
                last_node_offset[1] = - last_node["radius"] * \
                    np.sin(theta*np.pi/180)

            # offset edge ends if there are multiple edges between nodes
            # find the edges that share the first node
            edges_shared_node = [edg for edg in edges
                                 if first_node["id"] == edg["to"]
                                 or last_node["id"] == edg["from"]]
            for new_edge in edges_shared_node:
                new_first_node, new_last_node = get_edge_nodes(new_edge, nodes)
                new_theta = get_edge_angle(new_first_node, new_last_node)
                if new_theta == theta - 180 or new_theta == theta + 180:
                    first_node_offset[0] += lane_width * 0.5 *\
                        np.sin(theta * np.pi / 180)
                    first_node_offset[1] -= lane_width * 0.5 * \
                        np.cos(theta * np.pi / 180)
                    last_node_offset[0] += lane_width * 0.5 *\
                        np.sin(theta * np.pi / 180)
                    last_node_offset[1] -= lane_width * 0.5 *\
                        np.cos(theta * np.pi / 180)
                    break

            new_point = GKPoint()
            new_point.set(first_node['x'] + first_node_offset[0],
                          first_node['y'] + first_node_offset[1],
                          0)
            points.append(new_point)
            new_point = GKPoint()
            new_point.set(last_node['x'] + last_node_offset[0],
                          last_node['y'] + last_node_offset[1],
                          0)
            points.append(new_point)
            cmd = model.createNewCmd(type_section)
            cmd.setPoints(edge["numLanes"], lane_width, points)
            model.getCommander().addCommand(cmd)
            section = cmd.createdObject()
            section.setName(edge["id"])
            edge_aimsun = model.getCatalog().findByName(
                edge["id"], type_section)
            edge_aimsun.setSpeed(edge["speed"] * 3.6)

    # draw nodes and connections
    for node in nodes:
        # add a new node in Aimsun
        node_pos = GKPoint()
        node_pos.set(node['x'], node['y'], 0)
        cmd = model.createNewCmd(type_node)
        cmd.setPosition(node_pos)
        model.getCommander().addCommand(cmd)
        new_node = cmd.createdObject()
        new_node.setName(node["id"])

        # list of edges from and to the node
        from_edges = [
            edge['id'] for edge in edges if edge['from'] == node['id']]
        to_edges = [edge['id'] for edge in edges if edge['to'] == node['id']]

        # if the node is a junction with a list of connections
        if len(to_edges) > 1 and len(from_edges) > 1 \
                and connections[node['id']] is not None:
            # add connections
            for connection in connections[node['id']]:
                cmd = model.createNewCmd(type_turn)
                from_section = model.getCatalog().findByName(
                    connection["from"], type_section, True)
                to_section = model.getCatalog().findByName(
                    connection["to"], type_section, True)
                cmd.setTurning(from_section, to_section)
                model.getCommander().addCommand(cmd)
                turn = cmd.createdObject()
                turn_name = "{}_to_{}".format(connection["from"],
                                              connection["to"])
                turn.setName(turn_name)
                existing_node = turn.getNode()
                if existing_node is not None:
                    existing_node.removeTurning(turn)
                # add the turning to the node
                new_node.addTurning(turn, False, True)

        # if the node is not a junction or connections is None
        else:
            for i in range(len(from_edges)):
                for j in range(len(to_edges)):
                    cmd = model.createNewCmd(type_turn)
                    to_section = model.getCatalog().findByName(
                        from_edges[i], type_section, True)
                    from_section = model.getCatalog().findByName(
                        to_edges[j], type_section, True)
                    cmd.setTurning(from_section, to_section)
                    model.getCommander().addCommand(cmd)
                    turn = cmd.createdObject()
                    turn_name = "{}_to_{}".format(from_edges[i], to_edges[j])
                    turn.setName(turn_name)
                    existing_node = turn.getNode()
                    if existing_node is not None:
                        existing_node.removeTurning(turn)

                    # add the turning to the node
                    new_node.addTurning(turn, False, True)

    # get the control plan
    control_plan = model.getCatalog().findByName(
            "Control Plan", model.getType("GKControlPlan"))

    # add traffic lights
    tls_properties = traffic_lights.get_properties()
    # determine junctions
    junctions = get_junctions(nodes)
    # add meters for all nodes in junctions
    for node in junctions:
        phases = tls_properties[node['id']]["phases"]
        print(phases)
        create_node_meters(model, control_plan, node['id'], phases)

    # set vehicle types
    vehicles = model.getCatalog().getObjectsByType(type_vehicle)
    if vehicles is not None:
        for vehicle in vehicles.itervalues():
            name = vehicle.getName()
            if name == "Car":
                for veh_type in veh_types:
                    cmd = GKObjectDuplicateCmd()
                    cmd.init(vehicle)
                    model.getCommander().addCommand(cmd)
                    new_veh = cmd.createdObject()
                    new_veh.setName(veh_type["veh_id"])

    # Create new states based on vehicle types
    for veh_type in veh_types:
        new_state = create_state(model, veh_type["veh_id"])
        # find vehicle type
        veh_type = model.getCatalog().findByName(
            veh_type["veh_id"], model.getType("GKVehicle"))
        # set state vehicles
        new_state.setVehicle(veh_type)
        # set_state_vehicle(model, new_state, veh_type["veh_id"])
        # set_state_vehicle(model, veh_type["veh_id"], veh_type["veh_id"])

    # add traffic inflows to traffic states
    for inflow in inflows:
        traffic_state_aimsun = model.getCatalog().findByName(
            inflow["vtype"], type_traffic_state)
        edge_aimsun = model.getCatalog().findByName(
            inflow['edge'], type_section)
        traffic_state_aimsun.setEntranceFlow(
            edge_aimsun, None, inflow['vehsPerHour'])

    # for centroid in centroids:
    #     cmd = model.createNewCmd(model.getType("GKCentroid"))
    #     pos = GKPoint(centroid['x'], centroid['y'], 0)
    #     conf = model.getCatalog().findByName("Centroid Configuration 905",
    #                                          model.getType(
    #                                              "GKCentroidConfiguration"))
    #     cmd.setData(pos, conf);
    #     model.getCommander().addCommand(cmd);
    #     res = cmd.createdObject();
    #     res.setName(centroid["id"])
    #     print("done", res.getName())


    # get traffic demand
    demand = model.getCatalog().findByName(
        "Traffic Demand 864", type_demand)
    # clear the demand of any previous item
    demand.removeSchedule()

    # set traffic demand
    for veh_type in veh_types:
        # find the state for each vehicle type
        state_car = model.getCatalog().findByName(
            veh_type["veh_id"], type_traffic_state)
        if demand is not None and demand.isA("GKTrafficDemand"):
            # Add the state
            if state_car is not None and state_car.isA("GKTrafficState"):
                set_demand_item(model, demand, state_car)
            model.getCommander().addCommand(None)
        else:
            create_traffic_demand(model, veh_type["veh_id"])  # TODO debug

    # set the view to "whole world" in Aimsun
    view = gui.getActiveViewWindow().getView()
    if view is not None:
        view.wholeWorld()

    # set view mode, each vehicle type with different color
    set_vehicles_color(model)

    # set API
    scenario_name = data["scenario_name"]
    scenario = model.getCatalog().findByName(
        scenario_name, model.getType("GKScenario"))  # find scenario
    scenario_data = scenario.getInputData()
    scenario_data.addExtension(os.path.join(
        config.PROJECT_PATH, "flow/utils/aimsun/run.py"), True)

    # save
    gui.saveAs('flow.ang')


def generate_net_osm(file_name, inflows, veh_types):
    inflows = inflows.get()

    type_section = model.getType("GKSection")
    type_traffic_state = model.getType("GKTrafficState")
    type_vehicle = model.getType("GKVehicle")
    type_demand = model.getType("GKTrafficDemand")

    # load OSM file
    layer = None
    point = GKPoint()
    point.set(0, 0, 0)
    box = GKBBox()
    box.set(-1000, -1000, 0, 1000, 1000, 0)

    model.importFile(file_name, layer, point, box)

    # set vehicle types
    vehicles = model.getCatalog().getObjectsByType(type_vehicle)
    if vehicles is not None:
        for vehicle in vehicles.itervalues():
            name = vehicle.getName()
            if name == "Car":
                for veh_type in veh_types:
                    cmd = GKObjectDuplicateCmd()
                    cmd.init(vehicle)
                    model.getCommander().addCommand(cmd)
                    new_veh = cmd.createdObject()
                    new_veh.setName(veh_type["veh_id"])

    # Create new states based on vehicle types
    for veh_type in veh_types:
        new_state = create_state(model, veh_type["veh_id"])
        # find vehicle type
        veh_type = model.getCatalog().findByName(
            veh_type["veh_id"], model.getType("GKVehicle"))
        # set state vehicles
        new_state.setVehicle(veh_type)

    # add traffic inflows to traffic states
    if inflows is not None:
        for inflow in inflows:
            traffic_state_aimsun = model.getCatalog().findByName(
                inflow["vtype"], type_traffic_state)
            edge_aimsun = model.getCatalog().findByName(
                inflow['edge'], type_section)
            traffic_state_aimsun.setEntranceFlow(
                edge_aimsun, None, inflow['vehsPerHour'])

    # get traffic demand
    demand = model.getCatalog().findByName(
        "Traffic Demand 864", type_demand)
    # clear the demand of any previous item
    demand.removeSchedule()

    # set traffic demand
    for veh_type in veh_types:
        # find the state for each vehicle type
        state_car = model.getCatalog().findByName(
            veh_type["veh_id"], type_traffic_state)
        if demand is not None and demand.isA("GKTrafficDemand"):
            # Add the state
            if state_car is not None and state_car.isA("GKTrafficState"):
                set_demand_item(model, demand, state_car)
            model.getCommander().addCommand(None)
        else:
            create_traffic_demand(model, veh_type["veh_id"])  # TODO debug

    # set the view to "whole world" in Aimsun
    view = gui.getActiveViewWindow().getView()
    if view is not None:
        view.wholeWorld()

    # set view mode, each vehicle type with different color
    set_vehicles_color(model)

    # set API
    scenario_name = data["scenario_name"]
    scenario = model.getCatalog().findByName(
        scenario_name, model.getType("GKScenario"))  # find scenario
    scenario_data = scenario.getInputData()
    scenario_data.addExtension(os.path.join(
        config.PROJECT_PATH, "flow/utils/aimsun/run.py"), True)

    # save
    gui.saveAs('flow.ang')


def get_junctions(nodes):
    junctions = []  # TODO check
    for node in nodes:
        if "type" in node:
            if node["type"] == "traffic_light":
                junctions.append(node)
    return junctions


# get first and last nodes of an edge
def get_edge_nodes(edge, nodes):
    first_node = next(node for node in nodes
                      if node["id"] == edge["from"])
    last_node = next(node for node in nodes
                     if node["id"] == edge["to"])
    return first_node, last_node


# compute the edge angle
def get_edge_angle(first_node, last_node):
    del_x = np.array([last_node['x'] - first_node['x']])
    del_y = np.array([last_node['y'] - first_node['y']])
    theta = np.arctan2(del_y, del_x) * 180 / np.pi
    return theta


def get_state_folder(model):
    folder_name = "GKModel::trafficStates"
    folder = model.getCreateRootFolder().findFolder(folder_name)
    if folder is None:
        folder = GKSystem.getSystem().createFolder(
            model.getCreateRootFolder(), folder_name)
    return folder


def create_state(model, name):
    state = GKSystem.getSystem().newObject("GKTrafficState", model)
    state.setName(name)
    folder = get_state_folder(model)
    folder.append(state)
    return state


def get_demand_folder(model):
    folder_name = "GKModel::trafficDemands"
    folder = model.getCreateRootFolder().findFolder(folder_name)
    if folder is None:
        folder = GKSystem.getSystem().createFolder(
            model.getCreateRootFolder(), folder_name)
    return folder


def create_traffic_demand(model, name):
    demand = GKSystem.getSystem().newObject("GKTrafficDemand", model)
    demand.setName(name)
    folder = get_demand_folder(model)
    folder.append(demand)
    return demand


def set_demand_item(model, demand, item):
    if item.getVehicle() is None:
        model.getLog().addError("Invalid Demand Item: no vehicle")
    else:
        schedule = GKScheduleDemandItem()
        schedule.setTrafficDemandItem(item)
        # Starts at 8:00:00 AM
        schedule.setFrom(8 * 3600)
        # Duration: 500 hour
        schedule.setDuration(500 * 3600)
        demand.addToSchedule(schedule)


def set_state_vehicle(model, state, veh_type_name):
    # find vehicle type
    veh_type = model.getCatalog().findByName(
        veh_type_name, model.getType("GKVehicle"))
    # set state vehicles
    state.setVehicle(veh_type)
    # find the state object
    # state_car = model.getCatalog().findByName(
    #     state_name, model.getType("GKTrafficState"))
    # state_car.setVehicle(veh_type)


def set_vehicles_color(model):
    view_mode = model.getGeoModel().findMode(
        "GKViewMode::VehiclesByVehicleType", False)
    if view_mode is None:
        view_mode = GKSystem.getSystem().newObject("GKViewMode", model)
        view_mode.setInternalName("GKViewMode::VehiclesByVehicleType")
        view_mode.setName("DYNAMIC: Simulation Vehicles by Vehicle Type")
        model.getGeoModel().addMode(view_mode)
    view_mode.removeAllStyles()
    view_style = model.getGeoModel().findStyle(
        "GKViewModeStyle::VehiclesByVehicleType")
    if view_style is None:
        view_style = GKSystem.getSystem().newObject("GKViewModeStyle", model)
        view_style.setInternalName("GKViewModeStyle::VehiclesByVehicleType")
        view_style.setName("DYNAMIC: Simulation Vehicles by Vehicle Type")
        view_style.setStyleType(GKViewModeStyle.eColor)
        view_style.setVariableType(GKViewModeStyle.eDiscrete)
        sim_type = model.getType("GKSimVehicle")
        type_col = sim_type.getColumn("GKSimVehicle::vehicleTypeAtt",
                                       GKType.eSearchOnlyThisType)
        view_style.setColumn(sim_type, type_col)
        ramp = GKColorRamp()
        ramp.setType(GKColorRamp.eRGB)
        vehicles = model.getCatalog().getObjectsByType(
            model.getType("GKVehicle"))
        if vehicles is not None:<commit_msg>fix pep8<commit_after># flake8: noqa
# TODO adapt this file with respect to scripting_api.py

import sys
import os
import flow.config as config

from flow.core.params import InFlows
from flow.core.params import TrafficLightParams

from copy import deepcopy
import json
import numpy as np

SITEPACKAGES = os.path.join(config.AIMSUN_SITEPACKAGES,
                            "lib/python2.7/site-packages")
sys.path.append(SITEPACKAGES)

sys.path.append(os.path.join(config.AIMSUN_NEXT_PATH,
                             'programming/Aimsun Next API/AAPIPython/Micro'))


# Load an empty template
gui = GKGUISystem.getGUISystem().getActiveGui()
gui.newDoc(os.path.join(config.PROJECT_PATH,
                        "flow/utils/aimsun/Aimsun_Flow.ang"),
           "EPSG:32601")
model = gui.getActiveModel()


def generate_net(nodes, edges, connections, inflows, veh_types,
                 traffic_lights):
    inflows = inflows.get()
    lane_width = 3.6  # TODO additional params??
    type_section = model.getType("GKSection")
    type_node = model.getType("GKNode")
    type_turn = model.getType("GKTurning")
    type_traffic_state = model.getType("GKTrafficState")
    type_vehicle = model.getType("GKVehicle")
    type_demand = model.getType("GKTrafficDemand")

    # draw edges
    for edge in edges:
        points = GKPoints()
        if "shape" in edge:
            for p in edge["shape"]:  # TODO add x, y offset (radius)
                new_point = GKPoint()
                new_point.set(p[0], p[1], 0)
                points.append(new_point)

            cmd = model.createNewCmd(model.getType("GKSection"))
            cmd.setPoints(edge["numLanes"], lane_width, points)
            model.getCommander().addCommand(cmd)
            section = cmd.createdObject()
            section.setName(edge["id"])
            edge_aimsun = model.getCatalog().findByName(
                edge["id"], type_section)
            edge_aimsun.setSpeed(edge["speed"] * 3.6)
        else:
            first_node, last_node = get_edge_nodes(edge, nodes)
            theta = get_edge_angle(first_node, last_node)
            first_node_offset = [0, 0]  # x, and y offset
            last_node_offset = [0, 0]  # x, and y offset

            # offset edge ends if there is a radius in the node
            if "radius" in first_node:
                first_node_offset[0] = first_node["radius"] * \
                    np.cos(theta*np.pi/180)
                first_node_offset[1] = first_node["radius"] * \
                    np.sin(theta*np.pi/180)
            if "radius" in last_node:
                last_node_offset[0] = - last_node["radius"] * \
                    np.cos(theta*np.pi/180)
                last_node_offset[1] = - last_node["radius"] * \
                    np.sin(theta*np.pi/180)

            # offset edge ends if there are multiple edges between nodes
            # find the edges that share the first node
            edges_shared_node = [edg for edg in edges
                                 if first_node["id"] == edg["to"] or
                                 last_node["id"] == edg["from"]]
            for new_edge in edges_shared_node:
                new_first_node, new_last_node = get_edge_nodes(new_edge, nodes)
                new_theta = get_edge_angle(new_first_node, new_last_node)
                if new_theta == theta - 180 or new_theta == theta + 180:
                    first_node_offset[0] += lane_width * 0.5 *\
                        np.sin(theta * np.pi / 180)
                    first_node_offset[1] -= lane_width * 0.5 * \
                        np.cos(theta * np.pi / 180)
                    last_node_offset[0] += lane_width * 0.5 *\
                        np.sin(theta * np.pi / 180)
                    last_node_offset[1] -= lane_width * 0.5 *\
                        np.cos(theta * np.pi / 180)
                    break

            new_point = GKPoint()
            new_point.set(first_node['x'] + first_node_offset[0],
                          first_node['y'] + first_node_offset[1],
                          0)
            points.append(new_point)
            new_point = GKPoint()
            new_point.set(last_node['x'] + last_node_offset[0],
                          last_node['y'] + last_node_offset[1],
                          0)
            points.append(new_point)
            cmd = model.createNewCmd(type_section)
            cmd.setPoints(edge["numLanes"], lane_width, points)
            model.getCommander().addCommand(cmd)
            section = cmd.createdObject()
            section.setName(edge["id"])
            edge_aimsun = model.getCatalog().findByName(
                edge["id"], type_section)
            edge_aimsun.setSpeed(edge["speed"] * 3.6)

    # draw nodes and connections
    for node in nodes:
        # add a new node in Aimsun
        node_pos = GKPoint()
        node_pos.set(node['x'], node['y'], 0)
        cmd = model.createNewCmd(type_node)
        cmd.setPosition(node_pos)
        model.getCommander().addCommand(cmd)
        new_node = cmd.createdObject()
        new_node.setName(node["id"])

        # list of edges from and to the node
        from_edges = [
            edge['id'] for edge in edges if edge['from'] == node['id']]
        to_edges = [edge['id'] for edge in edges if edge['to'] == node['id']]

        # if the node is a junction with a list of connections
        if len(to_edges) > 1 and len(from_edges) > 1 \
                and connections[node['id']] is not None:
            # add connections
            for connection in connections[node['id']]:
                cmd = model.createNewCmd(type_turn)
                from_section = model.getCatalog().findByName(
                    connection["from"], type_section, True)
                to_section = model.getCatalog().findByName(
                    connection["to"], type_section, True)
                cmd.setTurning(from_section, to_section)
                model.getCommander().addCommand(cmd)
                turn = cmd.createdObject()
                turn_name = "{}_to_{}".format(connection["from"],
                                              connection["to"])
                turn.setName(turn_name)
                existing_node = turn.getNode()
                if existing_node is not None:
                    existing_node.removeTurning(turn)
                # add the turning to the node
                new_node.addTurning(turn, False, True)

        # if the node is not a junction or connections is None
        else:
            for i in range(len(from_edges)):
                for j in range(len(to_edges)):
                    cmd = model.createNewCmd(type_turn)
                    to_section = model.getCatalog().findByName(
                        from_edges[i], type_section, True)
                    from_section = model.getCatalog().findByName(
                        to_edges[j], type_section, True)
                    cmd.setTurning(from_section, to_section)
                    model.getCommander().addCommand(cmd)
                    turn = cmd.createdObject()
                    turn_name = "{}_to_{}".format(from_edges[i], to_edges[j])
                    turn.setName(turn_name)
                    existing_node = turn.getNode()
                    if existing_node is not None:
                        existing_node.removeTurning(turn)

                    # add the turning to the node
                    new_node.addTurning(turn, False, True)

    # get the control plan
    control_plan = model.getCatalog().findByName(
            "Control Plan", model.getType("GKControlPlan"))

    # add traffic lights
    tls_properties = traffic_lights.get_properties()
    # determine junctions
    junctions = get_junctions(nodes)
    # add meters for all nodes in junctions
    for node in junctions:
        phases = tls_properties[node['id']]["phases"]
        print(phases)
        create_node_meters(model, control_plan, node['id'], phases)

    # set vehicle types
    vehicles = model.getCatalog().getObjectsByType(type_vehicle)
    if vehicles is not None:
        for vehicle in vehicles.itervalues():
            name = vehicle.getName()
            if name == "Car":
                for veh_type in veh_types:
                    cmd = GKObjectDuplicateCmd()
                    cmd.init(vehicle)
                    model.getCommander().addCommand(cmd)
                    new_veh = cmd.createdObject()
                    new_veh.setName(veh_type["veh_id"])

    # Create new states based on vehicle types
    for veh_type in veh_types:
        new_state = create_state(model, veh_type["veh_id"])
        # find vehicle type
        veh_type = model.getCatalog().findByName(
            veh_type["veh_id"], model.getType("GKVehicle"))
        # set state vehicles
        new_state.setVehicle(veh_type)
        # set_state_vehicle(model, new_state, veh_type["veh_id"])
        # set_state_vehicle(model, veh_type["veh_id"], veh_type["veh_id"])

    # add traffic inflows to traffic states
    for inflow in inflows:
        traffic_state_aimsun = model.getCatalog().findByName(
            inflow["vtype"], type_traffic_state)
        edge_aimsun = model.getCatalog().findByName(
            inflow['edge'], type_section)
        traffic_state_aimsun.setEntranceFlow(
            edge_aimsun, None, inflow['vehsPerHour'])

    # for centroid in centroids:
    #     cmd = model.createNewCmd(model.getType("GKCentroid"))
    #     pos = GKPoint(centroid['x'], centroid['y'], 0)
    #     conf = model.getCatalog().findByName("Centroid Configuration 905",
    #                                          model.getType(
    #                                              "GKCentroidConfiguration"))
    #     cmd.setData(pos, conf);
    #     model.getCommander().addCommand(cmd);
    #     res = cmd.createdObject();
    #     res.setName(centroid["id"])
    #     print("done", res.getName())

    # get traffic demand
    demand = model.getCatalog().findByName(
        "Traffic Demand 864", type_demand)
    # clear the demand of any previous item
    demand.removeSchedule()

    # set traffic demand
    for veh_type in veh_types:
        # find the state for each vehicle type
        state_car = model.getCatalog().findByName(
            veh_type["veh_id"], type_traffic_state)
        if demand is not None and demand.isA("GKTrafficDemand"):
            # Add the state
            if state_car is not None and state_car.isA("GKTrafficState"):
                set_demand_item(model, demand, state_car)
            model.getCommander().addCommand(None)
        else:
            create_traffic_demand(model, veh_type["veh_id"])  # TODO debug

    # set the view to "whole world" in Aimsun
    view = gui.getActiveViewWindow().getView()
    if view is not None:
        view.wholeWorld()

    # set view mode, each vehicle type with different color
    set_vehicles_color(model)

    # set API
    scenario_name = data["scenario_name"]
    scenario = model.getCatalog().findByName(
        scenario_name, model.getType("GKScenario"))  # find scenario
    scenario_data = scenario.getInputData()
    scenario_data.addExtension(os.path.join(
        config.PROJECT_PATH, "flow/utils/aimsun/run.py"), True)

    # save
    gui.saveAs('flow.ang')


def generate_net_osm(file_name, inflows, veh_types):
    inflows = inflows.get()

    type_section = model.getType("GKSection")
    type_traffic_state = model.getType("GKTrafficState")
    type_vehicle = model.getType("GKVehicle")
    type_demand = model.getType("GKTrafficDemand")

    # load OSM file
    layer = None
    point = GKPoint()
    point.set(0, 0, 0)
    box = GKBBox()
    box.set(-1000, -1000, 0, 1000, 1000, 0)

    model.importFile(file_name, layer, point, box)

    # set vehicle types
    vehicles = model.getCatalog().getObjectsByType(type_vehicle)
    if vehicles is not None:
        for vehicle in vehicles.itervalues():
            name = vehicle.getName()
            if name == "Car":
                for veh_type in veh_types:
                    cmd = GKObjectDuplicateCmd()
                    cmd.init(vehicle)
                    model.getCommander().addCommand(cmd)
                    new_veh = cmd.createdObject()
                    new_veh.setName(veh_type["veh_id"])

    # Create new states based on vehicle types
    for veh_type in veh_types:
        new_state = create_state(model, veh_type["veh_id"])
        # find vehicle type
        veh_type = model.getCatalog().findByName(
            veh_type["veh_id"], model.getType("GKVehicle"))
        # set state vehicles
        new_state.setVehicle(veh_type)

    # add traffic inflows to traffic states
    if inflows is not None:
        for inflow in inflows:
            traffic_state_aimsun = model.getCatalog().findByName(
                inflow["vtype"], type_traffic_state)
            edge_aimsun = model.getCatalog().findByName(
                inflow['edge'], type_section)
            traffic_state_aimsun.setEntranceFlow(
                edge_aimsun, None, inflow['vehsPerHour'])

    # get traffic demand
    demand = model.getCatalog().findByName(
        "Traffic Demand 864", type_demand)
    # clear the demand of any previous item
    demand.removeSchedule()

    # set traffic demand
    for veh_type in veh_types:
        # find the state for each vehicle type
        state_car = model.getCatalog().findByName(
            veh_type["veh_id"], type_traffic_state)
        if demand is not None and demand.isA("GKTrafficDemand"):
            # Add the state
            if state_car is not None and state_car.isA("GKTrafficState"):
                set_demand_item(model, demand, state_car)
            model.getCommander().addCommand(None)
        else:
            create_traffic_demand(model, veh_type["veh_id"])  # TODO debug

    # set the view to "whole world" in Aimsun
    view = gui.getActiveViewWindow().getView()
    if view is not None:
        view.wholeWorld()

    # set view mode, each vehicle type with different color
    set_vehicles_color(model)

    # set API
    scenario_name = data["scenario_name"]
    scenario = model.getCatalog().findByName(
        scenario_name, model.getType("GKScenario"))  # find scenario
    scenario_data = scenario.getInputData()
    scenario_data.addExtension(os.path.join(
        config.PROJECT_PATH, "flow/utils/aimsun/run.py"), True)

    # save
    gui.saveAs('flow.ang')


def get_junctions(nodes):
    junctions = []  # TODO check
    for node in nodes:
        if "type" in node:
            if node["type"] == "traffic_light":
                junctions.append(node)
    return junctions


# get first and last nodes of an edge
def get_edge_nodes(edge, nodes):
    first_node = next(node for node in nodes
                      if node["id"] == edge["from"])
    last_node = next(node for node in nodes
                     if node["id"] == edge["to"])
    return first_node, last_node


# compute the edge angle
def get_edge_angle(first_node, last_node):
    del_x = np.array([last_node['x'] - first_node['x']])
    del_y = np.array([last_node['y'] - first_node['y']])
    theta = np.arctan2(del_y, del_x) * 180 / np.pi
    return theta


def get_state_folder(model):
    folder_name = "GKModel::trafficStates"
    folder = model.getCreateRootFolder().findFolder(folder_name)
    if folder is None:
        folder = GKSystem.getSystem().createFolder(
            model.getCreateRootFolder(), folder_name)
    return folder


def create_state(model, name):
    state = GKSystem.getSystem().newObject("GKTrafficState", model)
    state.setName(name)
    folder = get_state_folder(model)
    folder.append(state)
    return state


def get_demand_folder(model):
    folder_name = "GKModel::trafficDemands"
    folder = model.getCreateRootFolder().findFolder(folder_name)
    if folder is None:
        folder = GKSystem.getSystem().createFolder(
            model.getCreateRootFolder(), folder_name)
    return folder


def create_traffic_demand(model, name):
    demand = GKSystem.getSystem().newObject("GKTrafficDemand", model)
    demand.setName(name)
    folder = get_demand_folder(model)
    folder.append(demand)
    return demand


def set_demand_item(model, demand, item):
    if item.getVehicle() is None:
        model.getLog().addError("Invalid Demand Item: no vehicle")
    else:
        schedule = GKScheduleDemandItem()
        schedule.setTrafficDemandItem(item)
        # Starts at 8:00:00 AM
        schedule.setFrom(8 * 3600)
        # Duration: 500 hour
        schedule.setDuration(500 * 3600)
        demand.addToSchedule(schedule)


def set_state_vehicle(model, state, veh_type_name):
    # find vehicle type
    veh_type = model.getCatalog().findByName(
        veh_type_name, model.getType("GKVehicle"))
    # set state vehicles
    state.setVehicle(veh_type)
    # find the state object
    # state_car = model.getCatalog().findByName(
    #     state_name, model.getType("GKTrafficState"))
    # state_car.setVehicle(veh_type)


def set_vehicles_color(model):
    view_mode = model.getGeoModel().findMode(
        "GKViewMode::VehiclesByVehicleType", False)
    if view_mode is None:
        view_mode = GKSystem.getSystem().newObject("GKViewMode", model)
        view_mode.setInternalName("GKViewMode::VehiclesByVehicleType")
        view_mode.setName("DYNAMIC: Simulation Vehicles by Vehicle Type")
        model.getGeoModel().addMode(view_mode)
    view_mode.removeAllStyles()
    view_style = model.getGeoModel().findStyle(
        "GKViewModeStyle::VehiclesByVehicleType")
    if view_style is None:
        view_style = GKSystem.getSystem().newObject("GKViewModeStyle", model)
        view_style.setInternalName("GKViewModeStyle::VehiclesByVehicleType")
        view_style.setName("DYNAMIC: Simulation Vehicles by Vehicle Type")
        view_style.setStyleType(GKViewModeStyle.eColor)
        view_style.setVariableType(GKViewModeStyle.eDiscrete)
        sim_type = model.getType("GKSimVehicle")
        type_col = sim_type.getColumn("GKSimVehicle::vehicleTypeAtt",
                                      GKType.eSearchOnlyThisType)
        view_style.setColumn(sim_type, type_col)
        ramp = GKColorRamp()
        ramp.setType(GKColorRamp.eRGB)
        vehicles = model.getCatalog().getObjectsByType(
            model.getType("GKVehicle"))
        if vehicles is not None:
{'fraction_non_alphanumeric': 0.1024857431307812, 'fraction_numerical': 0.007176184889082921, 'mean_word_length': 2.2047918852745716, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6933507', 'n_tokens_mistral': 11127, 'n_tokens_neox': 10814, 'n_words': 2330}