Import deals from file and show Computing… on slow DD solves - #374
Import deals from file and show Computing… on slow DD solves#374tameware wants to merge 4 commits into
Conversation
Load the first deal from the chosen file into the diagram so users need not retype holdings. Co-authored-by: Cursor <cursoragent@cursor.com>
Files like sol10.txt start with four NESW holdings and an optional :results suffix. Co-authored-by: Cursor <cursoragent@cursor.com>
A delayed timer alone never runs during sync WASM, so the status must be painted first or long solves only show the final Solved line. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical correctness issues remain in stale solve invalidation and LIN dealer handling.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds deal-file importing and visible progress feedback for slow double-dummy solves.
Changes:
- Supports PBN, LIN, DLM, dtest, and sol-style formats.
- Adds an import button and file input.
- Shows “Computing…” after a 300 ms grace period.
- Adds parser, UI, and timing tests.
File summaries
| File | Reviewed changes | Findings |
|---|---|---|
web/tests/test_web_html.py |
Import-control markup tests | None noted |
web/tests/dds_web_test.mjs |
Parser and solve-status tests | None noted |
web/dds_web.js |
Import parsers, file handling, and solve-status flow | Critical stale-solve invalidation and LIN dealer handling issues; moderate deal validation issue; nit-level error messaging and browser file-selection coverage issues |
web/dds_web.html |
Import button and file input | None noted |
Review details
Suppressed comments (2)
web/dds_web.js:696
- The browser file-selection path is not covered: the tests call
importDealFromTextdirectly and only inspect the HTML markup, so regressions ininput.files[0],File.text(), or surfacing read/parse errors would pass. Add a JavaScript test forhandleDealFileSelectedwith a fake File covering success and failure.
const result = document.getElementById("result");
try {
const text = await file.text();
const err = importDealFromText(text);
web/dds_web.js:433
- This shared return path only checks that each direction exists and normalizes strings; it never verifies the four suit fields or uniqueness of the 52 cards. Because
normalizeHandHoldingfilters non-pips first, malformed input with repeated cards or extra/missing suit separators can be reported as a successful import and then sanitized byfillFormWithTestData, leaving altered or incomplete input instead of an import error. Validate the assembled deal before returning it.
if (!byDirection[direction]) {
return null;
}
deal[direction] = normalizeHandHolding(byDirection[direction]);
- Files reviewed: 4/4 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Pin LIN md| hands as fixed S/W/N/E (dealer digit is not a rotation), abandon stale PBNs before ccall after the grace wait, and mention sol-style in the import error. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved deal validation, stale-status, and asynchronous file-selection issues remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (3)
Previously missed (1) — in code that hasn't changed since the last review.
web/dds_web.js:700
- The new browser file-selection path is not covered by the added tests: all import tests call
importDealFromTextdirectly, and the HTML test only checks markup. A regression infile.text(),files[0], or the async success/error handler would therefore pass CI while the Import deal button is unusable. Add a unit or browser test that supplies a file through the actual input and verifies both successful import and read/parse errors.
web/dds_web.js:2664
- These guards reject stale WASM work but do not clear stale status. For a complete-deal edit during the wait,
updateActionButtons()only arms the 250 ms debounce, soddTableRequestIdcan remain unchanged; if the old timer fires, this branch clears the timer and returns while leavingresult.innerHTMLasComputing…until the debounced refresh starts. Clear the old status whenrequestId === ddTableRequestId(and apply the same cleanup to the second PBN guard) so the UI does not report computing for the edited deal.
// An import/edit during the grace wait can change the diagram while
// this invocation still holds the old PBN; do not solve stale input.
if (handsToPbn(collectHands()) !== pbn) {
clearDdTableComputingTimer();
return;
web/dds_web.js:701
file.text()is asynchronous, so two quick file selections can complete out of order. This handler imports whichever read resolves last without checking thatfileis stillinput.files[0], allowing a slower read of an earlier selection to overwrite the deal chosen afterward. Re-check the current file after the await (or use a selection token) before callingimportDealFromText.
const text = await file.text();
const err = importDealFromText(text);
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
| const holding = normalizeHandHolding(hands[i]); | ||
| if (holding.replace(/\./g, "").length !== 13) { | ||
| return null; |
Summary
.txt, or sol-style lines (e.g.sol10.txt) into the diagram.ccallso long solves are visible (a timer alone never fires during sync WASM).Test plan
bazel test //web:dds_web_js_test //web:dds_web_html_testpython3 web/serve_web.py→ open the page, hard-refreshhands/example.pbn,hands/list1.txt, a.lin, andhands/sol10.txt; confirm the first deal fills and solvesMade with Cursor