Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/tui.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: TUI

on:
push:
paths:
- "solverlab-tui/**"
- "solver-core-rs/**"
- ".github/workflows/tui.yml"
pull_request:
paths:
- "solverlab-tui/**"
- "solver-core-rs/**"
- ".github/workflows/tui.yml"

defaults:
run:
working-directory: solverlab-tui

jobs:
test:
name: Test (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: solverlab-tui
- run: cargo fmt --check
- run: cargo clippy --all-targets -- -D warnings
- run: cargo test
- name: Slow smoke tests
if: matrix.os == 'ubuntu-latest'
run: cargo test --release -- --ignored

seeded-run:
name: Seeded run (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: solverlab-tui
- name: Run headless simulations
shell: bash
run: |
for game in freecell pyramid tripeaks; do
cargo run --release -- --headless --quiet --game "$game" --sims 20 \
--parallel 2 --seed 1234 --csv "../seeded-$game.csv"
done
- uses: actions/upload-artifact@v4
with:
name: seeded-${{ matrix.os }}
path: seeded-*.csv

compare:
name: Compare seeded runs across platforms
needs: seeded-run
runs-on: ubuntu-latest
defaults:
run:
working-directory: .
steps:
- uses: actions/download-artifact@v4
- name: Diff CPU-independent columns
shell: bash
run: |
status=0
for game in freecell pyramid tripeaks; do
for os in macos-latest windows-latest; do
diff <(sed -n '/^details$/,$p' "seeded-ubuntu-latest/seeded-$game.csv" | tr -d '\r' | cut -d, -f1-5,8) \
<(sed -n '/^details$/,$p' "seeded-$os/seeded-$game.csv" | tr -d '\r' | cut -d, -f1-5,8) \
|| { echo "::error::$game differs between ubuntu and $os"; status=1; }
done
done
exit $status
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
.PHONY: build-rust generate-bindings xcframework clean check test coverage-rust
.PHONY: build-rust generate-bindings xcframework clean check test coverage-rust tui tui-run tui-test

# Configuration
MAKEFILE_DIR := $(CURDIR)/
CRATE_DIR = $(MAKEFILE_DIR)solver-core-rs
LIB_NAME = solver_core
OUT_DIR = $(MAKEFILE_DIR)Sources/SolverCoreRS
FRAMEWORK_NAME = SolverCoreRS
TUI_DIR = $(MAKEFILE_DIR)solverlab-tui
CARGO_TARGET_DIR ?= $(CRATE_DIR)/target

# Default target
Expand All @@ -23,6 +24,16 @@ test:
coverage-rust:
"$(MAKEFILE_DIR)scripts/coverage-rust.sh"

# Terminal console (ratatui)
tui:
cd "$(TUI_DIR)" && cargo build --release

tui-run:
cd "$(TUI_DIR)" && cargo run --release

tui-test:
cd "$(TUI_DIR)" && cargo test

# Build for both architectures
build-rust:
cd "$(CRATE_DIR)" && cargo build --release --target aarch64-apple-darwin
Expand Down
58 changes: 54 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@ Win rates vary by game variant, timeout, search limits, and resource budget.

## Requirements

- macOS 13 or newer
- Xcode with Swift 6.1 toolchain support
- Rust stable toolchain with Cargo
- Apple Silicon or Intel Mac for local development
- Rust stable toolchain with Cargo (1.86 or newer for the terminal console)
- For the SwiftUI dashboard only: macOS 13 or newer, Xcode with Swift 6.1 toolchain support, Apple Silicon or Intel Mac

## Quick Start

Expand All @@ -63,6 +61,51 @@ To rebuild the Rust core and regenerate the Swift bindings:
make xcframework
```

## Terminal Console (TUI)

`solverlab-tui/` is a cross-platform copy of the SwiftUI simulation console built with [ratatui](https://ratatui.rs). It links the Rust core directly (no UniFFI) and offers the same controls, metrics, results table and CSV export, so the solvers can be exercised on Linux, Windows and macOS.

```bash
cd solverlab-tui && cargo run --release
# or
make tui-run
```

| Keys | Action |
|---|---|
| `Tab` / `Shift+Tab` | Move focus |
| `Enter` / `Space` | Activate the focused control |
| `←` `→` on Game, `g` / `G` | Change game |
| digits, `Backspace`, `↑` `↓` on Sims / Parallel | Edit values (`Shift`: ±10) |
| `a` | Toggle auto parallelism |
| `s` | Start / Stop |
| `e` | Export CSV |
| `c` | Clear data |
| `↑` `↓` `PgUp` `PgDn` `Home` `End` | Scroll results |
| `[` `]` | Change sort column (always descending) |
| `?` | Help |
| `q` / `Esc` / `Ctrl+C` | Quit |

Useful flags (`--help` lists all of them): `--game`, `--sims`, `--parallel`, `--auto`, `--timeout`, `--seed`, `--config`, `--no-persist`, `--ascii`.

Headless mode runs without a terminal UI and prints the CSV, which is handy for CI or remote machines. With `--seed`, every platform deals the same boards, so results can be compared across machines:

```bash
solverlab-tui --headless --game tripeaks --sims 200 --auto --seed 1234 --csv linux.csv
# same command on another platform → windows.csv, then compare the CPU-independent columns
sed -n '/^details$/,$p' linux.csv | cut -d, -f1-5,8 > a
sed -n '/^details$/,$p' windows.csv | cut -d, -f1-5,8 > b
diff a b
```

Differences from the SwiftUI app:

- Config fields are locked while a run is active.
- `--seed` makes decks reproducible; without it decks are random, as in the app.
- CSV export asks for a path in the terminal instead of a save panel.
- The config is stored as JSON in the platform config directory, not in `UserDefaults`.
- Stopping a run, like in the app, does not interrupt games already being solved; their results are discarded.

## Tests

Run the default fast local test suite:
Expand All @@ -72,6 +115,12 @@ cd solver-core-rs && cargo test
swift test
```

Run the terminal console tests:

```bash
make tui-test
```

Run the slower ignored Rust smoke tests when validating full solver behavior:

```bash
Expand All @@ -83,6 +132,7 @@ cd solver-core-rs && cargo test --test integration_tests -- --ignored
```text
Sources/ SwiftUI app and Swift bridge code
solver-core-rs/ Rust solver core and UniFFI definitions
solverlab-tui/ Cross-platform terminal console (ratatui)
SolverCoreRS.xcframework Packaged native solver library
Tests/ Swift test target
scripts/ Local helper scripts
Expand Down
Loading
Loading