%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Parser for dog transcripts written in XML %%%
%%%                                           %%%
%%% Written by:                               %%%
%%% Tibor Bosse                               %%%
%%% e-mail: tbosse@cs.vu.nl                   %%%
%%%                                           %%%
%%% Updated: 10/10/2006                       %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



/**********************************************************************************
 * start(+InFile, +OutFile):
 *
 * Loads the XML-file InFile, parses this file, and returns its contents translated
 * to CLIPS facts in OutFile.
 **********************************************************************************/
start(InFile, OutFile):-
	tell(OutFile),
	load_xml_file(InFile,[element(transcript, [], [element(data, [], Dog_Data), element(general_circumstances, [], General), element(exercises, [], Exercises)])]),
	assert(bounded_action(init, [], 0, 0, [])),
	parse_exercises(Exercises, 0),
	assert_trial_end_time,
	compare_actions,
	write_actions,
	assert_trace_end_time,
	write_trace_end_time,
	parse_dog_data(Dog_Data),
	parse_general(General),
	retract_trace_end_time,
	told.


/**********************************************************************************
 * parse_exercises(+E):
 *
 * Recursive predicate that parses a list of exercises.
 * (e.g. exerciseA1I, ...)
 * Note that there are many possible combinations, e.g.:
 * 1) actions
 * 2) times + actions
 * 3) comment + actions
 * and so on...
 **********************************************************************************/
parse_exercises([], _).
parse_exercises([element(exercise, E, EI)|Rest], X):-
	parse_exercise_info(EI, X, E),
	assert_exercise_end_time(E),
	exercise_end_time(E, Y),
	write_exercise(E, X, Y),
	assert(real_times(E, dummy)),
	assert(comment(E, dummy)),
	write_all_real_times(E, X, Y),
	write_all_comments(E, X, Y),
	parse_exercises(Rest, Y).


/**********************************************************************************
 * parse_exercise_info(+EI, +X, +E):
 *
 * Recursive predicate that parses a list of exercise information.
 * (e.g. actions, times, comment)
 **********************************************************************************/
parse_exercise_info([], _, _).
parse_exercise_info([element(exercise_content, [], Actions)|Rest], X, E):-
	parse_actions(Actions, X, E),
	parse_exercise_info(Rest, X, E).
parse_exercise_info([element(times, [], T)|Rest], X, E):-
	assert(real_times(E, T)),
	Y is X + 10,
	assert(poss_end_time(Y)),
	parse_exercise_info(Rest, X, E).
parse_exercise_info([element(comment, [], C)|Rest], X, E):-
	assert(comment(E, C)),
	Y is X + 10,
	assert(poss_end_time(Y)),
	parse_exercise_info(Rest, X, E).


/**********************************************************************************
 * write_exercise(+E, +X, +Y):
 *
 * Predicate that writes an exercise.
 * (e.g. exerciseA1I, ...)
 * (write atom_trace, including the appropriate start_time and end_time)
 **********************************************************************************/
write_exercise([type=L, trial=N, index=S], X, Y):-
	write('atom_trace('),
	write('exercise('),
	write(L),
	write(','),
	write(N),
	write(','),
	write(S),
	write(')'),
	write(', '),
	write('exercise('),
	write(L),
	write(','),
	write(N),
	write(','),
	write(S),
	write(')'),
	write(', [range('),
	write(X),
	write(', '),
	write(Y),
	write(', true)]'),
	write(').'),
	nl.


/**********************************************************************************
 * write_all_real_times(+E, +X, +Y):
 *
 * Predicate that writes the real times (on the camera) of an exercise.
 **********************************************************************************/
write_all_real_times(_, _, _):-
	not(real_times(_, _)).
write_all_real_times(E, X, Y):-
	real_times(E, dummy),
	retract(real_times(E, dummy)),
	write_all_real_times(E, X, Y).
write_all_real_times(E, X, Y):-
	real_times(E, T),
	write_real_times(T, X, Y),
	retract(real_times(E, T)),
	write_all_real_times(E, X, Y).


/**********************************************************************************
 * write_real_times(+T, +X, +Y):
 *
 * Predicate that writes a single "times" slot of an exercise.
 **********************************************************************************/
write_real_times([element(starts, [min=SM, sec=SS], []), element(ends, [min=EM, sec=ES], []), element(on, [cam=Cam], [])], X, Y):-
	write('atom_trace('),
	write('times_on_camera('),
	write(SM),
	write(','),
	write(SS),
	write(','),
	write(EM),
	write(','),
	write(ES),
	write(','),
	write(Cam),
	write(')'),
	write(', '),
	write('times_on_camera('),
	write(SM),
	write(','),
	write(SS),
	write(','),
	write(EM),
	write(','),
	write(ES),
	write(','),
	write(Cam),
	write(')'),
	write(', [range('),
	write(X),
	write(', '),
	write(Y),
	write(', true)]'),
	write(').'),
	nl.


/**********************************************************************************
 * write_all_comments(+E, +X, +Y):
 *
 * Predicate that writes the real times (on the camera) of an exercise.
 **********************************************************************************/
write_all_comments(_, _, _):-
	not(comment(_, _)).
write_all_comments(E, X, Y):-
	comment(E, dummy),
	retract(comment(E, dummy)),
	write_all_comments(E, X, Y).
write_all_comments(E, X, Y):-
	comment(E, C),
	write_comment(C, X, Y),
	retract(comment(E, C)),
	write_all_comments(E, X, Y).


/**********************************************************************************
 * write_comment(+C, +X, +Y):
 *
 * Predicate that writes a comment.
 **********************************************************************************/
write_comment([C], X, Y):-
	write('atom_trace('),
	write('comment('),
	write(C),
	write(')'),
	write(', '),
	write('comment('),
	write(C),
	write(')'),
	write(', [range('),
	write(X),
	write(', '),
	write(Y),
	write(', true)]'),
	write(').'),
	nl.


/**********************************************************************************
 * parse_actions(+A, +X, +E):
 *
 * Recursive predicate that parses a list of actions.
 * (e.g. atomic, sequential, ...)
 * A:action, X:start_time, E:exercise
 **********************************************************************************/
parse_actions([element(comment, [], [Action])], X, E):-
	parse_comment(Action, X, E).
parse_actions([element(atomic, Args, [Action])], X, E):-
	parse_atomic_action(Action, Args, X, E).
parse_actions([element(parallel, [], Actions)], X, E):-
	parse_parallel_actions(Actions, X, E).
parse_actions([element(sequential, [], Actions)], X, E):-
	parse_sequential_actions(Actions, X, E).
parse_actions(Actions, X, _):-
	write('ACTIONS'),
	write(Actions), nl, nl, nl,
	Y is X + 10,
	assert(poss_end_time(Y)).


/**********************************************************************************
 * parse_sequential_actions(+A):
 *
 * Recursive predicate that parses a list of sequential actions.
 * (make sure that next action starts after current action is finished)
 **********************************************************************************/
parse_sequential_actions([], _, _).
parse_sequential_actions([element(comment, [], [Action])|Rest], X, E):-
	parse_comment(Action, X, E),
	Y is X + 10,
	parse_sequential_actions(Rest, Y, E).
parse_sequential_actions([element(atomic, Args, [Action])|Rest], X, E):-
	parse_atomic_action(Action, Args, X, E),
	Y is X + 10,
	parse_sequential_actions(Rest, Y, E).
parse_sequential_actions([element(parallel, [], Actions)|Rest], X, E):-
	parse_parallel_actions(Actions, X, E),
	Y is X + 10,
	parse_sequential_actions(Rest, Y, E).
parse_sequential_actions([element(sequential, [], Actions)|Rest], X, E):-
	parse_sequential_actions(Actions, X, E),
	Y is X + 10,
	parse_sequential_actions(Rest, Y, E).


/**********************************************************************************
 * parse_parallel_actions(+A):
 *
 * Recursive predicate that parses a list of parallel actions.
 * (make sure that next action starts at the same time as current action)
 **********************************************************************************/
parse_parallel_actions([], _, _).
parse_parallel_actions([element(comment, [], [Action])|Rest], X, E):-
	parse_comment(Action, X, E),
	parse_parallel_actions(Rest, X, E).
parse_parallel_actions([element(atomic, Args, [Action])|Rest], X, E):-
	parse_atomic_action(Action, Args, X, E),
	parse_parallel_actions(Rest, X, E).
parse_parallel_actions([element(parallel, [], Actions)|Rest], X, E):-
	parse_parallel_actions(Actions, X, E),
	parse_parallel_actions(Rest, X, E).
parse_parallel_actions([element(sequential, [], Actions)|Rest], X, E):-
	parse_sequential_actions(Actions, X, E),
	parse_parallel_actions(Rest, X, E).


/**********************************************************************************
 * parse_atomic_action(+A):
 *
 * Predicate that parses an atomic action (possible with some arguments).
 * (and asserts possible end time of exercise)
 **********************************************************************************/
parse_atomic_action(Action, Args, X, E):-
	assert(action(Action, Args, X, E)),
	Y is X + 10,
	assert(poss_end_time(Y)).


/**********************************************************************************
 * parse_comment(+A):
 *
 * Predicate that parses a comment.
 * (and asserts possible end time of exercise)
 **********************************************************************************/
parse_comment(Action, X, E):-
	assert(action(comment, [arg1=Action], X, E)),
	Y is X + 10,
	assert(poss_end_time(Y)).


/**********************************************************************************
 * assert_exercise_end_time(+E):
 *
 * Recursive predicate that reads all poss_end_time facts.
 * The latest poss_end_time is translated to the real end_time of the exercise.
 **********************************************************************************/
assert_exercise_end_time(E):-
	poss_end_time(X1),
	poss_end_time(X2),
	X1 > X2,
	retract(poss_end_time(X2)),
	assert_exercise_end_time(E).
assert_exercise_end_time(E):-
	poss_end_time(X),
	assert(exercise_end_time(E,X)),
	retract(poss_end_time(X)).


