themis / phase1 /scripts /graph_view.py
vg15o2's picture
Moonley backend (HF Space build)
1d9bd9b
Raw
History Blame Contribute Delete
2.15 kB
"""Source-independent API projection for citation-graph judgment nodes."""
from __future__ import annotations
import re
from typing import Any, Mapping
THEMIS_DECIMAL_ID = re.compile(r"^[1-9][0-9]{12}$")
def graph_node_card(
node_id: object,
metadata: Mapping[str, Any] | None = None,
*,
treatment: str | None = None,
cited_by: int = 0,
good_law_status: str = "unknown",
) -> dict[str, Any]:
"""Return the graph/UI contract for one judgment node.
The permanent Moonley ID remains the routing key. All presentation fields
use the human legal identity so internal IDs never need to be rendered.
"""
judgment_id = str(node_id)
meta = dict(metadata or {})
case_name = " ".join(str(meta.get("case_name") or "").split())
citation = " ".join(str(meta.get("neutral_citation") or "").split())
date = meta.get("date") or meta.get("decision_date")
display_name = case_name or citation or "Case name unavailable"
tooltip_parts = [display_name]
if citation and citation != display_name:
tooltip_parts.append(citation)
if date:
tooltip_parts.append(str(date))
tooltip_parts.append(str(good_law_status or "unknown").replace("_", " "))
return {
# Canonical graph contract.
"node_id": judgment_id,
"judgment_id": judgment_id,
"label": display_name,
"display_name": display_name,
"tooltip": " · ".join(tooltip_parts),
"hover": {
"case_name": case_name or None,
"neutral_citation": citation or None,
"decision_date": date,
"good_law_status": good_law_status or "unknown",
},
"open": {
"judgment_id": judgment_id,
"pdf_id": judgment_id,
},
"is_themis_decimal_id": bool(THEMIS_DECIMAL_ID.fullmatch(judgment_id)),
# Compatibility with the current phase 1.1 frontend.
"id": judgment_id,
"name": display_name,
"citation": citation or None,
"treatment": treatment,
"cited_by": int(cited_by or 0),
"good_law": good_law_status or "unknown",
}