Package-level declarations

Types

Link copied to clipboard
object AppLog

Thin KMP logging facade over Napier so call sites never import Napier directly (swap the backend in one place). Napier's antilog is installed per-platform at app startup by each entrypoint.

Link copied to clipboard
interface CrashReporter

Crash / non-fatal reporting behind an interface, so callers depend on the capability — not on Firebase Crashlytics or Sentry directly. Swapping in a real backend is a one-line DI change with no call-site edits.

Link copied to clipboard

Injectable dispatchers so ViewModels/repositories are testable (swap for a test dispatcher).

Link copied to clipboard
object Elo

Pure ELO ladder math — the rating step and expected-score curve any ranked/competitive feature wants. No clock, no I/O, no domain types: a rating is an Int, a bout is 1-v-opponent, and step returns the new rating. Deterministic and testable.

Link copied to clipboard
object Hashing

Pure-Kotlin SHA-1 / SHA-256 (no java.*, wasmJs-safe). Content-fingerprint / cache-key hashing — not a security primitive: no HMAC, no constant-time comparison, no salting.

Link copied to clipboard

Dependency-free default CrashReporter that routes everything through AppLog (Napier). Gives the same call sites and breadcrumb discipline as a real backend, minus the upload. Honors the setEnabled kill switch (starts enabled); when disabled, reporting calls drop silently.

Link copied to clipboard
data class Rng(val state: RngState)
Link copied to clipboard
data class RngState(val seed: Long, val step: Long)

Immutable, counter-based seeded PRNG (SplitMix64).

Link copied to clipboard
Link copied to clipboard
sealed interface UiText

Platform-agnostic text holder so ViewModel state/effects never carry raw, pre-resolved strings — the UI edge resolves a UiText to an actual String (via stringResource / moko-resources for Res, or directly for Dynamic). Domain/data layers stay locale-free.

Functions

Link copied to clipboard

Best-effort resolution with no resource table: Dynamic → its value, Res → its key, Empty → "".

Link copied to clipboard

EaseInQuart — sharp initial acceleration.

Link copied to clipboard

EaseOutBack — slight overshoot settle. s=1.70158 (same constant both origin apps used).

Link copied to clipboard

EaseOutCubic — smooth deceleration.

Link copied to clipboard

Decimal formatting without String.format. Rounds half-up to places digits.

Link copied to clipboard

Whole-number thousands-comma grouping, no String.format (e.g. 12345.6 -> "12,345").

Link copied to clipboard
fun formatTime12h(hour: Int, minute: Int): String

12-hour time with AM/PM, e.g. (13, 5) -> "1:05 PM".

Link copied to clipboard
fun formatTime24h(hour: Int, minute: Int): String

24-hour time, e.g. (9, 5) -> "09:05".

Link copied to clipboard
fun lerp(a: Float, b: Float, t: Float): Float

Linear interpolation, t clamped to 0, 1.

Link copied to clipboard
fun Long.minorToDecimalString(fractionDigits: Int = 2): String

Renders minor currency units (e.g. paise, cents) to a "<major>.<minor>" decimal string with fractionDigits digits — the single canonical minorUnits->decimal formatter for :common and its consumers.

Link copied to clipboard
fun Int.pad2(): String

Two-digit zero-padded string for an Int (e.g. 5 -> "05").

Link copied to clipboard
fun rngFrom(state: RngState): Rng
Link copied to clipboard
fun LocalDate.toFriendlyString(): String

Friendly date, e.g. "Jun 19, 2026".