
% supplied routines
% -----------------

% get data from user for two rectangles, see if they overlap
chkOvr :- getR(First), getR(Second), overlap(First, Second).

% get data from user for two rectangles, see if they are separate
chkSep :- getR(First), getR(Second), separate(First, Second).

% get data from user for one rectangle, check if valid
getR(Rt) :-
    write("please enter the left, right, top, then bottom rectangle positions, "),
    write("e.g. 1. 3. 5. 2."), nl,
    read(L), read(R), read(T), read(B), !, rectangle(L,R,T,B), Rt = rectangle(L,R,T,B).


% basic rectangle error checking
% ------------------------------
% base case: everything passes
rectangle(L,R,T,B) :- number(R), number(L), number(T), number(B), R > L, B < T.
% error case 1: one or more fields are wrong, find the first one
rectangle(A,B,C,D) :- getFailType(A,B,C,D), fail.

% identify which field is in error and what is wrong with it
getFailType(A,_,_,_) :- not(number(A)), format("Invalid rectangle: ~w is not a number~n", [A]).
getFailType(_,B,_,_) :- not(number(B)), format("Invalid rectangle: ~w is not a number~n", [B]).
getFailType(_,_,C,_) :- not(number(C)), format("Invalid rectangle: ~w is not a number~n", [C]).
getFailType(_,_,_,D) :- not(number(D)), format("Invalid rectangle: ~w is not a number~n", [D]).
getFailType(A,B,_,_) :- number(A), number(B), A>B, format("Invalid rectangle: left > right~n").
getFailType(_,_,C,D) :- number(C), number(D), C<D, format("Invalid rectangle: bottom > top~n").

% shorthand validity test
valid(Rect) :- Rect = rectangle(L,R,T,B), rectangle(L,R,T,B).


% separate(R1,R2)
% ---------------

% rules for valid, separate rectangles
separate(R1, R2) :- valid(R1), valid(R2), R1=rectangle(L,_,_,_), R2=rectangle(_,R,_,_), R < L.
separate(R1, R2) :- valid(R1), valid(R2), R1=rectangle(_,R,_,_), R2=rectangle(L,_,_,_), R < L.
separate(R1, R2) :- valid(R1), valid(R2), R1=rectangle(_,_,T,_), R2=rectangle(_,_,_,B), T < B.
separate(R1, R2) :- valid(R1), valid(R2), R1=rectangle(_,_,_,B), R2=rectangle(_,_,T,_), T < B.


% overlap(R1,R2)
% --------------

% they overlap if they are valid rectangles and are not separate
overlap(Rect1, Rect2) :- valid(Rect1), valid(Rect2), not(separate(Rect1, Rect2)).

