% --------------------------------------------------------------------------
%   FILE:       PAT.PL
%   AUTHOR:     Tim Duncan
%   UPDATED:    Tue Jul 21 17:13:00 BST 1987
%   PURPOSE:    Proposed treatment tree for ATTENDING.
% --------------------------------------------------------------------------


:- op(100,fx,*).
:- op(100,xfy,:).



/* Present the anaesthetics available and construct a proposed
approach tree (PAT). The predicate is called recursively for
sub-decisions. Thus it is called initially with the root node
of the anaesthetic hierarchy (ANES).
*/                    


get_plan(Node,Plan) :-
     node(Node,Arcs),
     decide(Node,Arcs,Arc),     % decide among the options
     expand(Arc,Plan).          % and move to the next node
get_plan(Node,[]) :-
     not(node(Node,_)).         % terminal node



/* Having obtained a choice, expand that arc by exploring any
subdecisions, then further decisions at the same level
(eg:  intubation then induction). The PAT is built as the
recursion is returned from.
*/

expand(arc(pop,t,t),[]).
expand(arc(Arc,To,Action),[[Arc|ArcPlan]|Continuation]) :-
     get_plan(Arc,ArcPlan),     % get subplan
     get_plan(To,Continuation). % then continue



/* Decide amongst the arcs leaving a node. If there is only one
arc, then there's no decision!  Otherwise generate a menu dynamically.
*/

decide(Node,[Arc],Arc) :- !.
decide(Node,Arclist,Arc) :- choice(Node,Arc), !.    % from test data
decide(Node,Arclist,Arc) :-
    make_menu(Arclist,Menu,Returns),
    ( Menu = [_,_|_], !,                    % at least two choices
      describe(question,[Node],Header),
      choose([Arc],Header,Menu,Returns)
    ; Returns = [Arc|_],
      Arc = arc(_,_,Id),
      describe(_,Id,Choice),
      runoff([*nl,'**',*cap|Choice]),
      runoff([assumed,*nl]) ), !.






/* Turn an arc list into a list of options for the menu */

make_menu([],[],[]).
make_menu([arc(Arc,To,Ref)|Arclist],Others,Arcs) :-
    recorded(block,blocked(Ref),_), !,      % exclude blocked arcs
    make_menu(Arclist,Others,Arcs).
make_menu([arc(Arc,To,Ref)|Arclist],[[Desc]|Rest],[arc(Arc,To,Ref)|Arcs]) :-
    describe(menu_item,[Ref],Desc), !,
    make_menu(Arclist,Rest,Arcs).




/* plan_summary(PAT,Runoff)
Produce a summary of proposed plan, to runoff.
*/

plan_summary([[ga,Intub,Maint,Induct],Premed],Runoff) :-
    plan_summary(Intub,INT),
    plan_summary(Induct,ID),
    plan_summary(Maint,M),
    plan_summary(Premed,PM),
    Summary =
         [[1,*period,general,*nl],
         [2,*period,premedication,:,PM,*nl],
         [3,*period,induction,:,ID,*nl],
         [4,*period,intubation,:,INT,*nl],
         [5,*period,maintenance,:,M,*nl]],
    flatten(Summary,Runoff), !.
plan_summary([[regional,REG],Premed],Runoff) :-
    plan_summary(REG,R),
    plan_summary(Premed,PM),
    Summary =
        [[1,*period,regional,:,R,*nl],
        [2,*period,premedication,:,PM,*nl]],
    flatten(Summary,Runoff), !.
plan_summary([Node,Decision|More],[*allcaps,Node,D|M]) :-
    member(Node,[epidural,spinal,nb,rapidseq,maskcricoid,conventional,awake]),
    !,                                              % special cases
    plan_summary(Decision,D),
    and_the_rest(More,M).
plan_summary([Node,Decision|More],[D|M]) :- !,      % general simplification
    plan_summary(Decision,D),
    and_the_rest(More,M).
plan_summary([Tech],[*allcaps,Tech]) :- !.
plan_summary([],[]) :- !.


and_the_rest([],[]).
and_the_rest([Tech|Others],[*comma,T|O]) :-
    plan_summary(Tech,T), !,
    and_the_rest(Others,O).
