encounter_argumentation/
resolver.rs1use argumentation::aspic::{Literal, RuleId, StructuredSystem};
4use argumentation_schemes::CatalogRegistry;
5use argumentation_schemes::aspic::add_scheme_to_system;
6use argumentation_schemes::instance::SchemeInstance;
7use argumentation_schemes::types::SchemeStrength;
8
9#[derive(Debug, Clone, PartialEq)]
11pub enum ArgumentOutcome {
12 ProposerWins {
14 survival_rate: f64,
16 },
17 ResponderWins {
19 defeat_rate: f64,
21 },
22 Undecided,
24}
25
26fn lookup_strength(instance: &SchemeInstance, registry: &CatalogRegistry) -> SchemeStrength {
31 let key = instance.scheme_name.to_lowercase().replace(' ', "_");
32 registry
33 .by_key(&key)
34 .map(|s| s.metadata.strength)
35 .unwrap_or(SchemeStrength::Moderate)
36}
37
38fn strength_rank(strength: SchemeStrength) -> u8 {
40 crate::strength_rank(strength)
41}
42
43pub fn resolve_argument(
49 proposer_instances: &[SchemeInstance],
50 responder_instances: &[SchemeInstance],
51 registry: &CatalogRegistry,
52) -> ArgumentOutcome {
53 if proposer_instances.is_empty() {
54 return ArgumentOutcome::Undecided;
55 }
56
57 if responder_instances.is_empty() {
58 return ArgumentOutcome::ProposerWins { survival_rate: 1.0 };
59 }
60
61 let mut system = StructuredSystem::new();
62
63 let proposer_rules: Vec<(RuleId, SchemeStrength)> = proposer_instances
65 .iter()
66 .map(|inst| {
67 let rule_id = add_scheme_to_system(inst, &mut system);
68 let strength = lookup_strength(inst, registry);
69 (rule_id, strength)
70 })
71 .collect();
72
73 let responder_rules: Vec<(RuleId, SchemeStrength)> = responder_instances
75 .iter()
76 .map(|inst| {
77 let rule_id = add_scheme_to_system(inst, &mut system);
78 let strength = lookup_strength(inst, registry);
79 (rule_id, strength)
80 })
81 .collect();
82
83 for &(p_rule, p_strength) in &proposer_rules {
87 for &(r_rule, r_strength) in &responder_rules {
88 let p_rank = strength_rank(p_strength);
89 let r_rank = strength_rank(r_strength);
90 if p_rank > r_rank {
91 let _ = system.prefer_rule(p_rule, r_rule);
93 } else if r_rank > p_rank {
94 let _ = system.prefer_rule(r_rule, p_rule);
96 }
97 }
99 }
100
101 let built = match system.build_framework() {
103 Ok(b) => b,
104 Err(_) => return ArgumentOutcome::Undecided,
105 };
106
107 let extensions = match built.framework.preferred_extensions() {
108 Ok(exts) => exts,
109 Err(_) => return ArgumentOutcome::Undecided,
110 };
111
112 if extensions.is_empty() {
113 return ArgumentOutcome::Undecided;
114 }
115
116 let proposer_conclusions: Vec<Literal> = proposer_instances
118 .iter()
119 .map(|inst| inst.conclusion.clone())
120 .collect();
121
122 let total = proposer_conclusions.len();
125 let survived_count = proposer_conclusions
126 .iter()
127 .filter(|conclusion| {
128 extensions.iter().all(|ext| {
131 let ext_conclusions = built.conclusions_in(ext);
132 ext_conclusions.contains(conclusion)
133 })
134 })
135 .count();
136
137 let survival_rate = survived_count as f64 / total as f64;
138
139 if survival_rate > 0.5 {
140 ArgumentOutcome::ProposerWins { survival_rate }
141 } else if survival_rate == 0.0 {
142 let responder_conclusions: Vec<Literal> = responder_instances
144 .iter()
145 .map(|inst| inst.conclusion.clone())
146 .collect();
147 let responder_survived = responder_conclusions.iter().any(|conclusion| {
148 extensions.iter().all(|ext| {
149 let ext_conclusions = built.conclusions_in(ext);
150 ext_conclusions.contains(conclusion)
151 })
152 });
153 if responder_survived {
154 let defeat_rate = 1.0 - survival_rate;
155 ArgumentOutcome::ResponderWins { defeat_rate }
156 } else {
157 ArgumentOutcome::Undecided
158 }
159 } else {
160 ArgumentOutcome::Undecided
161 }
162}