/**********************************************************************************
 * compare_actions:
 *
 * Recursive predicate that reads all "action(_,_,_,_)" facts
 * and translates them into "bounded_action(_,_,_,_,_)" facts (i.e., including end time).
 **********************************************************************************/
compare_actions:-
	not(action(_,_,_,_)).

compare_actions:-
	action(A,ArgsA1,X,[type=L, trial=N, index=S]),
	exclusive(action(A,ArgsA2), List),
	equal(ArgsA1,ArgsA2),
	member(action(B,ArgsB1), List),			/* action(A,ArgsA) - action(B,ArgsB) */
	action(B,ArgsB2,Y,[type=L, trial=N, index=_]),
	equal(ArgsB1,ArgsB2),
	Y > X,
	not(bounded_action(A,ArgsA1,X,Y,[type=L, trial=N, index=S])),
	assert(bounded_action(A,ArgsA1,X,Y,[type=L, trial=N, index=S])),
	retract(action(A,ArgsA1,X,[type=L, trial=N, index=S])),
	correct_bounded_action(A,ArgsA1,X,Y,[type=L, trial=N, index=S]),
	compare_actions.

compare_actions:-
	action(A,Args,X,E),
	exclusive(action(A,any), all),			/* action(A,any) - all */
	Y is X + 10,
	not(bounded_action(A,Args,X,Y,E)),
	assert(bounded_action(A,Args,X,Y,E)),
	retract(action(A,Args,X,E)),
	compare_actions.
compare_actions:-
	action(A,Args,X,E),
	exclusive(action(A,any), 2),			/* action(A,any) - 2 */
	Y is X + 20,
	not(bounded_action(A,Args,X,Y,E)),
	assert(bounded_action(A,Args,X,Y,E)),
	retract(action(A,Args,X,E)),
	compare_actions.

compare_actions:-
	action(A,ArgsA1,X,E),
	exclusive(action(A,ArgsA2), all),		/* action(A,args) - all */
	equal(ArgsA1,ArgsA2),
	Y is X + 10,
	not(bounded_action(A,ArgsA1,X,Y,E)),
	assert(bounded_action(A,ArgsA1,X,Y,E)),
	retract(action(A,ArgsA1,X,E)),
	compare_actions.
compare_actions:-
	action(A,ArgsA1,X,E),
	exclusive(action(A,ArgsA2), 2),			/* action(A,args) - 2 */
	equal(ArgsA1,ArgsA2),
	Y is X + 20,
	not(bounded_action(A,ArgsA1,X,Y,E)),
	assert(bounded_action(A,ArgsA1,X,Y,E)),
	retract(action(A,ArgsA1,X,E)),
	compare_actions.

compare_actions:-
	action(A,Args,X,[type=L, trial=N, index=S]),
	trial_end_time(L, N, Y),			/* action(A,args) - eot */
	not(bounded_action(A,Args,X,Y,[type=L, trial=N, index=S])),
	assert(bounded_action(A,Args,X,Y,[type=L, trial=N, index=S])),
	retract(action(A,Args,X,[type=L, trial=N, index=S])),
	compare_actions.


/**********************************************************************************
 * correct_bounded_action(+A, +Args, +X, +Y, +E):
 *
 * Recursive predicate that "corrects" all "bounded_action(_,_,_,_,_)" facts.
 * These are facts that indicate the start and end time of an action, e.g. from 10 to 90.
 * However, it could be the case that another action that is exclusive to the bounded_action
 * starts between 10 and 90, e.g. at 50. In that case the timing of the bounded_action
 * is changed to 10-50.
 **********************************************************************************/
correct_bounded_action(A,ArgsA1,X,Y,[type=L, trial=N, index=S]):-
	bounded_action(A,ArgsA1,X,Y,[type=L, trial=N, index=S]),
	exclusive(action(A,ArgsA2), List),
	equal(ArgsA1,ArgsA2),
	member(action(B,ArgsB1), List),
	action(B,ArgsB2,Z,[type=L, trial=N, index=_]),
	equal(ArgsB1,ArgsB2),
	X < Z,
	Z < Y,
	not(bounded_action(A,ArgsA1,X,Z,[type=L, trial=N, index=S])),
	assert(bounded_action(A,ArgsA1,X,Z,[type=L, trial=N, index=S])),
	retract(bounded_action(A,ArgsA1,X,Y,[type=L, trial=N, index=S])),
	correct_bounded_action(A,ArgsA1,X,Z,[type=L, trial=N, index=S]).
correct_bounded_action(_,_,_,_,_).


/**********************************************************************************
 * equal(+Args1, +Args2):
 *
 * Predicate that checks whether two lists of arguments can be considered identical.
 * E.g. [arg1=one, arg2=two, arg3=any] is equal to [arg1=one, arg2=two, arg3=three]
 **********************************************************************************/
equal(any, _).
equal(_, any).
equal(Args, Args).
equal(Args1, Args2):-
	equallist(Args1, Args2).

equallist([], []).
equallist([El|Rest1], [El|Rest2]):-
	equallist(Rest1, Rest2).
