1use serde::Serialize;
2
3use crate::Glyph;
4
5#[derive(Debug, Serialize)]
6pub struct Problem {
8 pub master_1_name: String,
10 pub master_2_name: String,
12 pub master_1_index: usize,
14 pub master_2_index: usize,
16 #[serde(flatten)]
18 pub details: ProblemDetails,
19 pub tolerance: Option<f64>,
21 pub contour: Option<usize>,
23 pub node: Option<usize>,
25}
26
27#[derive(Debug, Serialize)]
28#[serde(tag = "type")]
29pub enum ProblemDetails {
31 PathCount {
33 count_1: usize,
35 count_2: usize,
37 },
38 NodeCount {
40 count_1: usize,
42 count_2: usize,
44 },
45 NodeIncompatibility {
47 is_control_1: bool,
49 is_control_2: bool,
51 },
52 ContourOrder {
54 order_1: Vec<usize>,
56 order_2: Vec<usize>,
58 },
59 WrongStartPoint {
61 proposed_point: usize,
63 reverse: bool,
65 },
66 Overweight {
68 value_1: f64,
70 value_2: f64,
72 },
73 Underweight {
75 value_1: f64,
77 value_2: f64,
79 },
80 Kink,
82}
83
84impl Problem {
85 pub(crate) fn path_count(g1: &Glyph, g2: &Glyph, count_1: usize, count_2: usize) -> Problem {
86 Problem {
87 master_1_name: g1.master_name.to_string(),
88 master_2_name: g2.master_name.to_string(),
89 master_1_index: g1.master_index,
90 master_2_index: g2.master_index,
91 tolerance: None,
92 contour: None,
93 node: None,
94 details: ProblemDetails::PathCount { count_1, count_2 },
95 }
96 }
97
98 pub(crate) fn node_count(
99 g1: &Glyph,
100 g2: &Glyph,
101 path_index: usize,
102 count_1: usize,
103 count_2: usize,
104 ) -> Problem {
105 Problem {
106 master_1_name: g1.master_name.to_string(),
107 master_2_name: g2.master_name.to_string(),
108 master_1_index: g1.master_index,
109 master_2_index: g2.master_index,
110 tolerance: None,
111 contour: Some(path_index),
112 node: None,
113 details: ProblemDetails::NodeCount { count_1, count_2 },
114 }
115 }
116
117 pub(crate) fn node_incompatibility(
118 g1: &Glyph,
119 g2: &Glyph,
120 contour: usize,
121 node: usize,
122 is_control_1: bool,
123 is_control_2: bool,
124 ) -> Problem {
125 Problem {
126 master_1_name: g1.master_name.to_string(),
127 master_2_name: g2.master_name.to_string(),
128 master_1_index: g1.master_index,
129 master_2_index: g2.master_index,
130 contour: Some(contour),
131 node: Some(node),
132 tolerance: None,
133 details: ProblemDetails::NodeIncompatibility {
134 is_control_1,
135 is_control_2,
136 },
137 }
138 }
139
140 pub(crate) fn contour_order(
141 g1: &Glyph,
142 g2: &Glyph,
143 tolerance: f64,
144 order_1: Vec<usize>,
145 order_2: Vec<usize>,
146 ) -> Problem {
147 Problem {
148 master_1_name: g1.master_name.to_string(),
149 master_2_name: g2.master_name.to_string(),
150 master_1_index: g1.master_index,
151 master_2_index: g2.master_index,
152 tolerance: Some(tolerance),
153 contour: None,
154 node: None,
155 details: ProblemDetails::ContourOrder { order_1, order_2 },
156 }
157 }
158
159 pub(crate) fn wrong_start_point(
160 g1: &Glyph,
161 g2: &Glyph,
162 tolerance: f64,
163 contour: usize,
164 proposed_point: usize,
165 reverse: bool,
166 ) -> Problem {
167 Problem {
168 master_1_name: g1.master_name.to_string(),
169 master_2_name: g2.master_name.to_string(),
170 master_1_index: g1.master_index,
171 master_2_index: g2.master_index,
172 tolerance: Some(tolerance),
173 contour: Some(contour),
174 node: None,
175 details: ProblemDetails::WrongStartPoint {
176 proposed_point,
177 reverse,
178 },
179 }
180 }
181
182 pub(crate) fn overweight(
183 g1: &Glyph,
184 g2: &Glyph,
185 contour: usize,
186 tolerance: f64,
187 value_1: f64,
188 value_2: f64,
189 ) -> Problem {
190 Problem {
191 master_1_name: g1.master_name.to_string(),
192 master_2_name: g2.master_name.to_string(),
193 master_1_index: g1.master_index,
194 master_2_index: g2.master_index,
195 contour: Some(contour),
196 tolerance: Some(tolerance),
197 node: None,
198 details: ProblemDetails::Overweight { value_1, value_2 },
199 }
200 }
201
202 pub(crate) fn underweight(
203 g1: &Glyph,
204 g2: &Glyph,
205 contour: usize,
206 tolerance: f64,
207 value_1: f64,
208 value_2: f64,
209 ) -> Problem {
210 Problem {
211 master_1_name: g1.master_name.to_string(),
212 master_2_name: g2.master_name.to_string(),
213 master_1_index: g1.master_index,
214 master_2_index: g2.master_index,
215 contour: Some(contour),
216 tolerance: Some(tolerance),
217 details: ProblemDetails::Underweight { value_1, value_2 },
218 node: None,
219 }
220 }
221
222 pub(crate) fn kink(
223 g1: &Glyph,
224 g2: &Glyph,
225 contour: usize,
226 node: usize,
227 tolerance: f64,
228 ) -> Problem {
229 Problem {
230 master_1_name: g1.master_name.to_string(),
231 master_2_name: g2.master_name.to_string(),
232 master_1_index: g1.master_index,
233 master_2_index: g2.master_index,
234 contour: Some(contour),
235 node: Some(node),
236 tolerance: Some(tolerance),
237 details: ProblemDetails::Kink,
238 }
239 }
240
241 pub fn problem_type(&self) -> String {
243 match self.details {
244 ProblemDetails::PathCount { .. } => "PathCount".to_string(),
245 ProblemDetails::NodeCount { .. } => "NodeCount".to_string(),
246 ProblemDetails::NodeIncompatibility { .. } => "NodeIncompatibility".to_string(),
247 ProblemDetails::ContourOrder { .. } => "ContourOrder".to_string(),
248 ProblemDetails::WrongStartPoint { .. } => "WrongStartPoint".to_string(),
249 ProblemDetails::Overweight { .. } => "Overweight".to_string(),
250 ProblemDetails::Underweight { .. } => "Underweight".to_string(),
251 ProblemDetails::Kink => "Kink".to_string(),
252 }
253 }
254}