Newer
Older
mardis_calc / docs / plan.md

Plan: Fire Show Calculator (mardis_calc)

Context

New project: a single-page web calculator for fire show budgeting. The page must calculate one unknown variable from all known ones using the formula S = Pz + Tz + (Lz * Nl) + Rom + Rop + Rot + Rok + (Na * Z). Royalties are fixed percentages calculated from the net amount after material costs (Base = S - Pz - Tz - Lz*Nl). The UI must be built with gnexus-ui-kit (added as a git submodule). The page is a plain static HTML+JS app (no build system). Artists are stored in a local JSON file (names only). The calculator should show how much each assigned artist receives (salary + any assigned royalties). State must be persisted to localStorage, plus export/import as JSON.

Key clarifications

  • UI kit: add as git submodule (https://git.gnexus.space/root/gnexus-ui-kit).
  • Royalties base: Rom/Rop/Rot/Rok are percentages of Base = S - Pz - Tz - Lz*Nl.
  • One unknown at a time: when all fields but one are filled, auto-calculate the missing variable.
  • Artists can have multiple roles: e.g. one person can be both an artist (gets Z) and a director (gets Rop), etc.
  • Rounding: to 2 decimal places (cents).
  • Persistence: localStorage + JSON export/import.
  • Artists JSON: array of objects with at least { "name": "..." }.

Architecture

Single static page. No bundler. Use vanilla JS.

Files

  1. .gitmodules (via git submodule add) — link gnexus-ui-kit.
  2. index.html — main page, loads UI kit assets from submodule path, app CSS/JS.
  3. css/styles.css — minimal custom styles on top of UI kit.
  4. js/app.js — all calculator logic.
  5. data/artists.json — embedded artist list.

UI layout

  • Header: project title.
  • Inputs section: numeric inputs for S, Pz, Tz, Lz, Nl, Z. Na and royalty fields (Rom, Rop, Rot, Rok) are read-only / computed.
    • Na auto-updates from the artist roster table (count of rows with "Artist" role checked).
    • Royalties auto-calculate from Base.
    • When 5 of the 6 editable fields are filled, the 6th is computed on blur/change.
  • Artist roster section:
    • Add-artist dropdown (populated from data/artists.json).
    • Table of added artists with role checkboxes: Artist, Director (Rop), Technician (Rot), Commissioner (Rok), Organizer (Rom).
    • Each row shows the individual payout (sum of applicable shares).
  • Actions: Export JSON, Import JSON, Reset.
  • Summary: total show cost S, total material costs, total artist salaries, total royalties.

Calculation logic

Definitions:

  • Materials = Pz + Tz + Lz * Nl
  • Base = S - Materials
  • Rom = 0.10 * Base
  • Rop = 0.05 * Base
  • Rot = 0.05 * Base
  • Rok = 0.10 * Base
  • TotalRoyalties = Rom + Rop + Rot + Rok = 0.30 * Base
  • ArtistSalaries = Na * Z

Identity: S = Materials + TotalRoyalties + ArtistSalaries => S = Materials + 0.30 * (S - Materials) + Na * Z => 0.70 * S = 0.70 * Materials + Na * Z => S = Materials + (Na * Z) / 0.70

Solving for each variable (when all others are known):

  • S = Materials + (Na * Z) / 0.70
  • Z = (0.70 * (S - Materials)) / Na (if Na > 0)
  • Na = (0.70 * (S - Materials)) / Z (displayed as decimal guidance)
  • Pz = S - (Tz + Lz*Nl) - (Na*Z)/0.70
  • Tz = S - (Pz + Lz*Nl) - (Na*Z)/0.70
  • Lz = (S - Pz - Tz - (Na*Z)/0.70) / Nl (if Nl > 0)
  • Nl = (S - Pz - Tz - (Na*Z)/0.70) / Lz (if Lz > 0)

Validation / guardrails:

  • Negative results are flagged as errors (real-world values must be non-negative).
  • Division-by-zero protected.
  • If more than one field is empty, show a message like "Заполните все поля кроме одного" instead of computing.

Roster payout per person:

  • If role "Artist" checked: add Z.
  • If role "Organizer" (Rom) checked and only one such person: add Rom. If multiple organizers, split equally (or assign full to each? To be safe, split equally; UI can note this).
  • Same splitting logic for Rop, Rot, Rok if multiple persons share the same role.

Persistence

  • On every change, serialize the state (all input values + artist roster table) to localStorage key mardis_calc_state.
  • On page load, restore from localStorage if present.
  • Export: trigger browser download of a .json file containing the serialized state.
  • Import: read a .json file via <input type="file">, validate structure, replace current state.

Verification

  1. Open index.html in a browser.
  2. Fill in Pz=100, Tz=50, Lz=30, Nl=2, Na=2, leave S empty. S should auto-calculate to 100 + 50 + 60 + (2*Z)/0.70 depending on Z.
  3. Add artists from the dropdown, assign roles, verify individual payouts sum up to ArtistSalaries + TotalRoyalties.
  4. Refresh the page; values should restore from localStorage.
  5. Click Export, save JSON, clear fields, click Import with that file, verify restoration.

Risks / open questions

  • gnexus-ui-kit submodule path and exact CSS/JS files to include are unknown until the submodule is fetched; may need minor path adjustments in index.html after adding it.
  • Splitting royalties among multiple persons with the same role: plan assumes equal split. User can adjust later if needed.