equallist([_=any|Rest1], [_=_|Rest2]):-
	equallist(Rest1, Rest2).
equallist([_=_|Rest1], [_=any|Rest2]):-
	equallist(Rest1, Rest2).


/**********************************************************************************
 * write_actions:
 *
 * Recursive predicate that reads all "bounded_action(_,_,_,_,_)" facts
 * and writes them as "atom_trace".
 **********************************************************************************/
write_actions:-
	not(bounded_action(_,_,_,_,_)).
write_actions:-
	bounded_action(init,[],0,0,[]),
	retract(bounded_action(init,[],0,0,[])),
	write_actions.
write_actions:-
	bounded_action(A,Args,_,_,_),
	write('atom_trace('),
	write(A),
	write_args(Args),
	write(', '),
	write(A),
	write_args(Args),
	write(', ['),
	write_ranges(A,Args),
	write(']'),
	write(').'),
	nl,
	write_actions.


/**********************************************************************************
 * write_ranges(+A, +Args):
 *
 * Recursive predicate that write the "range" part of the "atom_trace" line.
 * Note that the times are ordered from the highest to the lowest range.
 **********************************************************************************/
write_ranges(A,Args):-
	setof(X, Y ^ E ^ bounded_action(A,Args,X,Y,E), XList),
	length(XList, 1),
	maxlist(XList, M),
	bounded_action(A,Args,M,N,F),
	write('range('),
	write(M),
	write(', '),
	write(N),
	write(', true)'),
	retract(bounded_action(A,Args,M,N,F)).
write_ranges(A,Args):-
	setof(X, Y ^ E ^ bounded_action(A,Args,X,Y,E), XList),
	length(XList, L),
	L > 1,
	maxlist(XList, M),
	bounded_action(A,Args,M,N,F),
	write('range('),
	write(M),
	write(', '),
	write(N),
	write(', true)'),
	write(', '),
	retract(bounded_action(A,Args,M,N,F)),
	write_ranges(A,Args).
		

/**********************************************************************************
 * write_args(+A):
 *
 * Recursive predicate that writes all arguments between brackets, separated by commas
 **********************************************************************************/
write_args([]).
write_args([arg1=A1]):-
	write('('),
	write(A1),
	write(')').
write_args([arg2=A2]):-
	write('('),
	write(A2),
	write(')').
write_args([arg3=A3]):-
	write('('),
	write(A3),
	write(')').
write_args([arg1=A1, arg2=A2]):-
	write('('),
	write(A1),
	write(','),
	write(A2),
	write(')').
write_args([arg1=A1, arg3=A3]):-
	write('('),
	write(A1),
	write(','),
	write(A3),
	write(')').
write_args([arg2=A2, arg3=A3]):-
	write('('),
	write(A2),
	write(','),
	write(A3),
	write(')').
write_args([arg1=A1, arg2=A2, arg3=A3]):-
	write('('),
	write(A1),
	write(','),
	write(A2),
	write(','),
	write(A3),
	write(')').


/**********************************************************************************
 * assert_trial_end_time:
 *
 * Recursive predicate that reads all exercise_end_time facts.
 * The latest exercise_end_time of one trial is translated to trial_end_time.
 **********************************************************************************/
assert_trial_end_time:-
	exercise_end_time([type=L, trial=N, index=_],X1),
	exercise_end_time([type=L, trial=N, index=S],X2),
	X1 > X2,
	retract(exercise_end_time([type=L, trial=N, index=S],X2)),
	assert_trial_end_time.
assert_trial_end_time:-
	exercise_end_time([type=L, trial=N, index=S],X),
	assert(trial_end_time(L, N, X)),
	retract(exercise_end_time([type=L, trial=N, index=S],X)),
	assert_trial_end_time.
assert_trial_end_time.


/**********************************************************************************
 * assert_trace_end_time:
 *
 * Recursive predicate that reads all trial_end_time facts.
 * The latest exercise_end_time is translated to trace_end_time.
 **********************************************************************************/
assert_trace_end_time:-
	trial_end_time(_,_,X1),
	trial_end_time(L,N,X2),
	X1 > X2,
	retract(trial_end_time(L,N,X2)),
	assert_trace_end_time.
assert_trace_end_time:-
	trial_end_time(L,N,X),
	assert(trace_end_time(X)),
	retract(trial_end_time(L,N,X)).


/**********************************************************************************
 * write_trace_end_time:
 *
 * Predicate that writes "times(0, X, X)".
 **********************************************************************************/
write_trace_end_time:-
	trace_end_time(X),
	write('times(0, '),
	write(X),
	write(', '),
	write(X),
	write(').'),
	nl.


/**********************************************************************************
 * retract_trace_end_time:
 *
 * Predicate that retracts "trace_end_time" facts.
 **********************************************************************************/
retract_trace_end_time:-
	trace_end_time(X),
	retract(trace_end_time(X)).


/**********************************************************************************
 * parse_dog_data(+D):
 *
 * Recursive predicate that parses a list of dog data.
 * (e.g. name, breed, ...)
 **********************************************************************************/
