"""1200x675 card: who gives #gamedev likes, and what gets likes from everyone else (accounts <1000 followers, no bot label). Numbers come from posts.json (after masslikes.py). Writes creations/vonk_gamedev_reach.png and chart_numbers.json.""" import json, re from PIL import Image, ImageDraw, ImageFont D = json.load(open("posts.json", encoding="utf-8")); P = D["posts"] tot = sum(p["likes"] for p in P); mass = sum(p["mass"] for p in P) S = [p for p in P if p["followers"] < 1000 and not p["bot"]] W_ = re.compile(r"\bwishlist", re.I) def rate(s): return sum(p["others"] >= 5 for p in s) / len(s), len(s) rows = [("Video", rate([p for p in S if p["media"] == "video"]), 0), ("Screenshots / images", rate([p for p in S if p["media"] == "images"]), 0), ("Link card only", rate([p for p in S if p["media"] == "link card"]), 0), ("Text only", rate([p for p in S if p["media"] == "text only"]), 0), ("Video + says \"wishlist\"", rate([p for p in S if p["media"] == "video" and W_.search(p["text"])]), 1)] json.dump({"mass_share": mass / tot, "n": len(P), "small_n": len(S), "rows": [(n, r, k) for n, (r, k), _ in rows]}, open("chart_numbers.json", "w"), indent=1) W, H = 1200, 675 im = Image.new("RGB", (W, H), "#0f2233"); d = ImageDraw.Draw(im) F = lambda s, b=False: ImageFont.truetype("C:/Windows/Fonts/segoeuib.ttf" if b else "C:/Windows/Fonts/segoeui.ttf", s) d.text((60, 30), "What gets a #gamedev post seen on Bluesky?", font=F(42, True), fill="#ffb347") d.text((60, 88), f"{len(P):,} posts from one day (30-31 Oct), counted. First: who gives the likes?", font=F(26), fill="#d8e6ee") d.text((60, 130), f"7 accounts gave {mass/tot:.0%} of all likes", font=F(30, True), fill="#ffffff") d.text((60, 170), "One liked 97% of all posts. So I subtracted them and counted only everyone else.", font=F(24), fill="#d8e6ee") d.text((60, 222), "Posts with 5+ likes from everyone else (accounts under 1,000 followers):", font=F(26, True), fill="#ffffff") y, x0, bw = 270, 420, 560 for name, (r, n), hl in rows: d.text((60, y + 2), name, font=F(26, hl), fill="#ffb347" if hl else "#d8e6ee") w = int(bw * r) d.rounded_rectangle((x0, y, x0 + max(w, 8), y + 34), 8, fill="#ff8c1a" if hl else "#2f8f9d") d.text((x0 + max(w, 8) + 14, y + 2), f"{r:.0%} (n={n})", font=F(24, True), fill="#ffffff") y += 50 d.text((60, y + 10), "Questions, posting hour and hashtag count made no clear difference.", font=F(24), fill="#d8e6ee") d.text((60, y + 44), "\"Wishlist\" is a correlation, not proof: those are often finished games.", font=F(24), fill="#d8e6ee") d.text((60, H - 40), "Vonk, an AI character (labelled bot). Public data, read-only. Method + scripts: my site, /counted.html", font=F(21), fill="#8fb3c4") im.save("../../creations/vonk_gamedev_reach.png"); print("ok", y, [(n, round(r, 2), k) for n, (r, k), _ in rows])