"""Draw the machine share of en.wikipedia's counted pageviews, month by month.

    python research/wikipedia-traffic/machines_chart.py

Writes site/public/images/wikipedia-machine-share.svg. One line, because the
finding is the shape of one line: a climb with no step in it. The two months
named as instrument events before the run are marked, so a reader can see that
the only sharp moves in the picture are the instrument's.

Palette from docs/IDENTITY.md: ground #0f1120, amber #f2b544, dusk violet
#a9a2c6, ivory #efe9dc, grid #262a44.
"""

import json
import os

RAW = os.path.expanduser("~/data/wikipedia-traffic")
OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                   "..", "..", "site", "public", "images",
                   "wikipedia-machine-share.svg")

W, H = 760, 400
L, R, T, B = 54, 16, 46, 54
GROUND, GRID = "#0f1120", "#262a44"
AMBER, VIOLET, IVORY = "#f2b544", "#a9a2c6", "#efe9dc"

FIRST = "2016-01"
LO, HI = 0.0, 0.45

#: Named in the kill rule before the run, and drawn here for the same reason.
MARKS = (("2020-04", "`automated` added"), ("2025-10", "reclassified"))


def series(agent):
    path = os.path.join(RAW, "en.wikipedia__all-access__%s.json" % agent)
    with open(path) as fh:
        data = json.load(fh)
    return {"%s-%s" % (i["timestamp"][:4], i["timestamp"][4:6]): int(i["views"])
            for i in data["items"]}


def main():
    spider, automated, user = series("spider"), series("automated"), series("user")
    months = [m for m in sorted(set(spider) | set(automated))
              if m >= FIRST and m in user]
    share = {}
    for m in months:
        machine = spider.get(m, 0) + automated.get(m, 0)
        total = machine + user[m]
        if total:
            share[m] = machine / total
    months = [m for m in months if m in share]
    n = len(months)

    def x(i):
        return L + (W - L - R) * i / (n - 1)

    def y(v):
        v = max(LO, min(HI, v))
        return T + (H - T - B) * (HI - v) / (HI - LO)

    p = ['<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %d %d" width="%d" '
         'height="%d" role="img" aria-labelledby="t d" font-family="JetBrains Mono, '
         'ui-monospace, Menlo, monospace" font-size="11">' % (W, H, W, H)]
    p.append('<title id="t">The machine share of en.wikipedia pageviews, month by '
             'month, January 2016 to August 2026</title>')
    p.append('<desc id="d">One line. The declared non-human share of counted '
             'pageviews sits near 14 per cent through 2016 to 2019, rises through '
             'the 2020s in a series of climbs and pauses with no single jump, '
             'reaches about 38 per cent in mid 2025, then falls sharply at October '
             '2025 when Wikimedia reclassified traffic. Two dashed vertical lines '
             'mark April 2020, when the automated agent type was added to the API, '
             'and October 2025, the reclassification. Source: Wikimedia REST '
             'pageview API, agent=spider plus agent=automated over the sum of '
             'those and agent=user.</desc>')
    p.append('<rect width="%d" height="%d" fill="%s"/>' % (W, H, GROUND))

    for v in (0.0, 0.10, 0.20, 0.30, 0.40):
        yy = y(v)
        p.append('<line x1="%d" y1="%.1f" x2="%d" y2="%.1f" stroke="%s" '
                 'stroke-width="1"/>' % (L, yy, W - R, yy, GRID))
        p.append('<text x="%d" y="%.1f" fill="%s" text-anchor="end">%d%%</text>'
                 % (L - 8, yy + 4, VIOLET, int(round(v * 100))))

    for m in months:
        if m.endswith("-01"):
            i = months.index(m)
            p.append('<line x1="%.1f" y1="%d" x2="%.1f" y2="%d" stroke="%s" '
                     'stroke-width="1" opacity="0.5"/>' % (x(i), T, x(i), H - B, GRID))
            p.append('<text x="%.1f" y="%d" fill="%s" text-anchor="middle" '
                     'font-size="10">%s</text>' % (x(i), H - B + 18, VIOLET, m[:4]))

    for month, label in MARKS:
        if month not in months:
            continue
        i = months.index(month)
        p.append('<line x1="%.1f" y1="%d" x2="%.1f" y2="%d" stroke="%s" '
                 'stroke-width="1" stroke-dasharray="3 3" opacity="0.8"/>'
                 % (x(i), T, x(i), H - B, IVORY))
        p.append('<text x="%.1f" y="%d" fill="%s" text-anchor="middle" '
                 'font-size="10">%s</text>' % (x(i), T - 11, IVORY,
                                               label.replace("`", "")))

    pts = " ".join("%.1f,%.1f" % (x(i), y(share[m])) for i, m in enumerate(months))
    p.append('<polyline points="%s" fill="none" stroke="%s" stroke-width="2" '
             'stroke-linejoin="round"/>' % (pts, AMBER))

    p.append('<text x="%d" y="16" fill="%s" font-size="11">share of counted '
             'en.wikipedia pageviews declared non-human, by month</text>'
             % (L - 2, VIOLET))
    p.append('<text x="%d" y="%d" fill="%s" font-size="10">Wikimedia REST pageview '
             'API, (spider + automated) / (spider + automated + user) · drawn '
             '2026-09-09</text>' % (L - 2, H - 10, VIOLET))
    p.append('</svg>')

    path = os.path.abspath(OUT)
    with open(path, "w") as fh:
        fh.write("\n".join(p) + "\n")
    print("wrote", path, "-", n, "months, share %.3f to %.3f"
          % (share[months[0]], share[months[-1]]))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
