class AuthorStats(BaseModel):
"""Complete statistics for a single author.
Generated by ``generate_author_stats.py``.
"""
author_id: int | None = Field(
default=None,
ge=1,
description="Stable integer identifier referencing the canonical author_index.",
)
name: str = Field(description="Full name in DBLP format (may include disambiguation suffix).")
display_name: str = Field(description="Name without DBLP disambiguation suffix.")
affiliation: str = Field(description="Normalized institution affiliation.")
artifact_count: int = Field(ge=0, description="Total artifacts authored.")
total_papers: int = Field(ge=0, description="Total papers at tracked conferences.")
total_papers_by_conf: dict[str, int] = Field(
description="Mapping of conference name to paper count at that conference.",
)
total_papers_by_conf_year: dict[str, dict[str, int]] = Field(
description="Nested mapping: conference name → { year → count }.",
)
artifact_rate: float = Field(ge=0, le=100, description="Percentage of papers with artifacts.")
repro_rate: float = Field(ge=0, le=100, description="Percentage of artifacts with a reproducibility badge.")
functional_rate: float = Field(ge=0, le=100, description="Percentage of artifacts with a functional badge.")
category: Literal["systems", "security", "both", "unknown"] = Field(
description="Research domain based on conferences published at.",
)
conferences: list[str] = Field(description="List of conferences where author has published.")
years: list[int] = Field(description="Sorted list of years with activity.")
year_range: str = Field(pattern=r"^\d{4}-\d{4}$", description="Activity range in 'YYYY-YYYY' format.")
recent_count: int = Field(ge=0, description="Number of papers in the last 3 years.")
artifact_citations: int = Field(ge=0, description="Total citation count for artifacts.")
badges_available: int = Field(ge=0, description="Count of 'available' badges across all artifacts.")
badges_functional: int = Field(ge=0, description="Count of 'functional' badges across all artifacts.")
badges_reproducible: int = Field(ge=0, description="Count of 'reproduced' badges across all artifacts.")
papers: list[ArtifactPaper] = Field(
default_factory=list,
description="DEPRECATED in YAML output (use paper_ids). Retained in JSON for backward compatibility.",
)
papers_without_artifacts: list[PlainPaper] = Field(
default_factory=list,
description="DEPRECATED in YAML output (use papers_without_artifact_ids). Retained in JSON.",
)
paper_ids: list[int] = Field(
default_factory=list,
description="List of paper index IDs for artifact papers. References papers.json.",
)
papers_without_artifact_ids: list[int] = Field(
default_factory=list,
description="List of paper index IDs for non-artifact papers. References papers.json.",
)
model_config = {"extra": "forbid"}