#!/usr/bin/env python3
"""Record the repository's daily star count and render its README chart."""
from __future__ import annotations
import json
import math
from datetime import datetime, timezone
from pathlib import Path
from urllib.request import Request, urlopen
ROOT = Path(__file__).resolve().parents[1]
DATA_PATH = ROOT / "data" / "star-history.json"
SVG_PATH = ROOT / "assets" / "star-history.svg"
REPOSITORY = "cporter202/coreclaw-api-directory"
def fetch_star_count() -> int:
request = Request(
f"https://api.github.com/repos/{REPOSITORY}",
headers={
"Accept": "application/vnd.github+json",
"User-Agent": "coreclaw-api-directory-star-history",
"X-GitHub-Api-Version": "2022-11-28",
},
)
with urlopen(request, timeout=20) as response:
return int(json.load(response)["stargazers_count"])
def update_history(stars: int) -> dict:
history = json.loads(DATA_PATH.read_text(encoding="utf-8"))
today = datetime.now(timezone.utc).date().isoformat()
points = history.setdefault("points", [])
if points and points[-1]["date"] == today:
points[-1]["stars"] = stars
else:
points.append({"date": today, "stars": stars})
points.sort(key=lambda point: point["date"])
DATA_PATH.write_text(json.dumps(history, indent=2) + "\n", encoding="utf-8")
return history
def render_svg(history: dict) -> str:
points = history["points"]
width, height = 1200, 430
left, right, top, bottom = 92, 1135, 132, 340
current = int(points[-1]["stars"])
max_value = max(int(point["stars"]) for point in points)
max_y = max(4, int(math.ceil(max_value / 4.0) * 4))
def x_at(index: int) -> float:
if len(points) == 1:
return (left + right) / 2
return left + (right - left) * index / (len(points) - 1)
def y_at(value: int) -> float:
return bottom - (bottom - top) * value / max_y
coordinates = [
(x_at(index), y_at(int(point["stars"])))
for index, point in enumerate(points)
]
polyline = " ".join(f"{x:.1f},{y:.1f}" for x, y in coordinates)
area = (
f"M {coordinates[0][0]:.1f} {bottom} "
+ " ".join(f"L {x:.1f} {y:.1f}" for x, y in coordinates)
+ f" L {coordinates[-1][0]:.1f} {bottom} Z"
)
grid = []
for step in range(5):
y = top + (bottom - top) * step / 4
label = round(max_y * (4 - step) / 4)
grid.append(
f''
f'{label}'
)
dots = "".join(
f''
for x, y in coordinates[-30:]
)
end_label = points[-1]["date"] if len(points) > 1 else "Tracking started"
return f'''
'''
def main() -> None:
history = update_history(fetch_star_count())
SVG_PATH.write_text(render_svg(history), encoding="utf-8")
print(
f"Recorded {history['points'][-1]['stars']} stars for "
f"{history['points'][-1]['date']}"
)
if __name__ == "__main__":
main()