/* Subject 0440949. AI department, UvA. Assignment 4, knowledge systems: CSI
 * Andreas van Cranenburgh. 
 *
 * Project history:
 * csi-1.pl started: Fri Nov  4 14:39:29 CET 2005.
 * -- enormous procastrination/postponement
 * csi-2.pl started: Fri Nov  15, somewhere 06:00:00 CET 2005.
 * -- manic brainstorming; mindmaps --
 * csi-3.pl started: Thu Nov 17 16:48:45 CET 2005
 * -- coding. alas, more debugging!
 
 *	1. time and place, actors, actions and objects
 * time is a point. an interval is two points. time is stored in microSec, or in any case sth very big.
 *
 */

%Convertors:
% Seconds to BigTime
timeformat( [ _Day,_Hour,_Min, Sec, BigTime ] ) :- var(BigTime),
	BigTime is Sec * 1000000.
	
/* as you may see here, there is a list with Day, Hour, Min and Sec. 
  This is the standard time object in this project. Another standard one is
  BigTime */
  
% BigTime back to Seconds
timeformat( [ _Day, _Hour, _Min, Sec, BigTime ] ) :- var(Sec),
	Sec is BigTime / 1000000.
	
 /* qualitative is mapped onto quantitative data, using conversion: */

% generate an appropriate seconds value:
quantime(Quant, BigTime) :-
	(
		parse_abs_quant(Quant, Sec)
		;
		parse_rel_quant(Quant, Sec)
	),
	timeformat( [ _D, _H, _M, Sec], BigTime).
	
% eg. 29 Oktober 00.45 uur
parse_abs_quant( [ DayOfMonth, Month, Time, Unit], ResultSec ], Sec) :-
	parse_time( Time, [ _Day, Hour, Minute, Sec ] ),
	%re-use "words" kb.
	words(Unit, 3600)
	(
		match_month(Month, MontNo)
		;
		( Month >= 1, Month is =< 12, MonthNo = Month )
	),

parse_abs_quant( [ DayOfMonth, Month, Time], ResultSec ], Sec) :-
	parse_abs_quant( [ DayOfMonth, Month, Time, 'uur'], ResultSec ], Sec).

%the months, in dutch. gosh, why am I doing this??
match_month(januarie, 1).
match_month(februarie, 2).
match_month(maart, 3).
match_month(mei, 5).
match_month(juni, 6).
match_month(juli, 7).
match_month(augustus, 8).

%both
match_month(april, 4).
match_month(september, 9).
match_month(oktober, 10).
match_month(november, 11).
match_month(december, 12).

%english
match_month(january, 1).
match_month(february, 2).
match_month(march, 3).
match_month(may, 5).
match_month(june, 7).
match_month(july, 8).
match_month(august, 9).
match_month(october, 10).

% first argument is word, second is conversion factor to seconds.
words(minute, 60).
words(minuten, 60).
words(minutes, 60).
words(min, 60).
words(m, 60).
words(uur, 3600).
%words(hour, 3600).
%words(hr, 3600).
%words(h, 3600).

%screw this (FIXME, std lib! or state automata):
parse_time(TimeStr, TimeObj) :- 
	%convert TimeStr to list??
	(
		%Define seperators:
		Sep = '.' ; Sep = ':'
	)
	( 
		TimeStr = [ Hour, Sep, Minute, _Unit ]
		;
		TimeStr = [ Hour, Sep, Minute ]
	),
	TimeObj = [ _Day, Hour, Sep, Minute, _Sec ].
	
%parse_rel_quant( [ DayOfMonth, MonthStr, DotTime ], ResultSec ) :-
% ...?	
	

qualtime(Quant, BigTime) :-
	approxquant(Quant, Sec),
	timeformat( [ _D, _H, _M, Sec ] , BigTime).

approxquant(Quant, Sec),
	str2list(Quant, List),
	(
		words(Word, Factor)
		member(Word, List),
		%N = [the word before that word]
		N = 0,
		Sec is N * Factor
	).
		


%qualquant(Qual, Quant) :- var(Quant),
% let's forget this for now..


