Skip to main content

automapper_validation/generated/fv2604/
utilmd_strom_conditions_fv2604.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2604/UTILMD_AHB_Strom_2_1_Fehlerkorrektur_20260629.xml
4// Generated: 2026-09-23T18:15:06Z
5// Delegates unchanged conditions to UtilmdStromConditionEvaluatorFV2510 (FV2510).
6// </auto-generated>
7
8#![allow(clippy::style, clippy::complexity)]
9
10#[allow(unused_imports)]
11use crate::eval::format_validators::*;
12use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
13use crate::generated::fv2510::UtilmdStromConditionEvaluatorFV2510;
14use mig_types::segment::OwnedSegment;
15
16/// Condition evaluator for UTILMD_Strom FV2604.
17///
18/// Delegates to [`UtilmdStromConditionEvaluatorFV2510`] for conditions whose AHB description is
19/// unchanged from that version. Local overrides: [160], [182], [183], [203], [271].
20pub struct UtilmdStromConditionEvaluatorFV2604 {
21    fallback: UtilmdStromConditionEvaluatorFV2510,
22}
23
24impl Default for UtilmdStromConditionEvaluatorFV2604 {
25    fn default() -> Self {
26        Self {
27            fallback: UtilmdStromConditionEvaluatorFV2510::default(),
28        }
29    }
30}
31
32/// Condition IDs whose implementation differs from the fallback.
33const FV2604_OVERRIDES: &[u32] = &[160, 182, 183, 203, 271];
34
35impl ConditionEvaluator for UtilmdStromConditionEvaluatorFV2604 {
36    fn message_type(&self) -> &str {
37        "UTILMD_Strom"
38    }
39
40    fn format_version(&self) -> &str {
41        "FV2604"
42    }
43
44    fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
45        match condition {
46            160 => self.evaluate_160(ctx),
47            182 => self.evaluate_182(ctx),
48            183 => self.evaluate_183(ctx),
49            203 => self.evaluate_203(ctx),
50            271 => self.evaluate_271(ctx),
51            other => self.fallback.evaluate(other, ctx),
52        }
53    }
54
55    fn is_external(&self, condition: u32) -> bool {
56        !FV2604_OVERRIDES.contains(&condition) && self.fallback.is_external(condition)
57    }
58
59    fn is_known(&self, condition: u32) -> bool {
60        FV2604_OVERRIDES.contains(&condition) || self.fallback.is_known(condition)
61    }
62}
63
64/// Whether some SG8 has an SG10 whose CCI and CAV segments satisfy `pred`.
65fn sg10_has(
66    ctx: &EvaluationContext,
67    pred: impl Fn(&[OwnedSegment], &[OwnedSegment]) -> bool,
68) -> ConditionResult {
69    let Some(nav) = ctx.navigator() else {
70        let ccis: Vec<OwnedSegment> = ctx.find_segments("CCI").into_iter().cloned().collect();
71        let cavs: Vec<OwnedSegment> = ctx.find_segments("CAV").into_iter().cloned().collect();
72        return ConditionResult::from(pred(&ccis, &cavs));
73    };
74    for i in 0..nav.group_instance_count(&["SG4", "SG8"]) {
75        for j in 0..nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10") {
76            let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
77            let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
78            if pred(&ccis, &cavs) {
79                return ConditionResult::True;
80            }
81        }
82    }
83    ConditionResult::False
84}
85
86impl UtilmdStromConditionEvaluatorFV2604 {
87    /// [160] Wenn der Objektcode im RFF+Z33 (Referenz auf den Objektcode in der Lokationsbündelstruktur) im DE1154 derselben SG8 SEQ+...
88    // Message-wide approximation: some two SG8 SEQ+Z58/ZC9/ZD0/ZD6 share Zeitraum-ID
89    // (SEQ C286 1050), DE1229 code and the RFF+Z33 Objektcode.
90    fn evaluate_160(&self, ctx: &EvaluationContext) -> ConditionResult {
91        let nav = match ctx.navigator() {
92            Some(n) => n,
93            None => return ConditionResult::Unknown,
94        };
95        let mut seen = std::collections::BTreeSet::new();
96        for i in 0..nav.group_instance_count(&["SG4", "SG8"]) {
97            let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
98            let Some(seq) = seqs.first() else { continue };
99            let code = seq
100                .elements
101                .first()
102                .and_then(|e| e.first())
103                .cloned()
104                .unwrap_or_default();
105            if !["Z58", "ZC9", "ZD0", "ZD6"].contains(&code.as_str()) {
106                continue;
107            }
108            let zeitraum = seq
109                .elements
110                .get(1)
111                .and_then(|e| e.first())
112                .cloned()
113                .unwrap_or_default();
114            for rff in
115                nav.find_segments_with_qualifier_in_group("RFF", 0, "Z33", &["SG4", "SG8"], i)
116            {
117                let objekt = rff
118                    .elements
119                    .first()
120                    .and_then(|e| e.get(1))
121                    .cloned()
122                    .unwrap_or_default();
123                if !seen.insert((zeitraum.clone(), code.clone(), objekt)) {
124                    return ConditionResult::True;
125                }
126            }
127        }
128        ConditionResult::False
129    }
130
131    /// [182] Wenn SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+E14 (TLP/TEP) in dieser S...
132    fn evaluate_182(&self, ctx: &EvaluationContext) -> ConditionResult {
133        sg10_has(ctx, |ccis, cavs| {
134            ccis.iter().any(|s| {
135                s.elements
136                    .get(2)
137                    .and_then(|e| e.first())
138                    .is_some_and(|v| v == "ZA6")
139            }) && cavs.iter().any(|s| {
140                s.elements
141                    .first()
142                    .and_then(|e| e.first())
143                    .is_some_and(|v| v == "E14")
144            })
145        })
146    }
147
148    /// [183] Wenn SG10 CCI+Z30++Z07 (Lieferrichtung: Verbrauch) in dieser SG8 vorhanden
149    fn evaluate_183(&self, ctx: &EvaluationContext) -> ConditionResult {
150        sg10_has(ctx, |ccis, _| {
151            ccis.iter().any(|s| {
152                s.elements
153                    .first()
154                    .and_then(|e| e.first())
155                    .is_some_and(|v| v == "Z30")
156                    && s.elements
157                        .get(2)
158                        .and_then(|e| e.first())
159                        .is_some_and(|v| v == "Z07")
160            })
161        })
162    }
163
164    /// [203] Wenn STS+7++E06 / Z39 / ZC6 / ZC7/ ZT6/ ZT7 / Z02 / ZZD vorhanden
165    fn evaluate_203(&self, ctx: &EvaluationContext) -> ConditionResult {
166        ctx.has_qualified_value(
167            "STS",
168            0,
169            "7",
170            2,
171            0,
172            &["E06", "Z39", "ZC6", "ZC7", "ZT6", "ZT7", "Z02", "ZZD"],
173        )
174    }
175
176    /// [271] Wenn das RFF+Z50 (Termine der Marktlokation) aus dieser SG6 (Termine der Marktlokation) auf das gleiche SG5 LOC+Z16 (Mar...
177    // As FV2504's [86] (RFF+Z50 of an SG6 references the LOC+Z16 an SG8 RFF+Z18 does),
178    // and some SG10 carries CCI+++Z83 with CAV+Z53 (kME/mME).
179    fn evaluate_271(&self, ctx: &EvaluationContext) -> ConditionResult {
180        let shared = ctx.groups_share_qualified_value(
181            "RFF",
182            0,
183            "Z50",
184            0,
185            2,
186            &["SG4", "SG6"],
187            "RFF",
188            0,
189            2,
190            &["SG4", "SG8"],
191        );
192        let messtechnik = sg10_has(ctx, |ccis, cavs| {
193            ccis.iter().any(|s| {
194                s.elements
195                    .get(2)
196                    .and_then(|e| e.first())
197                    .is_some_and(|v| v == "Z83")
198            }) && cavs.iter().any(|s| {
199                s.elements
200                    .first()
201                    .and_then(|e| e.first())
202                    .is_some_and(|v| v == "Z53")
203            })
204        });
205        shared.and(messtechnik)
206    }
207}