brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
add-puzzle-typeScaffold a new puzzle type across all 10+ pipeline integration points in jigsawR. Creates the core puzzle module, wires it into the unified pipeline (generation, positioning, rendering, adjacency), adds ggpuzzle geom/stat layers, updates DESCRIPTION and config.yml, extends the Shiny app, and creates a comprehensive test suite. Use when adding a completely n…
Independent GitHub snapshot · Automated classification · Original documentation governs
Scaffold a new puzzle type across all pipeline integration points in jigsawR.
"triangular")Create R/<type>_puzzle.R with the internal generation function:
#' Generate <type> puzzle pieces (internal)
#' @noRd
generate_<type>_pieces_internal <- function(params, seed) {
# 1. Initialize RNG state
# 2. Generate piece geometries
# 3. Build edge paths (SVG path data)
# 4. Compute adjacency
# 5. Return list: pieces, edges, adjacency, metadata
}
Follow the pattern in R/voronoi_puzzle.R or R/snic_puzzle.R for structure.
Expected: Function returns a list with $pieces, $edges, $adjacency, $metadata.
On failure: Compare the return structure against generate_voronoi_pieces_internal() to identify missing list elements or incorrect types.
Edit R/jigsawR_clean.R:
"<type>" to the valid_types vector"<type>" -> "<type>_")# In valid_types
valid_types <- c("rectangular", "hexagonal", "concentric", "voronoi", "snic", "<type>")
Expected: generate_puzzle(type = "<type>") is accepted without "unknown type" error.
On failure: Verify the type string is added to valid_types exactly as spelled, and that parameter extraction covers all required type-specific arguments.
Edit R/unified_piece_generation.R:
generate_pieces_internal()# In the switch/dispatch
"<type>" = generate_<type>_pieces_internal(params, seed)
Expected: Pieces are generated when the type is dispatched.
On failure: Confirm the dispatch case string matches the type name exactly and that generate_<type>_pieces_internal is defined and exported from the puzzle module.
Edit R/piece_positioning.R:
Add positioning dispatch for the new type. Most types use shared positioning logic, but some need custom handling.
Expected: apply_piece_positioning() handles the new type without errors and pieces are placed at correct coordinates.
On failure: Check whether the new type needs custom positioning logic or can reuse the shared positioning path. Add a dispatch case if the default path does not apply.
Edit R/unified_renderer.R:
render_puzzle_svg()get_<type>_edge_paths()get_<type>_piece_name()Expected: SVG output is generated for the new type with correct piece outlines and edge paths.
On failure: Verify get_<type>_edge_paths() returns valid SVG path data and get_<type>_piece_name() produces unique identifiers for each piece.
Edit R/adjacency_api.R:
Add neighbor dispatch so get_neighbors() and get_adjacency() work for the new type.
Expected: get_neighbors(result, piece_id) returns correct neighbors for any piece in the puzzle.
On failure: Check that the adjacency dispatch returns the correct data structure. Test with a small grid and manually verify neighbor relationships against the geometry.
Edit R/geom_puzzle.R:
Create geom_puzzle_<type>() using the make_puzzle_layer() factory:
#' @export
geom_puzzle_<type> <- function(mapping = NULL, data = NULL, ...) {
make_puzzle_layer(type = "<type>", mapping = mapping, data = data, ...)
}
Expected: ggplot() + geom_puzzle_<type>(aes(...)) renders without error.
On failure: Verify make_puzzle_layer() receives the correct type string and that the geom function is exported in the NAMESPACE via @export.
Edit R/stat_puzzle.R:
compute_panel()Expected: The stat layer computes puzzle geometry correctly and produces the expected number of polygons.
On failure: Check that the compute_panel() dispatch case returns a data frame with the required columns (x, y, group, piece_id) and that default parameters are sensible for the new type.
Edit DESCRIPTION:
Suggests: (if external dependency)Collate: to include the new R file (alphabetical order)Expected: devtools::document() succeeds. No NOTE about unlisted files.
On failure: Check that the new R file is listed in the Collate: field in alphabetical order and that any new Suggests packages are spelled correctly with version constraints.
Edit inst/config.yml:
Add defaults and constraints for the new type:
<type>:
grid:
default: [3, 3]
min: [2, 2]
max: [20, 20]
size:
default: [300, 300]
min: [100, 100]
max: [2000, 2000]
tabsize:
default: 20
min: 5
max: 50
# Add type-specific params here
Expected: Config is valid YAML. Defaults produce a working puzzle when used by generate_puzzle().
On failure: Validate YAML with yaml::yaml.load_file("inst/config.yml"). Ensure default grid and size values produce a sensible puzzle (not too small or too large).
Edit inst/shiny-app/app.R:
Expected: Shiny app shows the new type in the dropdown and generates puzzles when selected.
On failure: Check that the type is added to the choices argument of the UI selector, that the conditional panel for type-specific parameters uses conditionalPanel(condition = "input.type == '<type>'"), and that the server-side handler passes the correct parameters.
Create tests/testthat/test-<type>-puzzles.R:
test_that("<type> puzzle generates correct piece count", { ... })
test_that("<type> puzzle respects seed reproducibility", { ... })
test_that("<type> adjacency returns valid neighbors", { ... })
test_that("<type> fusion merges pieces correctly", { ... })
test_that("<type> geom layer renders without error", { ... })
test_that("<type> SVG output is well-formed", { ... })
test_that("<type> config constraints are enforced", { ... })
If the type requires an external package, wrap tests with skip_if_not_installed().
Expected: All tests pass. No skips unless external dependency is missing.
On failure: Check each integration point individually. The most common issue is missing dispatch cases — run grep -rn "switch\|valid_types" R/ to find all dispatch locations.
generate_puzzle(type = "<type>") produces valid outputdevtools::test() passes with new testsdevtools::check() returns 0 errors, 0 warningsdevtools::document() succeeds (NAMESPACE updated)paste(a, b, sep = "-"), negative piece labels produce keys like "1--1". Use "|" separator instead and split with "\\|".cat() for output: Always use cli package logging wrappers (log_info, log_warn, etc.)yaml::yaml.load_file("inst/config.yml")generate-puzzle — test the new type after scaffoldingrun-puzzle-tests — run the full test suite to verify integrationvalidate-piles-notation — test fusion with the new typewrite-testthat-tests — general test-writing patternswrite-roxygen-docs — document the new geom function