parse_dog_data([]).
parse_dog_data([element(age, [years=Y, months=M], [])|Rest]):-
	trace_end_time(X),
	write('atom_trace('),
	write(age),
	write('('),
	write(Y),
	write(','),
	write(M),
	write(')'),
	write(', '),
	write(age),
	write('('),
	write(Y),
	write(','),
	write(M),
	write(')'),
	write(', [range(0, '),
	write(X),
	write(', true)]'),
	write(').'),
	nl,
	parse_dog_data(Rest).
parse_dog_data([element(training, [arg1=A], [roedelmethode])|Rest]):-
	trace_end_time(X),
	write('atom_trace('),
	write(training),
	write('('),
	write('roedelmethode'),
	write(','),
	write(A),
	write(')'),
	write(', '),
	write(training),
	write('('),
	write('roedelmethode'),
	write(','),
	write(A),
	write(')'),
	write(', [range(0, '),
	write(X),
	write(', true)]'),
	write(').'),
	nl,
	parse_dog_data(Rest).
parse_dog_data([element(El, [], [Att])|Rest]):-
	trace_end_time(X),
	write('atom_trace('),
	write(El),
	write('('),
	write(Att),
	write(')'),
	write(', '),
	write(El),
	write('('),
	write(Att),
	write(')'),
	write(', [range(0, '),
	write(X),
	write(', true)]'),
	write(').'),
	nl,
	parse_dog_data(Rest).
parse_dog_data(D):-
	write('DOG DATA'),
	write(D),
	nl,nl,nl.


/**********************************************************************************
 * parse_general(+G):
 *
 * Recursive predicate that parses a list of general circumstances.
 * (e.g. date, weather...)
 **********************************************************************************/
parse_general([]).
parse_general([element(weather, [], W)|Rest]):-
	parse_general(W),
	parse_general(Rest).
parse_general([element(date, [year=Y, month=M, day=D], [])|Rest]):-
	trace_end_time(X),
	write('atom_trace('),
	write(date),
	write('('),
	write(Y),
	write(','),
	write(M),
	write(','),
	write(D),
	write(')'),
	write(', '),
	write(date),
	write('('),
	write(Y),
	write(','),
	write(M),
	write(','),
	write(D),
	write(')'),
	write(', [range(0, '),
	write(X),
	write(', true)]'),
	write(').'),
	nl,
	parse_general(Rest).
parse_general([element(precipitation, [arg1=A], [rain])|Rest]):-
	trace_end_time(X),
	write('atom_trace('),
	write(rain),
	write('('),
	write(A),
	write(')'),
	write(', '),
	write(rain),
	write('('),
	write(A),
	write(')'),
	write(', [range(0, '),
	write(X),
	write(', true)]'),
	write(').'),
	nl,
	parse_general(Rest).
parse_general([element(El, [], [Att])|Rest]):-
	trace_end_time(X),
	write('atom_trace('),
	write(El),
	write('('),
	write(Att),
	write(')'),
	write(', '),
	write(El),
	write('('),
	write(Att),
	write(')'),
	write(', [range(0, '),
	write(X),
	write(', true)]'),
	write(').'),
	nl,
	parse_general(Rest).
parse_general(G):-
	write('GENERAL'),
	write(G),
	nl,nl,nl.



/**********************************************************************************
 * Standard operations
 *
 * maxlist(List, X) : X is the highest element of List
 **********************************************************************************/
max(X,Y,X):-
	X >= Y.
max(X,Y,Y):-
	X < Y.

maxlist([X], X).
maxlist([X,Y|Rest], Max):-
	maxlist([Y|Rest], MaxRest),
	max(X, MaxRest, Max).



/**********************************************************************************
 * Facts
 *
 * Example:
 * exclusive(action(dog_torso_direction, any), [action(dog_torso_direction, any)]).
 **********************************************************************************/

exclusive(action(dog_torso_direction, any), [action(dog_torso_direction, any), action(dog_moves_to, any), action(dog_turns, any), action(individual_brings_dog_to, any), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler)]).

exclusive(action(dog_general_posture, any), [action(dog_general_posture, any), action(dog_body_posture, any), action(dog_head_posture, any), action(dog_tail_stance, any), action(dog_ear_stance, any)]).

exclusive(action(dog_body_posture, any), [action(dog_body_posture, any), action(dog_general_posture, any)]).

exclusive(action(dog_paw_front, any), [action(dog_paw_front, any), action(dog_moves_paw, any), action(dog_moves_to, any), action(individual_brings_dog_to, any),  action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_searches), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_synchronises, any), action(dog_digs), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_through_alley, any), action(dog_jumps_back, any) ]).

exclusive(action(dog_paw_bent, any), [action(dog_paw_bent, any), action(dog_moves_paw, any), action(dog_moves_to, any), action(individual_brings_dog_to, any), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_searches, any), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_synchronises, any), action(dog_digs), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_through_alley, any), action(dog_jumps_back, any), action(dog_lifts_paw, any), action(dog_replaces_paw, any)]).

exclusive(action(dog_moves_paw, any), all).

exclusive(action(dog_replaces_paw, any), all).

exclusive(action(dog_lifts_paw, any), [action(dog_lifts_paw, any), action(dog_moves_paw, any), action(dog_moves_to, any), action(individual_brings_dog_to, any), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_searches, any), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_synchronises, any), action(dog_digs, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_through_alley, any), action(dog_jumps_back, any), action(dog_paw_bent, any), action(dog_replaces_paw, any)]).

exclusive(action(dog_head_posture, any), [action(dog_head_posture, any), action(dog_general_posture, any), action(dog_head_tilt, any)]).

exclusive(action(dog_head_tilt, any), [action(dog_head_tilt, any), action(dog_looks, any), action(dog_head_pointed, any),  action(dog_turns_head, any), action(dog_searches), action(dog_jumps_up_to, any),  action(handler_holds_dog_head_away_from_goody_pylon, any)]).

exclusive(action(dog_ear_stance, any), [action(dog_ear_stance, any), action(dog_moves_ear, any), action(dog_general_posture, any)]).

exclusive(action(dog_moves_ear, any), all).

exclusive(action(dog_looks, any), all).

exclusive(action(dog_looks_at_handler_leg, any), all).
exclusive(action(dog_looks_at_pylon, any), all).
exclusive(action(dog_looks_inside_pylon, any), all).

exclusive(action(dog_head_pointed, any), all).

exclusive(action(dog_head_pointed_at_handler_leg, any), all).
exclusive(action(dog_head_pointed_at_pylon, any), all).
exclusive(action(dog_head_pointed_inside_pylon, any), all).

exclusive(action(dog_turns_head, any), all).
exclusive(action(dog_turns_head), all).

exclusive(action(dog_turns, any), all).

exclusive(action(dog_tail_direction, any), all).

exclusive(action(dog_tail_stance, any), [action(dog_tail_stance, any), action(dog_general_posture, any)]).

exclusive(action(dog_wags_tail, [arg1=slightly]), [action(dog_wags_tail, [arg1=hard]), action(dog_tail_activity_over_time, any), action(dog_tail_stance, any), action(dog_tail_direction, any)]).
exclusive(action(dog_wags_tail, [arg1=hard]), [action(dog_wags_tail, [arg1=slightly]), action(dog_tail_activity_over_time, any), action(dog_tail_stance, any), action(dog_tail_direction, any)]).

exclusive(action(pulls_leash, [arg1=any, arg2=slightly]), all).
exclusive(action(pulls_leash, [arg1=any, arg3=hard]), all).

/*exclusive(action(pulls_leash, [arg1=handler, arg2=hard]), all).
exclusive(action(pulls_leash, [arg1=handler, arg2=slightly]), all).
exclusive(action(pulls_leash, [arg1=dog, arg2=hard]), all).
exclusive(action(pulls_leash, [arg1=dog, arg2=slightly]), all). andForOtherIndividualsAsWell*/

exclusive(action(handler_pulls_dog, any), all). 

exclusive(action(handler_talks_to_dog, any), all).

exclusive(action(handler_gives_goody_to_dog, any), all).

exclusive(action(handler_offers_goody_to_dog, any), all).

exclusive(action(handler_pets_dog, any), all).

exclusive(action(handler_bends_over_dog, any), all).

exclusive(action(handler_pushes_dog_down, any), all).

exclusive(action(handler_holds_dog_between_legs, any), all).

exclusive(action(handler_hand_food_pose, any), 2).

exclusive(action(hand_goes_to_nose, any), all).

exclusive(action(individual_brings_dog_to, any), all).

exclusive(action(commands, any), all).

exclusive(action(handler_lets_dog_take_off, any), all).

exclusive(action(experimenter_talks_to_dog, any), all).

exclusive(action(experimenter_gives_goody_to_dog, any), all).

exclusive(action(experimenter_offers_goody_to_dogs_nose, any), all).

exclusive(action(individual_initiates_movement, any), all).

exclusive(action(individual_replaces_foot, any), all).

exclusive(action(individual_lifts_foot, any), all).

exclusive(action(dog_moves_to, [arg1=any]), [action(dog_moves_to, any), action(dog_turns, any), action(dog_sits, any), action(dog_lies, any), action(dog_stands, any),  action(individual_brings_dog_to, any), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_synchronises, any), action(dog_digs, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_lifts_paw, any), action(dog_moves_paw, any), action(dog_replaces_paw, any), action(dog_paw_bent, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any), action(dog_stands_between_pylons, any)]).

exclusive(action(dog_moves_to, [arg1=any, arg2=any]), [action(dog_moves_to, any), action(dog_turns, any), action(dog_sits, any), action(dog_lies, any), action(dog_stands, any), action(individual_brings_dog_to, any ), action(turns_around, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_synchronises, any), action(dog_digs), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_lifts_paw, any), action(dog_moves_paw, any), action(dog_replaces_paw, any), action(dog_paw_bent, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any), action(dog_stands_between_pylons, any)]).