/*
 * absolute gets converted to relative, or the other way around, whatever is better in code. original value is preserved, since consistency check is forced after EVERY addition. */

 /* Data representation
  *
  * 	Timeline
  * A branchable timeline is an instance of a linked list that can have an arbitrary number of links on each node, both has head and tail. As far as I know it's better not to express it as a tree, since then you end up storing the end twice and usually the crime itself is pretty sure (eg. dead body).
  *
  *	Objects (in OO sense):
  * all objects have one name/id, and a list of aliases (maybe empty). Also, a
  * list of relations (either to annother object's name or alias). Objects are:
  * - proper objects (so literally objects, no CS-speak). No extra properties etc.
  * - actors: objects that have a role, listed with (some of) their respective
  *   actions:
  *     - the accused [or criminal, I'd rather not make the distinction here!]
  *		killing, lying, possesing, etc.
  *	- victim
  *		dying, getting_hurt, etc.
  *	- witness
  *	 	lying, fact-reporting, opinion-speaking
  *	- none (anyone else)
  * - relation: any id to any other id. this relationship is an equivalence
  * relation, eg. it's symmetric. But for clarity facts are written with the
  * earlier event first, if there's any difference at all. For objects order
  * doesn't matter in the relationship.
  *
  * 	Trust:
  * The so called "certainty" attribute is actually better called "trust" (more
  * general), so that it applies to anything.
  *
  * This specific model is loosely inspired by GPG's ownertrust. */
 
 2 weights as much as 1, only in the reasoning it won't be considered that it might be false.
*/

event-time(melding1, [28, oktober, om, '21.30']).
event-whowhatwhere(melding1, ellieb, pistoolscot, alkmaar(elandstraat(12)), witness)
alias(melding1, 'De eerste melding').
trust(melding1, 3).
relation(melding1, evidence, moord1).
relation(melding1, similar, melding2).
%eg: relation(melding1, opposes, something).  ?


%etc:.....
event(melding1, [28, oktober, om, '21.30']).
whowhatwhere(ellieb, pistoolscot alkmaar(elandstraat(12)), witness)
alias(melding1, 'De eerste melding').
trust(melding1, 3).

event(melding1, [28, oktober, om, '21.30']).
whowhatwhere(ellieb, pistoolscot alkmaar(elandstraat(12)), witness)
alias(melding1, 'De eerste melding').
trust(melding1, 3).

 % in practice. do case.
 % Let python filter do that?

 /* Interface, timeline:
  * - printf the list, one event per line.
  * - branches: interactively ask which branches to act upon!
  * - [but: visually show branches, eg. by indenting.] */

#we're good to go!
go :-
	writeln("This is uCSI with hacky prolog CLI interface; so end input with a dot, even when you\'re only expected to enter a single letter").
	writeln("(web interface maybe soon to solve this??)"), nl,
	loop.

loop :- 
	write("Main: a. = Evidence-based tasks | b. = Events based task."),
	write(| c. = Close  | e. = Exit  | q. = Quit "),
	nl, input(Letter),
	(
		( Letter = 'a', evidence_tasks )
		;
		( Letter = 'b', events_tasks )
		;
		(
			( Letter = 'c' ; Letter = 'e' ; Letter = 'q' ), true
		)
		;
		loop
		)
	).
%probably reduntant parentheses etc. (we're not getting to LISP levels yet!)

evidence_tasks :-
	write("Evidence menu: a. = Add  | c. = Conflicts.  | i. = Inspect all evidence"),
	write(" | l. = leave menu / go back"), nl,
	input(Letter),
	(
		( Letter = 'a', add_event )
		;
		( Letter = 'c, list_conflicts )
		;
		( Letter = 'i', inspect_evidence )
		;
		( Letter = 'l', true )
		;
		evidence_tasks
	).

events_tasks :-
	writeln("Events menu: e. = list Evidence for an event | t. = Travers the Timeline"),
	input(Letter),
	(
		( Letter = 'e', evidence_tasks )
		;
		( Letter = 'e', events_tasks )
		;
		( Letter = 'l', true )
		;
		evidence_tasks.
	).

ask_trust (Number):-
	writeln("How much do you trust this assertion about X:"),
	writeln("-1: I do not trust it"),
	writeln(" 0: I will not answer"),
	writeln(" 1: I have done careful checking (beyond reasonable doubt)"),
	writeln(" 2: I trust it ultimately (scientific)"),
	write("[0]: "), input(Number),
	(
		( 
			nonvar(Number),
			Number is >= -1, Number is =< 2
		)
		;
		ask_trust(Number)
	).

