/**
* Name: Drive Random
* Description: Vehicles driving randomly in a road graph
* Author: Duc Pham
* Tags: gis, shapefile, graph, agent_movement, skill, transport
*/

model DriveRandom

import "Traffic.gaml"

global {
	float seed <- 42.0;
	float traffic_light_interval parameter: 'Traffic light interval' init: 60#s;
	float step <- 0.2#s;

	string map_name;
	file shp_roads <- file("../../includes/" + map_name + "/roads.shp");
	file shp_nodes <- file("../../includes/" + map_name + "/nodes.shp");

	geometry shape <- envelope(shp_roads) + 50;
	
	int num_cars;
	int num_motorbikes;

	graph road_network;
	list non_deadend_nodes;

	init {
		create road from: shp_roads {
			num_lanes <- rnd(4, 6);
			// Create another road in the opposite direction
			create road {
				num_lanes <- myself.num_lanes;
				shape <- polyline(reverse(myself.shape.points));
				maxspeed <- myself.maxspeed;
				linked_road <- myself;
				myself.linked_road <- self;
			}
		}
		
		create intersection from: shp_nodes
				with: [is_traffic_signal::(read("type") = "traffic_signals")] {
			time_to_change <- traffic_light_interval;
		}
		
		// Create a graph representing the road network, with road lengths as weights
		map edge_weights <- road as_map (each::each.shape.perimeter);
		road_network <- as_driving_graph(road, intersection) with_weights edge_weights;
		
		non_deadend_nodes <- intersection where !empty(each.roads_out);
		// Initialize the traffic lights
		ask intersection {
			do initialize;
		}
		
		create motorbike_random number: num_motorbikes;
		create car_random number: num_cars;
	}
}

species vehicle_random parent: base_vehicle {
	init {
		road_graph <- road_network;
		location <- one_of(non_deadend_nodes).location;
		right_side_driving <- true;
	}

	// Move the vehicle to a random node when it reaches a deadend
	reflex relocate when: next_road = nil and distance_to_current_target = 0.0 {
		do unregister;
		location <- one_of(non_deadend_nodes).location;
	}
	
	reflex commute {
		do drive_random graph: road_graph;
	}
}

species motorbike_random parent: vehicle_random {
	init {
		vehicle_length <- 1.9 #m;
		num_lanes_occupied <- 1;
		max_speed <- (50 + rnd(20)) #km / #h;

		proba_block_node <- 0.0;
		proba_respect_priorities <- 1.0;
		proba_respect_stops <- [1.0];
		proba_use_linked_road <- 0.5;

		lane_change_limit <- 2;		
		linked_lane_limit <- 1;
	}
}

species car_random parent: vehicle_random {
	init {
		vehicle_length <- 3.8 #m;
		num_lanes_occupied <- 2;
		max_speed <- (60 + rnd(10)) #km / #h;
				
		proba_block_node <- 0.0;
		proba_respect_priorities <- 1.0;
		proba_respect_stops <- [1.0];
		proba_use_linked_road <- 0.0;

		lane_change_limit <- 2;			
		linked_lane_limit <- 0;
	}
}

experiment ring type: gui {
	action _init_{ 
		create simulation with:[
			map_name::"ring",
			num_cars::50,
			num_motorbikes::100
		];
	}

	output synchronized: true {
		display map type: opengl background: #gray {
			species road aspect: base;
			species car_random aspect: base;
			species motorbike_random aspect: base;
			species intersection aspect: base;
		}
	}
}


experiment city type: gui {
	action _init_{
		create simulation with:[
			map_name::"rouen",
			num_cars::100,
			num_motorbikes::200
		];
	}

	output synchronized: true {
		display map type: opengl background: #gray {
			species road aspect: base;
			species car_random aspect: base;
			species motorbike_random aspect: base;
			species intersection aspect: base;
		}
	}
}