exclusive(action(goes_towards, any), all).

exclusive(action(goes_to, any), all).

exclusive(action(turns_around, any), all).

exclusive(action(passes, any), all).

exclusive(action(goes_towards_pylon, any), all).

exclusive(action(goes_to_pylon, any), all).

exclusive(action(turns_around_pylon, any), all).

exclusive(action(passes_pylon, any), all).

exclusive(action(handler_walks), [action(individual_brings_dog_to, [arg1=handler, arg2=any]), action(goes_towards, [arg1=handler, arg2=any]), action(goes_to, [arg1=handler, arg2=any]), action(passes, [arg1=handler, arg2=any]), action(turns_around, [arg1=handler, arg2=any]), action(goes_towards_pylon, [arg1=handler, arg2=any]), action(goes_to_pylon, [arg1=handler, arg2=any]), action(passes_pylon, [arg1=handler, arg2=any]), action(turns_around_pylon, [arg1=handler, arg2=any]), action(handler_turns_around, any), action(handler_gives_goody_to_dog), action(handler_offers_goody_to_dog, any), action(handler_pets_dog, any), action(handler_bends_over_dog, any), action(handler_pushes_dog_down, any), action(handler_holds_dog_between_legs, any), action(individual_initiates_movement, [arg1=handler, arg2=any]), action(individual_replaces_foot, [arg1=handler, arg2=any]), action(individual_lifts_foot, [arg1=handler, arg2=any]), action(handler_steps_with, any), action(pushes_over_pylon, [arg1=handler, arg2=any, arg3=hand]), action(handler_unleashes_dog), action(handler_steps_over_dog, any), action(handler_steps_on_dog, any), action(handler_frees_dogs_leg_from_leash, any), action(handler_holds_dog_head_away_from_goody_pylon, any), action(handler_pushes_dog, any) ]).
exclusive(action(handler_walks, any), [action(handler_walks, any), action(individual_brings_dog_to, [arg1=handler, arg2=any]), action(goes_towards, [arg1=handler, arg2=any]), action(goes_to, [arg1=handler, arg2=any]), action(passes, [arg1=handler, arg2=any]), action(turns_around, [arg1=handler, arg2=any]), action(goes_towards_pylon, [arg1=handler, arg2=any]), action(goes_to_pylon, [arg1=handler, arg2=any]), action(passes_pylon, [arg1=handler, arg2=any]), action(turns_around_pylon, [arg1=handler, arg2=any]), action(handler_gives_goody_to_dog), action(handler_offers_goody_to_dog, any), action(handler_pets_dog, any), action(handler_bends_over_dog, any), action(handler_pushes_dog_down, any), action(handler_holds_dog_between_legs, any), action(individual_initiates_movement, [arg1=handler, arg2=any]), action(individual_replaces_foot, [arg1=handler, arg2=any]), action(individual_lifts_foot, [arg1=handler, arg2=any]), action(handler_steps_with, any), action(handler_turns_around, any), action(pushes_over_pylon, [arg1=handler, arg2=any, arg3=hand]), action(handler_unleashes_dog, any), action(handler_steps_over_dog, any), action(handler_steps_on_dog, any), action(handler_frees_dogs_leg_from_leash, any), action(handler_holds_dog_head_away_from_goody_pylon, any), action(handler_pushes_dog, any) ]).

exclusive(action(experimenter_walks, any), all).
exclusive(action(experimenter_walks), all).

exclusive(action(handler_steps_with, any), [action(handler_steps_with, any), action(handler_stops_walking, any)]).

exclusive(action(handler_stops_walking, any), all).

exclusive(action(handler_turns_around, any), all).

exclusive(action(points_towards, any), all).

exclusive(action(individual_ends_trial, any), all).

exclusive(action(experimenter_places_goody_on_ground, any), all).

exclusive(action(dog_position, any), [action(dog_position, any), action(dog_moves_to, any), action(dog_turns, any), action(individual_brings_dog_to, any), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any)]).

exclusive(action(dog_sits), [action(dog_moves_to, any), action(dog_turns, any), action(individual_brings_dog_to, any ), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any ,arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any), action(dog_stands_up, any), action(dog_moves_paw, any), action(dog_resists, [arg1=sitting]), action(dog_stands, any), action(dog_lies, any), action(dog_stands_between_pylons, any), action(dog_drinks_from_puddle, any)]).
exclusive(action(dog_sits, any), [action(dog_moves_to, any), action(handler_steps_with, [arg1=left, arg2=forward]), action(dog_turns, any), action(individual_brings_dog_to, any ), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any), action(dog_stands_up, any), action(dog_moves_paw, any), action(dog_resists, [arg1=sitting]), action(dog_stands, any), action(dog_lies, any), action(dog_stands_between_pylons, any), action(dog_drinks_from_puddle, any)]).

