46 lines
1.4 KiB
Python
46 lines
1.4 KiB
Python
from datetime import datetime
|
|
from decimal import Decimal
|
|
from typing import Iterable
|
|
|
|
from app.domain.enums import NormalizationStatus
|
|
from app.domain.models import AttributeStatement
|
|
|
|
|
|
def statement_is_usable(statement: AttributeStatement | None, minimum_confidence: Decimal) -> bool:
|
|
if statement is None:
|
|
return False
|
|
if statement.normalization_status != NormalizationStatus.NORMALIZED:
|
|
return False
|
|
if statement.normalized_value is None:
|
|
return False
|
|
return statement.confidence >= minimum_confidence
|
|
|
|
|
|
def select_attribute_snapshot(
|
|
statements: Iterable[AttributeStatement],
|
|
*,
|
|
as_of: datetime,
|
|
snapshot_cutoff: datetime,
|
|
) -> dict[str, AttributeStatement]:
|
|
"""Pick the newest statement per key at or before the evaluation cutoff."""
|
|
chosen: dict[str, AttributeStatement] = {}
|
|
for statement in statements:
|
|
if statement.observed_at > as_of or statement.ingested_at > snapshot_cutoff:
|
|
continue
|
|
current = chosen.get(statement.attribute)
|
|
if current is None or _is_newer(statement, current):
|
|
chosen[statement.attribute] = statement
|
|
return chosen
|
|
|
|
|
|
def _is_newer(candidate: AttributeStatement, current: AttributeStatement) -> bool:
|
|
return (
|
|
candidate.observed_at,
|
|
candidate.ingested_at,
|
|
candidate.id,
|
|
) > (
|
|
current.observed_at,
|
|
current.ingested_at,
|
|
current.id,
|
|
)
|