-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
src/commonMain/kotlin/com/jeffpdavidson/kotwords/formats/Guardian.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package com.jeffpdavidson.kotwords.formats | ||
|
||
import com.jeffpdavidson.kotwords.formats.json.GuardianJson | ||
import com.jeffpdavidson.kotwords.formats.json.JsonSerializer | ||
import com.jeffpdavidson.kotwords.model.Crossword | ||
import com.jeffpdavidson.kotwords.model.Puzzle | ||
|
||
class Guardian( | ||
private val json: String, | ||
private val copyright: String = "", | ||
) : DelegatingPuzzleable() { | ||
override suspend fun getPuzzleable(): Puzzleable { | ||
val data = JsonSerializer.fromJson<GuardianJson.Data>(json) | ||
val cells = mutableMapOf<Pair<Int, Int>, Puzzle.Cell>() | ||
val acrossClues = mutableMapOf<Int, String>() | ||
val downClues = mutableMapOf<Int, String>() | ||
data.entries.forEach { entry -> | ||
val isAcross = entry.direction == "across" | ||
val clues = if (isAcross) acrossClues else downClues | ||
clues[entry.number] = entry.clue | ||
repeat(entry.length) { i -> | ||
val x = entry.position.x + if (isAcross) i else 0 | ||
val y = entry.position.y + if (!isAcross) i else 0 | ||
val solution = if (entry.solution.isNotEmpty()) "${entry.solution[i]}" else "" | ||
val existingCell = cells[x to y] | ||
require(existingCell == null || existingCell.solution == solution) { | ||
"Solution mismatch in cell ($x, $y)" | ||
} | ||
cells[x to y] = Puzzle.Cell( | ||
number = if (i == 0) "${entry.number}" else "", | ||
solution = solution, | ||
) | ||
} | ||
} | ||
val grid = (0 until data.dimensions.rows).map { y -> | ||
(0 until data.dimensions.cols).map { x -> | ||
val cell = cells[x to y] | ||
if (cell != null) { | ||
cell | ||
} else { | ||
Puzzle.Cell(cellType = Puzzle.CellType.BLOCK) | ||
} | ||
} | ||
} | ||
return Crossword( | ||
title = data.name, | ||
creator = data.creator.name, | ||
copyright = copyright, | ||
description = data.instructions, | ||
grid = grid, | ||
acrossClues = acrossClues, | ||
downClues = downClues, | ||
hasHtmlClues = true, | ||
) | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/commonMain/kotlin/com/jeffpdavidson/kotwords/formats/json/GuardianJson.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.jeffpdavidson.kotwords.formats.json | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
internal object GuardianJson { | ||
|
||
@Serializable | ||
internal data class Entry( | ||
val number: Int, | ||
val clue: String, | ||
val direction: String, | ||
val length: Int, | ||
val position: Position, | ||
val solution: String = "", | ||
) { | ||
@Serializable | ||
internal data class Position( | ||
val x: Int, | ||
val y: Int, | ||
) | ||
} | ||
|
||
@Serializable | ||
internal data class Data( | ||
val name: String, | ||
val creator: Creator = Creator(), | ||
val dimensions: Dimensions, | ||
val instructions: String = "", | ||
val entries: List<Entry>, | ||
) { | ||
@Serializable | ||
internal data class Dimensions( | ||
val cols: Int, | ||
val rows: Int, | ||
) | ||
|
||
@Serializable | ||
internal data class Creator( | ||
val name: String = "", | ||
) | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/commonTest/kotlin/com/jeffpdavidson/kotwords/formats/GuardianTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.jeffpdavidson.kotwords.formats | ||
|
||
import com.jeffpdavidson.kotwords.readBinaryResource | ||
import com.jeffpdavidson.kotwords.readStringResource | ||
import kotlinx.coroutines.test.runTest | ||
import kotlin.test.Test | ||
import kotlin.test.assertTrue | ||
|
||
class GuardianTest { | ||
@Test | ||
fun crossword() = runTest { | ||
assertTrue( | ||
readBinaryResource(GuardianTest::class, "puz/test-simple.puz").contentEquals( | ||
Guardian( | ||
readStringResource(GuardianTest::class, "guardian/test-simple.json"), | ||
copyright = "\u00a9 2018 Jeff Davidson", | ||
).asPuzzle().asAcrossLiteBinary() | ||
) | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
{ | ||
"name": "Example Puzzle for Kotwords", | ||
"creator": { | ||
"name": "Jeff Davidson" | ||
}, | ||
"entries": [ | ||
{ | ||
"number": 1, | ||
"clue": "First across clue", | ||
"direction": "across", | ||
"length": 4, | ||
"position": { | ||
"x": 0, | ||
"y": 0 | ||
}, | ||
"solution": "ABCD" | ||
}, | ||
{ | ||
"number": 5, | ||
"clue": "Second across clue", | ||
"direction": "across", | ||
"length": 4, | ||
"position": { | ||
"x": 0, | ||
"y": 1 | ||
}, | ||
"solution": "EFGH" | ||
}, | ||
{ | ||
"number": 6, | ||
"clue": "Third across clue", | ||
"direction": "across", | ||
"length": 5, | ||
"position": { | ||
"x": 0, | ||
"y": 2 | ||
}, | ||
"solution": "IJKLM" | ||
}, | ||
{ | ||
"number": 8, | ||
"clue": "Fourth across clue", | ||
"direction": "across", | ||
"length": 4, | ||
"position": { | ||
"x": 1, | ||
"y": 3 | ||
}, | ||
"solution": "NOPQ" | ||
}, | ||
{ | ||
"number": 9, | ||
"clue": "Fifth across clue", | ||
"direction": "across", | ||
"length": 4, | ||
"position": { | ||
"x": 1, | ||
"y": 4 | ||
}, | ||
"solution": "RSTU" | ||
}, | ||
{ | ||
"number": 1, | ||
"clue": "First down clue", | ||
"direction": "down", | ||
"length": 3, | ||
"position": { | ||
"x": 0, | ||
"y": 0 | ||
}, | ||
"solution": "AEI" | ||
}, | ||
{ | ||
"number": 2, | ||
"clue": "Second down clue", | ||
"direction": "down", | ||
"length": 5, | ||
"position": { | ||
"x": 1, | ||
"y": 0 | ||
}, | ||
"solution": "BFJNR" | ||
}, | ||
{ | ||
"number": 3, | ||
"clue": "Third down clue", | ||
"direction": "down", | ||
"length": 5, | ||
"position": { | ||
"x": 2, | ||
"y": 0 | ||
}, | ||
"solution": "CGKOS" | ||
}, | ||
{ | ||
"number": 4, | ||
"clue": "Fourth down clue", | ||
"direction": "down", | ||
"length": 5, | ||
"position": { | ||
"x": 3, | ||
"y": 0 | ||
}, | ||
"solution": "DHLPT" | ||
}, | ||
{ | ||
"number": 7, | ||
"clue": "Fifth down clue", | ||
"direction": "down", | ||
"length": 3, | ||
"position": { | ||
"x": 4, | ||
"y": 2 | ||
}, | ||
"solution": "MQU" | ||
} | ||
], | ||
"dimensions": { | ||
"cols": 5, | ||
"rows": 5 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters