1#![allow(clippy::style, clippy::complexity)]
9
10#[allow(unused_imports)]
11use crate::eval::format_validators::*;
12use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
13use crate::generated::fv2504::UtilmdStromConditionEvaluatorFV2504;
14
15pub struct UtilmdStromConditionEvaluatorFV2510 {
20 fallback: UtilmdStromConditionEvaluatorFV2504,
21}
22
23impl Default for UtilmdStromConditionEvaluatorFV2510 {
24 fn default() -> Self {
25 Self {
26 fallback: UtilmdStromConditionEvaluatorFV2504::default(),
27 }
28 }
29}
30
31const FV2510_OVERRIDES: &[u32] = &[
33 2, 3, 20, 28, 29, 79, 136, 139, 157, 158, 168, 169, 242, 253, 258, 263, 297, 312, 313, 326,
34 328, 346, 413, 414, 415, 416, 461, 534, 557, 560, 561, 562, 564, 565, 578, 681, 686, 2000,
35 2016, 2121,
36];
37
38const FV2510_EXTERNAL: &[u32] = &[3, 326, 328];
40
41impl ConditionEvaluator for UtilmdStromConditionEvaluatorFV2510 {
42 fn message_type(&self) -> &str {
43 "UTILMD_Strom"
44 }
45
46 fn format_version(&self) -> &str {
47 "FV2510"
48 }
49
50 fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
51 match condition {
52 2 => self.evaluate_2(ctx),
53 3 => self.evaluate_3(ctx),
54 20 => self.evaluate_20(ctx),
55 28 => self.evaluate_28(ctx),
56 29 => self.evaluate_29(ctx),
57 79 => self.evaluate_79(ctx),
58 136 => self.evaluate_136(ctx),
59 139 => self.evaluate_139(ctx),
60 157 => self.evaluate_157(ctx),
61 158 => self.evaluate_158(ctx),
62 168 => self.evaluate_168(ctx),
63 169 => self.evaluate_169(ctx),
64 242 => self.evaluate_242(ctx),
65 253 => self.evaluate_253(ctx),
66 258 => self.evaluate_258(ctx),
67 263 => self.evaluate_263(ctx),
68 297 => self.evaluate_297(ctx),
69 312 => self.evaluate_312(ctx),
70 313 => self.evaluate_313(ctx),
71 326 => self.evaluate_326(ctx),
72 328 => self.evaluate_328(ctx),
73 346 => self.evaluate_346(ctx),
74 413 => self.evaluate_413(ctx),
75 414 => self.evaluate_414(ctx),
76 415 => self.evaluate_415(ctx),
77 416 => self.evaluate_416(ctx),
78 461 => self.evaluate_461(ctx),
79 534 => self.evaluate_534(ctx),
80 557 => self.evaluate_557(ctx),
81 560 => self.evaluate_560(ctx),
82 561 => self.evaluate_561(ctx),
83 562 => self.evaluate_562(ctx),
84 564 => self.evaluate_564(ctx),
85 565 => self.evaluate_565(ctx),
86 578 => self.evaluate_578(ctx),
87 681 => self.evaluate_681(ctx),
88 686 => self.evaluate_686(ctx),
89 2000 => self.evaluate_2000(ctx),
90 2016 => self.evaluate_2016(ctx),
91 2121 => self.evaluate_2121(ctx),
92 other => self.fallback.evaluate(other, ctx),
93 }
94 }
95
96 fn is_external(&self, condition: u32) -> bool {
97 if FV2510_OVERRIDES.contains(&condition) {
98 FV2510_EXTERNAL.contains(&condition)
99 } else {
100 self.fallback.is_external(condition)
101 }
102 }
103
104 fn is_known(&self, condition: u32) -> bool {
105 FV2510_OVERRIDES.contains(&condition) || self.fallback.is_known(condition)
106 }
107}
108
109impl UtilmdStromConditionEvaluatorFV2510 {
110 fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
112 ctx.has_segment_matching("UNH", &[(3, 0, "1")])
113 }
114
115 fn evaluate_3(&self, ctx: &EvaluationContext) -> ConditionResult {
118 ctx.external.evaluate("is_highest_sequence_in_split")
119 }
120
121 fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
123 let nav = match ctx.navigator() {
124 Some(n) => n,
125 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
126 };
127 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
128 for i in 0..sg8_count {
129 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
130 let has_z01 = seq_segs.iter().any(|s| {
131 s.elements
132 .first()
133 .and_then(|e| e.first())
134 .is_some_and(|v| v == "Z01")
135 });
136 if !has_z01 {
137 continue;
138 }
139 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
140 for j in 0..sg10_count {
141 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
142 if ccis.iter().any(|s| {
143 s.elements
144 .first()
145 .and_then(|e| e.first())
146 .is_some_and(|v| v == "Z30")
147 && s.elements
148 .get(2)
149 .and_then(|e| e.first())
150 .is_some_and(|v| v == "Z07")
151 }) {
152 return ConditionResult::True;
153 }
154 }
155 }
156 ConditionResult::False
157 }
158
159 fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
162 let nav = match ctx.navigator() {
163 Some(n) => n,
164 None => {
165 let sts_segs = ctx.find_segments_with_qualifier("STS", 0, "E01");
166 let found = sts_segs.iter().any(|s| {
167 let code = s
168 .elements
169 .get(2)
170 .and_then(|e| e.first())
171 .map(|v| v.as_str());
172 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
173 (code == Some("A04") && list == Some("E_0017"))
174 || (code == Some("A03") && list == Some("E_0052"))
175 });
176 return ConditionResult::from(!found);
177 }
178 };
179 let sg4_count = nav.group_instance_count(&["SG4"]);
180 for i in 0..sg4_count {
181 let ide_segs = nav.find_segments_in_group("IDE", &["SG4"], i);
182 let has_ide_24 = ide_segs.iter().any(|s| {
183 s.elements
184 .first()
185 .and_then(|e| e.first())
186 .is_some_and(|v| v == "24")
187 });
188 if !has_ide_24 {
189 continue;
190 }
191 let sts_segs = nav.find_segments_in_group("STS", &["SG4"], i);
192 let found = sts_segs.iter().any(|s| {
193 let qual = s
194 .elements
195 .first()
196 .and_then(|e| e.first())
197 .map(|v| v.as_str());
198 let code = s
199 .elements
200 .get(2)
201 .and_then(|e| e.first())
202 .map(|v| v.as_str());
203 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
204 qual == Some("E01")
205 && ((code == Some("A04") && list == Some("E_0017"))
206 || (code == Some("A03") && list == Some("E_0052")))
207 });
208 if !found {
209 return ConditionResult::True;
210 }
211 }
212 ConditionResult::False
213 }
214
215 fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
218 let nav = match ctx.navigator() {
219 Some(n) => n,
220 None => {
221 let sts_segs = ctx.find_segments_with_qualifier("STS", 0, "E01");
222 let found = sts_segs.iter().any(|s| {
223 let code = s
224 .elements
225 .get(2)
226 .and_then(|e| e.first())
227 .map(|v| v.as_str());
228 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
229 (code == Some("A06") && list == Some("E_0017"))
230 || (code == Some("A05") && list == Some("E_0052"))
231 });
232 return ConditionResult::from(!found);
233 }
234 };
235 let sg4_count = nav.group_instance_count(&["SG4"]);
236 for i in 0..sg4_count {
237 let ide_segs = nav.find_segments_in_group("IDE", &["SG4"], i);
238 let has_ide_24 = ide_segs.iter().any(|s| {
239 s.elements
240 .first()
241 .and_then(|e| e.first())
242 .is_some_and(|v| v == "24")
243 });
244 if !has_ide_24 {
245 continue;
246 }
247 let sts_segs = nav.find_segments_in_group("STS", &["SG4"], i);
248 let found = sts_segs.iter().any(|s| {
249 let qual = s
250 .elements
251 .first()
252 .and_then(|e| e.first())
253 .map(|v| v.as_str());
254 let code = s
255 .elements
256 .get(2)
257 .and_then(|e| e.first())
258 .map(|v| v.as_str());
259 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
260 qual == Some("E01")
261 && ((code == Some("A06") && list == Some("E_0017"))
262 || (code == Some("A05") && list == Some("E_0052")))
263 });
264 if !found {
265 return ConditionResult::True;
266 }
267 }
268 ConditionResult::False
269 }
270
271 fn evaluate_79(&self, ctx: &EvaluationContext) -> ConditionResult {
273 ctx.has_segment_matching("STS", &[(0, 0, "7"), (2, 0, "Z33")])
276 }
277
278 fn evaluate_136(&self, ctx: &EvaluationContext) -> ConditionResult {
280 let nav = match ctx.navigator() {
281 Some(n) => n,
282 None => return ctx.has_qualified_value("CAV", 0, "EHZ", 0, 0, &["EHZ"]),
283 };
284 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
285 for i in 0..sg8_count {
286 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
287 for j in 0..sg10_count {
288 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
289 let has_cci_e13 = ccis.iter().any(|s| {
290 s.elements
291 .get(2)
292 .and_then(|e| e.first())
293 .is_some_and(|v| v == "E13")
294 });
295 if has_cci_e13 {
296 let cavs =
297 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
298 if cavs.iter().any(|s| {
299 s.elements
300 .first()
301 .and_then(|e| e.first())
302 .is_some_and(|v| v == "EHZ")
303 }) {
304 return ConditionResult::True;
305 }
306 }
307 }
308 }
309 ConditionResult::False
310 }
311
312 fn evaluate_139(&self, ctx: &EvaluationContext) -> ConditionResult {
315 let nav = match ctx.navigator() {
316 Some(n) => n,
317 None => return ctx.lacks_qualifier("CAV", 0, "IVA"),
318 };
319 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
320 for i in 0..sg8_count {
321 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
322 for j in 0..sg10_count {
323 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
324 if cavs.iter().any(|s| {
325 s.elements
326 .first()
327 .and_then(|e| e.first())
328 .is_some_and(|v| v == "IVA")
329 }) {
330 return ConditionResult::False;
331 }
332 }
333 }
334 ConditionResult::True
335 }
336
337 fn evaluate_157(&self, ctx: &EvaluationContext) -> ConditionResult {
339 let result = ctx.has_segment_matching("STS", &[(0, 0, "7"), (2, 0, "Z33"), (3, 0, "ZZB")]);
340 match result {
341 ConditionResult::True => ConditionResult::False,
342 ConditionResult::False => ConditionResult::True,
343 ConditionResult::Unknown => ConditionResult::Unknown,
344 }
345 }
346
347 fn evaluate_158(&self, ctx: &EvaluationContext) -> ConditionResult {
349 ConditionResult::from(ctx.self_segment_value_equals("DTM", 0, 2, "106"))
350 }
351
352 fn evaluate_168(&self, ctx: &EvaluationContext) -> ConditionResult {
354 ctx.any_group_has_qualified_value(
355 "PIA",
356 0,
357 "Z02",
358 1,
359 0,
360 &["1-02-0-002", "1-02-0-003", "1-02-0-004"],
361 &["SG4", "SG8"],
362 )
363 }
364
365 fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
368 let nav = match ctx.navigator() {
369 Some(n) => n,
370 None => return ConditionResult::Unknown,
371 };
372 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
373 let mut sg8_data: Vec<(String, String)> = Vec::new();
374 for i in 0..sg8_count {
375 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
376 let zeitraum_id = seqs
377 .iter()
378 .find(|s| {
379 s.elements
380 .first()
381 .and_then(|e| e.first())
382 .is_some_and(|v| v == "Z45")
383 })
384 .and_then(|s| s.elements.get(1))
385 .and_then(|e| e.first())
386 .filter(|v| !v.is_empty())
387 .cloned();
388 if let Some(zid) = zeitraum_id {
389 let pias = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
390 let article_id = pias
391 .iter()
392 .find(|s| {
393 s.elements
394 .first()
395 .and_then(|e| e.first())
396 .is_some_and(|v| v == "Z02")
397 })
398 .and_then(|s| s.elements.get(1))
399 .and_then(|e| e.first())
400 .cloned()
401 .unwrap_or_default();
402 sg8_data.push((zid, article_id));
403 }
404 }
405 for i in 0..sg8_data.len() {
406 for j in (i + 1)..sg8_data.len() {
407 if sg8_data[i].0 == sg8_data[j].0 {
408 let (id_i, id_j) = (&sg8_data[i].1, &sg8_data[j].1);
409 let i_is_002 = id_i == "1-02-0-002";
410 let j_is_002 = id_j == "1-02-0-002";
411 let i_is_003_004 = id_i == "1-02-0-003" || id_i == "1-02-0-004";
412 let j_is_003_004 = id_j == "1-02-0-003" || id_j == "1-02-0-004";
413 if (i_is_002 && j_is_003_004) || (j_is_002 && i_is_003_004) {
414 return ConditionResult::True;
415 }
416 }
417 }
418 }
419 if sg8_data.is_empty() {
420 ConditionResult::Unknown
421 } else {
422 ConditionResult::False
423 }
424 }
425
426 fn evaluate_242(&self, ctx: &EvaluationContext) -> ConditionResult {
428 let nav = match ctx.navigator() {
429 Some(n) => n,
430 None => return ConditionResult::Unknown,
431 };
432 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
433 let mut ids: Vec<String> = Vec::new();
434 for i in 0..sg8_count {
435 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
436 for seq in &seq_segs {
437 let qual = seq
438 .elements
439 .first()
440 .and_then(|e| e.first())
441 .map(|s| s.as_str());
442 if matches!(qual, Some("Z78") | Some("ZC7") | Some("ZC8") | Some("ZD5")) {
443 if let Some(id) = seq.elements.get(1).and_then(|e| e.first()) {
444 if !id.is_empty() {
445 ids.push(id.clone());
446 }
447 }
448 }
449 }
450 }
451 if ids.is_empty() {
452 return ConditionResult::Unknown;
453 }
454 let mut seen = std::collections::HashSet::new();
455 ConditionResult::from(ids.iter().any(|id| !seen.insert(id.as_str())))
456 }
457
458 fn evaluate_253(&self, ctx: &EvaluationContext) -> ConditionResult {
460 match ctx.has_segment_matching("STS", &[(0, 0, "E01"), (2, 0, "ZC9")]) {
461 ConditionResult::True => ConditionResult::False,
462 ConditionResult::False => ConditionResult::True,
463 ConditionResult::Unknown => ConditionResult::Unknown,
464 }
465 }
466
467 fn evaluate_258(&self, ctx: &EvaluationContext) -> ConditionResult {
469 let nav = match ctx.navigator() {
470 Some(n) => n,
471 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
472 };
473 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
474 for i in 0..sg8_count {
475 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
476 let has_z01 = seq_segs.iter().any(|s| {
477 s.elements
478 .first()
479 .and_then(|e| e.first())
480 .is_some_and(|v| v == "Z01")
481 });
482 if has_z01 {
483 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
484 for j in 0..sg10_count {
485 let ccis =
486 nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
487 if ccis.iter().any(|s| {
488 s.elements
489 .first()
490 .and_then(|e| e.first())
491 .is_some_and(|v| v == "Z30")
492 && s.elements
493 .get(2)
494 .and_then(|e| e.first())
495 .is_some_and(|v| v == "Z07")
496 }) {
497 return ConditionResult::True;
498 }
499 }
500 }
501 }
502 ConditionResult::False
503 }
504
505 fn evaluate_263(&self, ctx: &EvaluationContext) -> ConditionResult {
508 let nav = match ctx.navigator() {
509 Some(n) => n,
510 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
511 };
512 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
513 for i in 0..sg8_count {
514 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
515 let has_z01 = seq_segs.iter().any(|s| {
516 s.elements
517 .first()
518 .and_then(|e| e.first())
519 .is_some_and(|v| v == "Z01")
520 });
521 if !has_z01 {
522 continue;
523 }
524 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
525 for j in 0..sg10_count {
526 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
527 if ccis.iter().any(|s| {
528 s.elements
529 .first()
530 .and_then(|e| e.first())
531 .is_some_and(|v| v == "Z30")
532 && s.elements
533 .get(2)
534 .and_then(|e| e.first())
535 .is_some_and(|v| v == "Z07")
536 }) {
537 return ConditionResult::True;
538 }
539 }
540 }
541 ConditionResult::False
542 }
543
544 fn evaluate_297(&self, ctx: &EvaluationContext) -> ConditionResult {
547 let nav = match ctx.navigator() {
548 Some(n) => n,
549 None => return ConditionResult::Unknown,
550 };
551 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
552 let mut keys: Vec<(String, String)> = Vec::new();
554 for i in 0..sg8_count {
555 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
556 for seq in &seq_segs {
557 let qual = seq
558 .elements
559 .first()
560 .and_then(|e| e.first())
561 .map(|s| s.as_str());
562 if matches!(qual, Some("Z02") | Some("ZE3")) {
563 let pia_segs = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
564 let has_pia5 = pia_segs.iter().any(|s| {
565 s.elements
566 .first()
567 .and_then(|e| e.first())
568 .is_some_and(|v| v == "5")
569 });
570 if has_pia5 {
571 let zeitraum_id = seq
572 .elements
573 .get(1)
574 .and_then(|e| e.first())
575 .cloned()
576 .unwrap_or_default();
577 if !zeitraum_id.is_empty() {
578 keys.push((qual.unwrap_or_default().to_string(), zeitraum_id));
579 }
580 }
581 }
582 }
583 }
584 if keys.is_empty() {
585 return ConditionResult::Unknown;
586 }
587 let mut seen = std::collections::HashSet::new();
588 ConditionResult::from(keys.iter().any(|k| !seen.insert(k)))
589 }
590
591 fn evaluate_312(&self, ctx: &EvaluationContext) -> ConditionResult {
593 ctx.dtm_lt("137", "202603312200+00")
594 }
595
596 fn evaluate_313(&self, ctx: &EvaluationContext) -> ConditionResult {
598 ctx.dtm_ge("137", "202603312200+00")
599 }
600
601 fn evaluate_326(&self, ctx: &EvaluationContext) -> ConditionResult {
604 ctx.external.evaluate("market_location_not_decommissioned")
605 }
606
607 fn evaluate_328(&self, ctx: &EvaluationContext) -> ConditionResult {
610 ctx.external.evaluate("market_location_decommissioned")
611 }
612
613 fn evaluate_346(&self, ctx: &EvaluationContext) -> ConditionResult {
615 let nav = match ctx.navigator() {
616 Some(n) => n,
617 None => {
618 let has_cci = ctx.has_qualifier("CCI", 2, "E13");
620 let has_cav = ctx.has_qualifier("CAV", 0, "MME");
621 return match (has_cci, has_cav) {
622 (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
623 (ConditionResult::False, _) | (_, ConditionResult::False) => {
624 ConditionResult::False
625 }
626 _ => ConditionResult::Unknown,
627 };
628 }
629 };
630 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
631 for i in 0..sg8_count {
632 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
633 for j in 0..sg10_count {
634 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
635 let has_cci_e13 = ccis.iter().any(|s| {
636 s.elements
637 .get(2)
638 .and_then(|e| e.first())
639 .is_some_and(|v| v == "E13")
640 });
641 if has_cci_e13 {
642 let cavs =
643 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
644 if cavs.iter().any(|s| {
645 s.elements
646 .first()
647 .and_then(|e| e.first())
648 .is_some_and(|v| v == "MME")
649 }) {
650 return ConditionResult::True;
651 }
652 }
653 }
654 }
655 ConditionResult::False
656 }
657
658 fn evaluate_413(&self, ctx: &EvaluationContext) -> ConditionResult {
660 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_kumuliert) >= 1)
664 }
665
666 fn evaluate_414(&self, ctx: &EvaluationContext) -> ConditionResult {
668 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_kumuliert) == 0)
670 }
671
672 fn evaluate_415(&self, ctx: &EvaluationContext) -> ConditionResult {
674 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_quarter_hour) >= 2)
677 }
678
679 fn evaluate_416(&self, ctx: &EvaluationContext) -> ConditionResult {
681 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_quarter_hour) == 0)
684 }
685
686 fn evaluate_461(&self, ctx: &EvaluationContext) -> ConditionResult {
688 ctx.any_group_has_qualifier("CAV", 0, "ZG8", &["SG4", "SG8", "SG10"])
692 }
693
694 fn evaluate_534(&self, _ctx: &EvaluationContext) -> ConditionResult {
696 ConditionResult::True
700 }
701
702 fn evaluate_557(&self, _ctx: &EvaluationContext) -> ConditionResult {
704 ConditionResult::True
708 }
709
710 fn evaluate_560(&self, _ctx: &EvaluationContext) -> ConditionResult {
712 ConditionResult::True
714 }
715
716 fn evaluate_561(&self, _ctx: &EvaluationContext) -> ConditionResult {
718 ConditionResult::True
720 }
721
722 fn evaluate_562(&self, _ctx: &EvaluationContext) -> ConditionResult {
724 ConditionResult::True
726 }
727
728 fn evaluate_564(&self, _ctx: &EvaluationContext) -> ConditionResult {
730 ConditionResult::True
732 }
733
734 fn evaluate_565(&self, _ctx: &EvaluationContext) -> ConditionResult {
736 ConditionResult::True
738 }
739
740 fn evaluate_578(&self, _ctx: &EvaluationContext) -> ConditionResult {
742 ConditionResult::True
744 }
745
746 fn evaluate_681(&self, _ctx: &EvaluationContext) -> ConditionResult {
748 ConditionResult::True
750 }
751
752 fn evaluate_686(&self, _ctx: &EvaluationContext) -> ConditionResult {
754 ConditionResult::True
756 }
757
758 fn evaluate_2000(&self, ctx: &EvaluationContext) -> ConditionResult {
761 let nav = match ctx.navigator() {
764 Some(n) => n,
765 None => {
766 let count = ctx.count_qualified_in_group("LOC", 0, "Z16", &["SG4", "SG5"]);
767 return ConditionResult::from(count == 1);
768 }
769 };
770 let sg4_count = nav.group_instance_count(&["SG4"]);
771 if sg4_count == 0 {
772 return ConditionResult::Unknown;
773 }
774 for i in 0..sg4_count {
775 let sg5_count = nav.child_group_instance_count(&["SG4"], i, "SG5");
776 let mut loc_z16_count = 0usize;
777 for j in 0..sg5_count {
778 let locs = nav.find_segments_in_child_group("LOC", &["SG4"], i, "SG5", j);
779 for loc in &locs {
780 if loc
781 .elements
782 .first()
783 .and_then(|e| e.first())
784 .is_some_and(|v| v == "Z16")
785 {
786 loc_z16_count += 1;
787 }
788 }
789 }
790 if loc_z16_count != 1 {
791 return ConditionResult::False;
792 }
793 }
794 ConditionResult::True
795 }
796
797 fn evaluate_2016(&self, ctx: &EvaluationContext) -> ConditionResult {
800 let nav = match ctx.navigator() {
804 Some(n) => n,
805 None => return ConditionResult::Unknown,
806 };
807 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
808 let mut required_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
809 for i in 0..sg6_count {
810 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
811 for rff in &rffs {
812 let qual = rff
813 .elements
814 .first()
815 .and_then(|e| e.first())
816 .map(|s| s.as_str());
817 if matches!(qual, Some("Z49") | Some("Z53")) {
818 if let Some(zeitraum_id) = rff.elements.first().and_then(|e| e.get(2)) {
819 if !zeitraum_id.is_empty() {
820 required_ids.insert(zeitraum_id.clone());
821 }
822 }
823 }
824 }
825 }
826 if required_ids.is_empty() {
827 return ConditionResult::Unknown;
828 }
829 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
831 let mut found_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
832 for i in 0..sg8_count {
833 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
834 for seq in &seqs {
835 if let Some(ref_id) = seq.elements.get(1).and_then(|e| e.first()) {
836 if !ref_id.is_empty() {
837 found_ids.insert(ref_id.clone());
838 }
839 }
840 }
841 }
842 ConditionResult::from(required_ids.iter().all(|id| found_ids.contains(id)))
843 }
844
845 fn evaluate_2121(&self, ctx: &EvaluationContext) -> ConditionResult {
848 ctx.any_group_has_any_qualifier("SEQ", 0, &["Z01", "Z80", "Z81"], &["SG4", "SG8"])
851 }
852}