Skip to content

Refactor variable conditions to structured objects#200

Merged
mikkisguy merged 3 commits into
mainfrom
181-display-variable-condition-values-in-technical-badges
Jun 12, 2026
Merged

Refactor variable conditions to structured objects#200
mikkisguy merged 3 commits into
mainfrom
181-display-variable-condition-values-in-technical-badges

Conversation

@mikkisguy

@mikkisguy mikkisguy commented Jun 11, 2026

Copy link
Copy Markdown
Owner

No need for data migrations as this project is in development only.

Summary by CodeRabbit

  • New Features

    • Conditions now accept structured variable entries (value + operator: ==, !=, truthy, falsy) and are rendered as readable parts.
  • Bug Fixes

    • Improved validation and handling of referenced variables; invalid variable names produce clearer warnings.
  • Documentation

    • UI walkthroughs and console messages updated to show the richer condition formats.

…tion component

- Extract duplicated .map rendering pattern into FormattedCondition component
- Return FormattedConditionPart[] from format utils for differentiated styling
- Replace operator symbols with plain English text (≥ → is at least, etc.)
- Remove duplicate formatStatCondition definitions from both components
@mikkisguy mikkisguy linked an issue Jun 11, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3998fbbf-52a0-4b35-8ab3-43f8987c87e6

📥 Commits

Reviewing files that changed from the base of the PR and between 28a1fdf and 73ba265.

📒 Files selected for processing (3)
  • apps/backend/scripts/seed-technical-badges.ts
  • apps/backend/src/services/rpy-generator.service.ts
  • apps/backend/src/services/rpy-parser.service.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/backend/src/services/rpy-parser.service.ts
  • apps/backend/scripts/seed-technical-badges.ts

📝 Walkthrough

Walkthrough

This PR refactors variable conditions from string arrays to structured objects: Record<string, VariableCondition> where each variable maps to { value: string | boolean; operator: "==" | "!=" | "truthy" | "falsy" }. Changes span shared types, DB schemas, validation, Ren'Py parsing/generation, seed data, frontend formatting/rendering, and tests.

Changes

Variable Conditions Data Model Refactor

