From 10125139a92f34c9340683b401a84b98fba309f4 Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 20 Jun 2025 10:42:30 +0300 Subject: [PATCH] ipuz export --- cruciverb-core/src/export/ipuz.rs | 75 +++++++++++++++++++++++++++++++ cruciverb-core/src/export/mod.rs | 3 ++ 2 files changed, 78 insertions(+) create mode 100644 cruciverb-core/src/export/ipuz.rs create mode 100644 cruciverb-core/src/export/mod.rs diff --git a/cruciverb-core/src/export/ipuz.rs b/cruciverb-core/src/export/ipuz.rs new file mode 100644 index 0000000..5565730 --- /dev/null +++ b/cruciverb-core/src/export/ipuz.rs @@ -0,0 +1,75 @@ +use serde_json::{json, Value}; + +use crate::grid::Cell; +use crate::puzzle::Puzzle; + +/// Serialize a puzzle to ipuz JSON format. +/// Spec: http://www.ipuz.org/ +pub fn to_ipuz(puzzle: &Puzzle, title: &str) -> Value { + let mut puzzle_grid = Vec::new(); + let mut solution_grid = Vec::new(); + + // build cell number map + let mut cell_numbers = std::collections::HashMap::new(); + for word in &puzzle.words { + cell_numbers.entry((word.row, word.col)).or_insert(word.clue_number); + } + + for r in 0..puzzle.height { + let mut puzzle_row = Vec::new(); + let mut solution_row = Vec::new(); + for c in 0..puzzle.width { + match puzzle.grid.get(r, c) { + Cell::Black => { + puzzle_row.push(json!("#")); + solution_row.push(json!("#")); + } + Cell::Letter(ch) => { + let num = cell_numbers.get(&(r, c)); + if let Some(&n) = num { + puzzle_row.push(json!(n)); + } else { + puzzle_row.push(json!(0)); + } + solution_row.push(json!(ch.to_string())); + } + Cell::Empty => { + let num = cell_numbers.get(&(r, c)); + if let Some(&n) = num { + puzzle_row.push(json!(n)); + } else { + puzzle_row.push(json!(0)); + } + solution_row.push(json!(null)); + } + } + } + puzzle_grid.push(puzzle_row); + solution_grid.push(solution_row); + } + + let across_clues: Vec = puzzle.clues_across.iter().map(|c| { + json!([c.number, c.text]) + }).collect(); + + let down_clues: Vec = puzzle.clues_down.iter().map(|c| { + json!([c.number, c.text]) + }).collect(); + + json!({ + "version": "http://ipuz.org/v2", + "kind": ["http://ipuz.org/crossword#1"], + "title": title, + "dimensions": { + "width": puzzle.width, + "height": puzzle.height, + }, + "puzzle": puzzle_grid, + "solution": solution_grid, + "clues": { + "Across": across_clues, + "Down": down_clues, + }, + "difficulty": puzzle.difficulty_score, + }) +} diff --git a/cruciverb-core/src/export/mod.rs b/cruciverb-core/src/export/mod.rs new file mode 100644 index 0000000..91c9db7 --- /dev/null +++ b/cruciverb-core/src/export/mod.rs @@ -0,0 +1,3 @@ +pub mod puz; +pub mod ipuz; +pub mod pdf;