fix(coords): Chunk-Namen korrekt für Float-Indizes und Newlines
- chunk_name: Reject float/bool indices like JavaScript (Number.isInteger) - parse_chunk_name: Use fullmatch instead of match($) to reject strings with trailing newlines - Add invalidIndices fixture cases to catch these edge cases in both languages Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2f63779363
commit
f0f7692f14
4 files changed
+20
-4
No files matched your search
@@ -49,6 +49,12 @@ describe("Chunk-Namen", () => {
|
||||
expect(chunkName(1.5, 3)).toBeNull();
|
||||
});
|
||||
|
||||
it("lehnt ungültige Indextypen ab", () => {
|
||||
for (const [i, j] of NAMES.invalidIndices) {
|
||||
expect(chunkName(i, j)).toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
it("kommt für alle 144 Chunks hin und zurück", () => {
|
||||
for (let i = 0; i < 12; i++) {
|
||||
for (let j = 0; j < 12; j++) expect(parseChunkName(chunkName(i, j))).toEqual({ i, j });
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"pairs": [["A1", 0, 0], ["L1", 11, 0], ["A12", 0, 11], ["L12", 11, 11], ["C10", 2, 9]],
|
||||
"lowercase": [["c10", 2, 9], ["l12", 11, 11]],
|
||||
"invalid": ["M1", "A0", "A13", "A", "10", "", "A01", "B-3", " "]
|
||||
"invalid": ["M1", "A0", "A13", "A", "10", "", "A01", "B-3", " ", "A1\n"],
|
||||
"invalidIndices": [[1.5, 3], [3, 2.5], [true, 0], [0, false]]
|
||||
}
|
||||
@@ -32,19 +32,23 @@ def pixel_to_world(px: int, py: int) -> tuple[float, float]:
|
||||
|
||||
CHUNKS_PER_SIDE = (SLICE["x1"] - SLICE["x0"]) // CHUNK_SIZE # 12
|
||||
CHUNK_COLUMNS = "ABCDEFGHIJKL"
|
||||
_CHUNK_NAME = re.compile(r"^([A-La-l])([1-9]\d?)$")
|
||||
_CHUNK_NAME = re.compile(r"([A-La-l])([1-9]\d?)")
|
||||
|
||||
|
||||
def _is_index(k) -> bool:
|
||||
return isinstance(k, int) and not isinstance(k, bool) and 0 <= k < CHUNKS_PER_SIDE
|
||||
|
||||
|
||||
def chunk_name(i: int, j: int) -> str | None:
|
||||
"""Planquadrat-Name wie src/world/coords.js: Spalte A–L aus i, Zeile 1–12 aus j. A1 = Nordwest."""
|
||||
if not (0 <= i < CHUNKS_PER_SIDE and 0 <= j < CHUNKS_PER_SIDE):
|
||||
if not (_is_index(i) and _is_index(j)):
|
||||
return None
|
||||
return f"{CHUNK_COLUMNS[i]}{j + 1}"
|
||||
|
||||
|
||||
def parse_chunk_name(name: str) -> tuple[int, int] | None:
|
||||
"""Umkehrung von chunk_name. Akzeptiert Kleinschreibung, None außerhalb A1–L12."""
|
||||
match = _CHUNK_NAME.match(str(name))
|
||||
match = _CHUNK_NAME.fullmatch(str(name))
|
||||
if not match or int(match.group(2)) > CHUNKS_PER_SIDE:
|
||||
return None
|
||||
return CHUNK_COLUMNS.index(match.group(1).upper()), int(match.group(2)) - 1
|
||||
@@ -43,3 +43,8 @@ def test_chunk_names_round_trip_for_all_144_chunks():
|
||||
for i in range(12):
|
||||
for j in range(12):
|
||||
assert parse_chunk_name(chunk_name(i, j)) == (i, j)
|
||||
|
||||
|
||||
def test_chunk_names_reject_invalid_index_types():
|
||||
for i, j in NAMES["invalidIndices"]:
|
||||
assert chunk_name(i, j) is None
|
||||
Reference in new issue
Block a user