Add typed tactics panel templates

ober

1221f2b19ad2bf1d7fa9fa3934af89dbeb1cfdc1

diff --git a/templates/original-tactics-parts/CombatLogView.kt.ss b/templates/original-tactics-parts/CombatLogView.kt.ss
new file mode 100644
index 0000000..f020e00
--- /dev/null
+++ b/templates/original-tactics-parts/CombatLogView.kt.ss
@@ -0,0 +1,261 @@
+(import (jerboa prelude))
+
+(def fragment
+  '((typed-kotlin-file "com/jerboa/originaltactics/CombatLogView.kt"
+      (kotlin-imports
+        (android content Context)
+        (android graphics Canvas)
+        (android graphics Color)
+        (android graphics Paint)
+        (android graphics Paint Align)
+        (android graphics Paint Style)
+        (android graphics RectF)
+        (android view View)
+        (org json JSONArray)
+        (org json JSONObject))
+      (typed-library (com jerboa originaltactics)
+        (export CombatLogView)
+        (type Context)
+        (type Canvas)
+        (type Paint)
+        (type Style)
+        (type Align)
+        (type RectF)
+        (type View)
+        (type Resources)
+        (type DisplayMetrics)
+        (type JSONArray)
+        (type JSONObject)
+        (type Any)
+        (type Int32)
+        (type Float32)
+        (extern (clvPaintAntiAliasFlag) : Int32
+          (kotlin-value Paint ANTI_ALIAS_FLAG))
+        (extern (clvPaintStyleFill) : Style
+          (kotlin-value Paint Style FILL))
+        (extern (clvPaintStyleStroke) : Style
+          (kotlin-value Paint Style STROKE))
+        (extern (clvPaintAlignLeft) : Align
+          (kotlin-value Paint Align LEFT))
+        (extern (clvPaintAlignCenter) : Align
+          (kotlin-value Paint Align CENTER))
+        (extern (clvColorWhite) : Int32
+          (kotlin-value Color WHITE))
+        (extern (clvColorRgb (red : Int32) (green : Int32) (blue : Int32)) : Int32
+          (kotlin-call Color rgb))
+        (extern (clvPaintColorSet (paint : Paint) (value : Int32)) : Unit
+          (kotlin-member-set color))
+        (extern (clvPaintStyleSet (paint : Paint) (value : Style)) : Unit
+          (kotlin-member-set style))
+        (extern (clvPaintStrokeWidthSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set strokeWidth))
+        (extern (clvPaintTextSizeSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set textSize))
+        (extern (clvPaintFakeBoldSet (paint : Paint) (value : Bool)) : Unit
+          (kotlin-member-set isFakeBoldText))
+        (extern (clvPaintTextAlignSet (paint : Paint) (value : Align)) : Unit
+          (kotlin-member-set textAlign))
+        (extern (clvViewInvalidate (view : CombatLogView)) : Unit
+          (kotlin-member-call invalidate))
+        (extern (clvSuperOnDraw (canvas : Canvas)) : Unit
+          (kotlin-call super onDraw))
+        (extern (clvCanvasSave (canvas : Canvas)) : Int32
+          (kotlin-member-call save))
+        (extern (clvCanvasScale (canvas : Canvas) (x : Float32) (y : Float32)) : Unit
+          (kotlin-member-call scale))
+        (extern (clvCanvasRestoreToCount (canvas : Canvas) (state : Int32)) : Unit
+          (kotlin-member-call restoreToCount))
+        (extern (clvViewWidth (view : CombatLogView)) : Int32
+          (kotlin-member-get width))
+        (extern (clvViewHeight (view : CombatLogView)) : Int32
+          (kotlin-member-get height))
+        (extern (clvViewResources (view : CombatLogView)) : Resources
+          (kotlin-member-get resources))
+        (extern (clvResourcesDisplayMetrics (resources : Resources)) : DisplayMetrics
+          (kotlin-member-get displayMetrics))
+        (extern (clvDisplayMetricsDensity (metrics : DisplayMetrics)) : Float32
+          (kotlin-member-get density))
+        (extern (clvCanvasDrawRoundRect (canvas : Canvas)
+                                       (rect : RectF)
+                                       (rx : Float32)
+                                       (ry : Float32)
+                                       (paint : Paint)) : Unit
+          (kotlin-member-call drawRoundRect))
+        (extern (clvCanvasDrawText (canvas : Canvas)
+                                  (text : String)
+                                  (x : Float32)
+                                  (y : Float32)
+                                  (paint : Paint)) : Unit
+          (kotlin-member-call drawText))
+        (extern (clvJsonOptInt (object : JSONObject)
+                               (key : String)
+                               (fallback : Int32)) : Int32
+          (kotlin-member-call optInt))
+        (extern (clvJsonArrayLength (array : JSONArray)) : Int32
+          (kotlin-member-call length))
+        (def (clvConfigurePaint (paint : Paint)
+                                (color : Int32)
+                                (style : Style)) : Paint
+          (begin
+            (clvPaintColorSet paint color)
+            (clvPaintStyleSet paint style)
+            paint))
+        (def (clvConfigureTextPaint (paint : Paint)
+                                    (color : Int32)
+                                    (size : Float32)
+                                    (bold : Bool)) : Paint
+          (begin
+            (clvPaintColorSet paint color)
+            (clvPaintTextSizeSet paint size)
+            (clvPaintFakeBoldSet paint bold)
+            paint))
+        (def (clvDensity (view : CombatLogView)) : Float32
+          (let ((density
+                  (clvDisplayMetricsDensity
+                    (clvResourcesDisplayMetrics (clvViewResources view)))))
+            (if (< density (float32 1.0)) (float32 1.0) density)))
+        (class CombatLogView ((context : Context))
+          (extends View context)
+          (var game : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var events : JSONArray (new JSONArray)
+            (modifiers private))
+          (var dashboard : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var drawWidth : Float32 (float32 0.0)
+            (modifiers private))
+          (var drawHeight : Float32 (float32 0.0)
+            (modifiers private))
+          (val backgroundPaint : Paint
+            (clvConfigurePaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 9) (int32 14) (int32 22))
+              (clvPaintStyleFill))
+            (modifiers private))
+          (val rowPaint : Paint
+            (clvConfigurePaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 22) (int32 32) (int32 47))
+              (clvPaintStyleFill))
+            (modifiers private))
+          (val altRowPaint : Paint
+            (clvConfigurePaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 27) (int32 40) (int32 58))
+              (clvPaintStyleFill))
+            (modifiers private))
+          (val borderPaint : Paint
+            (clvConfigurePaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 70) (int32 88) (int32 118))
+              (clvPaintStyleStroke))
+            (modifiers private))
+          (val titlePaint : Paint
+            (clvConfigureTextPaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorWhite)
+              (float32 25.0)
+              #t)
+            (modifiers private))
+          (val eventPaint : Paint
+            (clvConfigureTextPaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 224) (int32 233) (int32 246))
+              (float32 18.0)
+              #t)
+            (modifiers private))
+          (val dimPaint : Paint
+            (clvConfigureTextPaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 150) (int32 168) (int32 194))
+              (float32 16.0)
+              #f)
+            (modifiers private))
+          (val alphaPaint : Paint
+            (clvConfigurePaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 67) (int32 144) (int32 232))
+              (clvPaintStyleFill))
+            (modifiers private))
+          (val betaPaint : Paint
+            (clvConfigurePaint
+              (new Paint (clvPaintAntiAliasFlag))
+              (clvColorRgb (int32 215) (int32 84) (int32 70))
+              (clvPaintStyleFill))
+            (modifiers private))
+          (def (setData (nextGame : (Nullable JSONObject))
+                        (nextEvents : JSONArray (default (new JSONArray)))
+                        (nextDashboard : (Nullable JSONObject)
+                          (default (nullable-none JSONObject)))) : Unit
+            (begin
+              (set! game nextGame)
+              (set! events nextEvents)
+              (set! dashboard nextDashboard)
+              (clvViewInvalidate this)))
+          (def (onDraw (canvas : Canvas)) : Unit
+            (modifiers override)
+            (begin
+              (clvSuperOnDraw canvas)
+              (let ((canvasState (clvCanvasSave canvas))
+                    (scale (clvDensity this)))
+                (begin
+                  (set! drawWidth (/ (float32 (clvViewWidth this)) scale))
+                  (set! drawHeight (/ (float32 (clvViewHeight this)) scale))
+                  (clvCanvasScale canvas scale scale)
+                  (try-finally
+                    (drawContent canvas)
+                    (clvCanvasRestoreToCount canvas canvasState))))))
+          (def (drawContent (canvas : Canvas)) : Unit
+            (modifiers private)
+            (begin
+              (clvCanvasDrawRoundRect
+                canvas
+                (new RectF
+                  (float32 0.0)
+                  (float32 0.0)
+                  drawWidth
+                  drawHeight)
+                (float32 10.0)
+                (float32 10.0)
+                backgroundPaint)
+              (if (nullable-null? game)
+                (begin
+                  (clvPaintTextAlignSet titlePaint (clvPaintAlignCenter))
+                  (clvCanvasDrawText
+                    canvas
+                    "COMBAT LOG"
+                    (/ drawWidth (float32 2.0))
+                    (- (/ drawHeight (float32 2.0)) (float32 4.0))
+                    titlePaint)
+                  (clvPaintTextAlignSet dimPaint (clvPaintAlignCenter))
+                  (clvCanvasDrawText
+                    canvas
+                    "No active engagement"
+                    (/ drawWidth (float32 2.0))
+                    (+ (/ drawHeight (float32 2.0)) (float32 22.0))
+                    dimPaint))
+                (let ((current (nullable-get game)))
+                  (begin
+                    (clvPaintTextAlignSet titlePaint (clvPaintAlignLeft))
+                    (clvCanvasDrawText canvas "COMBAT LOG" (float32 10.0) (float32 27.0) titlePaint)
+                    (clvPaintTextAlignSet eventPaint (clvPaintAlignLeft))
+                    (clvCanvasDrawText
+                      canvas
+                      (string-append
+                        "Turn "
+                        (string-append
+                          (int32->string (clvJsonOptInt current "turn" (int32 0)))
+                          (string-append
+                            "  Impulse "
+                            (int32->string (clvJsonOptInt current "impulse" (int32 0))))))
+                      (float32 10.0)
+                      (float32 57.0)
+                      eventPaint)
+                    (clvCanvasDrawText
+                      canvas
+                      (string-append
+                        (int32->string (clvJsonArrayLength events))
+                        " combat events")
+                      (float32 10.0)
+                      (float32 85.0)
+                      dimPaint)))))))))))
diff --git a/templates/original-tactics-parts/CombatTimelineView.kt.ss b/templates/original-tactics-parts/CombatTimelineView.kt.ss
new file mode 100644
index 0000000..8712be7
--- /dev/null
+++ b/templates/original-tactics-parts/CombatTimelineView.kt.ss
@@ -0,0 +1,191 @@
+(import (jerboa prelude))
+
+(def fragment
+  '((typed-kotlin-file "com/jerboa/originaltactics/CombatTimelineView.kt"
+      (kotlin-imports
+        (android content Context)
+        (android graphics Canvas)
+        (android graphics Color)
+        (android graphics Paint)
+        (android graphics Paint Align)
+        (android graphics Paint Style)
+        (android graphics RectF)
+        (android view View)
+        (org json JSONArray)
+        (org json JSONObject))
+      (typed-library (com jerboa originaltactics)
+        (export CombatTimelineView)
+        (type Context) (type Canvas) (type Paint) (type Align) (type Style)
+        (type RectF) (type View) (type Resources) (type DisplayMetrics)
+        (type JSONArray) (type JSONObject) (type Int32) (type Float32)
+        (extern (ctvPaintFlag) : Int32 (kotlin-value Paint ANTI_ALIAS_FLAG))
+        (extern (ctvFill) : Style (kotlin-value Paint Style FILL))
+        (extern (ctvStroke) : Style (kotlin-value Paint Style STROKE))
+        (extern (ctvLeft) : Align (kotlin-value Paint Align LEFT))
+        (extern (ctvCenter) : Align (kotlin-value Paint Align CENTER))
+        (extern (ctvWhite) : Int32 (kotlin-value Color WHITE))
+        (extern (ctvRgb (r : Int32) (g : Int32) (b : Int32)) : Int32
+          (kotlin-call Color rgb))
+        (extern (ctvPaintColorSet (paint : Paint) (value : Int32)) : Unit
+          (kotlin-member-set color))
+        (extern (ctvPaintStyleSet (paint : Paint) (value : Style)) : Unit
+          (kotlin-member-set style))
+        (extern (ctvPaintStrokeSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set strokeWidth))
+        (extern (ctvPaintSizeSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set textSize))
+        (extern (ctvPaintBoldSet (paint : Paint) (value : Bool)) : Unit
+          (kotlin-member-set isFakeBoldText))
+        (extern (ctvPaintAlignSet (paint : Paint) (value : Align)) : Unit
+          (kotlin-member-set textAlign))
+        (extern (ctvInvalidate (view : CombatTimelineView)) : Unit
+          (kotlin-member-call invalidate))
+        (extern (ctvSuperDraw (canvas : Canvas)) : Unit
+          (kotlin-call super onDraw))
+        (extern (ctvSave (canvas : Canvas)) : Int32 (kotlin-member-call save))
+        (extern (ctvScale (canvas : Canvas) (x : Float32) (y : Float32)) : Unit
+          (kotlin-member-call scale))
+        (extern (ctvRestore (canvas : Canvas) (state : Int32)) : Unit
+          (kotlin-member-call restoreToCount))
+        (extern (ctvWidth (view : CombatTimelineView)) : Int32
+          (kotlin-member-get width))
+        (extern (ctvHeight (view : CombatTimelineView)) : Int32
+          (kotlin-member-get height))
+        (extern (ctvResources (view : CombatTimelineView)) : Resources
+          (kotlin-member-get resources))
+        (extern (ctvMetrics (resources : Resources)) : DisplayMetrics
+          (kotlin-member-get displayMetrics))
+        (extern (ctvDensityValue (metrics : DisplayMetrics)) : Float32
+          (kotlin-member-get density))
+        (extern (ctvDrawRect (canvas : Canvas)
+                             (left : Float32) (top : Float32)
+                             (right : Float32) (bottom : Float32)
+                             (paint : Paint)) : Unit
+          (kotlin-member-call drawRect))
+        (extern (ctvDrawRoundRect (canvas : Canvas) (rect : RectF)
+                                  (rx : Float32) (ry : Float32)
+                                  (paint : Paint)) : Unit
+          (kotlin-member-call drawRoundRect))
+        (extern (ctvDrawText (canvas : Canvas) (text : String)
+                             (x : Float32) (y : Float32)
+                             (paint : Paint)) : Unit
+          (kotlin-member-call drawText))
+        (extern (ctvJsonInt (object : JSONObject) (key : String)
+                            (fallback : Int32)) : Int32
+          (kotlin-member-call optInt))
+        (def (ctvPaint (color : Int32) (style : Style)) : Paint
+          (let ((paint (new Paint (ctvPaintFlag))))
+            (begin
+              (ctvPaintColorSet paint color)
+              (ctvPaintStyleSet paint style)
+              paint)))
+        (def (ctvTextPaint (color : Int32) (size : Float32) (bold : Bool)) : Paint
+          (let ((paint (new Paint (ctvPaintFlag))))
+            (begin
+              (ctvPaintColorSet paint color)
+              (ctvPaintSizeSet paint size)
+              (ctvPaintBoldSet paint bold)
+              paint)))
+        (def (ctvDensity (view : CombatTimelineView)) : Float32
+          (let ((value (ctvDensityValue (ctvMetrics (ctvResources view)))))
+            (if (< value (float32 1.0)) (float32 1.0) value)))
+        (class CombatTimelineView ((context : Context))
+          (extends View context)
+          (var game : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var events : JSONArray (new JSONArray) (modifiers private))
+          (var tacticalDashboard : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var drawWidth : Float32 (float32 0.0) (modifiers private))
+          (var drawHeight : Float32 (float32 0.0) (modifiers private))
+          (val backgroundPaint : Paint
+            (ctvPaint (ctvRgb (int32 247) (int32 249) (int32 252)) (ctvFill))
+            (modifiers private))
+          (val cellPaint : Paint
+            (ctvPaint (ctvRgb (int32 231) (int32 237) (int32 245)) (ctvFill))
+            (modifiers private))
+          (val currentPaint : Paint
+            (ctvPaint (ctvRgb (int32 36) (int32 45) (int32 61)) (ctvFill))
+            (modifiers private))
+          (val borderPaint : Paint
+            (ctvPaint (ctvRgb (int32 167) (int32 179) (int32 196)) (ctvStroke))
+            (modifiers private))
+          (val textPaint : Paint
+            (ctvTextPaint (ctvRgb (int32 30) (int32 38) (int32 52)) (float32 27.0) #t)
+            (modifiers private))
+          (val smallTextPaint : Paint
+            (ctvTextPaint (ctvRgb (int32 64) (int32 75) (int32 94)) (float32 19.0) #f)
+            (modifiers private))
+          (def (setGame (nextGame : (Nullable JSONObject))
+                        (nextEvents : JSONArray (default (new JSONArray)))) : Unit
+            (begin
+              (set! game nextGame)
+              (set! events nextEvents)
+              (ctvInvalidate this)))
+          (def (setTacticalDashboard
+                 (nextDashboard : (Nullable JSONObject))) : Unit
+            (begin
+              (set! tacticalDashboard nextDashboard)
+              (ctvInvalidate this)))
+          (def (onDraw (canvas : Canvas)) : Unit
+            (modifiers override)
+            (begin
+              (ctvSuperDraw canvas)
+              (let ((state (ctvSave canvas)) (scale (ctvDensity this)))
+                (begin
+                  (set! drawWidth (/ (float32 (ctvWidth this)) scale))
+                  (set! drawHeight (/ (float32 (ctvHeight this)) scale))
+                  (ctvScale canvas scale scale)
+                  (try-finally (drawContent canvas) (ctvRestore canvas state))))))
+          (def (drawContent (canvas : Canvas)) : Unit
+            (modifiers private)
+            (begin
+              (ctvDrawRect canvas (float32 0.0) (float32 0.0)
+                drawWidth drawHeight backgroundPaint)
+              (if (nullable-null? game)
+                (begin
+                  (ctvPaintAlignSet textPaint (ctvCenter))
+                  (ctvDrawText canvas "Impulse track"
+                    (/ drawWidth (float32 2.0))
+                    (+ (/ drawHeight (float32 2.0)) (float32 8.0))
+                    textPaint))
+                (let ((current (nullable-get game)))
+                  (let ((turn (ctvJsonInt current "turn" (int32 1)))
+                        (impulse (ctvJsonInt current "impulse" (int32 0))))
+                    (begin
+                      (ctvPaintAlignSet textPaint (ctvLeft))
+                      (ctvDrawText canvas
+                        (string-append "Turn "
+                          (string-append (int32->string turn)
+                            (string-append "    Impulse "
+                              (string-append (int32->string impulse) "/32"))))
+                        (float32 12.0) (float32 28.0) textPaint)
+                      (drawImpulseCells canvas impulse)))))))
+          (def (drawImpulseCells (canvas : Canvas) (impulse : Int32)) : Unit
+            (modifiers private)
+            (let ((left (float32 10.0))
+                  (top (float32 42.0))
+                  (gap (float32 4.0))
+                  (cellWidth (/ (- drawWidth (float32 80.0)) (float32 16.0)))
+                  (cellHeight (/ (- drawHeight (float32 58.0)) (float32 2.0))))
+              (begin
+                (for/fold ((ignored (int32 0)))
+                          ((i (in-range (int32 1) (int32 33))))
+                  (let ((row (if (<= i (int32 16)) (int32 0) (int32 1)))
+                        (col (if (<= i (int32 16))
+                               (- i (int32 1))
+                               (- i (int32 17)))))
+                    (let ((x (+ left (* (float32 col) (+ cellWidth gap))))
+                          (y (+ top (* (float32 row) (+ cellHeight gap)))))
+                      (let ((rect (new RectF x y (+ x cellWidth) (+ y cellHeight))))
+                        (begin
+                          (ctvDrawRoundRect canvas rect (float32 6.0) (float32 6.0)
+                            (if (= i impulse) currentPaint cellPaint))
+                          (ctvDrawRoundRect canvas rect (float32 6.0) (float32 6.0) borderPaint)
+                          (ctvPaintAlignSet smallTextPaint (ctvCenter))
+                          (ctvDrawText canvas (int32->string i)
+                            (+ x (/ cellWidth (float32 2.0)))
+                            (+ y (/ cellHeight (float32 2.0)))
+                            smallTextPaint)
+                          ignored)))))
+                (begin)))))))))
diff --git a/templates/original-tactics-parts/CommandAvailabilityView.kt.ss b/templates/original-tactics-parts/CommandAvailabilityView.kt.ss
new file mode 100644
index 0000000..31173f5
--- /dev/null
+++ b/templates/original-tactics-parts/CommandAvailabilityView.kt.ss
@@ -0,0 +1,199 @@
+(import (jerboa prelude))
+
+(def fragment
+  '((typed-kotlin-file "com/jerboa/originaltactics/CommandAvailabilityView.kt"
+      (kotlin-imports
+        (android content Context)
+        (android graphics Canvas)
+        (android graphics Color)
+        (android graphics Paint)
+        (android graphics Paint Align)
+        (android graphics Paint Style)
+        (android graphics RectF)
+        (android view View)
+        (org json JSONArray)
+        (org json JSONObject))
+      (typed-library (com jerboa originaltactics)
+        (export CommandAvailabilityView)
+        (type Context) (type Canvas) (type Paint) (type Align) (type Style)
+        (type RectF) (type View) (type Resources) (type DisplayMetrics)
+        (type JSONArray) (type JSONObject) (type Int32) (type Float32)
+        (extern (cavPaintFlag) : Int32 (kotlin-value Paint ANTI_ALIAS_FLAG))
+        (extern (cavFill) : Style (kotlin-value Paint Style FILL))
+        (extern (cavStroke) : Style (kotlin-value Paint Style STROKE))
+        (extern (cavLeft) : Align (kotlin-value Paint Align LEFT))
+        (extern (cavCenter) : Align (kotlin-value Paint Align CENTER))
+        (extern (cavRgb (r : Int32) (g : Int32) (b : Int32)) : Int32
+          (kotlin-call Color rgb))
+        (extern (cavWhite) : Int32 (kotlin-value Color WHITE))
+        (extern (cavPaintColorSet (paint : Paint) (value : Int32)) : Unit
+          (kotlin-member-set color))
+        (extern (cavPaintStyleSet (paint : Paint) (value : Style)) : Unit
+          (kotlin-member-set style))
+        (extern (cavPaintStrokeSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set strokeWidth))
+        (extern (cavPaintSizeSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set textSize))
+        (extern (cavPaintBoldSet (paint : Paint) (value : Bool)) : Unit
+          (kotlin-member-set isFakeBoldText))
+        (extern (cavPaintAlignSet (paint : Paint) (value : Align)) : Unit
+          (kotlin-member-set textAlign))
+        (extern (cavInvalidate (view : CommandAvailabilityView)) : Unit
+          (kotlin-member-call invalidate))
+        (extern (cavSuperDraw (canvas : Canvas)) : Unit
+          (kotlin-call super onDraw))
+        (extern (cavSave (canvas : Canvas)) : Int32 (kotlin-member-call save))
+        (extern (cavScale (canvas : Canvas) (x : Float32) (y : Float32)) : Unit
+          (kotlin-member-call scale))
+        (extern (cavRestore (canvas : Canvas) (state : Int32)) : Unit
+          (kotlin-member-call restoreToCount))
+        (extern (cavWidth (view : CommandAvailabilityView)) : Int32
+          (kotlin-member-get width))
+        (extern (cavHeight (view : CommandAvailabilityView)) : Int32
+          (kotlin-member-get height))
+        (extern (cavResources (view : CommandAvailabilityView)) : Resources
+          (kotlin-member-get resources))
+        (extern (cavMetrics (resources : Resources)) : DisplayMetrics
+          (kotlin-member-get displayMetrics))
+        (extern (cavDensityValue (metrics : DisplayMetrics)) : Float32
+          (kotlin-member-get density))
+        (extern (cavDrawRoundRect (canvas : Canvas) (rect : RectF)
+                                  (rx : Float32) (ry : Float32)
+                                  (paint : Paint)) : Unit
+          (kotlin-member-call drawRoundRect))
+        (extern (cavDrawText (canvas : Canvas) (text : String)
+                             (x : Float32) (y : Float32)
+                             (paint : Paint)) : Unit
+          (kotlin-member-call drawText))
+        (extern (cavJsonInt (object : JSONObject) (key : String)
+                            (fallback : Int32)) : Int32
+          (kotlin-member-call optInt))
+        (extern (cavJsonArray (object : JSONObject)
+                              (key : String)) : (Nullable JSONArray)
+          (kotlin-member-call optJSONArray))
+        (extern (cavArrayLength (array : JSONArray)) : Int32
+          (kotlin-member-call length))
+        (def (cavPaint (color : Int32) (style : Style)) : Paint
+          (let ((paint (new Paint (cavPaintFlag))))
+            (begin
+              (cavPaintColorSet paint color)
+              (cavPaintStyleSet paint style)
+              paint)))
+        (def (cavTextPaint (color : Int32) (size : Float32) (bold : Bool)) : Paint
+          (let ((paint (new Paint (cavPaintFlag))))
+            (begin
+              (cavPaintColorSet paint color)
+              (cavPaintSizeSet paint size)
+              (cavPaintBoldSet paint bold)
+              paint)))
+        (def (cavDensity (view : CommandAvailabilityView)) : Float32
+          (let ((value (cavDensityValue (cavMetrics (cavResources view)))))
+            (if (< value (float32 1.0)) (float32 1.0) value)))
+        (def (cavActionCount (report : (Nullable JSONObject))) : Int32
+          (if (nullable-null? report)
+            (int32 0)
+            (let ((actions (cavJsonArray (nullable-get report) "actions")))
+              (if (nullable-null? actions)
+                (int32 0)
+                (cavArrayLength (nullable-get actions))))))
+        (class CommandAvailabilityView ((context : Context))
+          (extends View context)
+          (var alphaReport : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var betaReport : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var drawWidth : Float32 (float32 0.0) (modifiers private))
+          (var drawHeight : Float32 (float32 0.0) (modifiers private))
+          (val backgroundPaint : Paint
+            (cavPaint (cavRgb (int32 27) (int32 34) (int32 45)) (cavFill))
+            (modifiers private))
+          (val cardPaint : Paint
+            (cavPaint (cavRgb (int32 38) (int32 47) (int32 61)) (cavFill))
+            (modifiers private))
+          (val borderPaint : Paint
+            (cavPaint (cavRgb (int32 82) (int32 97) (int32 121)) (cavStroke))
+            (modifiers private))
+          (val readyPaint : Paint
+            (cavPaint (cavRgb (int32 69) (int32 171) (int32 104)) (cavFill))
+            (modifiers private))
+          (val blockedPaint : Paint
+            (cavPaint (cavRgb (int32 204) (int32 87) (int32 72)) (cavFill))
+            (modifiers private))
+          (val titlePaint : Paint
+            (cavTextPaint (cavWhite) (float32 24.0) #t) (modifiers private))
+          (val labelPaint : Paint
+            (cavTextPaint (cavRgb (int32 224) (int32 232) (int32 243))
+              (float32 19.0) #t)
+            (modifiers private))
+          (val smallPaint : Paint
+            (cavTextPaint (cavRgb (int32 167) (int32 180) (int32 199))
+              (float32 16.0) #f)
+            (modifiers private))
+          (def (setReports (alpha : (Nullable JSONObject))
+                           (beta : (Nullable JSONObject))) : Unit
+            (begin
+              (set! alphaReport alpha)
+              (set! betaReport beta)
+              (cavInvalidate this)))
+          (def (onDraw (canvas : Canvas)) : Unit
+            (modifiers override)
+            (begin
+              (cavSuperDraw canvas)
+              (let ((state (cavSave canvas)) (scale (cavDensity this)))
+                (begin
+                  (set! drawWidth (/ (float32 (cavWidth this)) scale))
+                  (set! drawHeight (/ (float32 (cavHeight this)) scale))
+                  (cavScale canvas scale scale)
+                  (try-finally (drawContent canvas) (cavRestore canvas state))))))
+          (def (drawContent (canvas : Canvas)) : Unit
+            (modifiers private)
+            (begin
+              (cavDrawRoundRect canvas
+                (new RectF (float32 0.0) (float32 0.0) drawWidth drawHeight)
+                (float32 10.0) (float32 10.0) backgroundPaint)
+              (if (and (nullable-null? alphaReport) (nullable-null? betaReport))
+                (drawEmpty canvas)
+                (begin
+                  (cavPaintAlignSet titlePaint (cavLeft))
+                  (cavDrawText canvas "COMMANDS" (float32 12.0) (float32 26.0) titlePaint)
+                  (drawReportCard canvas (float32 10.0) "ALPHA" alphaReport readyPaint)
+                  (drawReportCard canvas
+                    (+ (/ drawWidth (float32 2.0)) (float32 4.0))
+                    "BETA" betaReport blockedPaint)))))
+          (def (drawEmpty (canvas : Canvas)) : Unit
+            (modifiers private)
+            (begin
+              (cavPaintAlignSet titlePaint (cavCenter))
+              (cavDrawText canvas "Command availability"
+                (/ drawWidth (float32 2.0))
+                (- (/ drawHeight (float32 2.0)) (float32 2.0)) titlePaint)
+              (cavPaintAlignSet smallPaint (cavCenter))
+              (cavDrawText canvas "Waiting for tactical state"
+                (/ drawWidth (float32 2.0))
+                (+ (/ drawHeight (float32 2.0)) (float32 22.0)) smallPaint)))
+          (def (drawReportCard (canvas : Canvas) (left : Float32)
+                               (side : String)
+                               (report : (Nullable JSONObject))
+                               (accent : Paint)) : Unit
+            (modifiers private)
+            (let ((width (- (/ drawWidth (float32 2.0)) (float32 14.0)))
+                  (top (float32 40.0)))
+              (let ((rect (new RectF left top (+ left width) (- drawHeight (float32 10.0)))))
+                (begin
+                  (cavDrawRoundRect canvas rect (float32 8.0) (float32 8.0) cardPaint)
+                  (cavDrawRoundRect canvas rect (float32 8.0) (float32 8.0) borderPaint)
+                  (cavDrawRoundRect canvas
+                    (new RectF left top (+ left width) (+ top (float32 24.0)))
+                    (float32 8.0) (float32 8.0) accent)
+                  (cavPaintAlignSet labelPaint (cavLeft))
+                  (cavDrawText canvas side (+ left (float32 8.0))
+                    (+ top (float32 18.0)) labelPaint)
+                  (cavPaintAlignSet smallPaint (cavLeft))
+                  (cavDrawText canvas
+                    (if (nullable-null? report)
+                      "waiting"
+                      (string-append
+                        (int32->string (cavActionCount report))
+                        " command states"))
+                    (+ left (float32 8.0))
+                    (+ top (float32 50.0)) smallPaint))))))))))
diff --git a/templates/original-tactics-parts/Sfc2IntelView.kt.ss b/templates/original-tactics-parts/Sfc2IntelView.kt.ss
new file mode 100644
index 0000000..02b2e9c
--- /dev/null
+++ b/templates/original-tactics-parts/Sfc2IntelView.kt.ss
@@ -0,0 +1,242 @@
+(import (jerboa prelude))
+
+(def fragment
+  '((typed-kotlin-file "com/jerboa/originaltactics/Sfc2IntelView.kt" ; # gitsafe:ignore
+      (kotlin-imports
+        (android content Context)
+        (android graphics Canvas)
+        (android graphics Color)
+        (android graphics Paint)
+        (android graphics Paint Align)
+        (android graphics Paint Style)
+        (android graphics RectF)
+        (android view View)
+        (org json JSONArray)
+        (org json JSONObject))
+      (typed-library (com jerboa originaltactics)
+        (export Sfc2IntelView)
+        (type Context) (type Canvas) (type Paint) (type Align) (type Style)
+        (type RectF) (type View) (type Resources) (type DisplayMetrics)
+        (type JSONArray) (type JSONObject) (type Int32) (type Float32)
+        (extern (sivPaintFlag) : Int32 (kotlin-value Paint ANTI_ALIAS_FLAG))
+        (extern (sivFill) : Style (kotlin-value Paint Style FILL))
+        (extern (sivStroke) : Style (kotlin-value Paint Style STROKE))
+        (extern (sivLeft) : Align (kotlin-value Paint Align LEFT))
+        (extern (sivCenter) : Align (kotlin-value Paint Align CENTER))
+        (extern (sivRight) : Align (kotlin-value Paint Align RIGHT))
+        (extern (sivWhite) : Int32 (kotlin-value Color WHITE))
+        (extern (sivRgb (r : Int32) (g : Int32) (b : Int32)) : Int32
+          (kotlin-call Color rgb))
+        (extern (sivPaintColorSet (paint : Paint) (value : Int32)) : Unit
+          (kotlin-member-set color))
+        (extern (sivPaintStyleSet (paint : Paint) (value : Style)) : Unit
+          (kotlin-member-set style))
+        (extern (sivPaintSizeSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set textSize))
+        (extern (sivPaintBoldSet (paint : Paint) (value : Bool)) : Unit
+          (kotlin-member-set isFakeBoldText))
+        (extern (sivPaintAlignSet (paint : Paint) (value : Align)) : Unit
+          (kotlin-member-set textAlign))
+        (extern (sivInvalidate (view : Sfc2IntelView)) : Unit
+          (kotlin-member-call invalidate))
+        (extern (sivSuperDraw (canvas : Canvas)) : Unit
+          (kotlin-call super onDraw))
+        (extern (sivSave (canvas : Canvas)) : Int32 (kotlin-member-call save))
+        (extern (sivScale (canvas : Canvas) (x : Float32) (y : Float32)) : Unit
+          (kotlin-member-call scale))
+        (extern (sivRestore (canvas : Canvas) (state : Int32)) : Unit
+          (kotlin-member-call restoreToCount))
+        (extern (sivWidth (view : Sfc2IntelView)) : Int32
+          (kotlin-member-get width))
+        (extern (sivHeight (view : Sfc2IntelView)) : Int32
+          (kotlin-member-get height))
+        (extern (sivResources (view : Sfc2IntelView)) : Resources
+          (kotlin-member-get resources))
+        (extern (sivMetrics (resources : Resources)) : DisplayMetrics
+          (kotlin-member-get displayMetrics))
+        (extern (sivDensityValue (metrics : DisplayMetrics)) : Float32
+          (kotlin-member-get density))
+        (extern (sivDrawRoundRect (canvas : Canvas) (rect : RectF)
+                                  (rx : Float32) (ry : Float32)
+                                  (paint : Paint)) : Unit
+          (kotlin-member-call drawRoundRect))
+        (extern (sivDrawText (canvas : Canvas) (text : String)
+                             (x : Float32) (y : Float32)
+                             (paint : Paint)) : Unit
+          (kotlin-member-call drawText))
+        (extern (sivRectLeft (rect : RectF)) : Float32
+          (kotlin-member-get left))
+        (extern (sivRectTop (rect : RectF)) : Float32
+          (kotlin-member-get top))
+        (extern (sivRectRight (rect : RectF)) : Float32
+          (kotlin-member-get right))
+        (extern (sivJsonObject (object : JSONObject)
+                               (key : String)) : (Nullable JSONObject)
+          (kotlin-member-call optJSONObject))
+        (extern (sivJsonInt (object : JSONObject) (key : String)
+                            (fallback : Int32)) : Int32
+          (kotlin-member-call optInt))
+        (extern (sivJsonBoolean (object : JSONObject) (key : String)
+                                (fallback : Bool)) : Bool
+          (kotlin-member-call optBoolean))
+        (extern (sivShipTechnicalLabel (actor : (Nullable JSONObject))
+                                       (fallback : String)) : String
+          (kotlin-call shipTechnicalLabel))
+        (extern (sivShipDisplayLabel (actor : JSONObject)) : String
+          (kotlin-call shipDisplayLabel))
+        (def (sivPaint (color : Int32) (style : Style)) : Paint
+          (let ((paint (new Paint (sivPaintFlag))))
+            (begin
+              (sivPaintColorSet paint color)
+              (sivPaintStyleSet paint style)
+              paint)))
+        (def (sivTextPaint (color : Int32) (size : Float32) (bold : Bool)) : Paint
+          (let ((paint (new Paint (sivPaintFlag))))
+            (begin
+              (sivPaintColorSet paint color)
+              (sivPaintSizeSet paint size)
+              (sivPaintBoldSet paint bold)
+              paint)))
+        (def (sivDensity (view : Sfc2IntelView)) : Float32
+          (let ((value (sivDensityValue (sivMetrics (sivResources view)))))
+            (if (< value (float32 1.0)) (float32 1.0) value)))
+        (class Sfc2IntelView ((context : Context))
+          (extends View context)
+          (var statusReport : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var alphaTruth : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var betaTruth : (Nullable JSONObject) (nullable-none JSONObject)
+            (modifiers private))
+          (var drawWidth : Float32 (float32 0.0) (modifiers private))
+          (var drawHeight : Float32 (float32 0.0) (modifiers private))
+          (val backgroundPaint : Paint
+            (sivPaint (sivRgb (int32 13) (int32 19) (int32 28)) (sivFill))
+            (modifiers private))
+          (val panelPaint : Paint
+            (sivPaint (sivRgb (int32 25) (int32 34) (int32 47)) (sivFill))
+            (modifiers private))
+          (val borderPaint : Paint
+            (sivPaint (sivRgb (int32 70) (int32 86) (int32 112)) (sivStroke))
+            (modifiers private))
+          (val alphaPaint : Paint
+            (sivPaint (sivRgb (int32 58) (int32 134) (int32 221)) (sivFill))
+            (modifiers private))
+          (val betaPaint : Paint
+            (sivPaint (sivRgb (int32 205) (int32 82) (int32 66)) (sivFill))
+            (modifiers private))
+          (val titlePaint : Paint
+            (sivTextPaint (sivWhite) (float32 25.0) #t) (modifiers private))
+          (val labelPaint : Paint
+            (sivTextPaint (sivRgb (int32 222) (int32 231) (int32 243))
+              (float32 18.0) #t)
+            (modifiers private))
+          (val smallPaint : Paint
+            (sivTextPaint (sivRgb (int32 158) (int32 174) (int32 197))
+              (float32 16.0) #f)
+            (modifiers private))
+          (val dimPaint : Paint
+            (sivTextPaint (sivRgb (int32 116) (int32 132) (int32 157))
+              (float32 15.0) #f)
+            (modifiers private))
+          (def (setDashboard (report : (Nullable JSONObject))) : Unit
+            (begin
+              (set! statusReport
+                (if (nullable-null? report)
+                  (nullable-none JSONObject)
+                  (sivJsonObject (nullable-get report) "status")))
+              (sivInvalidate this)))
+          (def (setStatusReport (report : (Nullable JSONObject))) : Unit
+            (begin (set! statusReport report) (sivInvalidate this)))
+          (def (setTruthReports (alpha : (Nullable JSONObject))
+                                (beta : (Nullable JSONObject))) : Unit
+            (begin
+              (set! alphaTruth alpha)
+              (set! betaTruth beta)
+              (sivInvalidate this)))
+          (def (onDraw (canvas : Canvas)) : Unit
+            (modifiers override)
+            (begin
+              (sivSuperDraw canvas)
+              (let ((state (sivSave canvas)) (scale (sivDensity this)))
+                (begin
+                  (set! drawWidth (/ (float32 (sivWidth this)) scale))
+                  (set! drawHeight (/ (float32 (sivHeight this)) scale))
+                  (sivScale canvas scale scale)
+                  (try-finally (drawContent canvas) (sivRestore canvas state))))))
+          (def (drawContent (canvas : Canvas)) : Unit
+            (modifiers private)
+            (begin
+              (sivDrawRoundRect canvas
+                (new RectF (float32 0.0) (float32 0.0) drawWidth drawHeight)
+                (float32 10.0) (float32 10.0) backgroundPaint)
+              (if (nullable-null? statusReport)
+                (drawEmpty canvas)
+                (let ((status (nullable-get statusReport)))
+                  (begin
+                    (drawHeader canvas status)
+                    (let ((gap (float32 10.0))
+                          (top (float32 42.0))
+                          (cardWidth (/ (- drawWidth (float32 30.0)) (float32 2.0))))
+                      (begin
+                        (drawActorIntel canvas
+                          (new RectF gap top (+ gap cardWidth) (- drawHeight (float32 8.0)))
+                          "ALPHA" (sivJsonObject status "alpha") alphaTruth alphaPaint)
+                        (drawActorIntel canvas
+                          (new RectF (+ (float32 20.0) cardWidth) top
+                            (+ (float32 20.0) (* cardWidth (float32 2.0)))
+                            (- drawHeight (float32 8.0)))
+                          "BETA" (sivJsonObject status "beta") betaTruth betaPaint))))))))
+          (def (drawEmpty (canvas : Canvas)) : Unit
+            (modifiers private)
+            (begin
+              (sivPaintAlignSet titlePaint (sivCenter))
+              (sivDrawText canvas "SFC2 Tactical Intel"
+                (/ drawWidth (float32 2.0))
+                (- (/ drawHeight (float32 2.0)) (float32 4.0)) titlePaint)
+              (sivPaintAlignSet smallPaint (sivCenter))
+              (sivDrawText canvas "Waiting for dashboard"
+                (/ drawWidth (float32 2.0))
+                (+ (/ drawHeight (float32 2.0)) (float32 20.0)) smallPaint)))
+          (def (drawHeader (canvas : Canvas) (status : JSONObject)) : Unit
+            (modifiers private)
+            (begin
+              (sivPaintAlignSet titlePaint (sivLeft))
+              (sivDrawText canvas "SFC2 INTEL" (float32 12.0) (float32 27.0) titlePaint)
+              (sivPaintAlignSet smallPaint (sivRight))
+              (sivDrawText canvas
+                (string-append "T"
+                  (string-append (int32->string (sivJsonInt status "turn" (int32 0)))
+                    (string-append "."
+                      (int32->string (sivJsonInt status "impulse" (int32 0))))))
+                (- drawWidth (float32 12.0)) (float32 25.0) smallPaint)))
+          (def (drawActorIntel (canvas : Canvas) (rect : RectF)
+                               (side : String)
+                               (actor : (Nullable JSONObject))
+                               (truth : (Nullable JSONObject))
+                               (sidePaint : Paint)) : Unit
+            (modifiers private)
+            (begin
+              (sivDrawRoundRect canvas rect (float32 8.0) (float32 8.0) panelPaint)
+              (sivDrawRoundRect canvas rect (float32 8.0) (float32 8.0) borderPaint)
+              (sivDrawRoundRect canvas
+                (new RectF (sivRectLeft rect) (sivRectTop rect)
+                  (sivRectRight rect) (+ (sivRectTop rect) (float32 25.0)))
+                (float32 8.0) (float32 8.0) sidePaint)
+              (sivPaintAlignSet labelPaint (sivLeft))
+              (sivDrawText canvas side
+                (+ (sivRectLeft rect) (float32 8.0))
+                (+ (sivRectTop rect) (float32 20.0)) labelPaint)
+              (sivPaintAlignSet smallPaint (sivLeft))
+              (sivDrawText canvas
+                (if (or (nullable-null? actor)
+                        (not (sivJsonBoolean (nullable-get actor) "ship-present?" #f)))
+                  "No ship report"
+                  (sivShipDisplayLabel (nullable-get actor)))
+                (+ (sivRectLeft rect) (float32 8.0))
+                (+ (sivRectTop rect) (float32 52.0)) smallPaint)
+              (sivPaintAlignSet dimPaint (sivLeft))
+              (sivDrawText canvas
+                (if (nullable-null? truth) "No truth report" "Truth report loaded")
+                (+ (sivRectLeft rect) (float32 8.0))
+                (+ (sivRectTop rect) (float32 78.0)) dimPaint))))))))
diff --git a/templates/original-tactics-parts/SystemsReadinessView.kt.ss b/templates/original-tactics-parts/SystemsReadinessView.kt.ss
new file mode 100644
index 0000000..ba200c6
--- /dev/null
+++ b/templates/original-tactics-parts/SystemsReadinessView.kt.ss
@@ -0,0 +1,236 @@
+(import (jerboa prelude))
+
+(def fragment
+  '((typed-kotlin-file "com/jerboa/originaltactics/SystemsReadinessView.kt"
+      (kotlin-imports
+        (android content Context)
+        (android graphics Canvas)
+        (android graphics Color)
+        (android graphics Paint)
+        (android graphics Paint Align)
+        (android graphics Paint Style)
+        (android graphics RectF)
+        (android view View)
+        (org json JSONArray)
+        (org json JSONObject))
+      (typed-library (com jerboa originaltactics)
+        (export SystemsReadinessView)
+        (type Context) (type Canvas) (type Paint) (type Align) (type Style)
+        (type RectF) (type View) (type Resources) (type DisplayMetrics)
+        (type JSONArray) (type JSONObject) (type Int32) (type Float32)
+        (extern (srvPaintFlag) : Int32 (kotlin-value Paint ANTI_ALIAS_FLAG))
+        (extern (srvFill) : Style (kotlin-value Paint Style FILL))
+        (extern (srvStroke) : Style (kotlin-value Paint Style STROKE))
+        (extern (srvLeft) : Align (kotlin-value Paint Align LEFT))
+        (extern (srvCenter) : Align (kotlin-value Paint Align CENTER))
+        (extern (srvRight) : Align (kotlin-value Paint Align RIGHT))
+        (extern (srvWhite) : Int32 (kotlin-value Color WHITE))
+        (extern (srvRgb (r : Int32) (g : Int32) (b : Int32)) : Int32
+          (kotlin-call Color rgb))
+        (extern (srvPaintColorSet (paint : Paint) (value : Int32)) : Unit
+          (kotlin-member-set color))
+        (extern (srvPaintStyleSet (paint : Paint) (value : Style)) : Unit
+          (kotlin-member-set style))
+        (extern (srvPaintSizeSet (paint : Paint) (value : Float32)) : Unit
+          (kotlin-member-set textSize))
+        (extern (srvPaintBoldSet (paint : Paint) (value : Bool)) : Unit
+          (kotlin-member-set isFakeBoldText))
+        (extern (srvPaintAlignSet (paint : Paint) (value : Align)) : Unit
+          (kotlin-member-set textAlign))
+        (extern (srvInvalidate (view : SystemsReadinessView)) : Unit
+          (kotlin-member-call invalidate))
+        (extern (srvSuperDraw (canvas : Canvas)) : Unit
+          (kotlin-call super onDraw))
+        (extern (srvSave (canvas : Canvas)) : Int32 (kotlin-member-call save))
+        (extern (srvScale (canvas : Canvas) (x : Float32) (y : Float32)) : Unit
+          (kotlin-member-call scale))
+        (extern (srvRestore (canvas : Canvas) (state : Int32)) : Unit
+          (kotlin-member-call restoreToCount))
+        (extern (srvWidth (view : SystemsReadinessView)) : Int32
+          (kotlin-member-get width))
+        (extern (srvHeight (view : SystemsReadinessView)) : Int32
+          (kotlin-member-get height))
+        (extern (srvResources (view : SystemsReadinessView)) : Resources
+          (kotlin-member-get resources))
+        (extern (srvMetrics (resources : Resources)) : DisplayMetrics
+          (kotlin-member-get displayMetrics))
+        (extern (srvDensityValue (metrics : DisplayMetrics)) : Float32
+          (kotlin-member-get density))
+        (extern (srvDrawRect (canvas : Canvas)
+                             (left : Float32) (top : Float32)
+                             (right : Float32) (bottom : Float32)
+                             (paint : Paint)) : Unit
+          (kotlin-member-call drawRect))
+        (extern (srvDrawRoundRect (canvas : Canvas) (rect : RectF)
+                                  (rx : Float32) (ry : Float32)
+                                  (paint : Paint)) : Unit
+          (kotlin-member-call drawRoundRect))
+        (extern (srvDrawText (canvas : Canvas) (text : String)
+                             (x : Float32) (y : Float32)
+                             (paint : Paint)) : Unit
+          (kotlin-member-call drawText))
+        (extern (srvRectLeft (rect : RectF)) : Float32 (kotlin-member-get left))
+        (extern (srvRectTop (rect : RectF)) : Float32 (kotlin-member-get top))
+        (extern (srvRectRight (rect : RectF)) : Float32 (kotlin-member-get right))
+        (extern (srvJsonObject (object : JSONObject)
+                               (key : String)) : (Nullable JSONObject)
+          (kotlin-member-call optJSONObject))
+        (extern (srvJsonArray (object : JSONObject)
+                              (key : String)) : (Nullable JSONArray)
+          (kotlin-member-call optJSONArray))
+        (extern (srvJsonInt (object : JSONObject) (key : String)
+                            (fallback : Int32)) : Int32
+          (kotlin-member-call optInt))
+        (extern (srvJsonBoolean (object : JSONObject) (key : String)
+                                (fallback : Bool)) : Bool
+          (kotlin-member-call optBoolean))
+        (extern (srvArrayLength (array : JSONArray)) : Int32
+          (kotlin-member-call length))
+        (extern (srvShipDisplayLabel (actor : JSONObject)) : String
+          (kotlin-call shipDisplayLabel))
+        (def (srvPaint (color : Int32) (style : Style)) : Paint
+          (let ((paint (new Paint (srvPaintFlag))))
+            (begin
+              (srvPaintColorSet paint color)
+              (srvPaintStyleSet paint style)
+              paint)))