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 if let Some(scope) = ctx.enclosing_scope("SG4") {
165 let ide_24 = ctx
166 .find_segments_at(scope, "IDE")
167 .iter()
168 .any(|s| s.get_element(0) == "24");
169 let sts = ctx.find_segments_at(scope, "STS").iter().any(|s| {
170 s.get_element(0) == "E01"
171 && matches!(
172 (s.get_component(2, 0), s.get_component(2, 1)),
173 ("A04", "E_0017") | ("A03", "E_0052")
174 )
175 });
176 return ConditionResult::from(ide_24 && !sts);
177 }
178 let nav = match ctx.navigator() {
179 Some(n) => n,
180 None => {
181 let sts_segs = ctx.find_segments_with_qualifier("STS", 0, "E01");
182 let found = sts_segs.iter().any(|s| {
183 let code = s
184 .elements
185 .get(2)
186 .and_then(|e| e.first())
187 .map(|v| v.as_str());
188 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
189 (code == Some("A04") && list == Some("E_0017"))
190 || (code == Some("A03") && list == Some("E_0052"))
191 });
192 return ConditionResult::from(!found);
193 }
194 };
195 let sg4_count = nav.group_instance_count(&["SG4"]);
196 for i in 0..sg4_count {
197 let ide_segs = nav.find_segments_in_group("IDE", &["SG4"], i);
198 let has_ide_24 = ide_segs.iter().any(|s| {
199 s.elements
200 .first()
201 .and_then(|e| e.first())
202 .is_some_and(|v| v == "24")
203 });
204 if !has_ide_24 {
205 continue;
206 }
207 let sts_segs = nav.find_segments_in_group("STS", &["SG4"], i);
208 let found = sts_segs.iter().any(|s| {
209 let qual = s
210 .elements
211 .first()
212 .and_then(|e| e.first())
213 .map(|v| v.as_str());
214 let code = s
215 .elements
216 .get(2)
217 .and_then(|e| e.first())
218 .map(|v| v.as_str());
219 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
220 qual == Some("E01")
221 && ((code == Some("A04") && list == Some("E_0017"))
222 || (code == Some("A03") && list == Some("E_0052")))
223 });
224 if !found {
225 return ConditionResult::True;
226 }
227 }
228 ConditionResult::False
229 }
230
231 fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
234 if let Some(scope) = ctx.enclosing_scope("SG4") {
237 let ide_24 = ctx
238 .find_segments_at(scope, "IDE")
239 .iter()
240 .any(|s| s.get_element(0) == "24");
241 let sts = ctx.find_segments_at(scope, "STS").iter().any(|s| {
242 s.get_element(0) == "E01"
243 && matches!(
244 (s.get_component(2, 0), s.get_component(2, 1)),
245 ("A06", "E_0017") | ("A05", "E_0052")
246 )
247 });
248 return ConditionResult::from(ide_24 && !sts);
249 }
250 let nav = match ctx.navigator() {
251 Some(n) => n,
252 None => {
253 let sts_segs = ctx.find_segments_with_qualifier("STS", 0, "E01");
254 let found = sts_segs.iter().any(|s| {
255 let code = s
256 .elements
257 .get(2)
258 .and_then(|e| e.first())
259 .map(|v| v.as_str());
260 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
261 (code == Some("A06") && list == Some("E_0017"))
262 || (code == Some("A05") && list == Some("E_0052"))
263 });
264 return ConditionResult::from(!found);
265 }
266 };
267 let sg4_count = nav.group_instance_count(&["SG4"]);
268 for i in 0..sg4_count {
269 let ide_segs = nav.find_segments_in_group("IDE", &["SG4"], i);
270 let has_ide_24 = ide_segs.iter().any(|s| {
271 s.elements
272 .first()
273 .and_then(|e| e.first())
274 .is_some_and(|v| v == "24")
275 });
276 if !has_ide_24 {
277 continue;
278 }
279 let sts_segs = nav.find_segments_in_group("STS", &["SG4"], i);
280 let found = sts_segs.iter().any(|s| {
281 let qual = s
282 .elements
283 .first()
284 .and_then(|e| e.first())
285 .map(|v| v.as_str());
286 let code = s
287 .elements
288 .get(2)
289 .and_then(|e| e.first())
290 .map(|v| v.as_str());
291 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
292 qual == Some("E01")
293 && ((code == Some("A06") && list == Some("E_0017"))
294 || (code == Some("A05") && list == Some("E_0052")))
295 });
296 if !found {
297 return ConditionResult::True;
298 }
299 }
300 ConditionResult::False
301 }
302
303 fn evaluate_79(&self, ctx: &EvaluationContext) -> ConditionResult {
305 ctx.has_segment_matching("STS", &[(0, 0, "7"), (2, 0, "Z33")])
308 }
309
310 fn evaluate_136(&self, ctx: &EvaluationContext) -> ConditionResult {
312 if let Some(_scope) = ctx.enclosing_scope("SG8") {
315 return ConditionResult::from(
316 ctx.enclosing_child_segments("SG8", "SG10", &["CCI", "CAV"])
317 .unwrap_or_default()
318 .iter()
319 .any(|segs| {
320 segs.iter()
321 .any(|s| s.id == "CCI" && s.get_component(2, 0) == "E13")
322 && segs
323 .iter()
324 .any(|s| s.id == "CAV" && s.get_element(0) == "EHZ")
325 }),
326 );
327 }
328 let nav = match ctx.navigator() {
329 Some(n) => n,
330 None => return ctx.has_qualified_value("CAV", 0, "EHZ", 0, 0, &["EHZ"]),
331 };
332 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
333 for i in 0..sg8_count {
334 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
335 for j in 0..sg10_count {
336 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
337 let has_cci_e13 = ccis.iter().any(|s| {
338 s.elements
339 .get(2)
340 .and_then(|e| e.first())
341 .is_some_and(|v| v == "E13")
342 });
343 if has_cci_e13 {
344 let cavs =
345 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
346 if cavs.iter().any(|s| {
347 s.elements
348 .first()
349 .and_then(|e| e.first())
350 .is_some_and(|v| v == "EHZ")
351 }) {
352 return ConditionResult::True;
353 }
354 }
355 }
356 }
357 ConditionResult::False
358 }
359
360 fn evaluate_139(&self, ctx: &EvaluationContext) -> ConditionResult {
363 if let Some(scope) = ctx.enclosing_scope("SG8") {
366 return ConditionResult::from(
367 !ctx.find_segments_at(scope, "CAV")
368 .iter()
369 .any(|s| s.get_element(0) == "IVA"),
370 );
371 }
372 let nav = match ctx.navigator() {
373 Some(n) => n,
374 None => return ctx.lacks_qualifier("CAV", 0, "IVA"),
375 };
376 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
377 for i in 0..sg8_count {
378 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
379 for j in 0..sg10_count {
380 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
381 if cavs.iter().any(|s| {
382 s.elements
383 .first()
384 .and_then(|e| e.first())
385 .is_some_and(|v| v == "IVA")
386 }) {
387 return ConditionResult::False;
388 }
389 }
390 }
391 ConditionResult::True
392 }
393
394 fn evaluate_157(&self, ctx: &EvaluationContext) -> ConditionResult {
396 let result = ctx.has_segment_matching("STS", &[(0, 0, "7"), (2, 0, "Z33"), (3, 0, "ZZB")]);
397 match result {
398 ConditionResult::True => ConditionResult::False,
399 ConditionResult::False => ConditionResult::True,
400 ConditionResult::Unknown => ConditionResult::Unknown,
401 }
402 }
403
404 fn evaluate_158(&self, ctx: &EvaluationContext) -> ConditionResult {
406 ConditionResult::from(ctx.self_segment_value_equals("DTM", 0, 2, "106"))
407 }
408
409 fn evaluate_168(&self, ctx: &EvaluationContext) -> ConditionResult {
411 ctx.this_group_has_qualified_value(
413 "PIA",
414 0,
415 "Z02",
416 1,
417 0,
418 &["1-02-0-002", "1-02-0-003", "1-02-0-004"],
419 &["SG4", "SG8"],
420 )
421 }
422
423 fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
426 let nav = match ctx.navigator() {
427 Some(n) => n,
428 None => return ConditionResult::Unknown,
429 };
430 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
431 let mut sg8_data: Vec<(String, String)> = Vec::new();
432 for i in 0..sg8_count {
433 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
434 let zeitraum_id = seqs
435 .iter()
436 .find(|s| {
437 s.elements
438 .first()
439 .and_then(|e| e.first())
440 .is_some_and(|v| v == "Z45")
441 })
442 .and_then(|s| s.elements.get(1))
443 .and_then(|e| e.first())
444 .filter(|v| !v.is_empty())
445 .cloned();
446 if let Some(zid) = zeitraum_id {
447 let pias = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
448 let article_id = pias
449 .iter()
450 .find(|s| {
451 s.elements
452 .first()
453 .and_then(|e| e.first())
454 .is_some_and(|v| v == "Z02")
455 })
456 .and_then(|s| s.elements.get(1))
457 .and_then(|e| e.first())
458 .cloned()
459 .unwrap_or_default();
460 sg8_data.push((zid, article_id));
461 }
462 }
463 for i in 0..sg8_data.len() {
464 for j in (i + 1)..sg8_data.len() {
465 if sg8_data[i].0 == sg8_data[j].0 {
466 let (id_i, id_j) = (&sg8_data[i].1, &sg8_data[j].1);
467 let i_is_002 = id_i == "1-02-0-002";
468 let j_is_002 = id_j == "1-02-0-002";
469 let i_is_003_004 = id_i == "1-02-0-003" || id_i == "1-02-0-004";
470 let j_is_003_004 = id_j == "1-02-0-003" || id_j == "1-02-0-004";
471 if (i_is_002 && j_is_003_004) || (j_is_002 && i_is_003_004) {
472 return ConditionResult::True;
473 }
474 }
475 }
476 }
477 if sg8_data.is_empty() {
478 ConditionResult::Unknown
479 } else {
480 ConditionResult::False
481 }
482 }
483
484 fn evaluate_242(&self, ctx: &EvaluationContext) -> ConditionResult {
486 let nav = match ctx.navigator() {
487 Some(n) => n,
488 None => return ConditionResult::Unknown,
489 };
490 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
491 let mut ids: Vec<String> = Vec::new();
492 for i in 0..sg8_count {
493 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
494 for seq in &seq_segs {
495 let qual = seq
496 .elements
497 .first()
498 .and_then(|e| e.first())
499 .map(|s| s.as_str());
500 if matches!(qual, Some("Z78") | Some("ZC7") | Some("ZC8") | Some("ZD5")) {
501 if let Some(id) = seq.elements.get(1).and_then(|e| e.first()) {
502 if !id.is_empty() {
503 ids.push(id.clone());
504 }
505 }
506 }
507 }
508 }
509 if ids.is_empty() {
510 return ConditionResult::Unknown;
511 }
512 let mut seen = std::collections::HashSet::new();
513 ConditionResult::from(ids.iter().any(|id| !seen.insert(id.as_str())))
514 }
515
516 fn evaluate_253(&self, ctx: &EvaluationContext) -> ConditionResult {
518 match ctx.has_segment_matching("STS", &[(0, 0, "E01"), (2, 0, "ZC9")]) {
519 ConditionResult::True => ConditionResult::False,
520 ConditionResult::False => ConditionResult::True,
521 ConditionResult::Unknown => ConditionResult::Unknown,
522 }
523 }
524
525 fn evaluate_258(&self, ctx: &EvaluationContext) -> ConditionResult {
527 if let (Some(sg8), Some(nav)) = (ctx.enclosing_scope("SG8"), ctx.navigator()) {
530 let is_z01 = nav
531 .find_segments_in_instance("SEQ", sg8)
532 .iter()
533 .any(|s| s.get_element(0) == "Z01");
534 let verbrauch = nav
535 .find_segments_in_subtree("CCI", sg8)
536 .iter()
537 .any(|s| s.get_element(0) == "Z30" && s.get_component(2, 0) == "Z07");
538 return ConditionResult::from(is_z01 && verbrauch);
539 }
540 let nav = match ctx.navigator() {
541 Some(n) => n,
542 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
543 };
544 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
545 for i in 0..sg8_count {
546 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
547 let has_z01 = seq_segs.iter().any(|s| {
548 s.elements
549 .first()
550 .and_then(|e| e.first())
551 .is_some_and(|v| v == "Z01")
552 });
553 if has_z01 {
554 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
555 for j in 0..sg10_count {
556 let ccis =
557 nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
558 if ccis.iter().any(|s| {
559 s.elements
560 .first()
561 .and_then(|e| e.first())
562 .is_some_and(|v| v == "Z30")
563 && s.elements
564 .get(2)
565 .and_then(|e| e.first())
566 .is_some_and(|v| v == "Z07")
567 }) {
568 return ConditionResult::True;
569 }
570 }
571 }
572 }
573 ConditionResult::False
574 }
575
576 fn evaluate_263(&self, ctx: &EvaluationContext) -> ConditionResult {
578 self.fallback.evaluate(20, ctx)
581 }
582
583 fn evaluate_297(&self, ctx: &EvaluationContext) -> ConditionResult {
586 let nav = match ctx.navigator() {
587 Some(n) => n,
588 None => return ConditionResult::Unknown,
589 };
590 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
591 let mut keys: Vec<(String, String)> = Vec::new();
593 for i in 0..sg8_count {
594 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
595 for seq in &seq_segs {
596 let qual = seq
597 .elements
598 .first()
599 .and_then(|e| e.first())
600 .map(|s| s.as_str());
601 if matches!(qual, Some("Z02") | Some("ZE3")) {
602 let pia_segs = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
603 let has_pia5 = pia_segs.iter().any(|s| {
604 s.elements
605 .first()
606 .and_then(|e| e.first())
607 .is_some_and(|v| v == "5")
608 });
609 if has_pia5 {
610 let zeitraum_id = seq
611 .elements
612 .get(1)
613 .and_then(|e| e.first())
614 .cloned()
615 .unwrap_or_default();
616 if !zeitraum_id.is_empty() {
617 keys.push((qual.unwrap_or_default().to_string(), zeitraum_id));
618 }
619 }
620 }
621 }
622 }
623 if keys.is_empty() {
624 return ConditionResult::Unknown;
625 }
626 let mut seen = std::collections::HashSet::new();
627 ConditionResult::from(keys.iter().any(|k| !seen.insert(k)))
628 }
629
630 fn evaluate_312(&self, ctx: &EvaluationContext) -> ConditionResult {
632 ctx.dtm_lt("137", "202603312200+00")
633 }
634
635 fn evaluate_313(&self, ctx: &EvaluationContext) -> ConditionResult {
637 ctx.dtm_ge("137", "202603312200+00")
638 }
639
640 fn evaluate_326(&self, ctx: &EvaluationContext) -> ConditionResult {
643 ctx.external.evaluate("market_location_not_decommissioned")
644 }
645
646 fn evaluate_328(&self, ctx: &EvaluationContext) -> ConditionResult {
649 ctx.external.evaluate("market_location_decommissioned")
650 }
651
652 fn evaluate_346(&self, ctx: &EvaluationContext) -> ConditionResult {
654 if let Some(_scope) = ctx.enclosing_scope("SG8") {
657 return ConditionResult::from(
658 ctx.enclosing_child_segments("SG8", "SG10", &["CCI", "CAV"])
659 .unwrap_or_default()
660 .iter()
661 .any(|segs| {
662 segs.iter()
663 .any(|s| s.id == "CCI" && s.get_component(2, 0) == "E13")
664 && segs
665 .iter()
666 .any(|s| s.id == "CAV" && s.get_element(0) == "MME")
667 }),
668 );
669 }
670 let nav = match ctx.navigator() {
671 Some(n) => n,
672 None => {
673 let has_cci = ctx.has_qualifier("CCI", 2, "E13");
675 let has_cav = ctx.has_qualifier("CAV", 0, "MME");
676 return match (has_cci, has_cav) {
677 (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
678 (ConditionResult::False, _) | (_, ConditionResult::False) => {
679 ConditionResult::False
680 }
681 _ => ConditionResult::Unknown,
682 };
683 }
684 };
685 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
686 for i in 0..sg8_count {
687 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
688 for j in 0..sg10_count {
689 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
690 let has_cci_e13 = ccis.iter().any(|s| {
691 s.elements
692 .get(2)
693 .and_then(|e| e.first())
694 .is_some_and(|v| v == "E13")
695 });
696 if has_cci_e13 {
697 let cavs =
698 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
699 if cavs.iter().any(|s| {
700 s.elements
701 .first()
702 .and_then(|e| e.first())
703 .is_some_and(|v| v == "MME")
704 }) {
705 return ConditionResult::True;
706 }
707 }
708 }
709 }
710 ConditionResult::False
711 }
712
713 fn evaluate_413(&self, ctx: &EvaluationContext) -> ConditionResult {
715 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_kumuliert) >= 1)
719 }
720
721 fn evaluate_414(&self, ctx: &EvaluationContext) -> ConditionResult {
723 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_kumuliert) == 0)
725 }
726
727 fn evaluate_415(&self, ctx: &EvaluationContext) -> ConditionResult {
729 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_quarter_hour) >= 2)
732 }
733
734 fn evaluate_416(&self, ctx: &EvaluationContext) -> ConditionResult {
736 ConditionResult::from(ctx.count_sg8_obis_matches(is_obis_wirkarbeit_quarter_hour) == 0)
739 }
740
741 fn evaluate_461(&self, ctx: &EvaluationContext) -> ConditionResult {
743 ctx.this_group_has_qualifier("CAV", 0, "ZG8", &["SG4", "SG8", "SG10"])
748 }
749
750 fn evaluate_534(&self, _ctx: &EvaluationContext) -> ConditionResult {
752 ConditionResult::True
756 }
757
758 fn evaluate_557(&self, _ctx: &EvaluationContext) -> ConditionResult {
760 ConditionResult::True
764 }
765
766 fn evaluate_560(&self, _ctx: &EvaluationContext) -> ConditionResult {
768 ConditionResult::True
770 }
771
772 fn evaluate_561(&self, _ctx: &EvaluationContext) -> ConditionResult {
774 ConditionResult::True
776 }
777
778 fn evaluate_562(&self, _ctx: &EvaluationContext) -> ConditionResult {
780 ConditionResult::True
782 }
783
784 fn evaluate_564(&self, _ctx: &EvaluationContext) -> ConditionResult {
786 ConditionResult::True
788 }
789
790 fn evaluate_565(&self, _ctx: &EvaluationContext) -> ConditionResult {
792 ConditionResult::True
794 }
795
796 fn evaluate_578(&self, _ctx: &EvaluationContext) -> ConditionResult {
798 ConditionResult::True
800 }
801
802 fn evaluate_681(&self, _ctx: &EvaluationContext) -> ConditionResult {
804 ConditionResult::True
806 }
807
808 fn evaluate_686(&self, _ctx: &EvaluationContext) -> ConditionResult {
810 ConditionResult::True
812 }
813
814 fn evaluate_2000(&self, ctx: &EvaluationContext) -> ConditionResult {
817 let nav = match ctx.navigator() {
820 Some(n) => n,
821 None => {
822 let count = ctx.count_qualified_in_group("LOC", 0, "Z16", &["SG4", "SG5"]);
823 return ConditionResult::from(count == 1);
824 }
825 };
826 let sg4_count = nav.group_instance_count(&["SG4"]);
827 if sg4_count == 0 {
828 return ConditionResult::Unknown;
829 }
830 for i in 0..sg4_count {
831 let sg5_count = nav.child_group_instance_count(&["SG4"], i, "SG5");
832 let mut loc_z16_count = 0usize;
833 for j in 0..sg5_count {
834 let locs = nav.find_segments_in_child_group("LOC", &["SG4"], i, "SG5", j);
835 for loc in &locs {
836 if loc
837 .elements
838 .first()
839 .and_then(|e| e.first())
840 .is_some_and(|v| v == "Z16")
841 {
842 loc_z16_count += 1;
843 }
844 }
845 }
846 if loc_z16_count != 1 {
847 return ConditionResult::False;
848 }
849 }
850 ConditionResult::True
851 }
852
853 fn evaluate_2016(&self, ctx: &EvaluationContext) -> ConditionResult {
856 let nav = match ctx.navigator() {
860 Some(n) => n,
861 None => return ConditionResult::Unknown,
862 };
863 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
864 let mut required_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
865 for i in 0..sg6_count {
866 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
867 for rff in &rffs {
868 let qual = rff
869 .elements
870 .first()
871 .and_then(|e| e.first())
872 .map(|s| s.as_str());
873 if matches!(qual, Some("Z49") | Some("Z53")) {
874 if let Some(zeitraum_id) = rff.elements.first().and_then(|e| e.get(2)) {
875 if !zeitraum_id.is_empty() {
876 required_ids.insert(zeitraum_id.clone());
877 }
878 }
879 }
880 }
881 }
882 if required_ids.is_empty() {
883 return ConditionResult::Unknown;
884 }
885 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
887 let mut found_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
888 for i in 0..sg8_count {
889 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
890 for seq in &seqs {
891 if let Some(ref_id) = seq.elements.get(1).and_then(|e| e.first()) {
892 if !ref_id.is_empty() {
893 found_ids.insert(ref_id.clone());
894 }
895 }
896 }
897 }
898 ConditionResult::from(required_ids.iter().all(|id| found_ids.contains(id)))
899 }
900
901 fn evaluate_2121(&self, ctx: &EvaluationContext) -> ConditionResult {
904 ctx.any_group_has_any_qualifier("SEQ", 0, &["Z01", "Z80", "Z81"], &["SG4", "SG8"])
907 }
908}