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.this_group_has_qualified_value(
356 "PIA",
357 0,
358 "Z02",
359 1,
360 0,
361 &["1-02-0-002", "1-02-0-003", "1-02-0-004"],
362 &["SG4", "SG8"],
363 )
364 }
365
366 fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
369 let nav = match ctx.navigator() {
370 Some(n) => n,
371 None => return ConditionResult::Unknown,
372 };
373 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
374 let mut sg8_data: Vec<(String, String)> = Vec::new();
375 for i in 0..sg8_count {
376 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
377 let zeitraum_id = seqs
378 .iter()
379 .find(|s| {
380 s.elements
381 .first()
382 .and_then(|e| e.first())
383 .is_some_and(|v| v == "Z45")
384 })
385 .and_then(|s| s.elements.get(1))
386 .and_then(|e| e.first())
387 .filter(|v| !v.is_empty())
388 .cloned();
389 if let Some(zid) = zeitraum_id {
390 let pias = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
391 let article_id = pias
392 .iter()
393 .find(|s| {
394 s.elements
395 .first()
396 .and_then(|e| e.first())
397 .is_some_and(|v| v == "Z02")
398 })
399 .and_then(|s| s.elements.get(1))
400 .and_then(|e| e.first())
401 .cloned()
402 .unwrap_or_default();
403 sg8_data.push((zid, article_id));
404 }
405 }
406 for i in 0..sg8_data.len() {
407 for j in (i + 1)..sg8_data.len() {
408 if sg8_data[i].0 == sg8_data[j].0 {
409 let (id_i, id_j) = (&sg8_data[i].1, &sg8_data[j].1);
410 let i_is_002 = id_i == "1-02-0-002";
411 let j_is_002 = id_j == "1-02-0-002";
412 let i_is_003_004 = id_i == "1-02-0-003" || id_i == "1-02-0-004";
413 let j_is_003_004 = id_j == "1-02-0-003" || id_j == "1-02-0-004";
414 if (i_is_002 && j_is_003_004) || (j_is_002 && i_is_003_004) {
415 return ConditionResult::True;
416 }
417 }
418 }
419 }
420 if sg8_data.is_empty() {
421 ConditionResult::Unknown
422 } else {
423 ConditionResult::False
424 }
425 }
426
427 fn evaluate_242(&self, ctx: &EvaluationContext) -> ConditionResult {
429 let nav = match ctx.navigator() {
430 Some(n) => n,
431 None => return ConditionResult::Unknown,
432 };
433 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
434 let mut ids: Vec<String> = Vec::new();
435 for i in 0..sg8_count {
436 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
437 for seq in &seq_segs {
438 let qual = seq
439 .elements
440 .first()
441 .and_then(|e| e.first())
442 .map(|s| s.as_str());
443 if matches!(qual, Some("Z78") | Some("ZC7") | Some("ZC8") | Some("ZD5")) {
444 if let Some(id) = seq.elements.get(1).and_then(|e| e.first()) {
445 if !id.is_empty() {
446 ids.push(id.clone());
447 }
448 }
449 }
450 }
451 }
452 if ids.is_empty() {
453 return ConditionResult::Unknown;
454 }
455 let mut seen = std::collections::HashSet::new();
456 ConditionResult::from(ids.iter().any(|id| !seen.insert(id.as_str())))
457 }
458
459 fn evaluate_253(&self, ctx: &EvaluationContext) -> ConditionResult {
461 match ctx.has_segment_matching("STS", &[(0, 0, "E01"), (2, 0, "ZC9")]) {
462 ConditionResult::True => ConditionResult::False,
463 ConditionResult::False => ConditionResult::True,
464 ConditionResult::Unknown => ConditionResult::Unknown,
465 }
466 }
467
468 fn evaluate_258(&self, ctx: &EvaluationContext) -> ConditionResult {
470 let nav = match ctx.navigator() {
471 Some(n) => n,
472 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
473 };
474 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
475 for i in 0..sg8_count {
476 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
477 let has_z01 = seq_segs.iter().any(|s| {
478 s.elements
479 .first()
480 .and_then(|e| e.first())
481 .is_some_and(|v| v == "Z01")
482 });
483 if has_z01 {
484 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
485 for j in 0..sg10_count {
486 let ccis =
487 nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
488 if ccis.iter().any(|s| {
489 s.elements
490 .first()
491 .and_then(|e| e.first())
492 .is_some_and(|v| v == "Z30")
493 && s.elements
494 .get(2)
495 .and_then(|e| e.first())
496 .is_some_and(|v| v == "Z07")
497 }) {
498 return ConditionResult::True;
499 }
500 }
501 }
502 }
503 ConditionResult::False
504 }
505
506 fn evaluate_263(&self, ctx: &EvaluationContext) -> ConditionResult {
509 let nav = match ctx.navigator() {
510 Some(n) => n,
511 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
512 };
513 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
514 for i in 0..sg8_count {
515 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
516 let has_z01 = seq_segs.iter().any(|s| {
517 s.elements
518 .first()
519 .and_then(|e| e.first())
520 .is_some_and(|v| v == "Z01")
521 });
522 if !has_z01 {
523 continue;
524 }
525 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
526 for j in 0..sg10_count {
527 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
528 if ccis.iter().any(|s| {
529 s.elements
530 .first()
531 .and_then(|e| e.first())
532 .is_some_and(|v| v == "Z30")
533 && s.elements
534 .get(2)
535 .and_then(|e| e.first())
536 .is_some_and(|v| v == "Z07")
537 }) {
538 return ConditionResult::True;
539 }
540 }
541 }
542 ConditionResult::False
543 }
544
545 fn evaluate_297(&self, ctx: &EvaluationContext) -> ConditionResult {
548 let nav = match ctx.navigator() {
549 Some(n) => n,
550 None => return ConditionResult::Unknown,
551 };
552 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
553 let mut keys: Vec<(String, String)> = Vec::new();
555 for i in 0..sg8_count {
556 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
557 for seq in &seq_segs {
558 let qual = seq
559 .elements
560 .first()
561 .and_then(|e| e.first())
562 .map(|s| s.as_str());
563 if matches!(qual, Some("Z02") | Some("ZE3")) {
564 let pia_segs = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
565 let has_pia5 = pia_segs.iter().any(|s| {
566 s.elements
567 .first()
568 .and_then(|e| e.first())
569 .is_some_and(|v| v == "5")
570 });
571 if has_pia5 {
572 let zeitraum_id = seq
573 .elements
574 .get(1)
575 .and_then(|e| e.first())
576 .cloned()
577 .unwrap_or_default();
578 if !zeitraum_id.is_empty() {
579 keys.push((qual.unwrap_or_default().to_string(), zeitraum_id));
580 }
581 }
582 }
583 }
584 }
585 if keys.is_empty() {
586 return ConditionResult::Unknown;
587 }
588 let mut seen = std::collections::HashSet::new();
589 ConditionResult::from(keys.iter().any(|k| !seen.insert(k)))
590 }
591
592 fn evaluate_312(&self, ctx: &EvaluationContext) -> ConditionResult {
594 ctx.dtm_lt("137", "202603312200+00")
595 }
596
597 fn evaluate_313(&self, ctx: &EvaluationContext) -> ConditionResult {
599 ctx.dtm_ge("137", "202603312200+00")
600 }
601
602 fn evaluate_326(&self, ctx: &EvaluationContext) -> ConditionResult {
605 ctx.external.evaluate("market_location_not_decommissioned")
606 }
607
608 fn evaluate_328(&self, ctx: &EvaluationContext) -> ConditionResult {
611 ctx.external.evaluate("market_location_decommissioned")
612 }
613
614 fn evaluate_346(&self, ctx: &EvaluationContext) -> ConditionResult {
616 let nav = match ctx.navigator() {
617 Some(n) => n,
618 None => {
619 let has_cci = ctx.has_qualifier("CCI", 2, "E13");
621 let has_cav = ctx.has_qualifier("CAV", 0, "MME");
622 return match (has_cci, has_cav) {
623 (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
624 (ConditionResult::False, _) | (_, ConditionResult::False) => {
625 ConditionResult::False
626 }
627 _ => ConditionResult::Unknown,
628 };
629 }
630 };
631 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
632 for i in 0..sg8_count {
633 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
634 for j in 0..sg10_count {
635 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
636 let has_cci_e13 = ccis.iter().any(|s| {
637 s.elements
638 .get(2)
639 .and_then(|e| e.first())
640 .is_some_and(|v| v == "E13")
641 });
642 if has_cci_e13 {
643 let cavs =
644 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
645 if cavs.iter().any(|s| {
646 s.elements
647 .first()
648 .and_then(|e| e.first())
649 .is_some_and(|v| v == "MME")
650 }) {
651 return ConditionResult::True;
652 }
653 }
654 }
655 }
656 ConditionResult::False
657 }
658
659 fn evaluate_413(&self, ctx: &EvaluationContext) -> ConditionResult {
661 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_kumuliert) >= 1)
665 }
666
667 fn evaluate_414(&self, ctx: &EvaluationContext) -> ConditionResult {
669 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_kumuliert) == 0)
671 }
672
673 fn evaluate_415(&self, ctx: &EvaluationContext) -> ConditionResult {
675 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_quarter_hour) >= 2)
678 }
679
680 fn evaluate_416(&self, ctx: &EvaluationContext) -> ConditionResult {
682 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_quarter_hour) == 0)
685 }
686
687 fn evaluate_461(&self, ctx: &EvaluationContext) -> ConditionResult {
689 ctx.this_group_has_qualifier("CAV", 0, "ZG8", &["SG4", "SG8", "SG10"])
694 }
695
696 fn evaluate_534(&self, _ctx: &EvaluationContext) -> ConditionResult {
698 ConditionResult::True
702 }
703
704 fn evaluate_557(&self, _ctx: &EvaluationContext) -> ConditionResult {
706 ConditionResult::True
710 }
711
712 fn evaluate_560(&self, _ctx: &EvaluationContext) -> ConditionResult {
714 ConditionResult::True
716 }
717
718 fn evaluate_561(&self, _ctx: &EvaluationContext) -> ConditionResult {
720 ConditionResult::True
722 }
723
724 fn evaluate_562(&self, _ctx: &EvaluationContext) -> ConditionResult {
726 ConditionResult::True
728 }
729
730 fn evaluate_564(&self, _ctx: &EvaluationContext) -> ConditionResult {
732 ConditionResult::True
734 }
735
736 fn evaluate_565(&self, _ctx: &EvaluationContext) -> ConditionResult {
738 ConditionResult::True
740 }
741
742 fn evaluate_578(&self, _ctx: &EvaluationContext) -> ConditionResult {
744 ConditionResult::True
746 }
747
748 fn evaluate_681(&self, _ctx: &EvaluationContext) -> ConditionResult {
750 ConditionResult::True
752 }
753
754 fn evaluate_686(&self, _ctx: &EvaluationContext) -> ConditionResult {
756 ConditionResult::True
758 }
759
760 fn evaluate_2000(&self, ctx: &EvaluationContext) -> ConditionResult {
763 let nav = match ctx.navigator() {
766 Some(n) => n,
767 None => {
768 let count = ctx.count_qualified_in_group("LOC", 0, "Z16", &["SG4", "SG5"]);
769 return ConditionResult::from(count == 1);
770 }
771 };
772 let sg4_count = nav.group_instance_count(&["SG4"]);
773 if sg4_count == 0 {
774 return ConditionResult::Unknown;
775 }
776 for i in 0..sg4_count {
777 let sg5_count = nav.child_group_instance_count(&["SG4"], i, "SG5");
778 let mut loc_z16_count = 0usize;
779 for j in 0..sg5_count {
780 let locs = nav.find_segments_in_child_group("LOC", &["SG4"], i, "SG5", j);
781 for loc in &locs {
782 if loc
783 .elements
784 .first()
785 .and_then(|e| e.first())
786 .is_some_and(|v| v == "Z16")
787 {
788 loc_z16_count += 1;
789 }
790 }
791 }
792 if loc_z16_count != 1 {
793 return ConditionResult::False;
794 }
795 }
796 ConditionResult::True
797 }
798
799 fn evaluate_2016(&self, ctx: &EvaluationContext) -> ConditionResult {
802 let nav = match ctx.navigator() {
806 Some(n) => n,
807 None => return ConditionResult::Unknown,
808 };
809 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
810 let mut required_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
811 for i in 0..sg6_count {
812 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
813 for rff in &rffs {
814 let qual = rff
815 .elements
816 .first()
817 .and_then(|e| e.first())
818 .map(|s| s.as_str());
819 if matches!(qual, Some("Z49") | Some("Z53")) {
820 if let Some(zeitraum_id) = rff.elements.first().and_then(|e| e.get(2)) {
821 if !zeitraum_id.is_empty() {
822 required_ids.insert(zeitraum_id.clone());
823 }
824 }
825 }
826 }
827 }
828 if required_ids.is_empty() {
829 return ConditionResult::Unknown;
830 }
831 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
833 let mut found_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
834 for i in 0..sg8_count {
835 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
836 for seq in &seqs {
837 if let Some(ref_id) = seq.elements.get(1).and_then(|e| e.first()) {
838 if !ref_id.is_empty() {
839 found_ids.insert(ref_id.clone());
840 }
841 }
842 }
843 }
844 ConditionResult::from(required_ids.iter().all(|id| found_ids.contains(id)))
845 }
846
847 fn evaluate_2121(&self, ctx: &EvaluationContext) -> ConditionResult {
850 ctx.any_group_has_any_qualifier("SEQ", 0, &["Z01", "Z80", "Z81"], &["SG4", "SG8"])
853 }
854}