App

Light Show
OVERVIEW
Light Show is a puzzle game about real Outside Plant (OSP) fiber-optic engineering, built in Rust with Bevy for Android (Google Play + F-Droid) and desktop, in which the player routes light from the OLT (Point A) to the customer ONT (Point B) to land inside a target receive-power window while anime-styled companions — one per access technology — react to every splice. All loss figures are real: fusion vs. mechanical splice loss, UPC vs. APC connectors, PON splitter ratios, and wavelength-dependent fiber attenuation.
HOW IT WORKS
- 1Pick a companion from the menu before splicing — each is tied to a real access technology with its own dialogue bank (Séraphine — Fiber, Ondine — Coax, Linka — Mobile, Lattice — Ethernet in the README set).
- 2Survey the board: a grid-based OSP map of OLT, splice enclosures, splitters, patch panels, ONT, and cable spans (aerial, buried, conduit).
- 3Route the light by dragging fiber jumpers / choosing splice paths to connect A to B; every component placed consumes optical budget and the live dB ledger (OTDR-style) recomputes `P_rx (dBm) = P_tx (dBm) − Σ(loss) + Σ(gain)`.
- 4Hit the window: received power at B must land inside the level's design window (e.g. −8 dBm to −27 dBm for GPON per ITU-T G.984) with a single continuous A→B path — too hot fails as well as too cold.
- 5Survive the outage event: mid-level a fault fires (fiber cut, water intrusion, bad splice, macrobend, connector contamination) and the player must reroute, patch, or splice around it before the customer-complaint timer expires.
- 6Progress through worlds — Splice School → Patch Panel → PON Split → Storm Season (Outages) → Long Haul → Séraphine's Route (bonus/endless) — as the companion reacts to splices, outages, and results.
CONCEPTS
All powers in dBm, all losses and gains in dB. P_tx is the OLT launch power (+3.0 dBm in the bundled levels, the GPON class B+ figure of ITU-T G.984.2). Each loss term is one placed element: fiber attenuation (0.35 dB/km at 1310 nm, 0.28 at 1490 nm, 0.21 at 1550 nm), a splitter (3.6 dB at 1×2 up to 17.7 dB at 1×32), a splice (0.075 dB fusion, 0.4 dB mechanical), a connector (0.35 dB UPC, 0.30 dB APC). The route wins when P_rx lands inside the level's receive window — for GPON, −8 to −27 dBm — and too hot fails exactly as too cold does.
CONFIGURATION
| Option | Default | What it does |
|---|---|---|
`tx_dbm` (level JSON) | 3.0` in both bundled levels; `DEFAULT_TX_DBM = 3.0 | OLT launch power in dBm; GPON class B+ downstream per ITU-T G.984.2 unless a level overrides it |
`window_min_dbm` / `window_max_dbm` (level JSON) | `-27.0` / `-8.0` in both bundled levels | Target receive-power window the routed path must land inside to win |
`wavelength` (level JSON) | `Nm1490` in both bundled levels | Operating wavelength; attenuation is 0.35 dB/km at 1310 nm, 0.28 at 1490 nm, 0.21 at 1550 nm |
Fusion splice loss | `0.075 dB` typical (range 0.05–0.1 dB) | Lowest-loss splice; place time 45.0 s in the sim model |
Mechanical splice loss | `0.4 dB` typical (range 0.3–0.5 dB) | Faster splice used under outage pressure; place time 10.0 s |
Connector UPC / APC loss | `0.35 dB` / `0.30 dB` (return loss −50 dB / −60 dB) | Patch-panel connectors; APC required on reflectance-sensitive / PON levels |
Splitter 1×2 / 1×4 / 1×8 / 1×16 / 1×32 loss | 3.6` / `7.3` / `10.6` / `13.7` / `17.7 dB | PLC splitter insertion loss for PON fan-out levels |
Android `minSdk` / `targetSdk` | 26` / `34 | Android 8.0+ floor; `game/Cargo.toml` `[package.metadata.android]` (`package = ai.qompass.lightshow`, fullscreen, OpenGL ES 3.0) |
`instrumented-test-logging` Cargo feature | off by default | Emits board `level_ready` / `select` / `connect` events to Logcat (tag `LightShow`) for on-device tests only; zero footprint in retail builds |
CONTROLS
| Action | Control |
|---|---|
| Run the game (desktop dev loop) | cargo run -p light-show |
| Run simulation tests | cargo test -p osp_sim |
| Pick a companion | Click/tap a companion-picker button in the main menu (sets `SelectedCompanion`) |
| Route / place a component | Drag node → node with left mouse button (desktop) or touch drag (Android); press resolves the start node, release on a target node connects the chosen component |
| Build APK (fast path) | cargo apk build --release` in `game/` after `rustup target add …` + `cargo install cargo-apk |
| Build Play Store bundle | cargo ndk … build --release`, then `./gradlew bundleRelease` in `android/` → `app-release.aab |
| Windows trial build | Extract the Releases zip, keep `assets` next to the `.exe`, double-click; SmartScreen → More info → Run anyway (unsigned trial build) |
NOT COVERED
- Sandbox clone (`~/workspace/repos/light-show`, Sep 2025) is older than GitHub `main` and the primo clone (`~/.GH/Qompass/LightShow`): GitHub/primo add many more levels (per-companion 10-level tracks), four extra companions in primo `game/src/waifu/mod.rs` (Clara — Calix CMS, Aino — Nokia AMS, Hikari — FTTH/OSP, Léa — WA 09 Telecom Admin prep), a chiptune soundtrack, and trial-build downloads; only the two sandbox levels (`world1_level1.json`, `world4_level1_outage.json`) were field-verified here — level counts beyond those two are primo-listing only. - License differs by snapshot: sandbox `Cargo.toml`/`LICENSE` say GPL-3.0-or-later; GitHub README badge/text say Apache-2.0. Not reconciled in sources read. - No in-game settings/config file (volume, difficulty, window size) is documented in the sources read; difficulty is per-level data, not a user option. Full outage-repair UI was listed as “next milestone” in the sandbox README but as implemented (state machine menu → playing → outage-repair → results) in the GitHub README — status text was not re-verified by running the game.
REFERENCES
- ITU-T G.984.2 — GPON: Physical media dependent (PMD) layer specificationThe class B+ optical parameters behind the game's launch power and its −8 to −27 dBm receive window.
- ITU-T G.984.1 — GPON: General characteristicsThe GPON architecture the game's outside-plant board models: OLT, splitters, and ONTs on one passive tree.