encounter_argumentation/
value_argument.rs1use crate::resolver::ArgumentOutcome;
9use argumentation_schemes::CatalogRegistry;
10use encounter::value_argument::ValueArgumentResult;
11
12pub fn scheme_value_argument(
32 attacker: &str,
33 defender: &str,
34 value_at_stake: &str,
35 attacker_conviction: f64,
36 defender_conviction: f64,
37 defender_openness: f64,
38 registry: &CatalogRegistry,
39) -> ValueArgumentResult {
40 let attacker_wins_by_conviction = attacker_conviction >= defender_conviction;
41
42 let scheme_winner = registry.by_key("argument_from_values").and_then(|scheme| {
44 use argumentation::aspic::StructuredSystem;
45 use argumentation_schemes::aspic::add_scheme_to_system;
46
47 let attacker_bindings = [
48 ("action".into(), format!("uphold_{}", value_at_stake)),
49 ("value".into(), value_at_stake.into()),
50 ("agent".into(), attacker.into()),
51 ]
52 .into_iter()
53 .collect();
54
55 let attacker_instance = scheme.instantiate(&attacker_bindings).ok()?;
56
57 let mut system = StructuredSystem::new();
58 let attacker_rule = add_scheme_to_system(&attacker_instance, &mut system);
59
60 let counter_literal = attacker_instance.conclusion.contrary();
62 system.add_ordinary(counter_literal.clone());
63 let defender_rule = system.add_defeasible_rule(
64 vec![counter_literal],
65 attacker_instance.conclusion.contrary(),
66 );
67
68 if attacker_conviction > defender_conviction {
70 let _ = system.prefer_rule(attacker_rule, defender_rule);
71 } else if defender_conviction > attacker_conviction {
72 let _ = system.prefer_rule(defender_rule, attacker_rule);
73 }
74
75 let built = system.build_framework().ok()?;
76 let extensions = built.framework.preferred_extensions().ok()?;
77 if extensions.is_empty() {
78 return None;
79 }
80
81 let ext = &extensions[0];
82 let conclusions = built.conclusions_in(ext);
83 let attacker_survives = conclusions.contains(&attacker_instance.conclusion);
84
85 if attacker_survives {
86 Some(ArgumentOutcome::ProposerWins { survival_rate: 1.0 })
87 } else {
88 Some(ArgumentOutcome::ResponderWins { defeat_rate: 1.0 })
89 }
90 });
91
92 let attacker_wins = match scheme_winner {
94 Some(ArgumentOutcome::ProposerWins { .. }) => true,
95 Some(ArgumentOutcome::ResponderWins { .. }) => false,
96 _ => attacker_wins_by_conviction,
97 };
98
99 let (winner, loser) = if attacker_wins {
100 (attacker.to_string(), defender.to_string())
101 } else {
102 (defender.to_string(), attacker.to_string())
103 };
104
105 let conviction_gap = (attacker_conviction - defender_conviction).abs();
106 let loser_value_shift = (conviction_gap * defender_openness).clamp(0.0, 1.0);
107 let winner_value_shift = (conviction_gap * 0.1).clamp(0.0, 0.1);
108
109 ValueArgumentResult {
110 winner,
111 loser,
112 value_at_stake: value_at_stake.into(),
113 loser_value_shift,
114 winner_value_shift,
115 }
116}