Skip to main content

automapper_validation/generated/fv2510/
reqote_conditions_fv2510.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2510/REQOTE_AHB_1_1_20250401.xml
4// Generated: 2026-03-12T10:31:57Z
5// </auto-generated>
6
7// LLM-produced bodies aren't idiomatic Rust — silence stylistic lints at
8// file scope so `cargo clippy -D warnings` stays green. Correctness,
9// suspicious, and perf categories stay on so real bugs still surface.
10#![allow(clippy::style, clippy::complexity)]
11
12#[allow(unused_imports)]
13use crate::eval::format_validators::*;
14use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
15
16/// Generated condition evaluator for REQOTE FV2510.
17pub struct ReqoteConditionEvaluatorFV2510 {
18    // External condition IDs that require runtime context.
19    external_conditions: std::collections::HashSet<u32>,
20}
21
22impl Default for ReqoteConditionEvaluatorFV2510 {
23    fn default() -> Self {
24        let mut external_conditions = std::collections::HashSet::new();
25        external_conditions.insert(10);
26        external_conditions.insert(24);
27        external_conditions.insert(28);
28        external_conditions.insert(29);
29        external_conditions.insert(30);
30        external_conditions.insert(31);
31        external_conditions.insert(32);
32        external_conditions.insert(33);
33        external_conditions.insert(35);
34        external_conditions.insert(36);
35        external_conditions.insert(37);
36        external_conditions.insert(38);
37        external_conditions.insert(41);
38        external_conditions.insert(42);
39        external_conditions.insert(43);
40        external_conditions.insert(44);
41        external_conditions.insert(45);
42        external_conditions.insert(47);
43        external_conditions.insert(48);
44        external_conditions.insert(49);
45        external_conditions.insert(50);
46        external_conditions.insert(51);
47        external_conditions.insert(53);
48        external_conditions.insert(492);
49        external_conditions.insert(493);
50        external_conditions.insert(2065);
51        external_conditions.insert(2066);
52        Self {
53            external_conditions,
54        }
55    }
56}
57
58impl ConditionEvaluator for ReqoteConditionEvaluatorFV2510 {
59    fn message_type(&self) -> &str {
60        "REQOTE"
61    }
62
63    fn format_version(&self) -> &str {
64        "FV2510"
65    }
66
67    fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
68        match condition {
69            1 => self.evaluate_1(ctx),
70            2 => self.evaluate_2(ctx),
71            10 => self.evaluate_10(ctx),
72            15 => self.evaluate_15(ctx),
73            16 => self.evaluate_16(ctx),
74            17 => self.evaluate_17(ctx),
75            18 => self.evaluate_18(ctx),
76            19 => self.evaluate_19(ctx),
77            20 => self.evaluate_20(ctx),
78            21 => self.evaluate_21(ctx),
79            22 => self.evaluate_22(ctx),
80            23 => self.evaluate_23(ctx),
81            24 => self.evaluate_24(ctx),
82            25 => self.evaluate_25(ctx),
83            26 => self.evaluate_26(ctx),
84            27 => self.evaluate_27(ctx),
85            28 => self.evaluate_28(ctx),
86            29 => self.evaluate_29(ctx),
87            30 => self.evaluate_30(ctx),
88            31 => self.evaluate_31(ctx),
89            32 => self.evaluate_32(ctx),
90            33 => self.evaluate_33(ctx),
91            35 => self.evaluate_35(ctx),
92            36 => self.evaluate_36(ctx),
93            37 => self.evaluate_37(ctx),
94            38 => self.evaluate_38(ctx),
95            39 => self.evaluate_39(ctx),
96            40 => self.evaluate_40(ctx),
97            41 => self.evaluate_41(ctx),
98            42 => self.evaluate_42(ctx),
99            43 => self.evaluate_43(ctx),
100            44 => self.evaluate_44(ctx),
101            45 => self.evaluate_45(ctx),
102            47 => self.evaluate_47(ctx),
103            48 => self.evaluate_48(ctx),
104            49 => self.evaluate_49(ctx),
105            50 => self.evaluate_50(ctx),
106            51 => self.evaluate_51(ctx),
107            52 => self.evaluate_52(ctx),
108            53 => self.evaluate_53(ctx),
109            490 => self.evaluate_490(ctx),
110            491 => self.evaluate_491(ctx),
111            492 => self.evaluate_492(ctx),
112            493 => self.evaluate_493(ctx),
113            494 => self.evaluate_494(ctx),
114            500 => self.evaluate_500(ctx),
115            501 => self.evaluate_501(ctx),
116            502 => self.evaluate_502(ctx),
117            503 => self.evaluate_503(ctx),
118            504 => self.evaluate_504(ctx),
119            507 => self.evaluate_507(ctx),
120            508 => self.evaluate_508(ctx),
121            509 => self.evaluate_509(ctx),
122            510 => self.evaluate_510(ctx),
123            511 => self.evaluate_511(ctx),
124            512 => self.evaluate_512(ctx),
125            514 => self.evaluate_514(ctx),
126            515 => self.evaluate_515(ctx),
127            516 => self.evaluate_516(ctx),
128            517 => self.evaluate_517(ctx),
129            518 => self.evaluate_518(ctx),
130            520 => self.evaluate_520(ctx),
131            521 => self.evaluate_521(ctx),
132            903 => self.evaluate_903(ctx),
133            906 => self.evaluate_906(ctx),
134            911 => self.evaluate_911(ctx),
135            922 => self.evaluate_922(ctx),
136            931 => self.evaluate_931(ctx),
137            932 => self.evaluate_932(ctx),
138            933 => self.evaluate_933(ctx),
139            934 => self.evaluate_934(ctx),
140            935 => self.evaluate_935(ctx),
141            939 => self.evaluate_939(ctx),
142            940 => self.evaluate_940(ctx),
143            950 => self.evaluate_950(ctx),
144            951 => self.evaluate_951(ctx),
145            960 => self.evaluate_960(ctx),
146            961 => self.evaluate_961(ctx),
147            962 => self.evaluate_962(ctx),
148            967 => self.evaluate_967(ctx),
149            2005 => self.evaluate_2005(ctx),
150            2060 => self.evaluate_2060(ctx),
151            2061 => self.evaluate_2061(ctx),
152            2062 => self.evaluate_2062(ctx),
153            2063 => self.evaluate_2063(ctx),
154            2064 => self.evaluate_2064(ctx),
155            2065 => self.evaluate_2065(ctx),
156            2066 => self.evaluate_2066(ctx),
157            2067 => self.evaluate_2067(ctx),
158            2068 => self.evaluate_2068(ctx),
159            _ => ConditionResult::Unknown,
160        }
161    }
162
163    fn is_external(&self, condition: u32) -> bool {
164        self.external_conditions.contains(&condition)
165    }
166    fn is_known(&self, condition: u32) -> bool {
167        matches!(
168            condition,
169            1 | 2
170                | 10
171                | 15
172                | 16
173                | 17
174                | 18
175                | 19
176                | 20
177                | 21
178                | 22
179                | 23
180                | 24
181                | 25
182                | 26
183                | 27
184                | 28
185                | 29
186                | 30
187                | 31
188                | 32
189                | 33
190                | 35
191                | 36
192                | 37
193                | 38
194                | 39
195                | 40
196                | 41
197                | 42
198                | 43
199                | 44
200                | 45
201                | 47
202                | 48
203                | 49
204                | 50
205                | 51
206                | 52
207                | 53
208                | 490
209                | 491
210                | 492
211                | 493
212                | 494
213                | 500
214                | 501
215                | 502
216                | 503
217                | 504
218                | 507
219                | 508
220                | 509
221                | 510
222                | 511
223                | 512
224                | 514
225                | 515
226                | 516
227                | 517
228                | 518
229                | 520
230                | 521
231                | 903
232                | 906
233                | 911
234                | 922
235                | 931
236                | 932
237                | 933
238                | 934
239                | 935
240                | 939
241                | 940
242                | 950
243                | 951
244                | 960
245                | 961
246                | 962
247                | 967
248                | 2005
249                | 2060
250                | 2061
251                | 2062
252                | 2063
253                | 2064
254                | 2065
255                | 2066
256                | 2067
257                | 2068
258        )
259    }
260}
261
262impl ReqoteConditionEvaluatorFV2510 {
263    /// [33] Es sind nur die Messprodukte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.4 „Messprodukte mit Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW“ enthalten sind.
264    /// EXTERNAL: Requires context from outside the message.
265    fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
266        ctx.external
267            .evaluate("messprodukt_in_konfigurationserlaubnis_smgw_list")
268    }
269
270    /// [37] Es sind nur die Messprodukt-Position-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.7 „Art der Werte für Messprodukte nach Typ 2“ enthalten sind.
271    /// EXTERNAL: Requires context from outside the message.
272    fn evaluate_37(&self, ctx: &EvaluationContext) -> ConditionResult {
273        ctx.external
274            .evaluate("messprodukt_position_in_kapitel_4_7_list")
275    }
276
277    /// [38] Wenn innerhalb derselben SG27 LIN im PIA+5 DE7140 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) ein Produkt angegeben ist, das in der Codeliste der Konfigurationen...
278    /// EXTERNAL: Requires context from outside the message.
279    fn evaluate_38(&self, ctx: &EvaluationContext) -> ConditionResult {
280        ctx.external.evaluate("pia_product_triggers_schwellwert")
281    }
282
283    /// [41] Es sind nur die Messprodukte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.6.1 „Werte nach Typ 2 aus Backend“ enthalten sind.
284    /// EXTERNAL: Requires context from outside the message.
285    fn evaluate_41(&self, ctx: &EvaluationContext) -> ConditionResult {
286        ctx.external
287            .evaluate("messprodukt_in_kapitel_4_6_1_backend_list")
288    }
289
290    /// [42] Es sind nur die Messprodukte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.6.2 „Werte nach Typ 2 aus SMGW“ enthalten sind.
291    /// EXTERNAL: Requires context from outside the message.
292    fn evaluate_42(&self, ctx: &EvaluationContext) -> ConditionResult {
293        ctx.external
294            .evaluate("messprodukt_in_kapitel_4_6_2_smgw_list")
295    }
296
297    /// [43] Wenn innerhalb derselben SG27 LIN im PIA+5 DE7140 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) ein Produkt angegeben ist, das in der Codeliste der Konfigurationen...
298    /// EXTERNAL: Requires context from outside the message.
299    fn evaluate_43(&self, ctx: &EvaluationContext) -> ConditionResult {
300        ctx.external.evaluate("pia_config_schwellwert_ausloeser")
301    }
302
303    /// [44] Wenn in SG27 LIN (Erforderliches Produkt der Messlokation) das PIA+5 DE7140 mit einem Produkt-Code vorhanden ist der in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer...
304    /// EXTERNAL: Requires context from outside the message.
305    fn evaluate_44(&self, ctx: &EvaluationContext) -> ConditionResult {
306        ctx.external
307            .evaluate("pia_messlokation_weitere_energieflussrichtung")
308    }
309
310    /// [45] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Steuerbaren Ressource angegeben ist.
311    /// EXTERNAL: Requires context from outside the message.
312    fn evaluate_45(&self, ctx: &EvaluationContext) -> ConditionResult {
313        ctx.external.evaluate("loc_172_is_steuerbare_ressource")
314    }
315
316    /// [47] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Ebene" mit dem Wert "Mess...
317    /// EXTERNAL: Requires context from outside the message.
318    fn evaluate_47(&self, ctx: &EvaluationContext) -> ConditionResult {
319        ctx.external.evaluate("pia_product_code_messlokation_ebene")
320    }
321
322    /// [48] Es sind weiterhin nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Produkt gegenü...
323    /// EXTERNAL: Requires context from outside the message.
324    fn evaluate_48(&self, ctx: &EvaluationContext) -> ConditionResult {
325        ctx.external.evaluate("pia_product_code_nb_bestellbar")
326    }
327
328    /// [49] Es sind weiterhin nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Produkt gegenü...
329    /// EXTERNAL: Requires context from outside the message.
330    fn evaluate_49(&self, ctx: &EvaluationContext) -> ConditionResult {
331        ctx.external.evaluate("product_code_allowed_for_lf")
332    }
333
334    /// [50] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Ebene" mit dem Wert "Netz...
335    /// EXTERNAL: Requires context from outside the message.
336    fn evaluate_50(&self, ctx: &EvaluationContext) -> ConditionResult {
337        ctx.external.evaluate("product_code_level_netzlokation")
338    }
339
340    /// [51] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Ebene" mit dem Wert "Steu...
341    /// EXTERNAL: Requires context from outside the message.
342    fn evaluate_51(&self, ctx: &EvaluationContext) -> ConditionResult {
343        ctx.external
344            .evaluate("product_code_level_steuerbare_ressource")
345    }
346
347    /// [52] wenn im DE3155 in demselben COM der Code TE / AL vorhanden ist
348    fn evaluate_52(&self, ctx: &EvaluationContext) -> ConditionResult {
349        // wenn im DE3155 in demselben COM der Code TE / AL vorhanden ist
350        // COM segment: elements[0][0] = D3148 (address), elements[0][1] = D3155 (channel qualifier)
351        let com_segs = ctx.find_segments("COM");
352        if com_segs.is_empty() {
353            return ConditionResult::Unknown;
354        }
355        for seg in &com_segs {
356            if let Some(code) = seg.elements.first().and_then(|e| e.get(1)) {
357                if code == "TE" || code == "AL" {
358                    return ConditionResult::True;
359                }
360            }
361        }
362        ConditionResult::False
363    }
364
365    /// [53] wenn der LF der Marktlokation der genannten Lokation im gewünschten Umsetzungszeitraum nicht zugeordnet ist.
366    /// EXTERNAL: Requires context from outside the message.
367    fn evaluate_53(&self, ctx: &EvaluationContext) -> ConditionResult {
368        ctx.external
369            .evaluate("lf_not_assigned_to_lokation_in_umsetzungszeitraum")
370    }
371
372    /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
373    fn evaluate_494(&self, ctx: &EvaluationContext) -> ConditionResult {
374        // The date in this DE must be ≤ DTM+137 (Nachrichtendatum).
375        // Prefer the tree-resolved value; fall back to scanning for a
376        // non-137 DTM when unavailable.
377        let creation = match ctx
378            .find_segments_with_qualifier("DTM", 0, "137")
379            .first()
380            .and_then(|s| s.elements.first())
381            .and_then(|e| e.get(1))
382        {
383            Some(v) if !v.is_empty() => v.clone(),
384            _ => return ConditionResult::Unknown,
385        };
386        if let Some(val) = ctx.resolved_value {
387            if !val.is_empty() {
388                return ConditionResult::from(val <= creation.as_str());
389            }
390        }
391        // Fallback for non-tree callers: first non-137 DTM value.
392        for dtm in ctx.find_segments("DTM") {
393            let qual = dtm
394                .elements
395                .first()
396                .and_then(|e| e.first())
397                .map(|s| s.as_str());
398            if qual != Some("137") {
399                if let Some(val) = dtm.elements.first().and_then(|e| e.get(1)) {
400                    if !val.is_empty() {
401                        return ConditionResult::from(val.as_str() <= creation.as_str());
402                    }
403                }
404            }
405        }
406        ConditionResult::Unknown
407    }
408
409    /// [517] Hinweis: Verwendung der ID der Technischen Ressource
410    fn evaluate_517(&self, _ctx: &EvaluationContext) -> ConditionResult {
411        // Hinweis: Verwendung der ID der Technischen Ressource — informational note, always applies
412        ConditionResult::True
413    }
414
415    /// [518] Hinweis: zur Angabe von Kontaktdaten des Kunden des Lieferanten um die Änderung an der Technik zu vereinfachen.
416    fn evaluate_518(&self, _ctx: &EvaluationContext) -> ConditionResult {
417        // Hinweis: Angabe von Kontaktdaten des Kunden des Lieferanten — informational note, always applies
418        ConditionResult::True
419    }
420
421    /// [520] Hinweis: Angabe des Beginnzeitpunkts des gewünschten Umsetzungstermins aus Sicht des Anfragenden.
422    fn evaluate_520(&self, _ctx: &EvaluationContext) -> ConditionResult {
423        // Hinweis: Angabe des Beginnzeitpunkts des gewünschten Umsetzungstermins — informational note, always applies
424        ConditionResult::True
425    }
426
427    /// [521] Hinweis: Angabe des Endezeitpunkts des gewünschten Umsetzungstermins aus Sicht des Anfragenden.
428    fn evaluate_521(&self, _ctx: &EvaluationContext) -> ConditionResult {
429        // Hinweis: Angabe des Endezeitpunkts des gewünschten Umsetzungstermins — informational note, always applies
430        ConditionResult::True
431    }
432
433    /// [911] Format: Mögliche Werte: 1 bis n, je Nachricht oder Segmentgruppe bei 1 beginnend und fortlaufend aufsteigend
434    // REVIEW: Per-field check of the value carried in the current DE (typically LIN DE1082 Positionsnummer). Verifies it parses as a positive integer (>= 1). The structural "1..n without gaps, fortlaufend" aspect is a cross-field sequence invariant that cannot be verified within the per-field `ConditionResult` model without an evaluator-level pass — documented as a known limitation; fail reports for sequence gaps would need to come from a separate structural check.
435    fn evaluate_911(&self, ctx: &EvaluationContext) -> ConditionResult {
436        let value = match ctx.resolved_value {
437            Some(v) if !v.is_empty() => v,
438            _ => return ConditionResult::Unknown,
439        };
440        // Reject leading '+', '-', decimals, leading zeros → must be a plain
441        // positive integer literal.
442        if !value.chars().all(|c| c.is_ascii_digit()) {
443            return ConditionResult::False;
444        }
445        if value.starts_with('0') {
446            // "01" and "001" are also not in "1..n" form.
447            return ConditionResult::False;
448        }
449        validate_numeric(value, ">=", 1.0)
450    }
451
452    /// [922] Format: TR-ID
453    fn evaluate_922(&self, ctx: &EvaluationContext) -> ConditionResult {
454        // Validate the resolved field as a Transaktionsreferenz-ID
455        // (1–35 alphanumeric characters).
456        match ctx.resolved_value {
457            Some(val) => validate_tr_id(val),
458            None => ConditionResult::Unknown,
459        }
460    }
461
462    /// [967] Format: Zertifikatskörper gemäß X509.1, BSI TR-03109-4
463    fn evaluate_967(&self, ctx: &EvaluationContext) -> ConditionResult {
464        // Structural check on the certificate body (base64 charset + plausible
465        // length). Cryptographic validation (signature, CA, BSI profile) is
466        // out of scope for static AHB validation.
467        match ctx.resolved_value {
468            Some(val) => validate_x509_cert_body(val),
469            None => ConditionResult::Unknown,
470        }
471    }
472
473    /// [2065] Diese SG28 ist so oft zu wiederholen, wie zu den unterschiedlichen Messprodukt-Position-Codes zu dem innerhalb derselben SG27 LIN im PIA+5 DE7140 (Erforderliches Produkt Konfigurationserlaubnis fü...
474    /// EXTERNAL: Requires context from outside the message.
475    fn evaluate_2065(&self, ctx: &EvaluationContext) -> ConditionResult {
476        ctx.external
477            .evaluate("sg28_repetition_schwellwert_konfigurationserlaubnis_smgw")
478    }
479
480    /// [2066] Diese SG28 ist so oft zu wiederholen, wie zu den unterschiedlichen Messprodukt-Position-Codes zu dem innerhalb derselben SG27 LIN im PIA+5 DE7140 (Erforderliches Produkt Konfigurationserlaubnis fü...
481    /// EXTERNAL: Requires context from outside the message.
482    fn evaluate_2066(&self, ctx: &EvaluationContext) -> ConditionResult {
483        ctx.external
484            .evaluate("sg28_repetition_schwellwert_werte_typ2_smgw")
485    }
486
487    /// [2067] Die SG12 RFF+Z37 Referenz auf ID der Technischen Ressource ist so oft zu wiederholen, bis alle IDs der Technischen Ressourcen angegeben sind, die der Steuerbaren Ressource in LOC+172 DE3225 (Meldep...
488    fn evaluate_2067(&self, _ctx: &EvaluationContext) -> ConditionResult {
489        // Hinweis: SG12 RFF+Z37 (Referenz auf ID der Technischen Ressource) ist so oft zu wiederholen,
490        // bis alle IDs der Technischen Ressourcen angegeben sind, die der Steuerbaren Ressource in
491        // LOC+172 DE3225 (Meldepunkt) zugeordnet werden sollen — informational repetition cardinality note.
492        ConditionResult::True
493    }
494
495    /// [2068] Diese SG27 ist so oft zu wiederholen, dass alle Produkte zur Lokation die innerhalb des  gewünschten Umsetzungstermins (Zeitintervall aus DTM+469 (Startdatum oder Zeitpunkt) und DTM+472 (Endedatum...
496    fn evaluate_2068(&self, _ctx: &EvaluationContext) -> ConditionResult {
497        // Hinweis: SG27 ist so oft zu wiederholen, dass alle gewünschten Produkte zur Lokation
498        // innerhalb des Umsetzungstermins (DTM+469 bis DTM+472) genannt sind, deren Kombination
499        // gemäß Codeliste Kapitel 7 möglich ist — informational repetition cardinality note.
500        ConditionResult::True
501    }
502
503    /// [1] Wenn DTM+203 (Ausführungsdatum) nicht vorhanden
504    fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
505        ctx.lacks_qualifier("DTM", 0, "203")
506    }
507
508    /// [2] Wenn DTM+469 (Beginn zum (nächstmöglichen Termin)) nicht vorhanden
509    fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
510        ctx.lacks_qualifier("DTM", 0, "469")
511    }
512
513    /// [10] MP-ID nur aus Sparte Strom
514    /// EXTERNAL: Requires context from outside the message.
515    fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
516        ctx.external.evaluate("mp_id_strom_only")
517    }
518
519    /// [15] Wenn DTM+76 (Datum zum geplanten Leistungsbeginn) nicht vorhanden
520    fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
521        ctx.lacks_qualifier("DTM", 0, "76")
522    }
523
524    /// [16] Wenn SG1 RFF+Z41 (Referenznummer des Vorgangs der Anmeldung nach WiM) nicht vorhanden
525    fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
526        ctx.lacks_qualifier("RFF", 0, "Z41")
527    }
528
529    /// [17] Wenn SG1 RFF+Z41 (Referenznummer des Vorgangs der Anmeldung nach WiM) vorhanden
530    fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
531        ctx.has_qualifier("RFF", 0, "Z41")
532    }
533
534    /// [18] Wenn IMD++Z55 (Änderung Konfiguration) vorhanden
535    fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
536        ctx.has_qualifier("IMD", 1, "Z55")
537    }
538
539    /// [19] Wenn SG27 LIN++Z64 (Erforderliches Produkt Schaltzeitdefinitionen) vorhanden
540    fn evaluate_19(&self, ctx: &EvaluationContext) -> ConditionResult {
541        ctx.has_qualifier("LIN", 1, "Z64")
542    }
543
544    /// [20] Wenn SG27 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) vorhanden
545    fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
546        ctx.has_qualifier("LIN", 1, "Z65")
547    }
548
549    /// [21] Wenn SG27 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) vorhanden
550    fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
551        ctx.has_qualifier("LIN", 1, "Z66")
552    }
553
554    /// [22] Wenn SG27 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) vorhanden
555    fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
556        ctx.has_qualifier("LIN", 1, "Z67")
557    }
558
559    /// [23] Wenn SG27 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) vorhanden
560    fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
561        ctx.has_qualifier("LIN", 1, "Z68")
562    }
563
564    /// [24] Wenn Produkt bestellt werden soll
565    /// EXTERNAL: Requires context from outside the message.
566    // REVIEW: Whether a product should be ordered is a business-intent condition. In a REQOTE context this could theoretically be signalled by presence of PIA+5, but the AHB phrasing 'soll bestellt werden' indicates a business decision or workflow state that cannot be reliably inferred from message structure alone. (medium confidence)
567    fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
568        ctx.external.evaluate("product_to_be_ordered")
569    }
570
571    /// [25] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Marktlokation angegeben ist.
572    fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
573        // Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Marktlokation angegeben ist.
574        // LOC elements[0][0] == "172" (qualifier), elements[1][0] == DE3225 (Identifikator)
575        // Marktlokation ID: 11 digits with Luhn check digit
576        let segs = ctx.find_segments_with_qualifier("LOC", 0, "172");
577        match segs
578            .first()
579            .and_then(|s| s.elements.get(1))
580            .and_then(|e| e.first())
581        {
582            Some(val) if !val.is_empty() => validate_malo_id(val),
583            _ => ConditionResult::Unknown,
584        }
585    }
586
587    /// [26] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Messlokation angegeben ist.
588    fn evaluate_26(&self, ctx: &EvaluationContext) -> ConditionResult {
589        // Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Messlokation angegeben ist.
590        // LOC elements[0][0] == "172" (qualifier), elements[1][0] == DE3225 (Identifikator)
591        // Messlokation ID: 33 alphanumeric characters (Zählpunkt format)
592        let segs = ctx.find_segments_with_qualifier("LOC", 0, "172");
593        match segs
594            .first()
595            .and_then(|s| s.elements.get(1))
596            .and_then(|e| e.first())
597        {
598            Some(val) if !val.is_empty() => validate_zahlpunkt(val),
599            _ => ConditionResult::Unknown,
600        }
601    }
602
603    /// [27] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Netzlokation angegeben ist.
604    // REVIEW: Checks LOC+172 DE3225 value as a Netzlokation ID by exclusion: it is present but does not match Marktlokation format (11-digit Luhn) nor Messlokation format (33 alphanumeric). Medium confidence because there is no dedicated Netzlokation validator — the logic relies on the three location types being mutually exclusive and exhaustive for this qualifier. (medium confidence)
605    fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
606        // Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Netzlokation angegeben ist.
607        // LOC elements[0][0] == "172" (qualifier), elements[1][0] == DE3225 (Identifikator)
608        // Netzlokation ID: neither MaLo (11 digits Luhn) nor MeLo (33 alphanumeric)
609        let segs = ctx.find_segments_with_qualifier("LOC", 0, "172");
610        match segs
611            .first()
612            .and_then(|s| s.elements.get(1))
613            .and_then(|e| e.first())
614        {
615            Some(val) if !val.is_empty() => {
616                let is_malo = matches!(validate_malo_id(val), ConditionResult::True);
617                let is_melo = matches!(validate_zahlpunkt(val), ConditionResult::True);
618                ConditionResult::from(!is_malo && !is_melo)
619            }
620            _ => ConditionResult::Unknown,
621        }
622    }
623
624    /// [28] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Steuerbaren Ressource angegeben ist.
625    /// EXTERNAL: Requires context from outside the message.
626    fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
627        ctx.external.evaluate("loc_172_is_steuerbare_ressource")
628    }
629
630    /// [29] Es sind nur die Konfigurations-Produkte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.1 „Konfigurationsprodukte Schaltzeitdefinition“ enthalten sind.
631    /// EXTERNAL: Requires context from outside the message.
632    fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
633        ctx.external
634            .evaluate("product_in_konfiguration_schaltzeitdefinition")
635    }
636
637    /// [30] Es sind nur die Konfigurations-Produkte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.2 „Konfigurationsprodukte Leistungskurvendefinition“ enthalten sind.
638    /// EXTERNAL: Requires context from outside the message.
639    fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
640        ctx.external
641            .evaluate("product_in_konfiguration_leistungskurvendefinition")
642    }
643
644    /// [31] Es sind nur die Konfigurations-Produkte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.3 „Konfigurationsprodukte Ad-Hoc-Steuerkanal“ enthalten sind.
645    /// EXTERNAL: Requires context from outside the message.
646    fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
647        ctx.external
648            .evaluate("product_in_konfiguration_adhoc_steuerkanal")
649    }
650
651    /// [32] Es sind nur die Messprodukte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.5 „Messprodukte für Werte nach Typ 2 aus Backend für LF und NB“ enthalten sind.
652    /// EXTERNAL: Requires context from outside the message.
653    fn evaluate_32(&self, ctx: &EvaluationContext) -> ConditionResult {
654        ctx.external.evaluate("product_in_messprodukte_typ2_lf_nb")
655    }
656
657    /// [35] Wenn MP-ID in SG11 NAD+MS mit Rolle LF vorhanden
658    /// EXTERNAL: Requires context from outside the message.
659    // REVIEW: NAD+MS identifies the sender by MP-ID (elements[0]=MS), but the market role 'LF' (Lieferant) cannot be determined from the NAD segment alone — it requires an external participant role registry lookup. The segment only carries the ID, not the role. (medium confidence)
660    fn evaluate_35(&self, ctx: &EvaluationContext) -> ConditionResult {
661        ctx.external.evaluate("sender_is_lf")
662    }
663
664    /// [36] Wenn MP-ID in SG11 NAD+MS mit Rolle NB vorhanden
665    /// EXTERNAL: Requires context from outside the message.
666    // REVIEW: Same pattern as condition 35: NAD+MS carries the sender MP-ID but the market role 'NB' (Netzbetreiber) cannot be inferred from the EDIFACT segment alone — requires external role registry. (medium confidence)
667    fn evaluate_36(&self, ctx: &EvaluationContext) -> ConditionResult {
668        ctx.external.evaluate("sender_is_nb")
669    }
670
671    /// [39] wenn im DE3155 in demselben COM der Code EM vorhanden ist
672    fn evaluate_39(&self, ctx: &EvaluationContext) -> ConditionResult {
673        // COM segment: C076 composite — elements[0][0]=DE3148 (address), elements[0][1]=DE3155 (qualifier)
674        let coms = ctx.find_segments("COM");
675        if coms.is_empty() {
676            return ConditionResult::False;
677        }
678        ConditionResult::from(coms.iter().any(|s| {
679            s.elements
680                .first()
681                .and_then(|e| e.get(1))
682                .is_some_and(|v| v == "EM")
683        }))
684    }
685
686    /// [40] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
687    fn evaluate_40(&self, ctx: &EvaluationContext) -> ConditionResult {
688        // COM segment: C076 composite — elements[0][0]=DE3148 (address), elements[0][1]=DE3155 (qualifier)
689        // TE=Telephone, FX=Fax, AJ=Unknown, AL=Unknown (telephony-related codes)
690        let coms = ctx.find_segments("COM");
691        if coms.is_empty() {
692            return ConditionResult::False;
693        }
694        ConditionResult::from(coms.iter().any(|s| {
695            s.elements
696                .first()
697                .and_then(|e| e.get(1))
698                .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"))
699        }))
700    }
701
702    /// [490] wenn Wert in diesem DE, an der Stelle CCYYMMDDHHMM ein Zeitpunkt aus dem angegeben Zeitraum der Tabelle Kapitel 3.5 „Übersicht gesetzliche deutsche Sommerzeit (MESZ)“ der Spalten: „Sommerzei...
703    fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
704        match ctx.resolved_value {
705            Some(val) => is_mesz_utc(val),
706            None => ConditionResult::False,
707        }
708    }
709
710    /// [491] wenn Wert in diesem DE, an der Stelle CCYYMMDDHHMM ein Zeitpunkt aus dem angegeben Zeitraum der Tabelle Kapitel 3.6 „Übersicht gesetzliche deutsche Zeit (MEZ)“ der Spalten: „Winterzeit (MEZ)...
711    fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
712        match ctx.resolved_value {
713            Some(val) => is_mez_utc(val),
714            None => ConditionResult::False,
715        }
716    }
717
718    /// [492] wenn MP-ID in NAD+MR aus Sparte Strom
719    /// EXTERNAL: Requires context from outside the message.
720    // REVIEW: Checks whether the MP-ID in NAD+MR belongs to the electricity sector (Sparte Strom). The sector of a market participant cannot be derived from the EDIFACT message structure — it requires external market participant registry lookup. Delegated to external provider. (medium confidence)
721    fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
722        ctx.external.evaluate("recipient_is_electricity_sector")
723    }
724
725    /// [493] wenn MP-ID in NAD+MR aus Sparte Gas
726    /// EXTERNAL: Requires context from outside the message.
727    // REVIEW: Checks whether the MP-ID in NAD+MR belongs to the gas sector (Sparte Gas). Same reasoning as condition 492 — sector membership requires external registry lookup. (medium confidence)
728    fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
729        ctx.external.evaluate("recipient_is_gas_sector")
730    }
731
732    /// [500] Hinweis: Angabe eines technischen Ansprechpartners für die Geräteübernahme
733    fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
734        // Hinweis: Angabe eines technischen Ansprechpartners für die Geräteübernahme
735        // Informational note — always applies
736        ConditionResult::True
737    }
738
739    /// [501] Hinweis: Angabe eines Ansprechpartners für die Rechnungsabwicklung
740    fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
741        // Hinweis: Angabe eines Ansprechpartners für die Rechnungsabwicklung
742        // Informational note — always applies
743        ConditionResult::True
744    }
745
746    /// [502] Hinweis: Verwendung der ID der Marktlokation
747    fn evaluate_502(&self, _ctx: &EvaluationContext) -> ConditionResult {
748        // Hinweis: Verwendung der ID der Marktlokation
749        // Informational note — always applies
750        ConditionResult::True
751    }
752
753    /// [503] Hinweis: Verwendung der ID der Messlokation
754    fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
755        // Hinweis: Verwendung der ID der Messlokation
756        // Informational note — always applies
757        ConditionResult::True
758    }
759
760    /// [504] Hinweis: Verwendung der ID der Tranche
761    fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
762        // Hinweis: Verwendung der ID der Tranche — informational note, always applies
763        ConditionResult::True
764    }
765
766    /// [507] Hinweis: Vorgangsnummer aus SG4 IDE+24 DE7402 der UTILMD mit BGM+E01 mit der die Anmeldung des MSB-Wechsels erfolgt ist.
767    fn evaluate_507(&self, _ctx: &EvaluationContext) -> ConditionResult {
768        // Hinweis: Vorgangsnummer aus SG4 IDE+24 DE7402 der UTILMD — informational note, always applies
769        ConditionResult::True
770    }
771
772    /// [508] Hinweis: Wert aus BGM+Z73 DE1004 der IFTSTA mit der die Antwort auf die Bestellung der Konfiguration übermittelt wurde
773    fn evaluate_508(&self, _ctx: &EvaluationContext) -> ConditionResult {
774        // Hinweis: Wert aus BGM+Z73 DE1004 der IFTSTA — informational note, always applies
775        ConditionResult::True
776    }
777
778    /// [509] Hinweis: Vorgangsnummer aus CNI DE1490 der IFTSTA mit BGM+Z73 mit der die Antwort auf die Bestellung der Konfiguration übermittelt wurde
779    fn evaluate_509(&self, _ctx: &EvaluationContext) -> ConditionResult {
780        // Hinweis: Vorgangsnummer aus CNI DE1490 der IFTSTA — informational note, always applies
781        ConditionResult::True
782    }
783
784    /// [510] Hinweis: Verwendung der ID der Netzlokation
785    fn evaluate_510(&self, _ctx: &EvaluationContext) -> ConditionResult {
786        // Hinweis: Verwendung der ID der Netzlokation — informational note, always applies
787        ConditionResult::True
788    }
789
790    /// [511] Hinweis: Verwendung der ID der Steuerbaren Ressource
791    fn evaluate_511(&self, _ctx: &EvaluationContext) -> ConditionResult {
792        ConditionResult::True
793    }
794
795    /// [512] Hinweis: Für den Empfang der Werte nach Typ 2 aus dem SMGW.
796    fn evaluate_512(&self, _ctx: &EvaluationContext) -> ConditionResult {
797        ConditionResult::True
798    }
799
800    /// [514] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
801    fn evaluate_514(&self, _ctx: &EvaluationContext) -> ConditionResult {
802        ConditionResult::True
803    }
804
805    /// [515] Hinweis: Es ist eine URI IPv4 für die Bereitstellung der Werte anzugeben.
806    fn evaluate_515(&self, _ctx: &EvaluationContext) -> ConditionResult {
807        ConditionResult::True
808    }
809
810    /// [516] Hinweis: Es ist eine URI IPv6 für die Bereitstellung der Werte anzugeben.
811    fn evaluate_516(&self, _ctx: &EvaluationContext) -> ConditionResult {
812        ConditionResult::True
813    }
814
815    /// [903] Format: Möglicher Wert: 1
816    fn evaluate_903(&self, _ctx: &EvaluationContext) -> ConditionResult {
817        ConditionResult::True
818    }
819
820    /// [906] Format: max. 3 Nachkommastellen
821    fn evaluate_906(&self, _ctx: &EvaluationContext) -> ConditionResult {
822        ConditionResult::True
823    }
824
825    /// [931] Format: ZZZ = +00
826    fn evaluate_931(&self, _ctx: &EvaluationContext) -> ConditionResult {
827        ConditionResult::True
828    }
829
830    /// [932] Format: HHMM = 2200
831    fn evaluate_932(&self, _ctx: &EvaluationContext) -> ConditionResult {
832        ConditionResult::True
833    }
834
835    /// [933] Format: HHMM = 2300
836    fn evaluate_933(&self, _ctx: &EvaluationContext) -> ConditionResult {
837        ConditionResult::True
838    }
839
840    /// [934] Format: HHMM = 0400
841    fn evaluate_934(&self, _ctx: &EvaluationContext) -> ConditionResult {
842        ConditionResult::True
843    }
844
845    /// [935] Format: HHMM = 0500
846    fn evaluate_935(&self, _ctx: &EvaluationContext) -> ConditionResult {
847        ConditionResult::True
848    }
849
850    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
851    fn evaluate_939(&self, _ctx: &EvaluationContext) -> ConditionResult {
852        ConditionResult::True
853    }
854
855    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
856    fn evaluate_940(&self, _ctx: &EvaluationContext) -> ConditionResult {
857        ConditionResult::True
858    }
859
860    /// [950] Format: Marktlokations-ID
861    fn evaluate_950(&self, _ctx: &EvaluationContext) -> ConditionResult {
862        ConditionResult::True
863    }
864
865    /// [951] Format: Zählpunktbezeichnung
866    fn evaluate_951(&self, ctx: &EvaluationContext) -> ConditionResult {
867        ctx.format_check_qualified("LOC", 0, "Z17", 1, 0, validate_zahlpunkt)
868    }
869
870    /// [960] Format: Netzlokations-ID
871    // HAND-EDITED: a Netzlokations-ID is "E" + ten alphanumerics (`E1688117482`),
872    // not MaLo-shaped; `validate_malo_id` rejected every real one (#173).
873    fn evaluate_960(&self, ctx: &EvaluationContext) -> ConditionResult {
874        ctx.format_check_qualified("LOC", 0, "Z18", 1, 0, validate_nelo_id)
875    }
876
877    /// [961] Format: SR-ID
878    // REVIEW: SR-ID (SteuerbareRessource-ID) uses the same 11-digit Luhn check digit format as MaLo-ID. LOC+Z19 is the standard qualifier for SteuerbareRessource. (medium confidence)
879    fn evaluate_961(&self, ctx: &EvaluationContext) -> ConditionResult {
880        ctx.format_check_qualified("LOC", 0, "Z19", 1, 0, validate_malo_id)
881    }
882
883    /// [962] Format: max. 6 Vorkommastellen
884    fn evaluate_962(&self, ctx: &EvaluationContext) -> ConditionResult {
885        ctx.format_check("QTY", 0, 1, |val| validate_max_integer_digits(val, 6))
886    }
887
888    /// [2005] Pro Nachricht ist die SG27 genau einmal anzugeben
889    // REVIEW: SG27 must appear exactly once per message. LIN is the entry segment for SG27. Counting all LIN segments gives the SG27 instance count. Returns True when exactly one LIN exists. (medium confidence)
890    fn evaluate_2005(&self, ctx: &EvaluationContext) -> ConditionResult {
891        let lin_count = ctx.find_segments("LIN").len();
892        ConditionResult::from(lin_count == 1)
893    }
894
895    /// [2060] Pro Nachricht ist die SG27 LIN+Z64 (Erforderliches Produkt Schaltzeitdefinitionen) maximal einmal anzugeben
896    // REVIEW: LIN with DE1229=Z64 (Erforderliches Produkt Schaltzeitdefinitionen) must appear at most once. Per segment structure reference, DE1229 (Handlung, Code) is at elements[1][0]. Returns True when 0 or 1 such LIN segments exist. (medium confidence)
897    fn evaluate_2060(&self, ctx: &EvaluationContext) -> ConditionResult {
898        let lins = ctx.find_segments("LIN");
899        let count = lins
900            .iter()
901            .filter(|s| {
902                s.elements
903                    .get(1)
904                    .and_then(|e| e.first())
905                    .is_some_and(|v| v == "Z64")
906            })
907            .count();
908        ConditionResult::from(count <= 1)
909    }
910
911    /// [2061] Pro Nachricht ist die SG27 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) maximal einmal anzugeben
912    // REVIEW: LIN with DE1229=Z65 (Erforderliches Produkt Leistungskurvendefinitionen) must appear at most once. Per segment structure reference, DE1229 is at elements[1][0]. Returns True when 0 or 1 such LIN segments exist. (medium confidence)
913    fn evaluate_2061(&self, ctx: &EvaluationContext) -> ConditionResult {
914        let lins = ctx.find_segments("LIN");
915        let count = lins
916            .iter()
917            .filter(|s| {
918                s.elements
919                    .get(1)
920                    .and_then(|e| e.first())
921                    .is_some_and(|v| v == "Z65")
922            })
923            .count();
924        ConditionResult::from(count <= 1)
925    }
926
927    /// [2062] Pro Nachricht ist die SG27 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) maximal einmal anzugeben
928    // REVIEW: LIN with DE1229=Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) must appear at most once. Per segment structure reference, DE1229 is at elements[1][0]. Returns True when 0 or 1 such LIN segments exist. (medium confidence)
929    fn evaluate_2062(&self, ctx: &EvaluationContext) -> ConditionResult {
930        let lins = ctx.find_segments("LIN");
931        let count = lins
932            .iter()
933            .filter(|s| {
934                s.elements
935                    .get(1)
936                    .and_then(|e| e.first())
937                    .is_some_and(|v| v == "Z66")
938            })
939            .count();
940        ConditionResult::from(count <= 1)
941    }
942
943    /// [2063] Pro Nachricht ist die SG27 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) maximal einmal anzugeben
944    // REVIEW: LIN with DE1229=Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) must appear at most once. Per segment structure reference, DE1229 is at elements[1][0]. Returns True when 0 or 1 such LIN segments exist. (medium confidence)
945    fn evaluate_2063(&self, ctx: &EvaluationContext) -> ConditionResult {
946        let lins = ctx.find_segments("LIN");
947        let count = lins
948            .iter()
949            .filter(|s| {
950                s.elements
951                    .get(1)
952                    .and_then(|e| e.first())
953                    .is_some_and(|v| v == "Z67")
954            })
955            .count();
956        ConditionResult::from(count <= 1)
957    }
958
959    /// [2064] Pro Nachricht ist die SG27 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) maximal einmal anzugeben
960    // REVIEW: LIN with DE1229=Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) must appear at most once. Per segment structure reference, DE1229 is at elements[1][0]. Returns True when 0 or 1 such LIN segments exist. (medium confidence)
961    fn evaluate_2064(&self, ctx: &EvaluationContext) -> ConditionResult {
962        let lins = ctx.find_segments("LIN");
963        let count = lins
964            .iter()
965            .filter(|s| {
966                s.elements
967                    .get(1)
968                    .and_then(|e| e.first())
969                    .is_some_and(|v| v == "Z68")
970            })
971            .count();
972        ConditionResult::from(count <= 1)
973    }
974}