Progressive title truncation, publisher tiebreak, thematic-year fix

Long transcribed box titles that defeat search now retry with shorter
heads (pre-separator, pre-"Game ..." descriptor, first-two-words from
the pre-subtitle part) matched exact-only against the head — fuzzy
thresholds stay untouched. Tie-breaks gain a publisher pick: when the
box showed a publisher and exactly one exact-named candidate is from
that publisher, it wins (SPI's Sorcerer 1975 now beats the more-owned
White Wizard Sorcerer 2019). The extract prompt excludes thematic/
subject years from year_hint; re-extracting Flat Top's photo drops the
bogus 1942, and a regression test pins that a wrong year can never
drive version selection. Re-extraction also drifted two transcriptions
(DUNGEON!, and Herbaceous misread as "Hebarceos") — fixtures added; the
misread demos review's re-search rescue in the end-to-end run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-01 14:14:15 -04:00
parent 09274e039c
commit 4a466f2a68
10 changed files with 218 additions and 25 deletions
@@ -0,0 +1 @@
<items total="0"></items>
@@ -0,0 +1 @@
<items total="1"><item type="boardgame" id="1339"><name type="primary" value="Dungeon!"/><yearpublished value="1975"/></item></items>
@@ -0,0 +1 @@
<items total="0"></items>
+107
View File
@@ -187,3 +187,110 @@ def test_score_version_no_overlap():
languages=("English",),
)
assert _score_version(entry, version) == 0
# -- progressive title truncation (long transcribed box titles) ---------
from bggpipe.normalize import normalize_title # noqa: E402
from bggpipe.resolve import _truncation_heads # noqa: E402
CIV_TITLE = (
"CIVILIZATION Game of the Heroic Age - The Dawn of History 8000 BC to 250 BC"
)
AH_HINT = "The Avalon Hill Game Company, Baltimore, Maryland"
def _entry(title, **kw):
return TitleEntry(title_raw=title, title_normalized=normalize_title(title), **kw)
def test_truncation_heads_order_and_dedupe():
heads = _truncation_heads(CIV_TITLE)
assert heads[0] == "CIVILIZATION Game of the Heroic Age" # before separator
assert heads[1] == "CIVILIZATION" # before the "Game ..." descriptor
assert len(heads) <= 3
def test_truncation_heads_game_word_without_separator():
assert _truncation_heads("SORCERER The Game of Magical Conflict")[0] == "SORCERER"
def test_truncation_heads_two_word_fallback():
heads = _truncation_heads(
"STARFORCE ALPHA CENTAURI Interstellar Conflict in the 25th Century"
)
assert heads[-1] == "STARFORCE ALPHA"
def test_short_titles_get_no_heads():
assert _truncation_heads("Catan") == []
assert _truncation_heads("Herbaceous") == []
def test_civilization_resolves_via_truncation(client):
entry = _entry(
CIV_TITLE,
publisher_hint=AH_HINT,
edition_hint="Bookcase Game",
language_hint="English",
)
row = resolve_entry(client, entry)
assert (row.match_status, row.bgg_id) == ("auto", 71)
# publisher cue picks the Avalon Hill version, not Hartland/Gibsons
assert row.version_status == "version_auto"
assert row.version_id == 71001
def test_advanced_civilization_resolves_as_expansion(client):
entry = _entry(
"ADVANCED CIVILIZATION Game Expansion of the Heroic Age - "
"Featuring New Civilization, Commodity, and Calamity Cards",
publisher_hint=AH_HINT,
edition_hint="Bookcase Game",
language_hint="English",
)
row = resolve_entry(client, entry)
assert (row.match_status, row.bgg_id, row.type) == (
"auto",
177,
"boardgameexpansion",
)
assert row.version_status == "version_auto"
def test_sorcerer_publisher_tiebreak_beats_owned_dominance(client):
"""Head search finds TWO games named 'Sorcerer' (SPI 1975 vs White
Wizard 2019, which has far more owners) — the SPI publisher cue must
pick the SPI game, and the edition cue the Designer's Edition."""
entry = _entry(
"SORCERER The Game of Magical Conflict",
publisher_hint="Simulations Publications Incorporated (SPI)",
edition_hint="Designer's Edition",
language_hint="English",
)
row = resolve_entry(client, entry)
assert (row.match_status, row.bgg_id) == ("auto", 3585)
assert row.version_status == "version_auto"
assert row.version_name == "SPI Designer's Edition"
def test_starforce_two_word_head_matches_full_title(client):
entry = _entry(
"STARFORCE ALPHA CENTAURI Interstellar Conflict in the 25th Century",
publisher_hint="Simulations Publications Incorporated (SPI)",
edition_hint="Designer's Edition",
language_hint="English",
)
row = resolve_entry(client, entry)
assert (row.match_status, row.bgg_id) == ("auto", 2524)
assert row.version_status == "version_auto"
def test_wrong_year_hint_never_drives_a_version(client):
"""Flat Top's box says 1942 (the theme, not the print year): version
scoring must not pick any version off the back of it."""
entry = _entry("FLAT TOP", year_hint=1942, language_hint="English")
row = resolve_entry(client, entry)
assert (row.match_status, row.bgg_id) == ("auto", 2529)
assert row.version_status == "version_unknown"
assert row.version_id is None