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 PartinConditionEvaluatorFV2604 {
18 external_conditions: std::collections::HashSet<u32>,
20}
21
22impl Default for PartinConditionEvaluatorFV2604 {
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(9);
30 external_conditions.insert(17);
31 external_conditions.insert(18);
32 external_conditions.insert(19);
33 external_conditions.insert(20);
34 external_conditions.insert(21);
35 external_conditions.insert(22);
36 external_conditions.insert(23);
37 external_conditions.insert(24);
38 external_conditions.insert(25);
39 external_conditions.insert(26);
40 external_conditions.insert(35);
41 external_conditions.insert(36);
42 external_conditions.insert(41);
43 external_conditions.insert(45);
44 external_conditions.insert(46);
45 external_conditions.insert(49);
46 external_conditions.insert(50);
47 Self {
48 external_conditions,
49 }
50 }
51}
52
53impl ConditionEvaluator for PartinConditionEvaluatorFV2604 {
54 fn message_type(&self) -> &str {
55 "PARTIN"
56 }
57
58 fn format_version(&self) -> &str {
59 "FV2604"
60 }
61
62 fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
63 match condition {
64 1 => self.evaluate_1(ctx),
65 2 => self.evaluate_2(ctx),
66 3 => self.evaluate_3(ctx),
67 4 => self.evaluate_4(ctx),
68 5 => self.evaluate_5(ctx),
69 6 => self.evaluate_6(ctx),
70 7 => self.evaluate_7(ctx),
71 8 => self.evaluate_8(ctx),
72 9 => self.evaluate_9(ctx),
73 10 => self.evaluate_10(ctx),
74 11 => self.evaluate_11(ctx),
75 12 => self.evaluate_12(ctx),
76 13 => self.evaluate_13(ctx),
77 14 => self.evaluate_14(ctx),
78 15 => self.evaluate_15(ctx),
79 16 => self.evaluate_16(ctx),
80 17 => self.evaluate_17(ctx),
81 18 => self.evaluate_18(ctx),
82 19 => self.evaluate_19(ctx),
83 20 => self.evaluate_20(ctx),
84 21 => self.evaluate_21(ctx),
85 22 => self.evaluate_22(ctx),
86 23 => self.evaluate_23(ctx),
87 24 => self.evaluate_24(ctx),
88 25 => self.evaluate_25(ctx),
89 26 => self.evaluate_26(ctx),
90 27 => self.evaluate_27(ctx),
91 28 => self.evaluate_28(ctx),
92 29 => self.evaluate_29(ctx),
93 30 => self.evaluate_30(ctx),
94 31 => self.evaluate_31(ctx),
95 32 => self.evaluate_32(ctx),
96 33 => self.evaluate_33(ctx),
97 34 => self.evaluate_34(ctx),
98 35 => self.evaluate_35(ctx),
99 36 => self.evaluate_36(ctx),
100 41 => self.evaluate_41(ctx),
101 43 => self.evaluate_43(ctx),
102 44 => self.evaluate_44(ctx),
103 45 => self.evaluate_45(ctx),
104 46 => self.evaluate_46(ctx),
105 49 => self.evaluate_49(ctx),
106 50 => self.evaluate_50(ctx),
107 490 => self.evaluate_490(ctx),
108 491 => self.evaluate_491(ctx),
109 494 => self.evaluate_494(ctx),
110 500 => self.evaluate_500(ctx),
111 501 => self.evaluate_501(ctx),
112 502 => self.evaluate_502(ctx),
113 503 => self.evaluate_503(ctx),
114 504 => self.evaluate_504(ctx),
115 505 => self.evaluate_505(ctx),
116 506 => self.evaluate_506(ctx),
117 508 => self.evaluate_508(ctx),
118 908 => self.evaluate_908(ctx),
119 931 => self.evaluate_931(ctx),
120 932 => self.evaluate_932(ctx),
121 933 => self.evaluate_933(ctx),
122 939 => self.evaluate_939(ctx),
123 940 => self.evaluate_940(ctx),
124 _ => ConditionResult::Unknown,
125 }
126 }
127
128 fn is_external(&self, condition: u32) -> bool {
129 self.external_conditions.contains(&condition)
130 }
131 fn is_known(&self, condition: u32) -> bool {
132 matches!(
133 condition,
134 1 | 2
135 | 3
136 | 4
137 | 5
138 | 6
139 | 7
140 | 8
141 | 9
142 | 10
143 | 11
144 | 12
145 | 13
146 | 14
147 | 15
148 | 16
149 | 17
150 | 18
151 | 19
152 | 20
153 | 21
154 | 22
155 | 23
156 | 24
157 | 25
158 | 26
159 | 27
160 | 28
161 | 29
162 | 30
163 | 31
164 | 32
165 | 33
166 | 34
167 | 35
168 | 36
169 | 41
170 | 43
171 | 44
172 | 45
173 | 46
174 | 49
175 | 50
176 | 490
177 | 491
178 | 494
179 | 500
180 | 501
181 | 502
182 | 503
183 | 504
184 | 505
185 | 506
186 | 508
187 | 908
188 | 931
189 | 932
190 | 933
191 | 939
192 | 940
193 )
194 }
195}
196
197impl PartinConditionEvaluatorFV2604 {
198 fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
201 ctx.external.evaluate("sender_communication_inactive")
202 }
203
204 fn evaluate_41(&self, ctx: &EvaluationContext) -> ConditionResult {
207 ctx.external.evaluate("mp_id_is_gas_sector")
208 }
209
210 fn evaluate_43(&self, ctx: &EvaluationContext) -> ConditionResult {
212 ctx.has_segment_matching("NAD", &[(0, 0, "Z71"), (8, 0, "DE")])
214 }
215
216 fn evaluate_44(&self, ctx: &EvaluationContext) -> ConditionResult {
218 match ctx.has_segment_matching("NAD", &[(0, 0, "Z71"), (8, 0, "DE")]) {
220 ConditionResult::True => ConditionResult::False,
221 ConditionResult::False => ConditionResult::True,
222 ConditionResult::Unknown => ConditionResult::Unknown,
223 }
224 }
225
226 fn evaluate_45(&self, ctx: &EvaluationContext) -> ConditionResult {
229 ctx.external.evaluate("recipient_is_lf_or_nb")
230 }
231
232 fn evaluate_46(&self, ctx: &EvaluationContext) -> ConditionResult {
235 ctx.external.evaluate("recipient_is_lf_msb_mgv")
236 }
237
238 fn evaluate_49(&self, ctx: &EvaluationContext) -> ConditionResult {
241 ctx.external.evaluate("recipient_is_lf_mgv")
242 }
243
244 fn evaluate_50(&self, ctx: &EvaluationContext) -> ConditionResult {
247 ctx.external.evaluate("recipient_is_lf_mgv_nb")
248 }
249
250 fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
252 ConditionResult::True
254 }
255
256 fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
259 ctx.external.evaluate("mp_id_is_strom")
260 }
261
262 fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
265 ctx.external.evaluate("country_has_postal_code")
266 }
267
268 fn evaluate_3(&self, _ctx: &EvaluationContext) -> ConditionResult {
270 ConditionResult::True
272 }
273
274 fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
277 ctx.external.evaluate("predecessor_version_exists")
278 }
279
280 fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
283 ctx.external.evaluate("recipient_is_lf")
284 }
285
286 fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
288 let coms = ctx.find_segments("COM");
289 if coms.is_empty() {
290 return ConditionResult::Unknown;
291 }
292 ConditionResult::from(coms.iter().any(|s| {
293 s.elements
294 .first()
295 .and_then(|e| e.get(1))
296 .is_some_and(|v| v == "EM")
297 }))
298 }
299
300 fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
302 let coms = ctx.find_segments("COM");
303 if coms.is_empty() {
304 return ConditionResult::Unknown;
305 }
306 ConditionResult::from(coms.iter().any(|s| {
307 s.elements
308 .first()
309 .and_then(|e| e.get(1))
310 .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"))
311 }))
312 }
313
314 fn evaluate_8(&self, ctx: &EvaluationContext) -> ConditionResult {
316 let coms = ctx.find_segments("COM");
317 if coms.is_empty() {
318 return ConditionResult::Unknown;
319 }
320 ConditionResult::from(coms.iter().any(|s| {
321 s.elements
322 .first()
323 .and_then(|e| e.get(1))
324 .is_some_and(|v| matches!(v.as_str(), "TE" | "FX"))
325 }))
326 }
327
328 fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
330 match ctx.find_segment("BGM") {
331 None => ConditionResult::False, Some(bgm) => ConditionResult::from(
333 bgm.elements
334 .get(4)
335 .and_then(|e| e.first())
336 .map(|v| v != "11")
337 .unwrap_or(true),
338 ),
339 }
340 }
341
342 fn evaluate_11(&self, ctx: &EvaluationContext) -> ConditionResult {
344 let nads = ctx.find_segments_with_qualifier("NAD", 0, "SU");
345 match nads.first() {
346 None => ConditionResult::False, Some(nad) => ConditionResult::from(
348 nad.elements
349 .get(8)
350 .and_then(|e| e.first())
351 .is_some_and(|v| v == "DE"),
352 ),
353 }
354 }
355
356 fn evaluate_12(&self, ctx: &EvaluationContext) -> ConditionResult {
358 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DDM");
359 match nads.first() {
360 None => ConditionResult::False, Some(nad) => ConditionResult::from(
362 nad.elements
363 .get(8)
364 .and_then(|e| e.first())
365 .is_some_and(|v| v == "DE"),
366 ),
367 }
368 }
369
370 fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
372 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DEB");
373 match nads.first() {
374 None => ConditionResult::False, Some(nad) => ConditionResult::from(
376 nad.elements
377 .get(8)
378 .and_then(|e| e.first())
379 .is_some_and(|v| v == "DE"),
380 ),
381 }
382 }
383
384 fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
386 let nads = ctx.find_segments_with_qualifier("NAD", 0, "SU");
387 match nads.first() {
388 None => ConditionResult::False, Some(nad) => ConditionResult::from(
390 nad.elements
391 .get(8)
392 .and_then(|e| e.first())
393 .map(|v| v != "DE")
394 .unwrap_or(true),
395 ),
396 }
397 }
398
399 fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
401 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DDM");
402 match nads.first() {
403 None => ConditionResult::False, Some(nad) => ConditionResult::from(
405 nad.elements
406 .get(8)
407 .and_then(|e| e.first())
408 .map(|v| v != "DE")
409 .unwrap_or(true),
410 ),
411 }
412 }
413
414 fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
416 let nads = ctx.find_segments_with_qualifier("NAD", 0, "DEB");
417 match nads.first() {
418 None => ConditionResult::False, Some(nad) => ConditionResult::from(
420 nad.elements
421 .get(8)
422 .and_then(|e| e.first())
423 .map(|v| v != "DE")
424 .unwrap_or(true),
425 ),
426 }
427 }
428
429 fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
432 ctx.external.evaluate("recipient_is_lf_nb_msb")
433 }
434
435 fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
438 ctx.external.evaluate("recipient_is_lf_msb")
439 }
440
441 fn evaluate_19(&self, ctx: &EvaluationContext) -> ConditionResult {
444 ctx.external.evaluate("recipient_is_lf_msb_nb_uenb")
445 }
446
447 fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
450 ctx.external.evaluate("recipient_is_lf_msb_uenb")
451 }
452
453 fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
456 ctx.external.evaluate("recipient_is_lf_nb_esa")
457 }
458
459 fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
462 ctx.external.evaluate("recipient_is_msb")
463 }
464
465 fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
468 ctx.external.evaluate("recipient_is_nb_uenb")
469 }
470
471 fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
474 ctx.external.evaluate("recipient_is_nb_lf_msb_esa")
475 }
476
477 fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
480 ctx.external.evaluate("recipient_is_nb")
481 }
482
483 fn evaluate_26(&self, ctx: &EvaluationContext) -> ConditionResult {
486 ctx.external.evaluate("recipient_is_nb_lf_bkv_biko")
487 }
488
489 fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
491 ctx.has_qualified_value("NAD", 0, "Z31", 8, 0, &["DE"])
492 }
493
494 fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
496 ctx.has_qualified_value("NAD", 0, "Z34", 8, 0, &["DE"])
497 }
498
499 fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
501 ctx.has_qualified_value("NAD", 0, "Z35", 8, 0, &["DE"])
502 }
503
504 fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
506 ctx.has_qualified_value("NAD", 0, "Z36", 8, 0, &["DE"])
507 }
508
509 fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
511 match ctx.has_qualified_value("NAD", 0, "Z31", 8, 0, &["DE"]) {
512 ConditionResult::True => ConditionResult::False,
513 ConditionResult::False => ConditionResult::True,
514 ConditionResult::Unknown => ConditionResult::Unknown,
515 }
516 }
517
518 fn evaluate_32(&self, ctx: &EvaluationContext) -> ConditionResult {
520 let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z34");
521 if nads.is_empty() {
522 return ConditionResult::True;
523 }
524 let has_de = nads.iter().any(|s| {
525 s.elements
526 .get(8)
527 .and_then(|e| e.first())
528 .is_some_and(|v| v == "DE")
529 });
530 ConditionResult::from(!has_de)
531 }
532
533 fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
535 let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z35");
536 if nads.is_empty() {
537 return ConditionResult::True;
538 }
539 let has_de = nads.iter().any(|s| {
540 s.elements
541 .get(8)
542 .and_then(|e| e.first())
543 .is_some_and(|v| v == "DE")
544 });
545 ConditionResult::from(!has_de)
546 }
547
548 fn evaluate_34(&self, ctx: &EvaluationContext) -> ConditionResult {
550 let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z36");
551 if nads.is_empty() {
552 return ConditionResult::True;
553 }
554 let has_de = nads.iter().any(|s| {
555 s.elements
556 .get(8)
557 .and_then(|e| e.first())
558 .is_some_and(|v| v == "DE")
559 });
560 ConditionResult::from(!has_de)
561 }
562
563 fn evaluate_35(&self, ctx: &EvaluationContext) -> ConditionResult {
566 ctx.external.evaluate("recipient_is_uenb")
567 }
568
569 fn evaluate_36(&self, ctx: &EvaluationContext) -> ConditionResult {
572 ctx.external.evaluate("recipient_is_bkv")
573 }
574
575 fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
577 match ctx.resolved_value {
578 Some(val) => is_mesz_utc(val),
579 None => ConditionResult::False,
580 }
581 }
582
583 fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
585 match ctx.resolved_value {
586 Some(val) => is_mez_utc(val),
587 None => ConditionResult::False,
588 }
589 }
590
591 fn evaluate_494(&self, _ctx: &EvaluationContext) -> ConditionResult {
594 ConditionResult::True
598 }
599
600 fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
602 ConditionResult::True
605 }
606
607 fn evaluate_502(&self, _ctx: &EvaluationContext) -> ConditionResult {
609 ConditionResult::True
612 }
613
614 fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
616 ConditionResult::True
618 }
619
620 fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
622 ConditionResult::True
624 }
625
626 fn evaluate_505(&self, ctx: &EvaluationContext) -> ConditionResult {
629 let acw_segments = ctx.find_segments_with_qualifier("RFF", 0, "ACW");
630 if acw_segments.is_empty() {
631 return ConditionResult::False;
632 }
633 let agk_segments = ctx.find_segments_with_qualifier("RFF", 0, "AGK");
634 let current_version = agk_segments
635 .first()
636 .and_then(|s| s.elements.first())
637 .and_then(|e| e.get(3))
638 .and_then(|v| v.parse::<i64>().ok());
639 let predecessor_version = acw_segments
640 .first()
641 .and_then(|s| s.elements.first())
642 .and_then(|e| e.get(3))
643 .and_then(|v| v.parse::<i64>().ok());
644 match (current_version, predecessor_version) {
645 (Some(cur), Some(pred)) => ConditionResult::from(cur >= pred + 1),
646 _ => ConditionResult::Unknown,
647 }
648 }
649
650 fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
652 ConditionResult::True
654 }
655
656 fn evaluate_508(&self, _ctx: &EvaluationContext) -> ConditionResult {
658 ConditionResult::True
660 }
661
662 fn evaluate_908(&self, _ctx: &EvaluationContext) -> ConditionResult {
664 ConditionResult::True
666 }
667
668 fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
670 ctx.format_check("DTM", 0, 1, validate_timezone_utc)
671 }
672
673 fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
675 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2200"))
676 }
677
678 fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
680 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2300"))
681 }
682
683 fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
685 ctx.format_check("COM", 0, 0, validate_email)
686 }
687
688 fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
690 ctx.format_check("COM", 0, 0, validate_phone)
691 }
692}