95 lines
3.4 KiB
Prolog
95 lines
3.4 KiB
Prolog
% Write out the calender, because format can actually span multiple lines, it is easier
|
|
% to write out the static parts in place and insert the generated parts into that format.
|
|
write_calendar(Year) :-
|
|
month_x3_format(Year, 1, 2, 3, F1_3),
|
|
month_x3_format(Year, 4, 5, 6, F4_6),
|
|
month_x3_format(Year, 7, 8, 9, F7_9),
|
|
month_x3_format(Year, 10, 11, 12, F10_12),
|
|
|
|
format('
|
|
|
|
~w
|
|
|
|
January February March
|
|
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
|
|
~w
|
|
|
|
April May June
|
|
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
|
|
~w
|
|
|
|
July August September
|
|
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
|
|
~w
|
|
|
|
October November December
|
|
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
|
|
~w
|
|
', [Year, F1_3, F4_6, F7_9, F10_12]), !.
|
|
|
|
% Generate the data for a row of months and then create an atom one row at a time
|
|
% for all of the months.
|
|
month_x3_format(Year, M1, M2, M3, F) :-
|
|
calc_month_rows(Year, M1, M1r),
|
|
calc_month_rows(Year, M2, M2r),
|
|
calc_month_rows(Year, M3, M3r),
|
|
month_x3_format(M1r, M2r, M3r, F).
|
|
|
|
month_x3_format(M1, M2, M3, '') :- maplist(=(' '), M1), maplist(=(' '), M2), maplist(=(' '), M3).
|
|
month_x3_format(M1, M2, M3, F) :-
|
|
month_format(' ', M1, M1r, F1),
|
|
month_format(F1, M2, M2r, F2),
|
|
month_format(F2, M3, M3r, F3),
|
|
atom_concat(F3, '\n', F4),
|
|
month_x3_format(M1r, M2r, M3r, Fr),
|
|
atom_concat(F4, Fr, F).
|
|
|
|
month_format(Orig, [Su,Mo,Tu,We,Th,Fr,Sa|R], R, F) :-
|
|
maplist(day_format, [Su,Mo,Tu,We,Th,Fr,Sa], Formatted),
|
|
format(atom(F2), '~w~w~w~w~w~w~w ', Formatted),
|
|
atom_concat(Orig, F2, F).
|
|
|
|
day_format(' ', ' ') :- !.
|
|
day_format(D, F) :- D < 10, format(atom(F), '~w ', D).
|
|
day_format(D, F) :- D >= 10, format(atom(F), '~w ', D).
|
|
|
|
% Calculate the days of a month, this is done by getting the first day of the month,
|
|
% then offsetting that with spaces from the start and then adding 1-NumDaysinMonth and
|
|
% finally spaces until the end. The maximum possible size is used and then truncated later.
|
|
calc_month_rows(Year, Month, Result) :-
|
|
length(Result, 42), % max 6 rows of 7 days
|
|
month_days(Month, Year, DaysInMonth),
|
|
day_of_the_week(date(Year, Month, 1), FirstWeekDay),
|
|
day_offset(FirstWeekDay, Offset),
|
|
day_print_map(DaysInMonth, Offset, Result).
|
|
|
|
day_print_map(DaysInMonth, 0, [1|R]) :-
|
|
day_print_map2(DaysInMonth, 2, R).
|
|
day_print_map(DaysInMonth, Offset, [' '|R]) :-
|
|
dif(Offset, 0),
|
|
succ(NewOffset, Offset),
|
|
day_print_map(DaysInMonth, NewOffset, R).
|
|
|
|
day_print_map2(D, D, [D|R]) :- day_print_map(R).
|
|
day_print_map2(D, N, [N|R]) :- dif(D,N), succ(N, N1), day_print_map2(D, N1, R).
|
|
|
|
day_print_map([]).
|
|
day_print_map([' '|R]) :- day_print_map(R).
|
|
|
|
% Figure out the number of days in a month based on whether it is a leap year or not.
|
|
month_days(2, Year, Days) :-
|
|
is_leap_year(Year) -> Days = 29
|
|
; Days = 28.
|
|
month_days(Month, _, Days) :-
|
|
dif(Month, 2),
|
|
nth1(Month, [31, _, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], Days).
|
|
|
|
% Figure out the space offset based on the day the month starts on.
|
|
day_offset(D, D) :- dif(D, 7).
|
|
day_offset(7, 0).
|
|
|
|
% Test for leap years
|
|
is_leap_year(Year) :-
|
|
0 is Year mod 100 -> 0 is Year mod 400
|
|
; 0 is Year mod 4.
|