1:- module(ap_report, [print_report/1, print_comparison/1, bar/2]).    2
    3:- use_module(library(lists)).    4:- use_module(library(apply)).    5
    6print_report(R) :-
    7    S = R.scenario,
    8    format('~n============================================================~n', []),
    9    format(' ANTISIPASI PEJABAT - HASIL SIMULASI~n', []),
   10    format('============================================================~n', []),
   11    format('Skenario       : ~w~n', [S.name]),
   12    format('Wilayah        : ~w / ~w (~w)~n', [S.province, S.city, S.scope]),
   13    format('Isu            : ~w - ~w~n', [S.issue, S.subissue]),
   14    format('Target tuntutan: ~w~n~n', [S.target]),
   15    metric('Kemungkinan aksi', R.likelihood, R.likelihood_band),
   16    metric('Penyebaran', R.spread, R.spread_band),
   17    metric('Eskalasi', R.escalation, R.escalation_band),
   18    metric('Tekanan kebijakan', R.political_pressure, '-'),
   19    metric('Kelanjutan aksi', R.continuation, '-'),
   20    metric('Confidence model', R.confidence, 'maks 68 pada model heuristik'),
   21    format('~nState            : ~w~n', [R.predicted_state]),
   22    format('Skala            : ~w~n', [R.predicted_scale]),
   23    format('Turnout bucket   : ~w~n', [R.crowd_bucket]),
   24    format('Policy outlook   : ~w~n', [R.policy_outlook]),
   25    format('Status model     : ~w~n', [R.model_status]),
   26    format('~nFaktor pendorong utama:~n', []),
   27    forall(member(F, R.top_factors),
   28           format('  + ~w: ~1f poin (~w)~n', [F.label, F.contribution, F.field])),
   29    format('~nFaktor mitigasi yang dimodelkan:~n', []),
   30    forall(member(FP, R.protective_factors),
   31           format('  - ~w: nilai ~w, efek -~1f~n', [FP.label, FP.value, FP.effect])),
   32    format('~nCatatan hukum:~n  ~w~n', [R.legal_note]),
   33    format('~nPENTING: skor adalah estimasi heuristik, bukan fakta atau probabilitas empiris.~n', []),
   34    format('Tool tidak boleh dipakai untuk menarget individu, membatasi hak sipil, atau merancang represi.~n', []).
   35
   36metric(Label, Value, Band) :-
   37    bar(Value, B),
   38    format('~w: ~w/100  ~w  (~w)~n', [Label, Value, B, Band]).
   39
   40bar(Value, Bar) :-
   41    Filled is round(Value/5), Empty is 20-Filled,
   42    length(Fs, Filled), maplist(=('█'), Fs), atomic_list_concat(Fs, '', A),
   43    length(Es, Empty), maplist(=('░'), Es), atomic_list_concat(Es, '', B),
   44    atom_concat(A, B, Bar).
   45
   46print_comparison(Results) :-
   47    format('~nPERBANDINGAN RESPONS KEBIJAKAN (analisis, bukan rekomendasi penindakan)~n', []),
   48    format('------------------------------------------------------------------~n', []),
   49    forall(member(X, Results),
   50           format('~w~n  likelihood=~w spread=~w escalation=~w pressure=~w~n',
   51                  [X.variant, X.report.likelihood, X.report.spread,
   52                   X.report.escalation, X.report.political_pressure]))