Skip to content

GeometryFinding.kt

src/jvmMain/kotlin/afield/ui/visualization/GeometryFinding.kt · 49 lines

package afield.ui.visualization

import afield.geometry.path.div
import afield.geometry.path.minus
import afield.geometry.path.plus
import afield.geometry.path.times
import afield.lang.remotejs.JsFun

import afield.geometry.path.length
import kotlinx.serialization.json.*

GeometryFinding, the record a geometry checker or agent writes about a piece of geometry for review; it never changes whether a build is accepted.

data class GeometryFinding

Review metadata shared by checkers and agents. A finding never changes build acceptance.

data class GeometryFinding(
    val key: String,
    val kind: String,
    val stage: String,
    val runId: String,
    val producer: String,
    val consequence: String,
    val prompt: String,
) {

fun json(): JsonObject

    fun json(): JsonObject = buildJsonObject {
        put("key", key); put("kind", kind); put("stage", stage); put("runId", runId)
        put("producer", producer); put("consequence", consequence); put("prompt", prompt)
    }.also(::validateGeometryFinding)
}

internal fun validateGeometryFinding(value: JsonObject)

internal fun validateGeometryFinding(value: JsonObject) {
    require(value.keys == setOf("key", "kind", "stage", "runId", "producer", "consequence", "prompt")) {
        "A finding requires key, kind, stage, runId, producer, consequence and prompt"
    }
    for (field in value.keys) {
        val text = (value[field] as? JsonPrimitive)?.takeIf { it.isString }?.content
        val limit = if (field in setOf("consequence", "prompt")) 4000 else 256
        require(text != null && text.isNotBlank() && text.length <= limit) { "Finding $field must contain 1..$limit characters" }
    }
    require(value.getValue("kind").jsonPrimitive.content in setOf("error", "warning", "question")) {
        "Finding kind must be error, warning or question"
    }
}

internal fun sameFindingOccurrence(a: JsonObject, b: JsonObject): Boolean

internal fun sameFindingOccurrence(a: JsonObject, b: JsonObject): Boolean =
    listOf("key", "stage", "runId", "producer").all { a[it] == b[it] }