jefklakscodex/extras/end-of-year-poster.py

159 lines
4.7 KiB
Python

import glob
import re
import os
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import sys
from dateutil import parser
from datetime import datetime
def is_in_year(year, content):
return re.search(r"date:\s?\"?" + str(year) + "-", content) is not None
def end_of_year(year):
games = []
for name in glob.glob('../content/games/**/*.md'):
if not '/_index.md' in name:
with open(name) as file:
content = file.read()
if is_in_year(year, content):
games.append(to_game_entry(content, name))
return games
def to_game_entry(content, name):
parts = name.split('/')
game_name = parts[-1].replace(".md", "")
game_platform = parts[-2]
cover = "../static/games/" + game_platform + "/" + game_name + "/" + "cover.jpg"
def pry_out(key, defval):
val = re.search(key + r":\s?(.*)", content)
if val is None:
return defval
if type(defval) is float:
return float(val.group(1))
if type(defval) is int:
return int(val.group(1))
if type(defval) is datetime:
return parser.parse(val.group(1).replace("\"", ""))
return val.group(1).replace("\"", "")
return {
"cover": cover,
"hltb": pry_out("howlongtobeat_hrs", 0.0),
"name": pry_out("game_name", ""),
"platform": game_platform,
"score": pry_out("score", 0),
"playdate": pry_out("date", datetime.now()),
"release_date": pry_out("game_release_year", datetime.now())
}
def montage(games_list, year):
print(games_list)
by_playdate = sorted(games_list, key=lambda game: game["playdate"].timestamp())
coverlist = list(map(lambda game: game["cover"], by_playdate))
file = "collage-" + str(year) + ".jpg"
cmd = "montage " + " ".join(coverlist) + " -geometry +0+0 -tile 8x5 -resize 170x200! " + file
os.system(cmd)
os.system("open " + file)
def group_per_platform(games_list):
per_platform = {}
for game in games_list:
if game["platform"] not in per_platform:
per_platform[game["platform"]] = [game]
else:
per_platform[game["platform"]].append(game)
return per_platform
def print_stats(games_list):
games_list = sorted(games_list, key=lambda game: game["hltb"])
total_hours = sum(list(map(lambda game: game["hltb"], games_list)))
print(" -- total #games: " + str(len(games_list)))
print(" -- total hours: " + str(total_hours))
print(" -- average hours: " + str(round(total_hours / len(games_list), 2)))
print(" -- average a day: " + str(round(total_hours / 355, 2)))
print()
print(" -- longest game: " + str(games_list[-1]["hltb"]) + " hours; " + games_list[-1]["name"])
print(" -- shortest game: " + str(games_list[0]["hltb"]) + " hours; " + games_list[0]["name"])
print()
for k, v in group_per_platform(games_list).items():
print(" -- Platform: " + k + " (" + str(len(v)) + "/" + str(len(games_list)) + ")")
recent_years = 2
print()
print("The **Recent GOTY** list:")
recent = list(filter(lambda g: datetime.now().year - g["release_date"].year <= recent_years, filter(lambda g: g["score"] >= 4, games_list)))
for game in recent:
print("- 💖 " + game["name"] + " (" + game["platform"] + "; " + str(game["release_date"].year) + ")")
print()
print("The **Vintage GOTY** list:")
vintage = list(filter(lambda g: datetime.now().year - g["release_date"].year, filter(lambda g: g["score"] >= 4, games_list)))
for game in vintage:
print("- 💖 " + game["name"] + " (" + game["platform"] + "; " + str(game["release_date"].year) + ")")
def generate_chart(games_list):
games_list = sorted(games_list, key=lambda game: game["score"])
mean_list_x = []
mean_list_y = []
legend_keys = []
legend_lines = []
legend_colors = {
'3ds': 'mediumaquamarine',
'ds': 'mediumturquoise',
'gameboy': 'olivedrab',
'gameboycolor': 'yellowgreen',
'gamecube': 'darkviolet',
'gba': 'slateblue',
'megadrive': 'royalblue',
'nes': 'firebrick',
'pc': 'dimgray',
'snes': 'orange',
'switch': 'red',
'wii': 'lightgrey'
}
for k, games in group_per_platform(games_list).items():
x = list(map(lambda g: g["name"], games))
y = list(map(lambda g: g["score"], games))
plt.bar(x, y, color=legend_colors[k])
legend_lines.append(Line2D([0], [0], color=legend_colors[k], lw=4))
legend_keys.append(k)
mean_list_x.append(x[len(x)//2])
mean_list_y.append(sum(list(map(lambda g: g["score"], games))) / len(games))
plt.xticks(rotation = 90)
plt.plot(mean_list_x, mean_list_y, color='black')
plt.scatter(mean_list_x, mean_list_y, color='black')
for i, x in enumerate(mean_list_x):
y = mean_list_y[i]
plt.text(x, y + .2, round(y, 2))
plt.legend(legend_lines, legend_keys, loc="upper left")
plt.show()
if len(sys.argv) <= 1:
print("Please provide a year [e.g. end-of-year-poster.py 2022].")
exit(-1)
year = int(sys.argv[1])
os.system("rm -rf *.jpg")
games_list = end_of_year(year)
montage(games_list, year)
print_stats(games_list)
generate_chart(games_list)