1#![allow(clippy::style, clippy::complexity)]
11
12#[allow(unused_imports)]
13use crate::eval::format_validators::*;
14use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
15
16pub struct PartinConditionEvaluatorFV2504 {
18 external_conditions: std::collections::HashSet<u32>,
20}
21
22impl Default for PartinConditionEvaluatorFV2504 {
23 fn default() -> Self {
24 let mut external_conditions = std::collections::HashSet::new();
25 external_conditions.insert(1);
26 external_conditions.insert(2);
27 external_conditions.insert(4);
28 external_conditions.insert(5);
29 external_conditions.insert(17);
30 external_conditions.insert(18);
31 external_conditions.insert(19);
32 external_conditions.insert(20);
33 external_conditions.insert(21);
34 external_conditions.insert(22);
35 external_conditions.insert(23);
36 external_conditions.insert(24);
37 external_conditions.insert(25);
38 external_conditions.insert(26);
39 external_conditions.insert(35);
40 external_conditions.insert(36);
41 Self {
42 external_conditions,
43 }
44 }
45}
46
47impl ConditionEvaluator for PartinConditionEvaluatorFV2504 {
48 fn message_type(&self) -> &str {
49 "PARTIN"
50 }
51
52 fn format_version(&self) -> &str {
53 "FV2504"
54 }
55
56 fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
57 match condition {
58 1 => self.evaluate_1(ctx),
59 2 => self.evaluate_2(ctx),
60 3 => self.evaluate_3(ctx),
61 4 => self.evaluate_4(ctx),
62 5 => self.evaluate_5(ctx),
63 6 => self.evaluate_6(ctx),
64 7 => self.evaluate_7(ctx),
65 8 => self.evaluate_8(ctx),
66 10 => self.evaluate_10(ctx),
67 11 => self.evaluate_11(ctx),
68 12 => self.evaluate_12(ctx),
69 13 => self.evaluate_13(ctx),
70 14 => self.evaluate_14(ctx),
71 15 => self.evaluate_15(ctx),
72 16 => self.evaluate_16(ctx),
73 17 => self.evaluate_17(ctx),
74 18 => self.evaluate_18(ctx),
75 19 => self.evaluate_19(ctx),
76 20 => self.evaluate_20(ctx),
77 21 => self.evaluate_21(ctx),
78 22 => self.evaluate_22(ctx),
79 23 => self.evaluate_23(ctx),
80 24 => self.evaluate_24(ctx),
81 25 => self.evaluate_25(ctx),
82 26 => self.evaluate_26(ctx),
83 27 => self.evaluate_27(ctx),
84 28 => self.evaluate_28(ctx),
85 29 => self.evaluate_29(ctx),
86 30 => self.evaluate_30(ctx),
87 31 => self.evaluate_31(ctx),
88 32 => self.evaluate_32(ctx),
89 33 => self.evaluate_33(ctx),
90 34 => self.evaluate_34(ctx),
91 35 => self.evaluate_35(ctx),
92 36 => self.evaluate_36(ctx),
93 490 => self.evaluate_490(ctx),
94 491 => self.evaluate_491(ctx),
95 494 => self.evaluate_494(ctx),
96 500 => self.evaluate_500(ctx),
97 501 => self.evaluate_501(ctx),
98 502 => self.evaluate_502(ctx),
99 503 => self.evaluate_503(ctx),
100 504 => self.evaluate_504(ctx),
101 505 => self.evaluate_505(ctx),
102 506 => self.evaluate_506(ctx),
103 508 => self.evaluate_508(ctx),
104 908 => self.evaluate_908(ctx),
105 931 => self.evaluate_931(ctx),
106 932 => self.evaluate_932(ctx),
107 933 => self.evaluate_933(ctx),
108 939 => self.evaluate_939(ctx),
109 940 => self.evaluate_940(ctx),
110 _ => ConditionResult::Unknown,
111 }
112 }
113
114 fn is_external(&self, condition: u32) -> bool {
115 self.external_conditions.contains(&condition)
116 }
117 fn is_known(&self, condition: u32) -> bool {
118 matches!(
119 condition,
120 1 | 2
121 | 3
122 | 4
123 | 5
124 | 6
125 | 7
126 | 8
127 | 10
128 | 11
129 | 12
130 | 13
131 | 14
132 | 15
133 | 16
134 | 17
135 | 18
136 | 19
137 | 20
138 | 21
139 | 22
140 | 23
141 | 24
142 | 25
143 | 26
144 | 27
145 | 28
146 | 29
147 | 30
148 | 31
149 | 32
150 | 33
151 | 34
152 | 35
153 | 36
154 | 490
155 | 491
156 | 494
157 | 500
158 | 501
159 | 502
160 | 503
161 | 504
162 | 505
163 | 506
164 | 508
165 | 908
166 | 931
167 | 932
168 | 933
169 | 939
170 | 940
171 )
172 }
173}
174
175impl PartinConditionEvaluatorFV2504 {
176 fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
179 ctx.external.evaluate("mp_id_is_strom")
180 }
181
182 fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
185 ctx.external.evaluate("country_code_has_plz")
186 }
187
188 fn evaluate_3(&self, _ctx: &EvaluationContext) -> ConditionResult {
190 ConditionResult::True
192 }
193
194 fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
197 ctx.external.evaluate("vorgaengerversion_vorhanden")
198 }
199
200 fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
202 match ctx.resolved_value {
203 Some(val) => is_mesz_utc(val),
204 None => ConditionResult::False,
205 }
206 }
207
208 fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
210 match ctx.resolved_value {
211 Some(val) => is_mez_utc(val),
212 None => ConditionResult::False,
213 }
214 }
215
216 fn evaluate_494(&self, _ctx: &EvaluationContext) -> ConditionResult {
219 ConditionResult::True
223 }
224
225 fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
228 ctx.external.evaluate("recipient_is_lf")
229 }
230
231 fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
233 let coms = ctx.find_segments("COM");
234 if coms.is_empty() {
235 return ConditionResult::Unknown;
236 }
237 ConditionResult::from(coms.iter().any(|s| {
238 s.elements
239 .first()
240 .and_then(|e| e.get(1))
241 .is_some_and(|v| v == "EM")
242 }))
243 }
244
245 fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
247 let coms = ctx.find_segments("COM");
248 if coms.is_empty() {
249 return ConditionResult::Unknown;
250 }
251 ConditionResult::from(coms.iter().any(|s| {
252 s.elements
253 .first()
254 .and_then(|e| e.get(1))
255 .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"))
256 }))
257 }
258
259 fn evaluate_8(&self, ctx: &EvaluationContext) -> ConditionResult {
261 let coms = ctx.find_segments("COM");
262 if coms.is_empty() {
263 return ConditionResult::Unknown;
264 }
265 ConditionResult::from(coms.iter().any(|s| {
266 s.elements
267 .first()
268 .and_then(|e| e.get(1))
269 .is_some_and(|v| matches!(v.as_str(), "TE" | "FX"))
270 }))
271 }
272
273 fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
275 match ctx.find_segment("BGM") {
276 None => ConditionResult::False, Some(bgm) => ConditionResult::from(
278 bgm.elements
279 .get(4)
280 .and_then(|e| e.first())
281 .map(|v| v != "11")
282 .unwrap_or(true),
283 ),
284 }
285 }
286
287 fn evaluate_11(&self, ctx: &EvaluationContext) -> ConditionResult {
289 let nads = ctx.find_segments_with_qualifier("NAD", 0, "SU");
290 match nads.first() {
291 None => ConditionResult::False, Some(nad) => ConditionResult::from(
293 nad.elements
294 .get(8)
295 .and_then(|e| e.first())
296 .is_some_and(|v| v == "DE"),
297 ),
298 }
299 }
300
301 fn evaluate_12(&self, ctx: &EvaluationContext) -> ConditionResult {
303 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DDM");
304 match nads.first() {
305 None => ConditionResult::False, Some(nad) => ConditionResult::from(
307 nad.elements
308 .get(8)
309 .and_then(|e| e.first())
310 .is_some_and(|v| v == "DE"),
311 ),
312 }
313 }
314
315 fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
317 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DEB");
318 match nads.first() {
319 None => ConditionResult::False, Some(nad) => ConditionResult::from(
321 nad.elements
322 .get(8)
323 .and_then(|e| e.first())
324 .is_some_and(|v| v == "DE"),
325 ),
326 }
327 }
328
329 fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
331 let nads = ctx.find_segments_with_qualifier("NAD", 0, "SU");
332 match nads.first() {
333 None => ConditionResult::False, Some(nad) => ConditionResult::from(
335 nad.elements
336 .get(8)
337 .and_then(|e| e.first())
338 .map(|v| v != "DE")
339 .unwrap_or(true),
340 ),
341 }
342 }
343
344 fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
346 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DDM");
347 match nads.first() {
348 None => ConditionResult::False, Some(nad) => ConditionResult::from(
350 nad.elements
351 .get(8)
352 .and_then(|e| e.first())
353 .map(|v| v != "DE")
354 .unwrap_or(true),
355 ),
356 }
357 }
358
359 fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
361 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DEB");
362 match nads.first() {
363 None => ConditionResult::False, Some(nad) => ConditionResult::from(
365 nad.elements
366 .get(8)
367 .and_then(|e| e.first())
368 .map(|v| v != "DE")
369 .unwrap_or(true),
370 ),
371 }
372 }
373
374 fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
377 ctx.external.evaluate("recipient_is_lf_nb_msb")
378 }
379
380 fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
383 ctx.external.evaluate("recipient_is_lf_msb")
384 }
385
386 fn evaluate_19(&self, ctx: &EvaluationContext) -> ConditionResult {
389 ctx.external.evaluate("recipient_is_lf_msb_nb_uenb")
390 }
391
392 fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
395 ctx.external.evaluate("recipient_is_lf_msb_uenb")
396 }
397
398 fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
401 ctx.external.evaluate("recipient_is_lf_nb_esa")
402 }
403
404 fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
407 ctx.external.evaluate("recipient_is_msb")
408 }
409
410 fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
413 ctx.external.evaluate("recipient_is_nb_uenb")
414 }
415
416 fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
419 ctx.external.evaluate("recipient_is_nb_lf_msb_esa")
420 }
421
422 fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
425 ctx.external.evaluate("recipient_is_nb")
426 }
427
428 fn evaluate_26(&self, ctx: &EvaluationContext) -> ConditionResult {
431 ctx.external.evaluate("recipient_is_nb_lf_bkv_biko")
432 }
433
434 fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
436 ctx.has_qualified_value("NAD", 0, "Z31", 8, 0, &["DE"])
437 }
438
439 fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
441 ctx.has_qualified_value("NAD", 0, "Z34", 8, 0, &["DE"])
442 }
443
444 fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
446 ctx.has_qualified_value("NAD", 0, "Z35", 8, 0, &["DE"])
447 }
448
449 fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
451 ctx.has_qualified_value("NAD", 0, "Z36", 8, 0, &["DE"])
452 }
453
454 fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
456 match ctx.has_qualified_value("NAD", 0, "Z31", 8, 0, &["DE"]) {
457 ConditionResult::True => ConditionResult::False,
458 ConditionResult::False => ConditionResult::True,
459 ConditionResult::Unknown => ConditionResult::Unknown,
460 }
461 }
462
463 fn evaluate_32(&self, ctx: &EvaluationContext) -> ConditionResult {
465 let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z34");
466 if nads.is_empty() {
467 return ConditionResult::True;
468 }
469 let has_de = nads.iter().any(|s| {
470 s.elements
471 .get(8)
472 .and_then(|e| e.first())
473 .is_some_and(|v| v == "DE")
474 });
475 ConditionResult::from(!has_de)
476 }
477
478 fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
480 let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z35");
481 if nads.is_empty() {
482 return ConditionResult::True;
483 }
484 let has_de = nads.iter().any(|s| {
485 s.elements
486 .get(8)
487 .and_then(|e| e.first())
488 .is_some_and(|v| v == "DE")
489 });
490 ConditionResult::from(!has_de)
491 }
492
493 fn evaluate_34(&self, ctx: &EvaluationContext) -> ConditionResult {
495 let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z36");
496 if nads.is_empty() {
497 return ConditionResult::True;
498 }
499 let has_de = nads.iter().any(|s| {
500 s.elements
501 .get(8)
502 .and_then(|e| e.first())
503 .is_some_and(|v| v == "DE")
504 });
505 ConditionResult::from(!has_de)
506 }
507
508 fn evaluate_35(&self, ctx: &EvaluationContext) -> ConditionResult {
511 ctx.external.evaluate("recipient_is_uenb")
512 }
513
514 fn evaluate_36(&self, ctx: &EvaluationContext) -> ConditionResult {
517 ctx.external.evaluate("recipient_is_bkv")
518 }
519
520 fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
522 ConditionResult::True
525 }
526
527 fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
529 ConditionResult::True
532 }
533
534 fn evaluate_502(&self, _ctx: &EvaluationContext) -> ConditionResult {
536 ConditionResult::True
539 }
540
541 fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
543 ConditionResult::True
545 }
546
547 fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
549 ConditionResult::True
551 }
552
553 fn evaluate_505(&self, ctx: &EvaluationContext) -> ConditionResult {
556 let acw_segments = ctx.find_segments_with_qualifier("RFF", 0, "ACW");
557 if acw_segments.is_empty() {
558 return ConditionResult::False;
559 }
560 let agk_segments = ctx.find_segments_with_qualifier("RFF", 0, "AGK");
561 let current_version = agk_segments
562 .first()
563 .and_then(|s| s.elements.first())
564 .and_then(|e| e.get(3))
565 .and_then(|v| v.parse::<i64>().ok());
566 let predecessor_version = acw_segments
567 .first()
568 .and_then(|s| s.elements.first())
569 .and_then(|e| e.get(3))
570 .and_then(|v| v.parse::<i64>().ok());
571 match (current_version, predecessor_version) {
572 (Some(cur), Some(pred)) => ConditionResult::from(cur >= pred + 1),
573 _ => ConditionResult::Unknown,
574 }
575 }
576
577 fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
579 ConditionResult::True
581 }
582
583 fn evaluate_508(&self, _ctx: &EvaluationContext) -> ConditionResult {
585 ConditionResult::True
587 }
588
589 fn evaluate_908(&self, _ctx: &EvaluationContext) -> ConditionResult {
591 ConditionResult::True
593 }
594
595 fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
597 ctx.format_check("DTM", 0, 1, validate_timezone_utc)
598 }
599
600 fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
602 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2200"))
603 }
604
605 fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
607 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2300"))
608 }
609
610 fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
612 ctx.format_check("COM", 0, 0, validate_email)
613 }
614
615 fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
617 ctx.format_check("COM", 0, 0, validate_phone)
618 }
619}