1:- module(ap_simulation, [next_day/3, timeline/4]).    2
    3:- use_module(library(random)).    4:- use_module(ap_validation).    5:- use_module(ap_model).    6
    7next_day(Input, Next, Event) :-
    8    ap_validation:normalized_scenario(Input, S),
    9    Seed0 is S.seed + S.duration_days*7919,
   10    set_random(seed(Seed0)),
   11    random_between(-5, 8, OnlineJ),
   12    random_between(-4, 7, MediaJ),
   13    random_between(-3, 5, CoalitionJ),
   14    random_between(-2, 5, SupportJ),
   15    decay_incident(S.incident_shock, Incident1),
   16    adjust(S.online, OnlineJ, Online1),
   17    adjust(S.media_attention, MediaJ, Media1),
   18    adjust(S.coalition, CoalitionJ, Coalition1),
   19    adjust(S.public_support, SupportJ, Support1),
   20    D1 is S.duration_days + 1,
   21    Seed1 is S.seed + 1,
   22    put_dict(_{online:Online1, media_attention:Media1,
   23               coalition:Coalition1, public_support:Support1,
   24               incident_shock:Incident1, duration_days:D1, seed:Seed1}, S, Next0),
   25    policy_dynamics(Next0, Next),
   26    ap_model:score(Next, R),
   27    event_text(R, Event).
   28
   29adjust(Base, Delta, Value) :-
   30    Raw is Base + Delta,
   31    ap_validation:clamp(0, 100, Raw, Value).
   32
   33decay_incident(X, Y) :- Y0 is X*0.82, ap_validation:clamp(0, 100, Y0, Y).
   34
   35policy_dynamics(S0, S) :-
   36    Resp = S0.govt_responsiveness,
   37    Comm = S0.govt_communication,
   38    ( Resp >= 70 ->
   39        G0 is S0.grievance - 5, T0 is S0.trigger - 4,
   40        adjust(G0, 0, G), adjust(T0, 0, T),
   41        put_dict(_{grievance:G, trigger:T}, S0, S)
   42    ; Comm < 30, Resp < 30 ->
   43        G0 is S0.grievance + 3, adjust(G0, 0, G),
   44        put_dict(grievance, S0, G, S)
   45    ; S = S0
   46    ).
   47
   48event_text(R, Text) :-
   49    format(string(Text),
   50           'Hari berikutnya: likelihood ~w/100, spread ~w/100, escalation ~w/100, state ~w.',
   51           [R.likelihood, R.spread, R.escalation, R.predicted_state]).
   52
   53timeline(S, 0, [R], []) :- !, ap_model:score(S, R).
   54timeline(S, Days, [R|Rs], [Event|Events]) :-
   55    Days > 0,
   56    ap_model:score(S, R),
   57    next_day(S, N, Event),
   58    D1 is Days-1,
   59    timeline(N, D1, Rs, Events)