Skip to content

Show DD-table solve time and debounce hand-edit solves - #366

Merged
tameware merged 7 commits into
dds-bridge:developfrom
tameware:web/show-solve-time
Sep 7, 2026
Merged

Show DD-table solve time and debounce hand-edit solves#366
tameware merged 7 commits into
dds-bridge:developfrom
tameware:web/show-solve-time

Conversation

@tameware

@tameware tameware commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Display wall-clock DD-table solve time under the result table as Solved in X ms.
  • Debounce WASM solves while editing an already-complete deal so sync ccall does not freeze typing
  • Still solve immediately when the deal first becomes complete (fourth-hand auto-fill or final pip) and on contract selection

Test plan

  • bazelisk test //web:dds_web_js_test
  • Load a part-score test deal and confirm #result shows Solved in N ms. under the DD table
  • Fill three hands and confirm auto-fill of the fourth triggers an immediate solve
  • Edit a suit on a complete deal rapidly and confirm the UI stays responsive, then one trailing solve runs after typing pauses
  • Select a contract cell and confirm lead analysis still runs without waiting for the hand-edit debounce

Made with Cursor

tameware and others added 2 commits September 6, 2026 15:01
Measure calc_table with performance.now() and display "Solved in X ms." in the SE status line so solve cost is visible next to the tricks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sync WASM ccall was freezing the UI on every keystroke; delay those solves, but still run immediately when the deal first becomes complete (auto-fill or final pip).

Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Debouncing is currently applied even when the deal becomes incomplete/invalid, which delays clear_results() and can leave stale DD-table/status content visible for up to the debounce interval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the DDS web UI to (1) display wall-clock solve time under the DD results table and (2) debounce expensive WASM DD-table solves during hand editing to keep typing responsive, while still solving immediately on “deal becomes complete” and on contract selection.

Changes:

  • Add solve-time formatting and display (Solved in X ms.) after successful DD-table solves.
  • Introduce a configurable debounce for hand-edit-triggered solves, while preserving immediate solves for contract clicks and first-time deal completion.
  • Update unit/E2E tests and UI layout/CSS to support the new status line placement and behavior.
File summaries
File Description
web/tests/test_web_e2e.py Updates E2E expectation to assert the solve-time status text is shown.
web/tests/dds_web_test.mjs Adds unit tests for debounce behavior and solve-time formatting/display; updates test harness to provide timers/performance.
web/dds_web.js Implements debounced scheduling and solve-time measurement/formatting; updates refreshDdTable() to display elapsed time.
web/dds_web.html Moves #result under the DD result table and adds aria-live="polite".
web/dds_web.css Styles the #result status line under the table.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread web/dds_web.js
Debounce only applied within the same completeness state so stale numerals
no longer linger for the debounce window after a card is deleted.

Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

There’s an exported/awaitable API ambiguity in scheduleDealSolveDebounced() (returned promise doesn’t include the debounced work) plus a misleading new test comment/sleep that should be corrected.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

web/dds_web.js:130

  • scheduleDealSolveDebounced() returns solveQueue, but that promise does not include the work scheduled by the debounce timer. If any caller ever awaits the return value, it can observe completion before the debounced solve has actually run. Consider either (a) returning a promise that resolves/rejects with the eventual trailing scheduleDealSolve() call (including when superseded/cancelled), or (b) making this function explicitly void/internal (and avoid exporting it) so it can’t be misused as an awaitable API.
    web/tests/dds_web_test.mjs:745
  • This test comment says the initial fillFormWithPartScoreTestData() solve is debounced, but the production logic solves immediately on the first transition to a complete deal. The 250ms sleep is also longer than needed for the intent of this test (contract click should be immediate regardless of debounce).
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

…test.

Returning solveQueue implied the trailing debounced work had finished; stop
returning a promise and drop the export. Also correct the fillForm wait that
assumed that path was debounced.

Co-authored-by: Cursor <cursoragent@cursor.com>
@tameware

tameware commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the latest Copilot notes in 49675f5:

  • scheduleDealSolveDebounced() no longer returns solveQueue (and is no longer exported), so it can’t be mistaken for an awaitable that includes the trailing solve.
  • The contract-selection test now waits only for the immediate fillForm completion and no longer claims that path is debounced.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The changes are coherent and well-tested, with only a minor best-practice nit identified in the debounced timer callback.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread web/dds_web.js
Match the void usage used elsewhere so the returned Promise is clearly ignored.

Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The new debounce-configuration setter should cancel any already-scheduled debounce timer when disabling debounce to avoid unexpected trailing solves.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

web/dds_web.js:112

  • setDealSolveDebounceMs() updates the debounce delay but does not cancel any already-scheduled debounced solve. If a caller disables debounce (sets it to 0) while a timer is pending, that trailing solve will still fire later, which is surprising for a setting function and can cause redundant work.

Consider clearing any pending debounce timer when switching to a non-positive delay.

  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

setDealSolveDebounceMs(0) previously left a trailing solve scheduled at the
old delay, which was surprising and could cause redundant work.

Co-authored-by: Cursor <cursoragent@cursor.com>
@tameware

tameware commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the latest Copilot note in the follow-up commit: setDealSolveDebounceMs(0) now clears any pending debounce timer so a trailing solve cannot fire after debounce is disabled.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The current debounce routing also delays non-WASM “clear/error” updates for still-invalid/incomplete edits, which can leave stale validation/status visible until the debounce window elapses.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

web/dds_web.js:2103

  • The debounce decision is based on dealComplete !== lastDealWasComplete, which means edits that keep the deal incomplete/invalid also go through scheduleDealSolveDebounced(). Since refreshDdTable() does not run WASM in those states (it only clears results / updates the validation error), debouncing here can leave stale validation text (e.g., which duplicated cards) or other cleared state visible until the debounce window elapses. Consider debouncing only when the deal is solvable (13 cards + valid), and schedule immediately otherwise so clears/errors stay responsive without reintroducing sync-ccall freezes.
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Incomplete or invalid edits schedule immediately so clear/error status stays
responsive without waiting for the debounce window.

Co-authored-by: Cursor <cursoragent@cursor.com>
@tameware

tameware commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the latest Copilot note: debounce now applies only while the deal stays solvable (dealComplete && lastDealWasComplete). Incomplete/invalid edits (and first completion) schedule immediately so clear/error updates stay responsive.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The debounce behavior, immediate-solve exceptions, and solve-time UI/status updates are implemented consistently and are covered by targeted unit and E2E tests.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@tameware tameware self-assigned this Sep 7, 2026
@tameware tameware added the Clean Copilot review Copilot reviewed and had neither new comments nor new suppressed comments. label Sep 7, 2026
@tameware
tameware requested a review from tzimnoch September 7, 2026 09:12

@zzcgumn zzcgumn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Makes sense.

@tameware
tameware merged commit 3ef34dc into dds-bridge:develop Sep 7, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Clean Copilot review Copilot reviewed and had neither new comments nor new suppressed comments.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants