File size: 1,391 Bytes
80c6417
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
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
"""Helpers internes partagés par les détecteurs narratifs."""

from __future__ import annotations

from typing import Optional


def _engines_summary(data: dict) -> list[dict]:
    """Accès normalisé à la liste des résumés moteur."""
    return data.get("engines", []) or []


def _engine_by_name(data: dict, name: str) -> Optional[dict]:
    for e in _engines_summary(data):
        if e.get("name") == name:
            return e
    return None


def _n_docs(data: dict) -> int:
    meta = data.get("meta", {}) or {}
    return int(meta.get("document_count") or 0)


def _mean_duration_per_engine(data: dict) -> dict[str, float]:
    """Durée moyenne d'exécution par moteur (en secondes par document).

    Lit ``benchmark_data["documents"][i]["engine_results"][j]["duration"]``
    (format runner). Filtre les durées non-numériques.
    """
    durations: dict[str, list[float]] = {}
    for doc in data.get("documents") or []:
        for er in doc.get("engine_results") or []:
            engine_name = er.get("engine")
            d = er.get("duration")
            if engine_name is None or d is None:
                continue
            try:
                d_f = float(d)
            except (TypeError, ValueError):
                continue
            durations.setdefault(engine_name, []).append(d_f)
    return {k: sum(v) / len(v) for k, v in durations.items() if v}