commit 544ca1e8bda386448aeb42aeecc2a20c1f80393c
parent 4dd693c5392f7c8f48b5ef10a67fc678931338cb
Author: Michael Camilleri <[email protected]>
Date: Tue, 19 May 2026 07:11:57 +0900
Update select_puzzles.sh to copy a ranked puzzle batch
A new Scripts/select_puzzles.sh wraps the Pickmake tool: it builds Pickmake in
release, has it score and filter the candidate .xd files under the given inputs
(default Crossmake/Generated), and copies the chosen puzzles into an output
directory rather than only printing their paths. The output directory defaults
to Crossmake/Picked and is overridable with -o/--into; relative paths resolve
against the caller's directory and absolute paths are used as-is, matching how
candidate inputs are already resolved.
Pickmake's --verbose diagnostics still stream to stderr so the selected and
rejected summary stays visible; only the clean path list on stdout is captured
for the copy, so build noise can't contaminate it. --clean wipes existing .xd
files from the target first — scoped to *.xd, never the whole directory — and
runs only after a non-empty selection succeeds, so a failed run can't destroy
an existing curated set. The first positional argument is still the puzzle
count; remaining non-flag arguments are candidate dirs or .xd files.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Diffstat:
2 files changed, 59 insertions(+), 13 deletions(-)
diff --git a/Crossmake/.gitignore b/Crossmake/.gitignore
@@ -3,3 +3,4 @@
DerivedData/
Data/
Generated/
+Picked/
diff --git a/Crossmake/Scripts/select_puzzles.sh b/Crossmake/Scripts/select_puzzles.sh
@@ -2,29 +2,52 @@
set -euo pipefail
COUNT="${1:-10}"
-CANDIDATE_DIR="${2:-Generated}"
+DEFAULT_CANDIDATE_DIR="Generated"
PICKMAKE_EXECUTABLE=".build/release/Pickmake"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CROSSMAKE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
CALLER_DIR="$(pwd)"
+OUTPUT_DIR="${CROSSMAKE_DIR}/Picked"
+CLEAN=false
if ! [[ "$COUNT" =~ ^[0-9]+$ ]] || ((10#$COUNT < 1)); then
- echo "Usage: $0 [positive-puzzle-count] [candidate-dir-or-xd-file ...]" >&2
+ echo "Usage: $0 [positive-puzzle-count] [-o output-dir] [--clean] [candidate-dir-or-xd-file ...]" >&2
exit 1
fi
+resolve_path() {
+ if [[ "$1" = /* ]]; then
+ echo "$1"
+ else
+ echo "${CALLER_DIR}/$1"
+ fi
+}
+
shift || true
inputs=()
-if (($# == 0)); then
- inputs+=("${CROSSMAKE_DIR}/${CANDIDATE_DIR}")
-else
- for input in "$@"; do
- if [[ "$input" = /* ]]; then
- inputs+=("$input")
- else
- inputs+=("${CALLER_DIR}/${input}")
- fi
- done
+while (($# > 0)); do
+ case "$1" in
+ -o|--into)
+ if (($# < 2)); then
+ echo "$1 requires a directory argument" >&2
+ exit 1
+ fi
+ OUTPUT_DIR="$(resolve_path "$2")"
+ shift 2
+ ;;
+ --clean)
+ CLEAN=true
+ shift
+ ;;
+ *)
+ inputs+=("$(resolve_path "$1")")
+ shift
+ ;;
+ esac
+done
+
+if ((${#inputs[@]} == 0)); then
+ inputs+=("${CROSSMAKE_DIR}/${DEFAULT_CANDIDATE_DIR}")
fi
cd "$CROSSMAKE_DIR"
@@ -37,4 +60,26 @@ if [[ ! -x "$PICKMAKE_EXECUTABLE" ]]; then
exit 1
fi
-"$PICKMAKE_EXECUTABLE" --count "$COUNT" --verbose "${inputs[@]}"
+selected_paths="$("$PICKMAKE_EXECUTABLE" --count "$COUNT" --verbose "${inputs[@]}")"
+
+if [[ -z "$selected_paths" ]]; then
+ echo "No puzzles selected; nothing copied." >&2
+ exit 1
+fi
+
+mkdir -p "$OUTPUT_DIR"
+
+if [[ "$CLEAN" == true ]]; then
+ rm -f "$OUTPUT_DIR"/*.xd
+ echo "Cleaned existing .xd files from ${OUTPUT_DIR}." >&2
+fi
+
+copied_count=0
+while IFS= read -r selected_path; do
+ [[ -n "$selected_path" ]] || continue
+ cp "$selected_path" "$OUTPUT_DIR/"
+ echo "Copied ${selected_path} -> ${OUTPUT_DIR}/"
+ copied_count=$((copied_count + 1))
+done <<<"$selected_paths"
+
+echo "Copied ${copied_count} puzzle(s) into ${OUTPUT_DIR}." >&2