Skip to content

author_profiles

src.models.authors.author_profiles

Author profile schema.

Generated by generate_author_profiles.pyauthor_profiles.json.

AuthorProfile

Bases: AuthorCore

Unified author profile combining publication record, artifact metrics, and AE committee service.

Source code in src/models/authors/author_profiles.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
class AuthorProfile(AuthorCore):
    """Unified author profile combining publication record, artifact metrics, and AE committee service."""

    ae_memberships: int = Field(
        default=0,
        ge=0,
        description="Total number of AE committee memberships across all conferences and years.",
        examples=[4],
    )
    chair_count: int = Field(
        default=0, ge=0, description="Number of times served as AE chair (versus regular member).", examples=[1]
    )
    ae_conferences: list[AEMembership] = Field(
        default_factory=list,
        description="AE committee memberships, one per conference-year served. Each entry has conference, year, role.",
    )
    ae_years: dict[str, int] = Field(
        default_factory=dict,
        description="Year (as string key, e.g. '2023') → number of AE memberships that year. Example: {'2023': 5, '2024': 3}.",
    )
    combined_score: int = Field(
        ge=0, description="Total combined score: artifact_score + citation_score + ae_score.", examples=[15]
    )
    artifact_score: int = Field(
        ge=0,
        description="Points from artifacts: each artifact scores 1 (available) + 1 (functional) + 1 (reproducible).",
        examples=[9],
    )
    citation_score: int = Field(
        ge=0, description="Points from artifact citations. Currently 0 for all authors.", examples=[0]
    )
    ae_score: int = Field(ge=0, description="Points from AE service: memberships * 3 + chairs * 2.", examples=[6])
    rank: int | None = Field(
        default=None,
        ge=1,
        description="Ranking position among all author profiles (with ties). Null if unranked.",
        examples=[1],
    )

    @field_validator("conferences", mode="before")
    @classmethod
    def _coerce_conferences(cls, v: object) -> object:
        """Accept [conf, year, role] tuples and extract conference name strings."""
        if isinstance(v, list) and v and isinstance(v[0], (list, tuple)):
            seen: set[str] = set()
            result: list[str] = []
            for item in v:
                name = item[0] if isinstance(item, (list, tuple)) else item
                if name not in seen:
                    seen.add(name)
                    result.append(name)
            return result
        return v

    @field_validator("ae_conferences", mode="before")
    @classmethod
    def _coerce_ae_conferences(cls, v: object) -> object:
        """Accept both [conf, year, role] lists and {conference, year, role} dicts."""
        if isinstance(v, list):
            return [
                {"conference": item[0], "year": item[1], "role": item[2]} if isinstance(item, (list, tuple)) else item
                for item in v
            ]
        return v