package iace import ( "encoding/json" "os" "strconv" "testing" ) func TestExtractDistanceTokens_Normalisation(t *testing.T) { toks := extractDistanceTokens([]string{ "Abstand >= 25 mm und max. 250 mm/s", "Hand-Speed 1.600 mm/s", // German thousands → 1600 "Querschnitt 2,5 mm", // German decimal → 2.5 "850mm ohne Leerzeichen", }) got := map[string]bool{} for _, tk := range toks { got[tk.Unit+":"+strconv.FormatFloat(tk.Value, 'f', 1, 64)] = true } for _, want := range []string{"mm:25.0", "mm/s:250.0", "mm/s:1600.0", "mm:2.5", "mm:850.0"} { if !got[want] { t.Errorf("expected token %s, got %+v", want, toks) } } } func TestCompareDistances_MatchesAndGaps(t *testing.T) { gt := []string{"Abstand >= 25 mm", "max. 250 mm/s", "min. 850 mm", "<= 150 mm/s"} eng := []string{"Spalt 25 mm Fingerschutz", "Teach 250 mm/s", "850 mm Tunnel"} cmp := CompareDistances(gt, eng) if cmp.GTCount != 4 || cmp.MatchedCount != 3 { t.Fatalf("expected 3/4 matched, got %d/%d", cmp.MatchedCount, cmp.GTCount) } if len(cmp.GTOnly) != 1 || cmp.GTOnly[0].Value != 150 { t.Errorf("expected 150 mm/s as the gap, got %+v", cmp.GTOnly) } } // Real GT sessions: the engine library must cover the professional's headline // dimensions (the engine measures were authored from these sessions). func TestCompareSessionDistances_RealGT(t *testing.T) { var engTexts []string for _, m := range GetProtectiveMeasureLibrary() { engTexts = append(engTexts, m.Name, m.Description) } cases := []struct { file string must []DistanceToken }{ {"testdata/ground_truth_bremse.json", []DistanceToken{ {Value: 250, Unit: "mm/s"}, {Value: 250, Unit: "mm"}, {Value: 850, Unit: "mm"}, }}, {"testdata/ground_truth_kistenhub.json", []DistanceToken{ {Value: 25, Unit: "mm"}, {Value: 120, Unit: "mm"}, {Value: 150, Unit: "mm/s"}, {Value: 75, Unit: "mm/s"}, // filled by M603/M605 }}, } for _, tc := range cases { raw, err := os.ReadFile(tc.file) if err != nil { t.Fatalf("read %s: %v", tc.file, err) } var gt GroundTruth if err := json.Unmarshal(raw, >); err != nil { t.Fatalf("parse %s: %v", tc.file, err) } var gtTexts []string for _, e := range gt.Entries { gtTexts = append(gtTexts, e.Measures...) } cmp := CompareDistances(gtTexts, engTexts) for _, want := range tc.must { matched := false for _, m := range cmp.Matched { if m.Unit == want.Unit && m.Value == want.Value { matched = true break } } if !matched { t.Errorf("%s: engine should cover %.0f %s but it is a gap", tc.file, want.Value, want.Unit) } } } }