Move SSD OCR patterns to typed Kotlin

ober

ffd64e047e5248391af85a1a42eb7f32130634ac

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 1c9a969..40a9e27 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1377,7 +1377,7 @@
                 applyOcrCandidateToGroup)
         (type Float32)
         (record OcrPattern
-          ((tokens : (List String))
+          ((tokens : (MutableList String))
            (label : String)
            (confidence : Float32)))
         (record OcrCandidate
@@ -1406,6 +1406,93 @@
                     (OcrCandidate-label candidate)
                     (string-append ", " (OcrCandidate-reason candidate))))))))))
 
+    (typed-kotlin-file "com/sfb/ssdreview/OcrPatterns.kt"
+      (typed-library (com sfb ssdreview)
+        (export ocrPatterns)
+        (type Float32)
+        (def (ocrTokens1 (a : String)) : (MutableList String)
+          (let ((tokens (mutable-list-empty String)))
+            (begin
+              (mutable-list-add! tokens a)
+              tokens)))
+        (def (ocrTokens2 (a : String) (b : String)) : (MutableList String)
+          (let ((tokens (ocrTokens1 a)))
+            (begin
+              (mutable-list-add! tokens b)
+              tokens)))
+        (def (ocrTokens3 (a : String) (b : String) (c : String)) : (MutableList String)
+          (let ((tokens (ocrTokens2 a b)))
+            (begin
+              (mutable-list-add! tokens c)
+              tokens)))
+        (def (ocrTokens4 (a : String) (b : String) (c : String) (d : String)) : (MutableList String)
+          (let ((tokens (ocrTokens3 a b c)))
+            (begin
+              (mutable-list-add! tokens d)
+              tokens)))
+        (def (ocrTokens5 (a : String) (b : String) (c : String) (d : String) (e : String)) : (MutableList String)
+          (let ((tokens (ocrTokens4 a b c d)))
+            (begin
+              (mutable-list-add! tokens e)
+              tokens)))
+        (def (ocrTokens6 (a : String) (b : String) (c : String) (d : String) (e : String) (f : String)) : (MutableList String)
+          (let ((tokens (ocrTokens5 a b c d e)))
+            (begin
+              (mutable-list-add! tokens f)
+              tokens)))
+        (def (ocrPattern1 (token : String) (label : String) (confidence : Float32)) : OcrPattern
+          (make-OcrPattern (ocrTokens1 token) label confidence))
+        (def (ocrPattern2 (token1 : String) (token2 : String) (label : String) (confidence : Float32)) : OcrPattern
+          (make-OcrPattern (ocrTokens2 token1 token2) label confidence))
+        (def (ocrPattern3 (token1 : String) (token2 : String) (token3 : String)
+                          (label : String) (confidence : Float32)) : OcrPattern
+          (make-OcrPattern (ocrTokens3 token1 token2 token3) label confidence))
+        (def (ocrPattern4 (token1 : String) (token2 : String) (token3 : String) (token4 : String)
+                          (label : String) (confidence : Float32)) : OcrPattern
+          (make-OcrPattern (ocrTokens4 token1 token2 token3 token4) label confidence))
+        (def (ocrPattern5 (token1 : String) (token2 : String) (token3 : String) (token4 : String) (token5 : String)
+                          (label : String) (confidence : Float32)) : OcrPattern
+          (make-OcrPattern (ocrTokens5 token1 token2 token3 token4 token5) label confidence))
+        (def (ocrPattern6 (token1 : String) (token2 : String) (token3 : String) (token4 : String) (token5 : String) (token6 : String)
+                          (label : String) (confidence : Float32)) : OcrPattern
+          (make-OcrPattern (ocrTokens6 token1 token2 token3 token4 token5 token6) label confidence))
+        (def (ocrPatterns) : (MutableList OcrPattern)
+          (let ((patterns (mutable-list-empty OcrPattern)))
+            (begin
+              (mutable-list-add! patterns (ocrPattern4 "PH 1" "PH1" "PHASER 1" "PHASER1" "Phaser-1" (float32 0.94)))
+              (mutable-list-add! patterns (ocrPattern4 "PH 2" "PH2" "PHASER 2" "PHASER2" "Phaser-2" (float32 0.93)))
+              (mutable-list-add! patterns (ocrPattern4 "PH 3" "PH3" "PHASER 3" "PHASER3" "Phaser-3" (float32 0.93)))
+              (mutable-list-add! patterns (ocrPattern4 "PH 4" "PH4" "PHASER 4" "PHASER4" "Phaser-4" (float32 0.93)))
+              (mutable-list-add! patterns (ocrPattern3 "DISR" "DIS" "DISRUPTOR" "Disruptor" (float32 0.91)))
+              (mutable-list-add! patterns (ocrPattern2 "PHOT" "PHOTON" "Photon Torpedo" (float32 0.91)))
+              (mutable-list-add! patterns (ocrPattern2 "DRONE" "DRN" "Drone Rack" (float32 0.90)))
+              (mutable-list-add! patterns (ocrPattern6 "PLASMA" "PL A" "PL F" "PL G" "PL S" "PL R" "Plasma Torpedo" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern2 "HELLBORE" "HB" "Hellbore" (float32 0.90)))
+              (mutable-list-add! patterns (ocrPattern2 "FUSION" "FUS" "Fusion Beam" (float32 0.90)))
+              (mutable-list-add! patterns (ocrPattern1 "ESG" "ESG" (float32 0.90)))
+              (mutable-list-add! patterns (ocrPattern3 "LEFT WARP" "L WARP" "LWARP" "Left Warp Engine" (float32 0.89)))
+              (mutable-list-add! patterns (ocrPattern3 "RIGHT WARP" "R WARP" "RWARP" "Right Warp Engine" (float32 0.89)))
+              (mutable-list-add! patterns (ocrPattern3 "CENTER WARP" "C WARP" "CWARP" "Center Warp Engine" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern1 "WARP" "Warp Engine" (float32 0.82)))
+              (mutable-list-add! patterns (ocrPattern2 "IMPULSE" "IMP" "Impulse Engine" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern1 "APR" "APR" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern4 "BAT" "BATT" "BATTERY" "BATTERIES" "Battery" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern2 "LAB" "LABS" "Lab" (float32 0.90)))
+              (mutable-list-add! patterns (ocrPattern2 "BRIDGE" "BRDG" "Bridge" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern3 "SCAN" "SCANNER" "SCANNERS" "Scanner" (float32 0.84)))
+              (mutable-list-add! patterns (ocrPattern3 "SENS" "SENSOR" "SENSORS" "Sensor" (float32 0.84)))
+              (mutable-list-add! patterns (ocrPattern3 "DAMAGE CONTROL" "DAM CON" "DAMCON" "Damage Control" (float32 0.89)))
+              (mutable-list-add! patterns (ocrPattern4 "TRAN" "TRANS" "TRANSPORTER" "TRANSPORTERS" "Transporter" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern3 "TRACT" "TRACTOR" "TRACTORS" "Tractor Beam" (float32 0.88)))
+              (mutable-list-add! patterns (ocrPattern2 "PROBE" "PROBES" "Probe Launcher" (float32 0.87)))
+              (mutable-list-add! patterns (ocrPattern1 "CARGO" "Cargo" (float32 0.87)))
+              (mutable-list-add! patterns (ocrPattern3 "SHUTTLE" "SHUTTLES" "SHUTTLEBAY" "Shuttle" (float32 0.84)))
+              (mutable-list-add! patterns (ocrPattern1 "SECURITY" "Security" (float32 0.85)))
+              (mutable-list-add! patterns (ocrPattern1 "REPAIR" "Repair" (float32 0.85)))
+              (mutable-list-add! patterns (ocrPattern4 "PA PANEL" "PA PANELS" "POWER ABSORBER" "POWER ABSORBERS" "PA Panel" (float32 0.91)))
+              (mutable-list-add! patterns (ocrPattern5 "DISP DEV" "DISP DEVICE" "DISPLACEMENT DEV" "DISPLACEMENT DEVICE" "DISDEV" "Displacement Device" (float32 0.91)))
+              patterns)))))
+
     (typed-kotlin-file "com/sfb/ssdreview/OcrStrings.kt"
       (typed-library (com sfb ssdreview)
         (export normalizeOcr compact ocrTokenMatches
@@ -4836,40 +4923,7 @@
        "import com.google.mlkit.vision.text.latin.TextRecognizerOptions"
        ""
        "object SsdOcr {"
-       "    val patterns = listOf("
-       "        OcrPattern(listOf(\"PH 1\", \"PH1\", \"PHASER 1\", \"PHASER1\"), \"Phaser-1\", 0.94f),"
-       "        OcrPattern(listOf(\"PH 2\", \"PH2\", \"PHASER 2\", \"PHASER2\"), \"Phaser-2\", 0.93f),"
-       "        OcrPattern(listOf(\"PH 3\", \"PH3\", \"PHASER 3\", \"PHASER3\"), \"Phaser-3\", 0.93f),"
-       "        OcrPattern(listOf(\"PH 4\", \"PH4\", \"PHASER 4\", \"PHASER4\"), \"Phaser-4\", 0.93f),"
-       "        OcrPattern(listOf(\"DISR\", \"DIS\", \"DISRUPTOR\"), \"Disruptor\", 0.91f),"
-       "        OcrPattern(listOf(\"PHOT\", \"PHOTON\"), \"Photon Torpedo\", 0.91f),"
-       "        OcrPattern(listOf(\"DRONE\", \"DRN\"), \"Drone Rack\", 0.90f),"
-       "        OcrPattern(listOf(\"PLASMA\", \"PL A\", \"PL F\", \"PL G\", \"PL S\", \"PL R\"), \"Plasma Torpedo\", 0.88f),"
-       "        OcrPattern(listOf(\"HELLBORE\", \"HB\"), \"Hellbore\", 0.90f),"
-       "        OcrPattern(listOf(\"FUSION\", \"FUS\"), \"Fusion Beam\", 0.90f),"
-       "        OcrPattern(listOf(\"ESG\"), \"ESG\", 0.90f),"
-       "        OcrPattern(listOf(\"LEFT WARP\", \"L WARP\", \"LWARP\"), \"Left Warp Engine\", 0.89f),"
-       "        OcrPattern(listOf(\"RIGHT WARP\", \"R WARP\", \"RWARP\"), \"Right Warp Engine\", 0.89f),"
-       "        OcrPattern(listOf(\"CENTER WARP\", \"C WARP\", \"CWARP\"), \"Center Warp Engine\", 0.88f),"
-       "        OcrPattern(listOf(\"WARP\"), \"Warp Engine\", 0.82f),"
-       "        OcrPattern(listOf(\"IMPULSE\", \"IMP\"), \"Impulse Engine\", 0.88f),"
-       "        OcrPattern(listOf(\"APR\"), \"APR\", 0.88f),"
-       "        OcrPattern(listOf(\"BAT\", \"BATT\", \"BATTERY\", \"BATTERIES\"), \"Battery\", 0.88f),"
-       "        OcrPattern(listOf(\"LAB\", \"LABS\"), \"Lab\", 0.90f),"
-       "        OcrPattern(listOf(\"BRIDGE\", \"BRDG\"), \"Bridge\", 0.88f),"
-       "        OcrPattern(listOf(\"SCAN\", \"SCANNER\", \"SCANNERS\"), \"Scanner\", 0.84f),"
-       "        OcrPattern(listOf(\"SENS\", \"SENSOR\", \"SENSORS\"), \"Sensor\", 0.84f),"
-       "        OcrPattern(listOf(\"DAMAGE CONTROL\", \"DAM CON\", \"DAMCON\"), \"Damage Control\", 0.89f),"
-       "        OcrPattern(listOf(\"TRAN\", \"TRANS\", \"TRANSPORTER\", \"TRANSPORTERS\"), \"Transporter\", 0.88f),"
-       "        OcrPattern(listOf(\"TRACT\", \"TRACTOR\", \"TRACTORS\"), \"Tractor Beam\", 0.88f),"
-       "        OcrPattern(listOf(\"PROBE\", \"PROBES\"), \"Probe Launcher\", 0.87f),"
-       "        OcrPattern(listOf(\"CARGO\"), \"Cargo\", 0.87f),"
-       "        OcrPattern(listOf(\"SHUTTLE\", \"SHUTTLES\", \"SHUTTLEBAY\"), \"Shuttle\", 0.84f),"
-       "        OcrPattern(listOf(\"SECURITY\"), \"Security\", 0.85f),"
-       "        OcrPattern(listOf(\"REPAIR\"), \"Repair\", 0.85f),"
-       "        OcrPattern(listOf(\"PA PANEL\", \"PA PANELS\", \"POWER ABSORBER\", \"POWER ABSORBERS\"), \"PA Panel\", 0.91f),"
-       "        OcrPattern(listOf(\"DISP DEV\", \"DISP DEVICE\", \"DISPLACEMENT DEV\", \"DISPLACEMENT DEVICE\", \"DISDEV\"), \"Displacement Device\", 0.91f)"
-       "    )"
+       "    val patterns: List<OcrPattern> = ocrPatterns()"
        ""
        "    fun recognizeWords(bitmap: Bitmap): List<OcrWord> {"
        "        val recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)"