From d084a0a785edecb42abce7e3c6d42eab5fd49af0 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Mon, 29 Jun 2026 14:50:03 +0000 Subject: [PATCH] =?UTF-8?q?Rank=20historic=20EPC=20records=20by=20address?= =?UTF-8?q?=20similarity=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- datatypes/epc/domain/historic_epc_matching.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/datatypes/epc/domain/historic_epc_matching.py b/datatypes/epc/domain/historic_epc_matching.py index d31c918fd..09da3bf9a 100644 --- a/datatypes/epc/domain/historic_epc_matching.py +++ b/datatypes/epc/domain/historic_epc_matching.py @@ -66,7 +66,31 @@ def rank_historic_epc( """Score ``records`` against ``user_address`` (best first), keeping every record — including hard-zero non-matches. The pure scoring half of the historic-EPC lookup: no I/O, so it is unit-testable without S3.""" - raise NotImplementedError + if not user_address: + raise ValueError("user_address must be non-empty") + if not records: + return [] + + df = pd.DataFrame( + { + address_column: [r.address for r in records], + uprn_column: [r.uprn for r in records], + } + ) + scored = rank_address_similarity( + df, + user_address=user_address, + address_column=address_column, + uprn_column=uprn_column, + ) + return [ + ScoredHistoricEpc( + record=records[i], + lexiscore=float(row["lexiscore"]), + lexirank=int(row["lexirank"]), + ) + for i, row in scored.iterrows() + ] def _sanitise_postcode(postcode: str) -> str: