%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Pravidla pro vyhodnocování aktivity osob
% rules_person.pl
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init_person_activity :-
  assert(person_activity(1, 2, 3)),
  retractall(person_activity(_, _, _)),
  (   test_mode([offline])
  ->  write_begin('generating persons actvity'),
      begin(B),
      end(E),
      step(S),
      ignore(generate_person_activity_step(B, E, S)),
      write_done
  ;   true
  ).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% generování aktivity předem při offline zpracování
generate_person_activity(Time) :-
   ignore(forall(person(P),
		 (evaluate_person_activity(Time, P, A),
		  assert(person_activity(Time, P, A))))).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
generate_person_activity_step(Time, End, Step) :-
  Time =< End -> (generate_person_activity(Time),
		  T is Time + Step,
		  generate_person_activity_step(T, End, Step)).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% vyhodnocení aktivity jedné osoby - aplikace osobních pravidel
evaluate_person_activity(Time, Person, Activity) :-
  rule_configuration_dynamic(s_person_mult, Person, Importance),
  findall(W, person_rule(_, Time, Person, W), Weights),
  ((Weights = []) -> Weight is 0;
  (maxlist(Weights, Weight))),
%  (sumlist(Weights, Sum), Weight is Sum / 3)),
  Activity is min(Weight * Importance, 1.0).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% obsluha osobních pravidel zavislých na kameře
person_rule(Name, Time, Person, Weight) :-
  bagof(W, Camera^Parent^(camera(Camera, _, _, _, _, Parent, _),
			  Camera = Parent,
			  person_rule(Name, Time, Person, Camera, W)
			 ), L),
  maxlist(L, Weight).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% konstantní pravidlo
person_rule(Name, _, Person, Weight) :-
  Name = 'p_const',
  rule_configuration_dynamic(Name, Person, Weight).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 99% maximalní hodnoty pravidla
speaking_exp_base(X) :-
  X is -log(0.01).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo řeči z minulých dat (exponenciální)
person_rule(Name, Time, Person, Weight) :-
  Name = 'p_past_speaking_exp',
  rule_configuration(Name, PastMaxTime),

  is_speaking(Time, Person, HL),
  speaking_exp_base(Base),
  Weight is 1 - exp(-(Base * (HL / PastMaxTime))).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo řeči z minulých dat (inverzne exponenciální)
person_rule(Name, Time, Person, Weight) :-
  Name = 'p_past_speaking_inv_exp',
  rule_configuration(Name, PastMaxTime),

  is_speaking(Time, Person, HL),
  speaking_exp_base(Base),
  Weight is exp(-(Base * (HL / PastMaxTime))).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo řeči z minulých dat (cos)
person_rule(Name, Time, Person, Weight) :-
  Name = 'p_past_speaking_cos',
  rule_configuration(Name, PastMaxTime),

  is_speaking(Time, Person, HL),
  Weight is 1 - (cos((min(HL, PastMaxTime) / PastMaxTime) * pi) + 1) / 2.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo řeči z budoucích dat (exponenciální)
person_rule(Name, Time, Person, Weight) :-
  Name = 'p_future_speaking_exp',
  rule_configuration(Name, FutureMaxTime),

  will_speak(Time, Person, HL),
  speaking_exp_base(Base),
  HL < FutureMaxTime,
  Weight is 1 - exp(-(Base * ((FutureMaxTime - HL) / FutureMaxTime))).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo řeči z budoucích dat (cos)
person_rule(Name, Time, Person, Weight) :-
  Name = 'p_future_speaking_cos',
  rule_configuration(Name, FutureMaxTime),

  will_speak(Time, Person, HL),
  HL < FutureMaxTime,
  Weight is 1 - (cos(((FutureMaxTime - HL) / FutureMaxTime) * pi) + 1) / 2.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo řeči z kombinovaných  dat (exponenciální)
person_rule(Name, Time, Person, Weight) :-
  Name = 'p_future_past_speaking_exp',
  rule_configuration(Name, FutureMaxTime, PastMaxTime),

  (   will_speak(Time, Person, FHL)
  ->  FHL < FutureMaxTime,
      RT is FutureMaxTime - FHL
  ;   is_speaking(Time, Person, PHL)
  ->  RT is FutureMaxTime + PHL
  ;   fail
  ),
  
  speaking_exp_base(Base),
  Weight is 1 - exp(-(Base * (RT / (FutureMaxTime + PastMaxTime)))).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo pohybu hlavy z minulých dat
person_rule(Name, Time, Person, Camera, Weight) :-
  Name = 'p_past_head_moving',
  rule_configuration(Name, Window, Minimum, Maximum),

  camera(Camera, _, _, _, _, Parent, _),
  step(Step),
  head_moves(Time, -Step, Window, Parent, Person, LA),

  sumlist(LA, S),
  W1 is S / Window,
  W1 >= Minimum,
  ((W1 > Maximum) -> W2 is Maximum; W2 is W1),
  Weight is (W2 - Minimum) / (Maximum - Minimum).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo pohybu hlavy z budoucích dat
person_rule(Name, Time, Person, Camera, Weight) :-
  Name = 'p_future_head_moving',
  rule_configuration(Name, Window, Minimum, Maximum),

  camera(Camera, _, _, _, _, Parent, _),
  step(Step),
  head_moves(Time, Step, Window, Parent, Person, LA),

  sumlist(LA, S),
  W1 is S / Window,
  W1 >= Minimum,
  ((W1 > Maximum) -> W2 is Maximum; W2 is W1),
  Weight is (W2 - Minimum) / (Maximum - Minimum).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo pohybu hlavy z kombinovaných dat
person_rule(Name, Time, Person, Camera, Weight) :-
  Name = 'p_future_past_head_moving',
  rule_configuration(Name, PastWindow, FutureWindow, Minimum, Maximum),

  camera(Camera, _, _, _, _, Parent, _),
  step(Step),
  head_moves(Time, Step, FutureWindow, Parent, Person, LF),
  sumlist(LF, SF),
  head_moves(Time, -Step, PastWindow, Parent, Person, LP),
  sumlist(LP, SP),
 
  W1 is (SF + SP) / (FutureWindow + PastWindow),
  W1 >= Minimum,
  ((W1 > Maximum) -> W2 is Maximum; W2 is W1),
  Weight is (W2 - Minimum) / (Maximum - Minimum).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo pohybu rukou z minulých dat
person_rule(Name, Time, Person, Camera, Weight) :-
  Name = 'p_past_hand_moving',
  rule_configuration(Name, Window, Minimum, Maximum),

  camera(Camera, _, _, _, _, Parent, _),
  step(Step),
  hand_moves(Time, -Step, Window, Parent, Person, LA),

  sumlist(LA, S),
  W1 is S / Window,
  W1 >= Minimum,
  ((W1 > Maximum) -> W2 is Maximum; W2 is W1),
  Weight is (W2 - Minimum) / (Maximum - Minimum).
	  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo pohybu rukou z budoucích dat
person_rule(Name, Time, Person, Camera, Weight) :-
  Name = 'p_future_hand_moving',
  rule_configuration(Name, Window, Minimum, Maximum),

  camera(Camera, _, _, _, _, Parent, _),
  step(Step),
  hand_moves(Time, Step, Window, Parent, Person, LA),

  sumlist(LA, S),
  W1 is S / Window,
  W1 >= Minimum,
  ((W1 > Maximum) -> W2 is Maximum; W2 is W1),
  Weight is (W2 - Minimum) / (Maximum - Minimum).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo pohybu rukou z kombinovaných dat
person_rule(Name, Time, Person, Camera, Weight) :-
  Name = 'p_future_past_hand_moving',
  rule_configuration(Name, PastWindow, FutureWindow, Minimum, Maximum),

  camera(Camera, _, _, _, _, Parent, _),
  step(Step),
  hand_moves(Time, Step, FutureWindow, Parent, Person, LF),
  sumlist(LF, SF),
  hand_moves(Time, -Step, PastWindow, Parent, Person, LP),
  sumlist(LP, SP),

  W1 is (SF + SP) / (FutureWindow + PastWindow),
  W1 >= Minimum,
  ((W1 > Maximum) -> W2 is Maximum; W2 is W1),
  Weight is (W2 - Minimum) / (Maximum - Minimum).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pravidlo řeči skokové
person_rule(Name, Time, Person, Weight) :-
  Name = 'square_speaking',
  rule_configuration(Name),
  is_speaking(Time, Person),
  Weight is 1.
  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% testing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% generate rule weights
%
test_person_rule_step(Name, Person, Time, End, Step, Color) :-
	Time =< End -> ((person_rule(Name, Time, Person, Weight) -> 
			export('graph', Time, [('color', Color), ('value', Weight)]);
%			export('graph', Time, [('color', Color), ('value', 0)])
			true 
		        ),
			T is Time + Step,
			test_person_rule_step(Name, Person, T, End, Step, Color)).

test_person_rule(Name, Person, Color) :-
	begin(B),
	end(E),
	step(S),
	(test_person_rule_step(Name, Person, B, E, S, Color); true).


test_person_rule(Name, Person) :-
	test_person_rule(Name, Person, 0).

test_person_rulef(Name, Person, Color) :-
	string_concat(Name, '_', File1), 
	string_concat(File1, Person, File2), 
	string_concat(File2, '_', File3), 
%	string_concat(File3, Camera, File4), 
	File4 = File3,
	string_concat(File4, '.pl', File),
	tell(File),
	test_person_rule(Name, Person, Color),
	told.

test_person_rulef(Name, Person, Camera) :-
	test_person_rulef(Name, Person, Camera, 0).

test_mult_camera_rule_step(Name, Camera, Time, End, Step, Color) :-
	Time =< End -> ((mult_camera_rule(Name, Time, Camera, Weight) -> 
			export('graph', Time, [('color', Color), ('value', Weight)]);
			true 
		        ),
			T is Time + Step,
			test_mult_camera_rule_step(Name, Camera, T, End, Step, Color)).

%test_person_rule(Name, Person, Camera) :-
%	begin(B),
%	end(E),
%	step(S),
%	(test_person_rule_step(Name, Person, Camera, B, E, S); true).

test_person_activity_step(Person, Time, End, Step, Color) :-
  Time =< End -> ((evaluate_person_activity(Time, Person, Activity) -> 
		   export('graph', Time, [('color', Color), ('value', Activity)]); 
		   true),
		  T is Time + Step,
		  test_person_activity_step(Person, T, End, Step, Color)).

test_person_activity(Person, Color) :-
  begin(B),
  end(E),
  step(S),
  (test_person_activity_step(Person, B, E, S, Color); true).

test_person_activityf(Person, Color) :-
	Name = 'activity',
	string_concat(Name, '_', File1), 
	string_concat(File1, Person, File2), 
	string_concat(File2, '.pl', File),
	tell(File),
	test_person_activity(Person, Color),
	told.
