Index: applications/doprava/traffic_agent_cycle_time.h
===================================================================
--- applications/doprava/traffic_agent_cycle_time.h (revision 1076)
+++ applications/doprava/traffic_agent_cycle_time.h (revision 1129)
@@ -1,42 +1,81 @@
 #include "traffic_agent.cpp"
 const string testMessage = "test_message";
+const double measurement_cycle_time = 90; // s
+const double saturated_stream = 0.5; // car/s
+const int sample_cycles = 5;
+
+
+class SignalGroup {
+public:
+	string name;
+	Array <Lane*> lanes;
+	double green_time_ratio;
+	int average_queue_length;
+	string queue_name;
+	int cycle_counter;
+
+	SignalGroup () {
+		average_queue_length = 0;
+	}
+
+	void adapt() {
+		if ( (cycle_counter +1)% sample_cycles == 0 )
+			average_queue_length = 0;
+	}
+
+	
+	int getSumCarsWaitingTime ( double time_cycle ) {
+		int q = average_queue_length/sample_cycles; // pomocna delka fronty - UPRAVIT - pocitat s vetsi nez prumernou?
+		int cars_per_green = time_cycle * green_time_ratio * lanes.length() * saturated_stream; // pocet aut ktere projedou na zelenou
+		int sum_cars_waiting_time = 0; // suma aut * cekacich casu
+		int i = 0; // iterator
+		while ( q > cars_per_green ) {
+			q -= cars_per_green;
+			sum_cars_waiting_time += q*time_cycle;
+			i ++;
+		}
+		// + zbytek fronty + prvni nezapocitana vlna
+		if ( i > 0 ) {
+			sum_cars_waiting_time += q*time_cycle + cars_per_green*(1.0-green_time_ratio)*time_cycle*0,5;
+			//cout << "delsi fronta " << q << " ";
+		}
+
+		// pocet aut * stredni hodnota cekaci doby pri volne krizovatces
+		else {
+			sum_cars_waiting_time += (0.5*(1.0-green_time_ratio))*(time_cycle*q);
+			//cout << "kratsi fronta " << q << " ";
+		}
+
+		//cout << "signal group " << name << " tc " << time_cycle << " cekani " << sum_cars_waiting_time << " fronta " << average_queue_length << endl;
+		
+		return sum_cars_waiting_time;
+	}
+
+	void addQueue( int q ) {
+		
+		if ( q > 0 )
+			average_queue_length += q;
+	}	
+
+	
+};
 
 class TrafficAgentCycleTime : public BaseTrafficAgent {
-private:
-	static double measurement_cycle_time; // s
-	static double saturated_stream; // car/s
-	static double Tc;
+public:
+	int Tc;
+	int minTc;
+	int maxTc;
+	int stepTc;
+	int idealTc;
+	static const int d_Tc = 3; // pocet navrhovanych delek cyklu	
 	int cycle_counter;
+	int max_profit;
+	unsigned int n_of_broadcast;
 	Array <int> lane_sum;
-
-	void sum_lanes() {
-		for ( int i = 0; i < lane_sum.length(); i ++ ) {
-			if ( inputs(2*i) > 0 ) {
-				lane_sum(i) = lane_sum(i) + inputs(2*i);
-			}
-		}
-	}
-
-	void echo ( string message ) {
-		cout << name << " hlasi: " << message << endl;		
-	}
-
-	void send2neighbour( Setting &set, int i, string messageName, double messageValue ) {		
-		if ( i < neighbours.length() ) {
-			Setting &msg =set.add(Setting::TypeGroup);
-			UI::save( neighbours(i), msg, "to" );
-			UI::save (name,msg,"from");
-			UI::save( messageName, msg, "what" );
-			UI::save( messageValue, msg, "value" );
-		}
-		else {
-			//throw new Exception("soused "+((string)i)+" neexistuje");
-			//cout << endl << endl << "soused " << i << mimo
-			std::stringstream out;
-			out << "soused " << i << " neexistuje";
-			//throw out.str();
-			cout << out.str();
-		}
-	}
+	Array <SignalGroup*> signal_groups;
+	Array <int> received_Tcs;
+	Array <int> received_profit_sum;
+
+// POMOCNE FUNKCE
 
 	void printVector ( RV rv_vector, vec vector, string description ) {
@@ -54,23 +93,208 @@
 	}
 
+	void echo ( string message ) {
+		cout << name << " hlasi: " << message << endl;		
+	}
+
+	unsigned int find_index ( RV rv_vector, string index_string ) {
+		for ( unsigned int i = 0; i < (int) rv_vector.length(); i ++) {
+			if ( rv_vector.name(i) == index_string )
+				return i;
+		}
+		return rv_vector.length();
+	}
+
+	unsigned int find_index ( Array <string> arr, string index_string ) {
+		for ( unsigned int i = 0; i < (int) arr.length(); i ++) {
+			if ( arr(i) == index_string )
+				return i;
+		}
+		return arr.length();
+	}
+
+// VYPOCETNI FUNKCE
+
+	int getSumCarsWaitingTime ( double time_cycle ) {
+		int sum = 0;
+		SignalGroup * sg;
+		for ( int i = 0; i < signal_groups.length(); i ++ ) {
+			sg = signal_groups(i);
+			sum += sg->getSumCarsWaitingTime( time_cycle );
+		}
+		return sum;
+	}
+
+	int getQueue () {
+		int queue = 0;
+		SignalGroup *sg;
+		for ( int i = 0; i < signal_groups.length(); i ++ ) {
+			sg = signal_groups(i);
+			queue += sg->average_queue_length;
+		}
+		return queue;
+	}
+
+	// NEPOUZIVAT?
+	//int getIdealTc() {
+	//	int min_waiting_time = getSumCarsWaitingTime(Tc);
+	//	int waiting_time;
+	//	int idealTc = Tc;
+	//	cout << name << " Tc wt" << endl;
+	//	for ( int t_c = Tc - 2*stepTc; t_c <= Tc + 2*stepTc; t_c += stepTc ) {
+	//		waiting_time = getSumCarsWaitingTime(t_c);
+	//		cout << t_c << " " << waiting_time << endl;
+	//			if ( waiting_time < min_waiting_time ) {
+	//				min_waiting_time = waiting_time;
+	//				idealTc = t_c;
+	//			}
+	//	}
+	//	cout << "IDEAL " << idealTc << endl;
+	//	return idealTc;
+	//}
+
+	int getIdealTc() {
+			
+	}
+
+
+	void send2neighbour( Setting &set, int i, string messageName, double messageValue ) {		
+		if ( i < neighbours.length() ) {
+			Setting &msg =set.add(Setting::TypeGroup);
+			UI::save( neighbours(i), msg, "to" );
+			UI::save (name,msg,"from");
+			UI::save( messageName, msg, "what" );
+			UI::save( messageValue, msg, "value" );
+		}
+		else {
+			//throw new Exception("soused "+((string)i)+" neexistuje");
+			//cout << endl << endl << "soused " << i << mimo
+			std::stringstream out;
+			out << "soused " << i << " neexistuje";
+			//throw out.str();
+			cout << out.str();
+		}
+	}
+
+	void send2allNeighbours ( Setting &set, string messageName, double messageValue ) {
+		for ( int i = 0; i < neighbours.length(); i++ ) {
+			send2neighbour( set, i, messageName, messageValue );
+		}
+	}
+
+	int getProfit( int time_cycle ) {
+		if ( Tc != time_cycle )
+			return getSumCarsWaitingTime( Tc ) - getSumCarsWaitingTime ( time_cycle );
+		else
+			return 0;
+	}
+
 	
-
-public:
+// FUNKCE VOLANE V main_loop NA ZACATKU
 	void from_setting( Setting &set ) {
 		BaseTrafficAgent::from_setting(set);
-		TrafficAgentCycleTime::measurement_cycle_time = 90; //s
-		TrafficAgentCycleTime::saturated_stream = 0.5;
-		TrafficAgentCycleTime::Tc = 80;
-	}
-
-	void broadcast(Setting &set){
-		//BaseTrafficAgent::broadcast(set);
-		try {
-			for ( int i = 0; i < neighbours.length(); i ++ ) {
-				send2neighbour( set, i, testMessage, 2.3 );				
-			}
-		} catch ( string s ) {
-			cout << s << endl;
-		}		
+		//TrafficAgentCycleTime::Tc = 80;
+	}
+
+	void validate (){
+		rv_action = RV("Tc",1);
+		rv_action.add( RV( stage_names, ones_i(stage_names.length()) ) );
+		Tc = 80;
+		minTc = 60;
+		maxTc = 120;
+		stepTc = 5;
+		max_profit = 0;
+		received_profit_sum.set_length( 2*d_Tc +1 );
+		received_Tcs.set_length( 2*d_Tc +1 );
+		cycle_counter = 0;
+
+		BaseTrafficAgent::validate();
+		// inicializace signalnich skupin
+		for ( int i = 0; i < lanes.length(); i ++ ) {
+			Lane * l = & lanes(i);
+			int sg_index = -1;
+			for ( int j = 0; j < signal_groups.length(); j ++ ) {
+				SignalGroup * sg;
+				sg = signal_groups(j);
+				if ( sg->name == l->sg )
+					sg_index = j;
+			}
+			SignalGroup * sg;
+			if ( sg_index >= 0 ) {				
+				sg = signal_groups(sg_index);
+			}
+			else {
+				sg = new SignalGroup();
+				sg->name = l->sg;
+				sg->average_queue_length = 0;
+				signal_groups.set_size( signal_groups.length()+1, true );
+				signal_groups(signal_groups.length()-1) = sg;
+			}			
+			sg->lanes.set_size(sg->lanes.length()+1, true);
+			sg->lanes(sg->lanes.length()-1) = l;
+		}
+	}
+
+// FUNKCE VOLANE V main_loop V KAZDEM CYKLU
+
+	void adapt (const vec &glob_dt) {
+		// inicializes vars of cycle of broadcast
+		n_of_broadcast = 0;
+		max_profit = 0;
+		idealTc = Tc;
+		
+		for ( int i = 0; i < signal_groups.length(); i ++ ) {
+			signal_groups(i)->adapt();
+		}
+
+		for ( int i = 0; i < received_profit_sum.length(); i++ ) {
+			received_profit_sum(i) = 0;
+		}
+
+		// nacteni dat do signalnich skupin
+		cout << endl << cycle_counter << " SG " << (cycle_counter%sample_cycles +1) << endl;
+		for ( int i = 0; i < rv_queues.length(); i ++ ) {
+			SignalGroup * sg;
+			sg = signal_groups(i);
+			sg->queue_name = rv_queues.name(i);
+			sg->addQueue(queues(i));
+			sg->green_time_ratio = green_times(i);
+			sg->cycle_counter = cycle_counter;
+			//cout << sg->name << " " << sg->getSumCarsWaitingTime(Tc) << " " << sg->average_queue_length << " " << sg->green_time_ratio*Tc << " " << sg->getTime2zeroQue() << endl;
+			cout << sg->name << " " << queues(i) << " " << sg->average_queue_length << " " << sg->average_queue_length / (cycle_counter%sample_cycles +1) << endl;
+		}
+
+		//suggestedTc = idealTc = getIdealTc();		
+		
+		//cout << endl << "CELKOVA FRONTA " << name << " " << getQueue() << endl;
+
+		BaseTrafficAgent::adapt(glob_dt);
+	}
+
+	void broadcast(Setting &set){		
+		
+		// 1. cycle of communication
+		// sends all tcs in range +- d_tc and expected profits according to tc
+		// format: tc_index, profit_index
+		if ( n_of_broadcast == 0 && ( cycle_counter % sample_cycles == 0 ) ) {
+			for ( int i = -d_Tc; i <= d_Tc; i++ ) {				
+				int time_cycle = Tc + i*stepTc;
+				int profit = getProfit(time_cycle);
+
+				// send tc
+				stringstream time_cycle_stream;
+				time_cycle_stream << "tc_" << (i+d_Tc);
+				send2allNeighbours( set, time_cycle_stream.str(), time_cycle);
+				
+				// send profit
+				stringstream profit_stream;
+				profit_stream << "profit_" << (i+d_Tc);
+				send2allNeighbours( set, profit_stream.str(), profit );
+
+				//cout << name << " tc " << time_cycle << " profit " << profit << " cekani " << getSumCarsWaitingTime(time_cycle) << endl;
+			}
+			//cout << endl;
+		}
+		
+		n_of_broadcast ++;
 	}
 
@@ -78,67 +302,68 @@
 		string what;
 		string from;
-		string to;
-		double val;
-		try {
-			UI::get(what, msg, "what", UI::compulsory);
-			UI::get(from, msg, "from", UI::compulsory);
-			UI::get(to, msg, "to", UI::compulsory);
-			UI::get(val, msg, "value");
-			if ( what == testMessage ) {
-				//cout << endl << name << ": OD: " << from << " CO: " << what << " KOLIK: " << val <<endl;
-			}
-			if ( what == "new_stable_state" ) {
-				//echo("new_stable_state");
-				BaseTrafficAgent::receive(msg);		
-			}
-
-			
-		} catch ( UISettingException e ) {
-			echo(e.what());
-		}
-	}
-
-	void validate (){
-		BaseTrafficAgent::validate();
-		lane_sum.set_size( rv_inputs.length() );
-		for ( int i = 0; i < lane_sum.length(); i ++ ) {
-			lane_sum(i) = 0;
-			cout << endl << endl << "lane_sum initialization " << name << " " << lane_sum(i) <<endl << endl ;
-		}
-		echo("validate");
-	}
-
-	void adapt (const vec &glob_dt) {
-		sum_lanes();
-		//printVector( rv_queues, queues, "queues" );
-		printVector( rv_inputs, inputs, "inputs" );
-		for ( int i = 0; i < lane_sum.length(); i ++ ) {
-			cout << lane_sum(i) << endl;
-		}
-		cout << endl << endl;
-		//printVector( green_names, green_times, "inputs" );
-		//cout << endl << name << "green times: " << endl;
-		for ( int i = 0; i < green_times.length(); i ++ ) {
-			//cout << green_names(i) << " " << green_starts(i) << " " << green_times(i) << endl;
-		}
-
-		
-/*
-		for ( int i = 0; i < outputs.length(); i ++ ) {
-			cout << name << " outputs " << outputs(i) << endl;
-		}
-
-		for ( int i = 0; i < rv_outputs.length(); i ++ ) {
-			cout << name << " rv_outputs " << rv_outputs.name(i) << endl;
-		}
-
-	*/	
-
-		BaseTrafficAgent::adapt(glob_dt);
-		//echo("adapted");
+		double val;		
+		UI::get(what, msg, "what", UI::compulsory);
+		UI::get(from, msg, "from", UI::compulsory);
+		UI::get(val, msg, "value");
+		
+		//cout << name << " receiving from " << from << " " << what << " : " << val<<endl;
+		if ( n_of_broadcast == 1 ) {
+			if ( what.substr(0,2) == "tc" ) {			
+				istringstream tc_i( what.substr(3, what.length()-3) );
+				int index;
+				tc_i >> index;
+				received_Tcs( index ) = val;
+				//cout << "tc " << val << endl;
+			}
+			if ( what.substr(0,6) == "profit" ) {				
+				istringstream profiti( what.substr(7, what.length()-7) );
+				int index;
+				profiti >> index;
+				received_profit_sum( index ) = received_profit_sum( index ) + val;
+				//cout << "profit " << val << endl;			
+			}
+		}
+		
+		if ( what == "new_stable_state" ) {
+			//echo("new_stable_state");
+			BaseTrafficAgent::receive(msg);		
+		}	
+		
 	}
 
 	void act (vec &glob_ut){
-		
+		if ( cycle_counter % sample_cycles == 0 ) {
+			// choose tc with max profit		
+			for ( int i = 0; i < received_profit_sum.length(); i ++ ) {
+				int time_cycle = received_Tcs(i);
+				int profit = received_profit_sum(i) + getProfit(time_cycle);
+				if ( profit > max_profit ) {
+					max_profit = profit;
+					idealTc = time_cycle;
+					//cout << name << " idealni Tc " << time_cycle << " s celkovym ziskem " << profit << endl;
+				}
+			}
+			//cout << endl << name << " nastevuje TC na " << idealTc << endl;
+			Tc = idealTc;
+
+
+			// nastaveni delky cyklu na Tc
+			vec action;
+			action.set_size(rv_action._dsize());	
+			int st;
+			int stage_time_sum = 0;  // soucet delky fazi
+			action(find_index(rv_action, "Tc")) = Tc;		
+			for ( int i =0; i < stage_names.length(); i ++) {			
+				if ( (i+1) < stage_names.length() ) {
+					st = (stage_times(i)/80)*Tc;
+					stage_time_sum += st;
+					action(find_index(rv_action, stage_names(i))) = st;
+				}
+				else // dopocitani posledni faze - oprava zaokrouhlovaci chyby
+					action(find_index(rv_action, stage_names(i))) = Tc - stage_time_sum;
+			}
+			action2ds.filldown(action,glob_ut);
+		}
+		cycle_counter ++;
 	}
 	