Layer / File(s) Summary
Shared type definition and schema foundation
packages/shared/src/index.ts, apps/backend/src/db/schema/tables/label-lines.ts, apps/backend/src/db/schema/tables/labels.ts
Adds VariableCondition and updates LineConditions, PublicLabel.conditions, and IncomingJump.conditions to use Record<string, VariableCondition>.
Backend validation schema
apps/backend/src/lib/validation.ts
updateLabelSchema now validates conditions.variables as an optional record mapping variable names to `{ value: string
Label service & generator wiring
apps/backend/src/services/labels.service.ts, apps/backend/src/services/rpy-generator.service.ts
Labels service imports VariableCondition, extracts variable keys via Object.keys(...) for validation, emits MENU_CHOICE jump conditions.variables as { value: true, operator: "truthy" } objects; RPY generator adds escapeRenpyString, iterates record entries, validates identifiers, and emits operator/value-specific Ren'Py expressions.
Ren'Py parsing and tests
apps/backend/src/services/rpy-parser.service.ts, apps/backend/src/services/__tests__/technical-parser.service.unit.test.ts
extractTechnicalConstructs now builds conditions.variables records from expression fragments (string/bool equality, falsy, truthy), adds splitConditionParts helper, and updates test expectations to the truthy object form.
Seed script and walkthrough text
apps/backend/scripts/seed-technical-badges.ts
Seed data switched to structured variable-condition objects for label lines and incoming jumps; console output and walkthrough steps updated to reference operator/value coverage.
Frontend formatting primitives
apps/frontend/src/lib/format-conditions.ts, apps/frontend/src/components/write-mode/FormattedCondition.tsx
New formatVariableCondition/formatStatCondition utilities and FormattedCondition component produce and render keyword/value parts for conditions.
Frontend UI rendering and tests
apps/frontend/src/components/write-mode/TechnicalPopover.tsx, apps/frontend/src/components/write-mode/LabelPropertiesPanel.tsx, apps/frontend/src/components/write-mode/TechnicalBadge.tsx, apps/frontend/src/components/__tests__/TechnicalPopover.test.tsx
Components retyped to use record-based variables, hasVars/counts use Object.keys(...), rendering switched to FormattedCondition with shared formatters, visuals target styling simplified, and tests updated to assert plain-English parts.
Frontend API and prose types
apps/frontend/src/lib/api/labels.ts, apps/frontend/src/lib/prose-types.ts
Client-side UpdateLabelInput and DialogueEntry.technicalInfo.conditions.variables now use Record<string, VariableCondition>.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • mikkisguy/branchforge#168: Related UI change that introduced LabelPropertiesPanel rendering patterns this PR updates to the structured variable format.
  • mikkisguy/branchforge#169: Prior work on technical badges and line-level conditions that this PR extends by switching variables to VariableCondition records.
  • mikkisguy/branchforge#182: Related parser/operator work; this PR adds variable operator extraction alongside stat operators.

"🐰 I hopped through code both old and new,
variables grew bodies—operators too,
parsed and printed, escaped with care,
now conditions speak plainly everywhere."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Refactor variable conditions to structured objects' directly and accurately describes the main architectural change across the entire changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 181-display-variable-condition-values-in-technical-badges

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

React Doctor found 3 issues in 2 files · 3 warnings · score 85 / 100 (Great) · vs main

3 warnings

src/components/write-mode/FormattedCondition.tsx

  • ⚠️ L16 Array index used as a key no-array-index-as-key
  • ⚠️ L18 Array index used as a key no-array-index-as-key

src/components/write-mode/LabelPropertiesPanel.tsx

  • ⚠️ L47 Large component is hard to read and change no-giant-component

Reviewed by React Doctor for commit 73ba265. See inline comments for fixes.

@coderabbitai coderabbitai Bot changed the title @coderabbitai Refactor variable conditions to structured objects Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/backend/scripts/seed-technical-badges.ts (1)

809-832: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the walkthrough copy to match plain-English condition rendering.

Lines 818-825 still describe symbol-based output (e.g., , , ¬, =), but the formatter now renders plain-English phrases. This can mislead QA when validating seeded badge output.

Suggested text update
-  console.log(
-    "  6. Click/hover on badges on lines 3, 8, and 10 to see operator symbols"
-  );
-  console.log("  7. Verify symbols: ≥, ≤, =, ≠ are displayed correctly");
+  console.log(
+    "  6. Click/hover on badges on lines 3, 8, and 10 to verify condition text"
+  );
+  console.log(
+    '  7. Verify plain-English operators are shown (for example: "is at least", "is not")'
+  );
   console.log("  8. Line 8 showcases all variable condition types:");
-  console.log("     - truthy: has_spell (displayed as just the name)");
-  console.log("     - falsy: ¬is_main_quest (displayed with ¬ prefix)");
-  console.log("     - ==: alignment = good, has_drink = True");
-  console.log("     - !=: faction ≠ evil, is_cursed ≠ False");
+  console.log('     - truthy: "is has_spell"');
+  console.log('     - falsy: "not is_main_quest"');
+  console.log('     - ==: alignment is "good", has_drink is true');
+  console.log('     - !=: faction is not "evil", is_cursed is not false');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/scripts/seed-technical-badges.ts` around lines 809 - 832, Update
the walkthrough console.log copy that currently lists symbol-based output (e.g.,
the message containing "Verify symbols: ≥, ≤, =, ≠ are displayed correctly" and
the subsequent lines describing "truthy: has_spell", "falsy: ¬is_main_quest",
"==: alignment = good", "!=: faction ≠ evil", etc.) so it describes the
formatter's plain‑English rendering instead of symbols; replace symbol examples
with their word forms (e.g., "greater than or equal to", "less than or equal
to", "equals", "not equals") and change negation/variable-condition lines to
plain phrases like "truthy: has_spell", "falsy: not is_main_quest (shown as 'not
...')", "equality: alignment equals good", "inequality: faction does not equal
evil", and note that boolean conditions render as True/False words (refer to the
console.log statements that use TEST_EMAIL and TEST_PASSWORD for proximity).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/backend/src/services/rpy-generator.service.ts`:
- Around line 96-119: The string branches in the switch inside the function
building conditions push unescaped condition.value into Ren'Py code, allowing
quotes/backslashes to break the RPY; create and use a small helper (e.g.
escapeRenpyString(value: string): string) and call it in both the `==` and `!=`
string branches to replace backslashes with \\ and double quotes with \" (and
optionally escape newlines) before embedding, leaving the boolean branches as-is
so generated conditions are always valid Ren'Py string literals.

In `@apps/backend/src/services/rpy-parser.service.ts`:
- Around line 2281-2284: The current split of conditionExpr into varParts using
.split(/\s+(?:and|or|\|\||&&)\s+/) loses connective semantics and breaks quoted
strings; replace this approach by tokenizing/parsing the condition expression to
preserve logical operators and quoted literals (e.g., write a small tokenizer
that recognizes strings in quotes, identifiers, comparison operators, and the
connectives "and"/"or"/"&&"/"||"), produce an AST or an array of {expr,
connective} nodes instead of flat strings, and update downstream code that used
varParts to consume this structured representation; target the code around the
varParts variable and any functions that process those parts so quoted values
and operator tokens are preserved.

---

Outside diff comments:
In `@apps/backend/scripts/seed-technical-badges.ts`:
- Around line 809-832: Update the walkthrough console.log copy that currently
lists symbol-based output (e.g., the message containing "Verify symbols: ≥, ≤,
=, ≠ are displayed correctly" and the subsequent lines describing "truthy:
has_spell", "falsy: ¬is_main_quest", "==: alignment = good", "!=: faction ≠
evil", etc.) so it describes the formatter's plain‑English rendering instead of
symbols; replace symbol examples with their word forms (e.g., "greater than or
equal to", "less than or equal to", "equals", "not equals") and change
negation/variable-condition lines to plain phrases like "truthy: has_spell",
"falsy: not is_main_quest (shown as 'not ...')", "equality: alignment equals
good", "inequality: faction does not equal evil", and note that boolean
conditions render as True/False words (refer to the console.log statements that
use TEST_EMAIL and TEST_PASSWORD for proximity).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 38314c1a-3d23-4473-b364-a611cf25fce3

📥 Commits

Reviewing files that changed from the base of the PR and between 130956d and 28a1fdf.

📒 Files selected for processing (18)
  • apps/backend/scripts/seed-technical-badges.ts
  • apps/backend/src/db/schema/tables/label-lines.ts
  • apps/backend/src/db/schema/tables/labels.ts
  • apps/backend/src/lib/validation.ts
  • apps/backend/src/services/__tests__/technical-parser.service.unit.test.ts
  • apps/backend/src/services/label-line-mapper.ts
  • apps/backend/src/services/labels.service.ts
  • apps/backend/src/services/rpy-generator.service.ts
  • apps/backend/src/services/rpy-parser.service.ts
  • apps/frontend/src/components/__tests__/TechnicalPopover.test.tsx
  • apps/frontend/src/components/write-mode/FormattedCondition.tsx
  • apps/frontend/src/components/write-mode/LabelPropertiesPanel.tsx
  • apps/frontend/src/components/write-mode/TechnicalBadge.tsx
  • apps/frontend/src/components/write-mode/TechnicalPopover.tsx
  • apps/frontend/src/lib/api/labels.ts
  • apps/frontend/src/lib/format-conditions.ts
  • apps/frontend/src/lib/prose-types.ts
  • packages/shared/src/index.ts

Comment thread apps/backend/src/services/rpy-generator.service.ts
Comment thread apps/backend/src/services/rpy-parser.service.ts Outdated
Comment thread apps/frontend/src/components/write-mode/FormattedCondition.tsx
Comment thread apps/frontend/src/components/write-mode/FormattedCondition.tsx
@mikkisguy mikkisguy merged commit bcdff68 into main Jun 12, 2026
7 checks passed
@mikkisguy mikkisguy deleted the 181-display-variable-condition-values-in-technical-badges branch June 12, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Display variable condition values in technical badges

1 participant