%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% exe.pl         6/25/2002 
%%
%% execute one action, this program calls library.pl
%% that use_module(library(lists)). 
%%
%% note that communication predicates are in comm.pl
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    

:- multifile exec/2. 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    
% Primitive Actions 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    

exec(_, create(X)) :-
    assert(dyn(X)). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    

exec(_, delete(X) ) :-
     retract(dyn(X)). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    
% x is the new value 
exec(_, update(X)) :-

    %% checking the correctness of the update action    
    X = instance_att(Instance, Att, _),

    dyn(instance_att(Instance, Att, _)), 
    retract(dyn(instance_att(Instance, Att, _))), 
    assert(dyn(X)). 

%%%%% check update actions 

exec(_, update(X)) :-

    %%% checking the correctness of the update action    
    ( \+ current_predicate(_, X) ;
      X = instance_of(Instance, _Entity) ; 
      X = instance_att(Instance, Att, _),
      \+ instance_att(Instance,  Att, _)
    ), 

    write('Error: the below update operation has been failed: '), 
    write(X),nl, 
    write('Analysis: the process has either tried to update an instance 
or an attribute that does not exist. To update an instance, one needs
to delete it and create it from scratch. To insert a new attribute,
use create/1 command.'), nl, fail. 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    

exec(_, cond_action(Cond, Actions)) :- 

     writeln('--- calling exec/2: cond_action'), 
     writeln(Cond), 
     writeln(Actions), 

     test_all_cond(Cond), 

     writeln('--- pass exec cond_action'),nl, 

     execute_actions(Actions). 

%%%%%%%%%%%%%%%%%%%

execute_actions([]). 
execute_actions([X|Actions]) :-

     writeln('--- calling execute_actions'), 
     writeln(X), 

     exec(none, X), 

     writeln('--- execution succeed '), 

     execute_actions(Actions). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    

exec(_, update_event_status(Instance, New_status)):-

    writeln('--- calling exec update_event_status '), 

        dyn(event_occ(Instance, Event, TStatus, Priority, 
                      Begin_time/End_time, 
                      (Provider/Provider_type, Receiver/Receiver_type), 
                       Event_content)), 

    TStatus = _/IDList, 

    Old = dyn(event_occ(Instance, Event, TStatus, Priority, 
                      Begin_time/End_time, 
                      (Provider/Provider_type, Receiver/Receiver_type), 
                       Event_content)), 

    New = dyn(event_occ(Instance, Event, New_status/IDList, 
                      Priority, Begin_time/End_time, 
                      (Provider/Provider_type, Receiver/Receiver_type), 
                       Event_content)), 

    writeln(Old), nl, writeln(New), 

    retract(Old), 
    assert(New). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

exec(_, report(Title, Content)) :-

   write('************** Report *************'), nl, 
   write(Title), nl, nl, 
   write(Content), nl, 
   write('********** End of Report **********'), nl, nl. 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Domain Actions 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% predicate not used !! 

exec(Instance/Process, 
     store_customer_requirements(Event_content)) :- 

     Event_content = event_occ(_, _, _, _, _, _, List), 
   
     setof(Req, 
        ( member(instance_of(Instance, customer_requirements, Req), List), 
          exec(Instance/Process, 
               create(instance_of(Instance, customer_requirements, Req)))
        ), _list ). 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% construct issue occ 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% note that when an issue is transmitted to another system,
% the time factor is determined external to the system, the 
% end_time of the process now becomes un-determined. 

exec(Instance/Process, construct_issue(Issue, _, Content)) :-

    writeln('--- calling exec/2: construct_issue' ), 
   
    dyn(agenda(process(Instance, Process/_PID, Status, Priority, 
               Begin_time/_, _Time_cost, 
               (Provider/Provider_type, Receiver/Receiver_type), 
                _P_Trigger, _Precond, _Action, _Postcond ))), 

     %%% get issue occ 

     issue_packet(_, Content), 

     Content = issue_occ(Instance, Issue, Status, 
                         Priority, Begin_time/_, 
                         (Provider/Provider_type, Receiver/Receiver_type), 
                         solution(Provider, _Requirements, 
                         _Old_solution, _new_sol, _diff ) ), 

   write('------- this is the issue content ----'),nl, 
   write(Content), nl. 


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
% This action fishes out the constraint and solve it. 
% If the constraint is true, return true; otherwise, falise. 
% The total cost should be already mapped when calling 
% calculating the total cost exec/2. 

%  check_cost_constraint(Solution, Requirements, Total, Result), 

exec(_Instance/_Process, 
     check_cost_constraint(Sol, Requirements, Total, Result)) :- 

    writeln('--- calling exec check_cost_constraint '),
    writeln(Sol), nl, 
    writeln(Requirements),
    writeln(Total),

    Sol = [static_constraint(_Typing, Conclusion )], 

     math_formula(Math), 
     member(Constraint, Math), 

     member(Constraint, Requirements), 
     
     member(total_cost(Total), Conclusion), 

     (    Constraint, Result = true; 
       \+ Constraint, Result = false), 

    writeln(Result). 


%%%%%%%%%%%%%%%%%

/*************************************************** 
  see library.pl 

less_than(A, B)     :- A < B.
equal(A, B)         :- A = B. 
greater_than(A, B)  :- A > B.
greater_equal(A, B) :- A >= B. 
less_equal(A, B)    :- A =< B. 

exec(_, calculate_total_cost(
     [allocate(process_x, _), allocate(io_x, _)], Total) ). 

******************************************************/ 

% Total_cost to start with is a variable, this action
% calculate the value of it. This action also allows
% the total cost to be unified with the constraint
% predicates, such as less_than/2. 

exec(_, calculate_total_cost(Sol, Total_cost ) ) :-

    
    writeln('--- calling exec calculate_total_cost '), 
    writeln(Sol), nl, 

    Sol = [static_constraint(Typing, Conclusion )], 
    member(total_cost(Total_cost), Conclusion), 

    find_all_cost(Typing, List), 
    sum_list(List, Total_cost), 

    writeln(List), writeln(Total_cost). 
    
%%%%%%%%%%%%%%%%%%%
% find_all_cost(+Listing, -Cost_list)
/**********
                    [ static_constraint(
                      [ instance_of(processor_x, processor),    
                        instance_of(disk_controller_x, disk_controller),
                        instance_of(io_x, io) ], 

                      [ allocate(processor_x,  Slot1),
                        allocate(disk_controller_x,  Slot2),
                        allocate(io_x,  Slot3), 
                        instance_of(Slot1, slot),
                        instance_of(Slot2, slot),
                        instance_of(Slot3, slot), 
                        total_cost(M) ]
                      )
                    ]
*************/


find_all_cost([], []). 

find_all_cost([X| Rest], [Cost|List]) :-
    X = instance_of(_, Board), 
    class_rel(is_a, Board, board),
    property(Board, cost, Cost),
    find_all_cost(Rest, List), !. 

find_all_cost([_| Rest], List) :-
    find_all_cost(Rest, List). 
                      

%%%%%%%%%%%%%%%%%%%%%%%   end of file %%%%%%%%%%%%%%%%%%%%    
    