exclusive(action(dog_lies), [action(dog_moves_to, any), action(dog_turns, any), action(individual_brings_dog_to, any ), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any), action(dog_stands_up, any), action(dog_moves_paw, any), action(dog_stands, any), action(dog_sits, any), action(dog_stands_between_pylons, any), action(dog_drinks_from_puddle, any)]).
exclusive(action(dog_lies, any), [action(dog_moves_to, any), action(dog_turns, any), action(individual_brings_dog_to, any ), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any), action(dog_stands_up, any), action(dog_moves_paw, any), action(dog_stands, any), action(dog_sits, any), action(dog_stands_between_pylons, any), action(dog_drinks_from_puddle, any)]).

exclusive(action(dog_stands_up, any), all).

exclusive(action(dog_stands, any), [action(dog_moves_to, any), action(dog_turns, any), action(individual_brings_dog_to, any), action(goes_towards, [arg1=dog, arg2=any]), action(goes_to, [arg1=dog, arg2=any]), action(passes, [arg1=dog, arg2=any]), action(turns_around, [arg1=dog, arg2=any]), action(goes_towards_pylon, [arg1=dog, arg2=any]), action(goes_to_pylon, [arg1=dog, arg2=any]), action(passes_pylon, [arg1=dog, arg2=any]), action(turns_around_pylon, [arg1=dog, arg2=any]), action(dog_jumps_up_to, any), action(dog_pushes_over_handler, any), action(dog_follows, any), action(dog_enters_alley_between, any), action(dog_leaves_alley_between, any), action(pushes_over_pylon, [arg1=dog, arg2=any, arg3=paw]), action(dog_jumps_back, any), action(dog_bites_pylon, any), action(dog_sniffs, any), action(dog_sniffs_at_pylon, any), action(dog_stands_up, any), action(dog_moves_paw, any), action(dog_lies, any), action(dog_sits, any)]).

exclusive(action(dog_stiffens, any), all).

exclusive(action(dog_licks_nose, any), all).

exclusive(action(dog_licks, any), all).

exclusive(action(dog_sniffs, any), all).
exclusive(action(dog_sniffs_at_pylon, any), all).

exclusive(action(dog_searches, any), all).

exclusive(action(dog_jumps_up_to, any), all).

exclusive(action(dog_pushes_over_handler, any), all).

exclusive(action(dog_licks_handler_hand, any), all).

exclusive(action(dog_marks, any), all).

exclusive(action(dog_follows, any), all).

exclusive(action(dog_synchronises, any), all).

exclusive(action(dog_hesitates, any), all).

exclusive(action(dog_twitches_paw, any), all).

exclusive(action(dog_flicks_tongue, any), all).

exclusive(action(dog_sneezes, any), all).

exclusive(action(dog_yawns, any), all).

exclusive(action(dog_shakes_body, any), all).

exclusive(action(dog_scratches, any), all).

exclusive(action(dog_shivers, any), all).

exclusive(action(dog_coughs, any), all).

exclusive(action(dogs_eyes_covered, any), [action(handler_lets_dog_take_off, any)]).

exclusive(action(dog_resists, any), all).

exclusive(action(experimenter_puts_goody_under_pylon, any), all).

exclusive(action(pylon_is_replaced, any), all).

exclusive(action(pushes_over_pylon, any), all).

exclusive(action(dog_bites_pylon, any), all).

exclusive(action(position_from_alley, [arg1=handler, arg2=any]), [action(position_from_alley, [arg1=handler, arg2=any])]).

exclusive(action(position_from_alley, [arg1=experimenter, arg2=any]), [action(position_from_alley, [arg1=experimenter, arg2=any])]).

exclusive(action(position_from_alley, [arg1=dog, arg2=any]), [action(position_from_alley, [arg1=dog, arg2=any]), action(dog_leaves_alley_between, any), action(dog_enters_alley_between, any)]).

exclusive(action(dog_enters_alley_between, any), all).

exclusive(action(dog_leaves_alley_between, any), all).

exclusive(action(dog_stands_between_pylons, any), all).

exclusive(action(dog_through_alley, any), all).

exclusive(action(dog_tries_for_handler_goody, any), all).

exclusive(action(dog_eats, any), all).

exclusive(action(dog_takes, any), all).

exclusive(action(dog_digs, any), all).

exclusive(action(dog_makes_snap_at_hand, any), all).

exclusive(action(dog_jumps_back, any), all).

exclusive(action(dog_yelps, any), all).

exclusive(action(dog_bites_leash, any), all).

exclusive(action(dog_sees_goody, any), all).

exclusive(action(dog_spits_out_goody, any), all).

exclusive(action(dog_drinks_from_puddle, any), all).

exclusive(action(dog_tilts_pylon, any), all).

exclusive(action(dog_paw_turned_outwards, any), all).

exclusive(action(handler_unleashes_dog, any), all).

exclusive(action(handler_steps_over_dog, any), all).

exclusive(action(handler_steps_on_dog, any), all).

exclusive(action(handler_frees_dogs_leg_from_leash, any), all).

exclusive(action(handler_holds_dog_head_away_from_goody_pylon, any), all).

exclusive(action(handler_pushes_dog, any), all).

exclusive(action(dog_snaps, any), all).

exclusive(action(current_time, any), all).

