Coverage Summary for Class: CanonicalEventsJsonKt (core.serde)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| CanonicalEventsJsonKt |
100%
(1/1)
|
81%
(34/42)
|
76.8%
(63/82)
|
81.3%
(222/273)
|
80.3%
(1125/1401)
|
package core.serde
import core.*
/**
* Canonical JSON serialization for domain [Event] lists.
*
* The output is intended to be stable across runs given identical in-memory [Event] instances:
* - Compact JSON (no insignificant whitespace).
* - Explicit, event-type-specific field order.
* - Type discriminator is always the first JSON key.
* - Common fields are always present and emitted in fixed order: `type`, `day`, `revision`, `cmdId`, `seq`.
*
* ## Contract
* - Produces a single JSON array containing one JSON object per input event, in the same order as `events`.
* - Each event is serialized according to the concrete subtype branch in [serializeEvent].
* - Strings are escaped by [escapeJson] for the subset of escapes implemented there.
*
* ## Preconditions
* - All numeric fields must already satisfy their domain constraints (this serializer does not validate).
* - Each event subtype listed in [serializeEvent] must have a corresponding `serializeXxx` implementation.
*
* ## Postconditions
* - Returned string is valid JSON for the emitted subset of types and fields.
* - No trailing commas are emitted.
*
* ## Invariants
* - Field order is stable by construction (append-only in a fixed sequence).
* - Event order is preserved (`events[0]` becomes JSON element 0, etc.).
*
* ## Determinism
* - Deterministic for a fixed `events` sequence and fixed per-event field values.
* - Does not read wall-clock time or global mutable state.
*
* ## Complexity
* - Time: O(total_output_chars)
* - Memory: O(total_output_chars)
*
* @param events Events to serialize; order is preserved.
* @return Compact canonical JSON array string.
*/
fun serializeEvents(events: List<Event>): String {
val sb = StringBuilder()
sb.append('[')
events.forEachIndexed { index, event ->
if (index > 0) sb.append(',')
serializeEvent(event, sb)
}
sb.append(']')
return sb.toString()
}
/**
* Serializes a single [Event] into `sb` as one JSON object (without surrounding commas/array brackets).
*
* ## Contract
* - Appends exactly one JSON object to `sb`.
* - Dispatch is performed by Kotlin `when` on the runtime subtype of [Event].
*
* ## Preconditions
* - `event` runtime type must be covered by one of the `when` branches; otherwise compilation fails when
* [Event] is sealed and extended, or a missing branch will be required when new subtypes are added.
*
* ## Postconditions
* - `sb` is appended with a JSON object that begins with `{` and ends with `}`.
*
* ## Invariants
* - The first field appended by each serializer must be produced by [StringBuilder.appendCommonFields].
*
* ## Determinism
* - Deterministic given deterministic `event` data.
*
* ## Complexity
* - Time: O(event_output_chars)
* - Memory: O(event_output_chars) incremental append
*
* @param event Concrete event instance to serialize.
* @param sb Destination buffer to append to.
*/
private fun serializeEvent(event: Event, sb: StringBuilder) {
when (event) {
is DayStarted -> serializeDayStarted(event, sb)
is InboxGenerated -> serializeInboxGenerated(event, sb)
is HeroesArrived -> serializeHeroesArrived(event, sb)
is ContractPosted -> serializeContractPosted(event, sb)
is ContractTaken -> serializeContractTaken(event, sb)
is WipAdvanced -> serializeWipAdvanced(event, sb)
is ContractResolved -> serializeContractResolved(event, sb)
is ReturnClosed -> serializeReturnClosed(event, sb)
is ReturnRejected -> serializeReturnRejected(event, sb)
is TrophySold -> serializeTrophySold(event, sb)
is StabilityUpdated -> serializeStabilityUpdated(event, sb)
is DayEnded -> serializeDayEnded(event, sb)
is CommandRejected -> serializeCommandRejected(event, sb)
is InvariantViolated -> serializeInvariantViolated(event, sb)
is HeroDeclined -> serializeHeroDeclined(event, sb)
is TrophyTheftSuspected -> serializeTrophyTheftSuspected(event, sb)
is TaxDue -> serializeTaxDue(event, sb)
is TaxPaid -> serializeTaxPaid(event, sb)
is TaxMissed -> serializeTaxMissed(event, sb)
is GuildShutdown -> serializeGuildShutdown(event, sb)
is GuildRankUp -> serializeGuildRankUp(event, sb)
is ProofPolicyChanged -> serializeProofPolicyChanged(event, sb)
is ContractDraftCreated -> serializeContractDraftCreated(event, sb)
is ContractTermsUpdated -> serializeContractTermsUpdated(event, sb)
is ContractCancelled -> serializeContractCancelled(event, sb)
is ContractAutoResolved -> serializeContractAutoResolved(event, sb)
is HeroDied -> serializeHeroDied(event, sb)
is ReturnClosureBlocked -> serializeReturnClosureBlocked(event, sb)
// Fraud investigation events (v0)
is FraudInvestigated -> serializeFraudInvestigated(event, sb)
is HeroWarned -> serializeHeroWarned(event, sb)
is HeroBanned -> serializeHeroBanned(event, sb)
is RumorScheduled -> serializeRumorScheduled(event, sb)
is WeeklyReportPublished -> serializeWeeklyReportPublished(event, sb)
}
}
/**
* Appends the JSON object prefix and the common fields shared by all events.
*
* Output shape prefix (no closing `}`):
* `{"type":"<type>","day":<n>,"revision":<n>,"cmdId":<n>,"seq":<n>`
*
* ## Contract
* - Must be called exactly once at the beginning of each event-specific serializer.
* - Does not close the JSON object; the caller must append additional fields (optional) and close with `}`.
*
* ## Preconditions
* - `type` must match the discriminator string expected by the corresponding deserializer (if any).
*
* ## Postconditions
* - `sb` contains a `{` and five fields in fixed order: `type`, `day`, `revision`, `cmdId`, `seq`.
*
* ## Determinism
* - Deterministic given `type` and `event` field values.
*
* ## Complexity
* - Time: O(1) relative to event size (constant number of appends)
* - Memory: O(1) incremental append
*
* @param type Type discriminator string written into the JSON `type` field.
* @param event Event providing `day`, `revision`, `cmdId`, `seq`.
*/
private fun StringBuilder.appendCommonFields(type: String, event: Event) {
append("{\"type\":\"")
append(type)
append("\",\"day\":")
append(event.day)
append(",\"revision\":")
append(event.revision)
append(",\"cmdId\":")
append(event.cmdId)
append(",\"seq\":")
append(event.seq)
}
/**
* Appends a string field to an existing JSON object being built in this [StringBuilder].
*
* The emitted fragment has the form: `,"<name>":"<escaped>"`
*
* ## Contract
* - Prepends a comma before the field (caller must already be inside an object).
* - Escapes the value using [escapeJson].
*
* ## Preconditions
* - Caller has already started a JSON object and has not closed it.
*
* ## Postconditions
* - `sb` is appended with a JSON string field.
*
* ## Complexity
* - Time: O(value.length)
* - Memory: O(1) incremental append
*
* @param name JSON field name (unescaped; emitted as-is inside quotes).
* @param value Raw string value; will be escaped by [escapeJson].
*/
private fun StringBuilder.appendStringField(name: String, value: String) {
append(",\"")
append(name)
append("\":\"")
append(escapeJson(value))
append("\"")
}
/**
* Appends an integer field to an existing JSON object being built in this [StringBuilder].
*
* The emitted fragment has the form: `,"<name>":<value>`
*
* ## Contract
* - Prepends a comma before the field.
* - Writes the integer value as a JSON number (no quotes).
*
* ## Preconditions
* - Caller has already started a JSON object and has not closed it.
*
* ## Postconditions
* - `sb` is appended with a JSON numeric field.
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*
* @param name JSON field name.
* @param value Integer value.
*/
private fun StringBuilder.appendIntField(name: String, value: Int) {
append(",\"")
append(name)
append("\":")
append(value)
}
/**
* Appends an `IntArray` field to an existing JSON object being built in this [StringBuilder].
*
* The emitted fragment has the form: `,"<name>":[v0,v1,...]`
*
* ## Contract
* - Prepends a comma before the field.
* - Emits values in the array's iteration order with comma separation and no whitespace.
*
* ## Preconditions
* - Caller has already started a JSON object and has not closed it.
*
* ## Postconditions
* - `sb` is appended with a JSON array of numbers (possibly empty).
*
* ## Complexity
* - Time: O(array.size)
* - Memory: O(1) incremental append
*
* @param name JSON field name.
* @param array Integer array to emit.
*/
private fun StringBuilder.appendIntArray(name: String, array: IntArray) {
append(",\"")
append(name)
append("\":[")
array.forEachIndexed { index, value ->
if (index > 0) append(',')
append(value)
}
append("]")
}
/**
* Appends a nullable integer field to an existing JSON object being built in this [StringBuilder].
*
* The emitted fragment has the form: `,"<name>":null` or `,"<name>":<value>`
*
* ## Contract
* - Prepends a comma before the field.
* - Emits JSON `null` when `value == null`.
*
* ## Preconditions
* - Caller has already started a JSON object and has not closed it.
*
* ## Postconditions
* - `sb` is appended with a JSON numeric-or-null field.
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*
* @param name JSON field name.
* @param value Nullable integer; `null` is emitted as JSON `null`.
*/
private fun StringBuilder.appendNullableIntField(name: String, value: Int?) {
append(",\"")
append(name)
append("\":")
if (value == null) {
append("null")
} else {
append(value)
}
}
/**
* Appends a nullable string field to an existing JSON object being built in this [StringBuilder].
*
* The emitted fragment has the form: `,"<name>":null` or `,"<name>":"<escaped>"`
*
* ## Contract
* - Prepends a comma before the field.
* - Emits JSON `null` when `value == null`.
* - Escapes non-null values via [escapeJson].
*
* ## Preconditions
* - Caller has already started a JSON object and has not closed it.
*
* ## Postconditions
* - `sb` is appended with a JSON string-or-null field.
*
* ## Complexity
* - Time: O(value.length) when non-null; otherwise O(1)
* - Memory: O(1) incremental append
*
* @param name JSON field name.
* @param value Nullable string; non-null values are escaped.
*/
private fun StringBuilder.appendNullableStringField(name: String, value: String?) {
append(",\"")
append(name)
append("\":")
if (value == null) {
append("null")
} else {
append("\"")
append(escapeJson(value))
append("\"")
}
}
/**
* Escapes a string for embedding into a JSON string literal.
*
* Implemented escapes:
* - `\` -> `\\`
* - `"` -> `\"`
* - newline -> `\n`
* - carriage return -> `\r`
* - tab -> `\t`
*
* ## Contract
* - Returns a string that can be safely inserted between JSON quotes for the above characters.
*
* ## Preconditions
* - Input must not contain other control characters that require JSON escaping if strict JSON compliance
* for all code points is required; this function does not implement full JSON escaping.
*
* ## Postconditions
* - Returned string has no unescaped occurrences of the handled characters.
*
* ## Determinism
* - Pure function over `str`.
*
* ## Complexity
* - Time: O(str.length)
* - Memory: O(str.length) (due to successive replacements)
*
* @param str Raw string to escape.
* @return Escaped string suitable for JSON string literal content.
*/
private fun escapeJson(str: String): String {
return str
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t")
}
// Event-specific serializers
/**
* Serializes [DayStarted] into a JSON object with only common fields.
*
* ## Contract
* - Emits: `{"type":"DayStarted","day":...,"revision":...,"cmdId":...,"seq":...}`
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeDayStarted(event: DayStarted, sb: StringBuilder) {
sb.appendCommonFields("DayStarted", event)
sb.append('}')
}
/**
* Serializes [InboxGenerated].
*
* Emitted additional fields (in order):
* - `count` (Int)
* - `contractIds` (IntArray)
*
* ## Complexity
* - Time: O(contractIds.size)
* - Memory: O(1)
*/
private fun serializeInboxGenerated(event: InboxGenerated, sb: StringBuilder) {
sb.appendCommonFields("InboxGenerated", event)
sb.appendIntField("count", event.count)
sb.appendIntArray("contractIds", event.contractIds)
sb.append('}')
}
/**
* Serializes [HeroesArrived].
*
* Emitted additional fields (in order):
* - `count` (Int)
* - `heroIds` (IntArray)
*
* ## Complexity
* - Time: O(heroIds.size)
* - Memory: O(1)
*/
private fun serializeHeroesArrived(event: HeroesArrived, sb: StringBuilder) {
sb.appendCommonFields("HeroesArrived", event)
sb.appendIntField("count", event.count)
sb.appendIntArray("heroIds", event.heroIds)
sb.append('}')
}
/**
* Serializes [ContractPosted].
*
* Emitted additional fields (in order):
* - `boardContractId` (Int)
* - `fromInboxId` (Int)
* - `rank` (String; `event.rank.name`)
* - `fee` (Int)
* - `salvage` (String; `event.salvage.name`)
* - `clientDeposit` (Int; client's contribution towards the fee)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeContractPosted(event: ContractPosted, sb: StringBuilder) {
sb.appendCommonFields("ContractPosted", event)
sb.appendIntField("boardContractId", event.boardContractId)
sb.appendIntField("fromInboxId", event.fromInboxId)
sb.appendStringField("rank", event.rank.name)
sb.appendIntField("fee", event.fee)
sb.appendStringField("salvage", event.salvage.name)
sb.appendIntField("clientDeposit", event.clientDeposit)
sb.append('}')
}
/**
* Serializes [ContractTaken].
*
* Emitted additional fields (in order):
* - `activeContractId` (Int)
* - `boardContractId` (Int)
* - `heroIds` (IntArray)
* - `daysRemaining` (Int)
*
* ## Complexity
* - Time: O(heroIds.size)
* - Memory: O(1)
*/
private fun serializeContractTaken(event: ContractTaken, sb: StringBuilder) {
sb.appendCommonFields("ContractTaken", event)
sb.appendIntField("activeContractId", event.activeContractId)
sb.appendIntField("boardContractId", event.boardContractId)
sb.appendIntArray("heroIds", event.heroIds)
sb.appendIntField("daysRemaining", event.daysRemaining)
sb.append('}')
}
/**
* Serializes [WipAdvanced].
*
* Emitted additional fields (in order):
* - `activeContractId` (Int)
* - `daysRemaining` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeWipAdvanced(event: WipAdvanced, sb: StringBuilder) {
sb.appendCommonFields("WipAdvanced", event)
sb.appendIntField("activeContractId", event.activeContractId)
sb.appendIntField("daysRemaining", event.daysRemaining)
sb.append('}')
}
/**
* Serializes [ContractResolved].
*
* Emitted additional fields (in order):
* - `activeContractId` (Int)
* - `outcome` (String; `event.outcome.name`)
* - `trophiesCount` (Int)
* - `quality` (String; `event.quality.name`)
* - `reasonTags` (IntArray)
*
* ## Complexity
* - Time: O(reasonTags.size)
* - Memory: O(1)
*/
private fun serializeContractResolved(event: ContractResolved, sb: StringBuilder) {
sb.appendCommonFields("ContractResolved", event)
sb.appendIntField("activeContractId", event.activeContractId)
sb.appendStringField("outcome", event.outcome.name)
sb.appendIntField("trophiesCount", event.trophiesCount)
sb.appendStringField("quality", event.quality.name)
sb.appendIntArray("reasonTags", event.reasonTags)
sb.append('}')
}
/**
* Serializes [ReturnClosed].
*
* Emitted additional fields (in order):
* - `activeContractId` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeReturnClosed(event: ReturnClosed, sb: StringBuilder) {
sb.appendCommonFields("ReturnClosed", event)
sb.appendIntField("activeContractId", event.activeContractId)
sb.append('}')
}
/**
* Serializes [ReturnRejected].
*
* Emitted additional fields (in order):
* - `activeContractId` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeReturnRejected(event: ReturnRejected, sb: StringBuilder) {
sb.appendCommonFields("ReturnRejected", event)
sb.appendIntField("activeContractId", event.activeContractId)
sb.append('}')
}
/**
* Serializes [TrophySold].
*
* Emitted additional fields (in order):
* - `amount` (Int)
* - `moneyGained` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeTrophySold(event: TrophySold, sb: StringBuilder) {
sb.appendCommonFields("TrophySold", event)
sb.appendIntField("amount", event.amount)
sb.appendIntField("moneyGained", event.moneyGained)
sb.append('}')
}
/**
* Serializes [StabilityUpdated].
*
* Emitted additional fields (in order):
* - `oldStability` (Int)
* - `newStability` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeStabilityUpdated(event: StabilityUpdated, sb: StringBuilder) {
sb.appendCommonFields("StabilityUpdated", event)
sb.appendIntField("oldStability", event.oldStability)
sb.appendIntField("newStability", event.newStability)
sb.append('}')
}
/**
* Serializes [DayEnded] including its nested `snapshot` object.
*
* Emitted additional fields:
* - `snapshot` (object) with a fixed set of numeric fields (as appended below).
*
* ## Contract
* - `snapshot` is emitted as an inline object; field order inside `snapshot` is the append order in this method.
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeDayEnded(event: DayEnded, sb: StringBuilder) {
sb.appendCommonFields("DayEnded", event)
sb.append(",\"snapshot\":{")
val snap = event.snapshot
sb.append("\"day\":")
sb.append(snap.day)
sb.append(",\"revision\":")
sb.append(snap.revision)
sb.append(",\"money\":")
sb.append(snap.money)
sb.append(",\"trophies\":")
sb.append(snap.trophies)
sb.append(",\"regionStability\":")
sb.append(snap.regionStability)
sb.append(",\"guildReputation\":")
sb.append(snap.guildReputation)
sb.append(",\"inboxCount\":")
sb.append(snap.inboxCount)
sb.append(",\"boardCount\":")
sb.append(snap.boardCount)
sb.append(",\"activeCount\":")
sb.append(snap.activeCount)
sb.append(",\"returnsNeedingCloseCount\":")
sb.append(snap.returnsNeedingCloseCount)
sb.append("}}")
}
/**
* Serializes [CommandRejected].
*
* Emitted additional fields (in order):
* - `cmdType` (String)
* - `reason` (String; `event.reason.name`)
* - `detail` (String; escaped)
*
* ## Complexity
* - Time: O(detail.length)
* - Memory: O(1)
*/
private fun serializeCommandRejected(event: CommandRejected, sb: StringBuilder) {
sb.appendCommonFields("CommandRejected", event)
sb.appendStringField("cmdType", event.cmdType)
sb.appendStringField("reason", event.reason.name)
sb.appendStringField("detail", event.detail)
sb.append('}')
}
/**
* Serializes [InvariantViolated].
*
* Emitted additional fields (in order):
* - `invariantId` (String; `event.invariantId.name`)
* - `details` (String; escaped)
*
* ## Complexity
* - Time: O(details.length)
* - Memory: O(1)
*/
private fun serializeInvariantViolated(event: InvariantViolated, sb: StringBuilder) {
sb.appendCommonFields("InvariantViolated", event)
sb.appendStringField("invariantId", event.invariantId.name)
sb.appendStringField("details", event.details)
sb.append('}')
}
/**
* Serializes [HeroDeclined].
*
* Emitted additional fields (in order):
* - `heroId` (Int)
* - `boardContractId` (Int)
* - `reason` (String; escaped)
*
* ## Complexity
* - Time: O(reason.length)
* - Memory: O(1)
*/
private fun serializeHeroDeclined(event: HeroDeclined, sb: StringBuilder) {
sb.appendCommonFields("HeroDeclined", event)
sb.appendIntField("heroId", event.heroId)
sb.appendIntField("boardContractId", event.boardContractId)
sb.appendStringField("reason", event.reason)
sb.append('}')
}
/**
* Serializes [TrophyTheftSuspected].
*
* Emitted additional fields (in order):
* - `activeContractId` (Int)
* - `heroId` (Int)
* - `expectedTrophies` (Int)
* - `reportedTrophies` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeTrophyTheftSuspected(event: TrophyTheftSuspected, sb: StringBuilder) {
sb.appendCommonFields("TrophyTheftSuspected", event)
sb.appendIntField("activeContractId", event.activeContractId)
sb.appendIntField("heroId", event.heroId)
sb.appendIntField("expectedTrophies", event.expectedTrophies)
sb.appendIntField("reportedTrophies", event.reportedTrophies)
sb.append('}')
}
/**
* Serializes [TaxDue].
*
* Emitted additional fields (in order):
* - `amountDue` (Int)
* - `dueDay` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeTaxDue(event: TaxDue, sb: StringBuilder) {
sb.appendCommonFields("TaxDue", event)
sb.appendIntField("amountDue", event.amountDue)
sb.appendIntField("dueDay", event.dueDay)
sb.append('}')
}
/**
* Serializes [TaxPaid].
*
* Emitted additional fields (in order):
* - `amountPaid` (Int)
* - `amountDue` (Int)
* - `isPartialPayment` (Boolean)
*
* ## Contract
* - Boolean is emitted as JSON `true`/`false` without quotes.
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeTaxPaid(event: TaxPaid, sb: StringBuilder) {
sb.appendCommonFields("TaxPaid", event)
sb.appendIntField("amountPaid", event.amountPaid)
sb.appendIntField("amountDue", event.amountDue)
sb.append(",\"isPartialPayment\":")
sb.append(if (event.isPartialPayment) "true" else "false")
sb.append('}')
}
/**
* Serializes [TaxMissed].
*
* Emitted additional fields (in order):
* - `amountDue` (Int)
* - `penaltyAdded` (Int)
* - `missedCount` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeTaxMissed(event: TaxMissed, sb: StringBuilder) {
sb.appendCommonFields("TaxMissed", event)
sb.appendIntField("amountDue", event.amountDue)
sb.appendIntField("penaltyAdded", event.penaltyAdded)
sb.appendIntField("missedCount", event.missedCount)
sb.append('}')
}
/**
* Serializes [GuildShutdown].
*
* Emitted additional fields (in order):
* - `reason` (String; escaped)
*
* ## Complexity
* - Time: O(reason.length)
* - Memory: O(1)
*/
private fun serializeGuildShutdown(event: GuildShutdown, sb: StringBuilder) {
sb.appendCommonFields("GuildShutdown", event)
sb.appendStringField("reason", event.reason)
sb.append('}')
}
/**
* Serializes [GuildRankUp].
*
* Emitted additional fields (in order):
* - `oldRank` (Int)
* - `newRank` (Int)
* - `completedContracts` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeGuildRankUp(event: GuildRankUp, sb: StringBuilder) {
sb.appendCommonFields("GuildRankUp", event)
sb.appendIntField("oldRank", event.oldRank)
sb.appendIntField("newRank", event.newRank)
sb.appendIntField("completedContracts", event.completedContracts)
sb.append('}')
}
/**
* Serializes [ProofPolicyChanged].
*
* Emitted additional fields (in order):
* - `oldPolicy` (Int)
* - `newPolicy` (Int)
*
* ## Note
* This serializer emits `oldPolicy` and `newPolicy` as integers; the mapping of those integers to a
* domain enum/type is defined by the event model, not by this serializer.
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeProofPolicyChanged(event: ProofPolicyChanged, sb: StringBuilder) {
sb.appendCommonFields("ProofPolicyChanged", event)
sb.appendIntField("oldPolicy", event.oldPolicy)
sb.appendIntField("newPolicy", event.newPolicy)
sb.append('}')
}
/**
* Serializes [ContractDraftCreated].
*
* Emitted additional fields (in order):
* - `draftId` (Int)
* - `title` (String; escaped)
* - `rank` (String; `event.rank.name`)
* - `difficulty` (Int)
* - `reward` (Int)
* - `salvage` (String; `event.salvage.name`)
*
* ## Complexity
* - Time: O(title.length)
* - Memory: O(1)
*/
private fun serializeContractDraftCreated(event: ContractDraftCreated, sb: StringBuilder) {
sb.appendCommonFields("ContractDraftCreated", event)
sb.appendIntField("draftId", event.draftId)
sb.appendStringField("title", event.title)
sb.appendStringField("rank", event.rank.name)
sb.appendIntField("difficulty", event.difficulty)
sb.appendIntField("reward", event.reward)
sb.appendStringField("salvage", event.salvage.name)
sb.append('}')
}
/**
* Serializes [ContractTermsUpdated].
*
* Emitted additional fields (in order):
* - `contractId` (Int)
* - `location` (String; escaped)
* - `oldFee` (Int?; JSON number or null)
* - `newFee` (Int?; JSON number or null)
* - `oldSalvage` (String?; JSON string or null; uses `name` when non-null)
* - `newSalvage` (String?; JSON string or null; uses `name` when non-null)
*
* ## Complexity
* - Time: O(location.length + (oldSalvage?.name?.length ?: 0) + (newSalvage?.name?.length ?: 0))
* - Memory: O(1)
*/
private fun serializeContractTermsUpdated(event: ContractTermsUpdated, sb: StringBuilder) {
sb.appendCommonFields("ContractTermsUpdated", event)
sb.appendIntField("contractId", event.contractId)
sb.appendStringField("location", event.location)
sb.appendNullableIntField("oldFee", event.oldFee)
sb.appendNullableIntField("newFee", event.newFee)
sb.appendNullableStringField("oldSalvage", event.oldSalvage?.name)
sb.appendNullableStringField("newSalvage", event.newSalvage?.name)
sb.append('}')
}
/**
* Serializes [ContractCancelled].
*
* Emitted additional fields (in order):
* - `contractId` (Int)
* - `location` (String; escaped)
* - `refundedCopper` (Int)
*
* ## Complexity
* - Time: O(location.length)
* - Memory: O(1)
*/
private fun serializeContractCancelled(event: ContractCancelled, sb: StringBuilder) {
sb.appendCommonFields("ContractCancelled", event)
sb.appendIntField("contractId", event.contractId)
sb.appendStringField("location", event.location)
sb.appendIntField("refundedCopper", event.refundedCopper)
sb.append('}')
}
/**
* Serializes [ContractAutoResolved].
*
* Emitted additional fields (in order):
* - `draftId` (Int)
* - `bucket` (String; `event.bucket.name`)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeContractAutoResolved(event: ContractAutoResolved, sb: StringBuilder) {
sb.appendCommonFields("ContractAutoResolved", event)
sb.appendIntField("draftId", event.draftId)
sb.appendStringField("bucket", event.bucket.name)
sb.append('}')
}
/**
* Serializes [HeroDied].
*
* Emitted additional fields (in order):
* - `heroId` (Int)
* - `activeContractId` (Int)
* - `boardContractId` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeHeroDied(event: HeroDied, sb: StringBuilder) {
sb.appendCommonFields("HeroDied", event)
sb.appendIntField("heroId", event.heroId)
sb.appendIntField("activeContractId", event.activeContractId)
sb.appendIntField("boardContractId", event.boardContractId)
sb.append('}')
}
/**
* Serializes [ReturnClosureBlocked].
*
* Emitted additional fields (in order):
* - `activeContractId` (Int)
* - `policy` (String; `event.policy.name`)
* - `reason` (String; escaped)
*
* ## Complexity
* - Time: O(reason.length)
* - Memory: O(1)
*/
private fun serializeReturnClosureBlocked(event: ReturnClosureBlocked, sb: StringBuilder) {
sb.appendCommonFields("ReturnClosureBlocked", event)
sb.appendIntField("activeContractId", event.activeContractId)
sb.appendStringField("policy", event.policy.name)
sb.appendStringField("reason", event.reason)
sb.append('}')
}
// ─────────────────────────────────────────────────────────────────────────────
// Fraud Investigation Events (v0)
// ─────────────────────────────────────────────────────────────────────────────
/**
* Serializes [FraudInvestigated].
*
* Emitted additional fields (in order):
* - `heroId` (Int)
* - `activeContractId` (Int)
* - `policy` (String; `event.policy.name`)
* - `caught` (Boolean)
* - `rumorScheduled` (Boolean)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeFraudInvestigated(event: FraudInvestigated, sb: StringBuilder) {
sb.appendCommonFields("FraudInvestigated", event)
sb.appendIntField("heroId", event.heroId)
sb.appendIntField("activeContractId", event.activeContractId)
sb.appendStringField("policy", event.policy.name)
sb.append(",\"caught\":")
sb.append(if (event.caught) "true" else "false")
sb.append(",\"rumorScheduled\":")
sb.append(if (event.rumorScheduled) "true" else "false")
sb.append('}')
}
/**
* Serializes [HeroWarned].
*
* Emitted additional fields (in order):
* - `heroId` (Int)
* - `untilDay` (Int)
* - `reason` (String; escaped)
*
* ## Complexity
* - Time: O(reason.length)
* - Memory: O(1)
*/
private fun serializeHeroWarned(event: HeroWarned, sb: StringBuilder) {
sb.appendCommonFields("HeroWarned", event)
sb.appendIntField("heroId", event.heroId)
sb.appendIntField("untilDay", event.untilDay)
sb.appendStringField("reason", event.reason)
sb.append('}')
}
/**
* Serializes [HeroBanned].
*
* Emitted additional fields (in order):
* - `heroId` (Int)
* - `untilDay` (Int)
* - `reason` (String; escaped)
*
* ## Complexity
* - Time: O(reason.length)
* - Memory: O(1)
*/
private fun serializeHeroBanned(event: HeroBanned, sb: StringBuilder) {
sb.appendCommonFields("HeroBanned", event)
sb.appendIntField("heroId", event.heroId)
sb.appendIntField("untilDay", event.untilDay)
sb.appendStringField("reason", event.reason)
sb.append('}')
}
/**
* Serializes [RumorScheduled].
*
* Emitted additional fields (in order):
* - `policy` (String; `event.policy.name`)
* - `repDeltaPlanned` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeRumorScheduled(event: RumorScheduled, sb: StringBuilder) {
sb.appendCommonFields("RumorScheduled", event)
sb.appendStringField("policy", event.policy.name)
sb.appendIntField("repDeltaPlanned", event.repDeltaPlanned)
sb.append('}')
}
/**
* Serializes [WeeklyReportPublished].
*
* Emitted additional fields (in order):
* - `reputationDeltaApplied` (Int)
* - `rumorsCount` (Int)
* - `bansCount` (Int)
* - `warnsCount` (Int)
*
* ## Complexity
* - Time: O(1)
* - Memory: O(1)
*/
private fun serializeWeeklyReportPublished(event: WeeklyReportPublished, sb: StringBuilder) {
sb.appendCommonFields("WeeklyReportPublished", event)
sb.appendIntField("reputationDeltaApplied", event.reputationDeltaApplied)
sb.appendIntField("rumorsCount", event.rumorsCount)
sb.appendIntField("bansCount", event.bansCount)
sb.appendIntField("warnsCount", event.warnsCount)
sb.append('}')
}