"""Render analysis/results.json as results.md: every number the script uses, with the definition and source next to it."""
import json
from pathlib import Path

HERE = Path(__file__).resolve().parent
R = json.loads((HERE / "results.json").read_text(encoding="utf-8"))
L = []
w = L.append


def table(rows, head):
    w("| " + " | ".join(head) + " |")
    w("|" + "---|" * len(head))
    for r in rows:
        w("| " + " | ".join("" if v is None else str(v) for v in r) + " |")
    w("")


w("# Results: isekai titles\n")
w("Generated by `make_results_md.py` from `results.json` (`analyze.py`). Data: AniList GraphQL API, pulled 2026-10-16.")
w("Every number in the script must appear here. Do not edit by hand, rerun the scripts.\n")
w("## Definitions\n")
for k, v in R["definitions"].items():
    w(f"- **{k}:** {v}")
w("- **first season:** no PREQUEL relation to another anime and no sequel marker in the title (Season 2, 2nd Season, Part 2, II)")
w("- **2026 is incomplete** (pulled mid October, includes announced shows of the season). Fits use 2010 to 2025 only.")
w("- **Robustness:** with an isekai tag cutoff of 50, 60, 70, 80 or 90 the 2022 to 2025 average stays between 6.8 and 7.3 words (2010 to 2017: 3.3 to 4.0).\n")

c = R["counts"]
w("## Sizes\n")
table([[k, v] for k, v in c.items()], ["what", "n"])

w("## The curve (English title, first seasons, TV + ONA)\n")
table([[r["year"], r["n_isekai"], r["mean_isekai"], r["median_isekai"], r["chars_isekai"], r["native_isekai"], r["n_control"],
        r["mean_control"], r["chars_control"], r["native_control"], r["sentence_pct_isekai"]]
       for r in R["curve_by_year"] if r["year"] >= 2005],
      ["year", "n isekai", "words isekai", "median", "chars isekai", "JP chars isekai", "n other", "words other", "chars other",
       "JP chars other", "% sentence titles isekai"])

w("### By era\n")
rows = []
for era, d in R["eras_words"].items():
    jp = R["eras_native_chars"][era]
    rows.append([era, d["isekai"]["n"], d["isekai"]["mean"], d["control"]["mean"], jp["isekai"]["mean"], jp["control"]["mean"]])
table(rows, ["era", "n isekai", "words isekai", "words other", "JP chars isekai", "JP chars other"])

w("### Isekai share of new anime (%)\n")
table([[y, v] for y, v in R["isekai_share_pct_by_year"].items()], ["year", "% isekai"])

w("## Phone (AniList mobile layout, measured with `measure_truncation.py`)\n")
w("One full phone line (390 px wide phone, AniList 16px Overpass, 16 px margins): about **40 characters**. "
  "Result cards: 115 px wide, 12px font, clamped to 2 lines.\n")
rows = [[era, R["anilist_phone_card_cut_pct"]["isekai"].get(era), R["anilist_phone_card_cut_pct"]["control"].get(era),
         R["anilist_phone_line_over_40_pct"]["isekai"].get(era), R["anilist_phone_line_over_40_pct"]["control"].get(era)]
        for era in R["anilist_phone_card_cut_pct"]["isekai"]]
table(rows, ["era", "% isekai cut on result card", "% other cut", "% isekai over 40 chars", "% other over 40 chars"])

w("## By source material, 2018 to 2025 (mean English words)\n")
table([[k.replace("|", ", "), v["n"], v["mean_words"]] for k, v in sorted(R["by_source_2018_2025"].items(), key=lambda kv: kv[1]["mean_words"])],
      ["source, group", "n", "mean words"])

w("## Records\n")
w("Longest isekai titles, English, all formats (AniList title.english):\n")
table([[r["year"], r["format"], r["words_en"], r["chars_en"], r["title_used"]] for r in R["longest_isekai_words"]], ["year", "format", "words", "chars", "title"])
w("Longest English titles of any anime, all formats:\n")
table([[r["year"], r["format"], r["words_en"], r["chars_en"], r["title_used"]] for r in R["longest_any_words"]], ["year", "format", "words", "chars", "title"])
w("Backstabbed in a Backwater Dungeon, full light novel title (39 English words), wording from "
  "[Anime Corner](https://animecorner.me/?p=185098) and the Hobby Japan announcement via "
  "[AniTrendz](https://www.anitrendz.com/news/2024/11/15/backstabbed-in-a-backwater-dungeon-light-novels-receive-anime-adaptation). "
  "Japanese: 79 characters ([BOOK☆WALKER](https://bookwalker.jp/select/3446/)). The anime's AniList English title has 15 words.\n")

