359 lines
7.9 KiB
Plaintext
359 lines
7.9 KiB
Plaintext
|
% ICD: it does not take into account missing values
|
||
|
%
|
||
|
% utility to translate from CSV style files to Prolog facts.
|
||
|
%
|
||
|
% assumes key is first argument.
|
||
|
%
|
||
|
% call as yap csv2pl -- prefix < Inp.csv > Out
|
||
|
%
|
||
|
% ICD: yap -l csv2pl_v3 -- --modes in.csv out
|
||
|
% alternatively you can call yap and invoke: main(['--modes','in.csv',out]).
|
||
|
% this will generate three files: out.facts, out.modes and out.txt
|
||
|
% out.facts contains all prolog facts for the csv table
|
||
|
% out.modes contains all modes to run with aleph (change as appropriate)
|
||
|
% out.txt contains basic data description (counters)
|
||
|
|
||
|
:- source.
|
||
|
|
||
|
:- style_check(all).
|
||
|
|
||
|
:- yap_flag(unknown, error).
|
||
|
|
||
|
:- yap_flag(write_strings, on).
|
||
|
|
||
|
:- use_module(library(readutil),
|
||
|
[read_line_to_codes/2]).
|
||
|
|
||
|
:- use_module(library(lineutils),
|
||
|
[split/3]).
|
||
|
|
||
|
:- use_module(library(system),
|
||
|
[mktime/2]).
|
||
|
|
||
|
:- ensure_loaded(order_by). % order predicate values
|
||
|
|
||
|
:- ensure_loaded(daynumber).
|
||
|
|
||
|
:- initialization(main).
|
||
|
|
||
|
:- dynamic output_modes/0.
|
||
|
|
||
|
main :-
|
||
|
unix(argv(Args)),
|
||
|
% write(Args),
|
||
|
main(Args).
|
||
|
|
||
|
main(['--modes'|R]) :- !,
|
||
|
assert(output_modes),
|
||
|
main(R).
|
||
|
%ICD: changed here to write in two different files
|
||
|
% also added counters
|
||
|
main([F,O]) :-
|
||
|
open(F, read, S),
|
||
|
atom_concat(O,'.modes',W1),
|
||
|
atom_concat(O,'.facts',W2),
|
||
|
open(W1, write, WModes),
|
||
|
open(W2, write, WFacts),
|
||
|
do(S, WModes, WFacts),
|
||
|
close(WModes), close(WFacts),
|
||
|
close(S),
|
||
|
write('WILL START COUNTING'), nl,
|
||
|
count(O).
|
||
|
/*
|
||
|
main([F]) :-
|
||
|
unix(argv([F])), !,
|
||
|
open(F, read, S),
|
||
|
W = user_output,
|
||
|
do(S, W),
|
||
|
close(S).
|
||
|
main([]) :-
|
||
|
S = user_input,
|
||
|
W = user_output,
|
||
|
do(S, W).
|
||
|
*/
|
||
|
do(S, WModes, WFacts) :-
|
||
|
get_titles(S, WModes, Titles),
|
||
|
get_lines(S, WFacts, Titles).
|
||
|
|
||
|
get_titles(S, W, Titles) :-
|
||
|
read_line_to_codes(S,Line),
|
||
|
split(Line, ",", OTitles),
|
||
|
list_of_titles(OTitles, Titles),
|
||
|
% format('~q~n~q~n',[OTitles,Titles]),
|
||
|
output_modes(Titles, W).
|
||
|
|
||
|
%ICD: changed here to use the Key name
|
||
|
%output_modes(_Key.Titles, W) :-
|
||
|
output_modes([Key|Titles], W) :-
|
||
|
format('~q~n',[[Key|Titles]]),
|
||
|
output_modes, !,
|
||
|
send_determinations(Titles, W),
|
||
|
% format(W, ':- modeh(*,upgrade(+key)).~n',[]),
|
||
|
format(W, ':- modeh(*,upgrade(+~q)).~n',[Key]),
|
||
|
% send_modes(Titles, W).
|
||
|
send_modes(Titles, Key, W).
|
||
|
|
||
|
send_determinations([], W) :-
|
||
|
nl(W).
|
||
|
send_determinations([T|Titles], W) :-
|
||
|
format(W, ':- determination(upgrade/1,~q/2).~n',[T]),
|
||
|
send_determinations(Titles, W).
|
||
|
|
||
|
%ICD: changed to use the key name
|
||
|
send_modes([], _, W) :-
|
||
|
nl(W).
|
||
|
send_modes([T|Titles], Key, W) :-
|
||
|
format(W, ':- modeb(*,~q(+~q,-~q)).~n',[T,Key,T]),
|
||
|
format(W, ':- modeb(*,~q(+~q,#~q)).~n',[T,Key,T]),
|
||
|
send_modes(Titles, Key, W).
|
||
|
|
||
|
list_of_titles([],[]).
|
||
|
list_of_titles([S|Ss], [A|As]) :-
|
||
|
% atom(A, S), % ICD: convert first letter to lowercase, remove plics
|
||
|
S = [H|T], char_type(LowH,to_lower(H)), atom_codes(A,[LowH|T]),
|
||
|
list_of_titles(Ss, As).
|
||
|
|
||
|
continue_list(Titles) -->
|
||
|
",", !,
|
||
|
list_of_titles(Titles).
|
||
|
continue_list([]) --> [].
|
||
|
|
||
|
|
||
|
get_lines(S, W, Titles) :-
|
||
|
read_line_to_codes(S, Line),
|
||
|
write(Line), nl, % ICD
|
||
|
add_line(Line, S, W, Titles).
|
||
|
|
||
|
add_line(end_of_file, _, _, _) :- !.
|
||
|
add_line(Line, S, W, Titles) :-
|
||
|
get_data(Titles, W, Line, []), !,
|
||
|
% write('Parsed correctly'), nl,
|
||
|
get_lines(S, W, Titles).
|
||
|
|
||
|
get_data([_|Titles], W, S1, S) :-
|
||
|
get_field(N, S1,S2),
|
||
|
% write(S1), nl, write(N), nl, write(S2), nl,
|
||
|
get_more_data(Titles, W, N, S2, S).
|
||
|
|
||
|
get_more_data([Field|L], W, Key, L, L) :- !,
|
||
|
add_as_empty([Field|L], W, Key).
|
||
|
get_more_data([Field|L], W, Key) -->
|
||
|
% {write([Field|L]), nl},
|
||
|
",", !,
|
||
|
get_field(N),
|
||
|
% { write(N), write('--'), nl },
|
||
|
{ output_field(W, Field, Key, N) },
|
||
|
get_more_data(L, W, Key).
|
||
|
get_more_data([], _, _) --> [].
|
||
|
|
||
|
get_field(N) -->
|
||
|
"\"", time(N), "\"", !.
|
||
|
get_field(N) -->
|
||
|
time(N), !.
|
||
|
get_field(N) -->
|
||
|
timeHours(N), !.
|
||
|
get_field(N) -->
|
||
|
atom(N), !.
|
||
|
get_field(N) -->
|
||
|
number(N), !.
|
||
|
get_field(?) -->
|
||
|
empty, !.
|
||
|
get_field(A) -->
|
||
|
any(S),
|
||
|
{atom_codes(A, S) }.
|
||
|
|
||
|
any([], [0',|L], [0',|L]) :- !.
|
||
|
any([], [], []) :- !.
|
||
|
any([C|Cs]) --> [C], any(Cs).
|
||
|
|
||
|
time(N) -->
|
||
|
natural(Year),
|
||
|
"-",
|
||
|
% "/",
|
||
|
month(Month),
|
||
|
"-",
|
||
|
% "/",
|
||
|
natural(Day),
|
||
|
{ %writeln(Day:Month:Year),
|
||
|
cvt_to_n(Day, Month, Year, N) }.
|
||
|
|
||
|
timeHours(H:M:S) -->
|
||
|
natural(H),
|
||
|
{format('~q~n',[H])},
|
||
|
":",
|
||
|
natural(M),
|
||
|
":",
|
||
|
natural(S).
|
||
|
|
||
|
cvt_to_n(D, M, Y0, N) :-
|
||
|
Y0 =< 10,
|
||
|
!,
|
||
|
Y is 2000+Y0,
|
||
|
days(Y,M,D,N).
|
||
|
cvt_to_n(D, M, Y0, N) :-
|
||
|
Y0 > 10,
|
||
|
Y0 < 100,
|
||
|
!,
|
||
|
Y is 1900+Y0,
|
||
|
days(Y,M,D,N).
|
||
|
cvt_to_n(D, M, Y, N) :-
|
||
|
days(Y,M,D,N).
|
||
|
|
||
|
number(N) -->
|
||
|
"-", !,
|
||
|
pos_number(N1),
|
||
|
{ N is -N1 }.
|
||
|
number(N) -->
|
||
|
"+", !,
|
||
|
pos_number(N1),
|
||
|
{ N is -N1 }.
|
||
|
number(N) -->
|
||
|
pos_number(N).
|
||
|
|
||
|
pos_number(N) -->
|
||
|
natural(L, L0),
|
||
|
do_float(L0),
|
||
|
{ number_codes(N,L) }.
|
||
|
|
||
|
do_float([0'e|L0]) -->
|
||
|
"e", !,
|
||
|
integer(L0, []).
|
||
|
do_float([0'E|L0]) -->
|
||
|
"E", !,
|
||
|
integer(L0, []).
|
||
|
do_float([0'.|L0]) -->
|
||
|
".", !,
|
||
|
natural(L0, []).
|
||
|
do_float([]) -->
|
||
|
[].
|
||
|
|
||
|
natural(N) -->
|
||
|
natural(L, []),
|
||
|
{ number_codes(N, L) }.
|
||
|
|
||
|
natural([C|L], L0) -->
|
||
|
[C],
|
||
|
{ C >= 0'0, C =< 0'9 }, !,
|
||
|
more_naturals(L, L0).
|
||
|
|
||
|
more_naturals([C|L], L0) -->
|
||
|
[C],
|
||
|
{ C >= 0'0, C =< 0'9 }, !,
|
||
|
more_naturals(L, L0).
|
||
|
more_naturals(L0, L0) --> [].
|
||
|
|
||
|
integer(L,L0) -->
|
||
|
"+", !,
|
||
|
natural(L, L0).
|
||
|
integer([0'-|L],L0) -->
|
||
|
"-", !,
|
||
|
natural(L, L0).
|
||
|
integer(L,L0) -->
|
||
|
natural(L, L0).
|
||
|
|
||
|
atom(T) -->
|
||
|
"\"",
|
||
|
quoted(Name),
|
||
|
{ atom_codes(T, Name) }.
|
||
|
|
||
|
quoted([0'"|Name]) --> "\"\"", !, %"
|
||
|
quoted(Name).
|
||
|
quoted([]) --> "\"", !.
|
||
|
quoted([C|Name]) --> [C],
|
||
|
quoted(Name).
|
||
|
|
||
|
empty([0',|L], [0',|L]).
|
||
|
empty([], []).
|
||
|
|
||
|
month(1) --> "Jan", !.
|
||
|
month(2) --> "Feb", !.
|
||
|
month(3) --> "Mar", !.
|
||
|
month(4) --> "Apr", !.
|
||
|
month(5) --> "May", !.
|
||
|
month(6) --> "Jun", !.
|
||
|
month(7) --> "Jul", !.
|
||
|
month(8) --> "Aug", !.
|
||
|
month(9) --> "Sep", !.
|
||
|
month(10) --> "Oct", !.
|
||
|
month(11) --> "Nov", !.
|
||
|
month(12) --> "Dec", !.
|
||
|
month(I) --> natural(I).
|
||
|
|
||
|
add_as_empty([], _, _).
|
||
|
add_as_empty([Field|L], W, Key) :-
|
||
|
output_field(W, Field, Key, ?),
|
||
|
add_as_empty(L, W, Key).
|
||
|
|
||
|
% ICD: changed
|
||
|
%output_field(_W, _Field, _Key, ?) :- !.
|
||
|
% format(W,'~q(~q,~q).~n',[Field,Key,N]).
|
||
|
%output_field(W, Field, Key, N) :-
|
||
|
% format(W,'~q(~q,~q).~n',[Field,Key,N]).
|
||
|
% ICD: included counters for Field/Value
|
||
|
output_field(W, Field, Key, ?) :- !,
|
||
|
format(W,'~q(~q,~q).~n',[Field,Key,?]),
|
||
|
counting(Field,missing).
|
||
|
/*
|
||
|
output_field(W, Field, Key, N) :-
|
||
|
not atom(N), !,
|
||
|
format(W,'~q(~q,~q).~n',[Field,Key,N]),
|
||
|
counting(Field,N).
|
||
|
output_field(W, Field, Key, N) :-
|
||
|
% convert first letter of predicate value N to lower case if it is uppercase
|
||
|
atom_chars(N,[Char|Chars]),
|
||
|
char_type(Char,upper),
|
||
|
atom_codes(Char,Code),
|
||
|
char_type(LowChar,to_lower(Code)), atom_chars(A,[LowChar|Chars]),
|
||
|
format(W,'~q(~q,~q).~n',[Field,Key,A]),
|
||
|
counting(Field,A), !.
|
||
|
*/
|
||
|
output_field(W, Field, Key, N) :-
|
||
|
format(W,'~q(~q,~q).~n',[Field,Key,N]),
|
||
|
counting(Field,N).
|
||
|
|
||
|
% ICD: include counters
|
||
|
counting(Field,Value) :-
|
||
|
retract(counter(Field,Value,C)),
|
||
|
C1 is C + 1,
|
||
|
assertz(counter(Field,Value,C1)), !.
|
||
|
counting(Field,Value) :-
|
||
|
assertz(counter(Field,Value,1)).
|
||
|
|
||
|
% when it ends
|
||
|
count(FileDescription) :-
|
||
|
write('WILL START COUNTING'), nl,
|
||
|
atom_concat(FileDescription,'.txt',File),
|
||
|
tell(File),
|
||
|
% listing(counter),
|
||
|
counter(Field,_Value,_C),
|
||
|
once(counter(Field,_Value,_C)),
|
||
|
% format('**** WILL WRITE ALL VALUES FOR FIELD: ~q~n',[Field]),
|
||
|
mydisplay(Field),
|
||
|
% format('**** WROTE ALL VALUES FOR FIELD: ~q~n',[Field]),
|
||
|
fail.
|
||
|
count(_) :- told.
|
||
|
|
||
|
/*
|
||
|
mydisplay(Field) :-
|
||
|
write(Field), nl,
|
||
|
counter(Field,Value,C),
|
||
|
tab(4),
|
||
|
format('~q: ~q~n',[Value,C]),
|
||
|
fail.
|
||
|
mydisplay(Field) :-
|
||
|
% format('**** REMOVING ALL FIELD: ~q~n',[Field]),
|
||
|
retractall(counter(Field,_,_)).
|
||
|
*/
|
||
|
% other solution
|
||
|
mydisplay(Field) :-
|
||
|
write(Field), nl,
|
||
|
order_by(counter/3, 2),
|
||
|
forall(counter(Field,Value,C),
|
||
|
(tab(4), format('~q: ~q~n',[Value,C]))
|
||
|
),
|
||
|
retractall(counter(Field,_,_)). %,
|
||
|
% format('REMOVED ALL FIELD: ~q~n',[Field]). %,
|
||
|
% listing(counter).
|
||
|
|
||
|
|