w("## Compression (gzip -9, compressed size / raw size, same amount of text per group, lower = more repetitive)\n")
table([[k, v] for k, v in R["gzip_ratio_2018_2025_same_length_text"].items()], ["group (2018 to 2025)", "ratio"])
table([[k, v["isekai"], v["control"]] for k, v in R["gzip_ratio_30_titles"].items()], ["era (1500 chars per sample)", "isekai", "other"])
w("Top words in isekai titles since 2018: " + ", ".join(f"{a} ({b})" for a, b in R["top_words_isekai_2018_2026"][:15]) + "\n")
w("Share of isekai titles containing a phrase (%):\n")
eras = list(next(iter(R["phrase_share_pct_isekai_by_era"].values())).keys())
table([[p] + [d[e] for e in eras] for p, d in R["phrase_share_pct_isekai_by_era"].items()], ["phrase"] + eras)

w("## Score vs length (isekai, popularity ≥ 5000)\n")
table([[k, v] for k, v in R["score_vs_words_isekai"].items()], ["what", "value"])
w(f"Spearman popularity vs words (isekai): {R['popularity_vs_words_isekai_spearman']}\n")

w("## Forecast (mean characters of isekai titles, fit on 2010 to 2025)\n")
w("Thresholds: phone line 40 (measured), Google result title about 60 (common SEO rule of thumb, Google truncates by pixel width), "
  "PEP 8 line length 79 ([PEP 8](https://peps.python.org/pep-0008/#maximum-line-length)), YouTube title limit 100, tweet 280.\n")
table([[k, v.get("threshold_chars"), v["linear_cross_year"], v["exp_cross_year"], v["linear_slope_per_year"], v["exp_growth_per_year_pct"], v["r"]]
       for k, v in R["forecast"].items()], ["threshold", "chars", "linear year", "exponential year", "+chars/yr", "+%/yr", "r"])

if "novel_vs_anime" in R:
    nv = R["novel_vs_anime"]
    w("## Light novels vs their anime\n")
    table([[k, v] for k, v in nv.items() if k != "biggest_cuts"], ["what", "value"])
    table([[r["year"], r["novel_words"], r["anime_words"], r["novel"], r["anime"]] for r in nv["biggest_cuts"]], ["year", "LN words", "anime words", "light novel", "anime"])
    w("Light novels on AniList, isekai, mean English words per year:\n")
    table([[r["year"], r["n"], r["mean"]] for r in R["novels_isekai_words_by_year"]], ["year", "n", "mean words"])
    w("Light novels, isekai, mean Japanese characters per year:\n")
    table([[r["year"], r["n"], r["mean"]] for r in R["novels_native_isekai_by_year"]], ["year", "n", "mean chars"])

w("## External facts used in the script (sources in research/niche_research.md)\n")
for line in [
    "Red Bard, 'When Light Novel Titles Started to get so Long' (2019): LN titles, jump around 2014, data to 2017. https://www.youtube.com/watch?v=pi79l5k8gBM",
    "@GenreCodeLovers via Nlab (2019): every LN 1975 to 2018 in Japanese characters. https://nlab.itmedia.co.jp/nl/amp/1902/18/news067.html",
    "BookLive via AdverTimes (2026-09-28): about 2 million manga titles, 9.14 characters (2011) to 18.45 (2026). https://www.advertimes.com/?p=558855",
    "Narou: over 1.15 million works, about 300 new per day (March 2025). https://note.com/shin038/n/n0c0bd095c44c",
    "Narou title limit 100 characters: widely reported, 11 TS-genre works sit at exactly 100. https://ncode.syosetu.com/n5357hj/12/ (no official help page found, say 'reportedly')",
    "BOOK☆WALKER longest LN series name per year 2021 to 2024: 96, 98, 97, 93. https://bookwalker.jp/select/3446/",
    "Narou writers: on a phone the list shows only the title. https://posfie.com/@mou_tamn/p/FuWTwro",
    "Gigguk, 'This Light Novel Does Not Exist.' (2021), real or fake game. https://www.youtube.com/watch?v=21zDl4sX3nE",
]:
    w(f"- {line}")

(HERE / "results.md").write_text("\n".join(L) + "\n", encoding="utf-8")
print("results.md written,", len(L), "lines")
