The whole-ass thing

This commit is contained in:
Nikolaj
2021-12-24 18:14:59 +01:00
commit 64b309b085
63 changed files with 374 additions and 0 deletions

5
font_game/__init__.py Normal file
View File

@ -0,0 +1,5 @@
from .util import (base64, FONT_SIZE, FONT_COLOR, IMAGE_BACKGROUND, IMAGE_SIZE,
MARGINS, FONTS)
from . import images
from . import web
from . import game

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

47
font_game/game.py Normal file
View File

@ -0,0 +1,47 @@
import random
import time
import os
from font_game.images import gen_image
from font_game import base64, FONTS
def purge_games():
for root, _, files in os.walk("current_games"):
for file in files:
os.remove(os.path.join(root, file))
def gen_id():
return base64(int(time.time()*10000))
def pick_fonts(game_length: int):
weights = {key: 100 for key in FONTS}
font_list = []
for _ in range(game_length):
picked = random.choice([k for k in weights for _ in range(weights[k])])
font_list.append(picked)
weights[picked] = weights[picked] // 2
return [(i, FONTS[i]) for i in font_list]
def start_game(game_length: int = 10) -> str:
picked_fonts = pick_fonts(game_length)
images = []
for font in picked_fonts:
images.append(gen_image(font[1]))
game_id = gen_id()
game_dict = {
"points": "0",
"i": "0",
"game_length": str(game_length),
"images": ','.join(images),
"fonts": ','.join(i[0] for i in picked_fonts)
}
game = "\n".join([f"{key}:{value}" for key, value in game_dict.items()])
with open(f"current_games/{game_id}", "w", encoding="utf-8") as file:
file.write(game)
return game_id

45
font_game/images.py Normal file
View File

@ -0,0 +1,45 @@
import os
import time
from PIL import Image, ImageFont, ImageDraw
import lorem
from font_game import base64, IMAGE_SIZE, IMAGE_BACKGROUND, MARGINS, FONT_COLOR
def gen_image(font: ImageFont.ImageFont) -> str:
img = Image.new("RGB", IMAGE_SIZE, IMAGE_BACKGROUND)
drawer = ImageDraw.Draw(img)
text_width = IMAGE_SIZE[0] - 2 * MARGINS
text = lorem.sentence()
text_list = []
line = ""
for word in text.split(" "):
if drawer.textsize(line + word, font)[0] > text_width:
text_list.append(line)
line = ""
else:
line += word + " "
text_list.append(line)
drawer.text(
(MARGINS, MARGINS),
'\n'.join(text_list),
FONT_COLOR,
font,
spacing=30
)
filename = base64(int(time.time() * 10000) % 0xffffff)
path = f"static/images/{filename}.png"
new_size = (IMAGE_SIZE[0] // 2, IMAGE_SIZE[1] // 2)
img = img.resize(new_size, resample=Image.ANTIALIAS)
img.save(path)
return filename
def purge_images():
for root, _, files in os.walk("static/images"):
for file in files:
os.remove(os.path.join(root, file))

49
font_game/util.py Normal file
View File

@ -0,0 +1,49 @@
import string
import pathlib
from PIL import ImageFont
BASE64_DIGITS = string.digits + string.ascii_letters + "+_"
FONT_SIZE = 120
FONT_COLOR = (0,0,0)
IMAGE_BACKGROUND = (255,255,255)
IMAGE_SIZE = (1800, 1200)
MARGINS = 60
def base64(num: int) -> str:
temp = ""
while num > 0:
temp = BASE64_DIGITS[num % 64] + temp
num = num//64
return temp
def make_fonts():
with open("font-list.txt", "r", encoding="utf-8") as file_pointer:
fonts = file_pointer.read().split("\n")
image_fonts = {}
for font_name in fonts:
if font_name[0] == "#":
continue
font_name = font_name.replace(" ","-")
if pathlib.Path(f"./fonts/{font_name}.TTF").is_file():
file_type = "TTF"
elif pathlib.Path(f"./fonts/{font_name}.OTF").is_file():
file_type = "OTF"
else:
print(f"Could not locate font \033[0;31m{font_name}\033[0m")
continue
font_path = f"./fonts/{font_name}.{file_type}"
new_font = ImageFont.truetype(font_path, FONT_SIZE)
image_fonts[font_name] = new_font
print(f"Successfully loaded font \033[0;32m{font_name}\033[0m")
return image_fonts
FONTS = make_fonts()

89
font_game/web.py Normal file
View File

@ -0,0 +1,89 @@
import pathlib
import flask
from font_game.images import purge_images
from font_game.game import start_game, purge_games
from font_game import FONTS
app = flask.Flask(
__name__,
static_folder="../static",
template_folder="../templates"
)
@app.before_first_request
def activate():
purge_images()
purge_games()
@app.route("/fontgame", methods=["GET", "POST"])
def font_game():
if flask.request.method == "POST":
game_id = flask.request.form['id']
font_guess = flask.request.form['font']
if not pathlib.Path(f"current_games/{game_id}").is_file():
return flask.redirect("/")
with open(f"current_games/{game_id}", "r+", encoding="utf-8") as file:
game_dict = dict(
[tuple(line.split(":")) for line in file.read().split('\n')]
)
i = int(game_dict['i'])
font = game_dict['fonts'].split(',')[i]
if font_guess == font:
game_dict['points'] = str(int(game_dict['points']) + 1)
game_dict['i'] = str(i+1)
game = "\n".join(
[f"{key}:{value}" for key, value in game_dict.items()]
)
file.seek(0)
file.write(game)
args = flask.request.args
if 'id' in args:
if not pathlib.Path(f"current_games/{args['id']}").is_file():
return flask.redirect("/")
with open(f"current_games/{args['id']}", "r", encoding="utf-8") as file:
game = dict(
[tuple(line.split(":")) for line in file.read().split('\n')]
)
if int(game['i']) == int(game['game_length']):
return flask.render_template("final.html", points=game['points'],
game_length=game['game_length'])
images = game['images'].split(",")
image = images[int(game['i'])]
url = f"/static/images/{image}.png"
parameters = {
"url": url,
"i": str(int(game['i']) + 1),
"round_n": game['i'],
"game_length": game['game_length'],
"points":game['points'],
"fonts":FONTS,
"id":args['id']
}
return flask.render_template("fontgame.html", **parameters)
if 'n' in flask.request.args:
game_length = int(flask.request.args['n'])
else:
game_length = 10
game_id = start_game(game_length)
return flask.redirect(f"/fontgame?id={game_id}")
@app.route("/")
def root():
return flask.render_template("menu.html")
@app.route("/startgame", methods=["POST"])
def start():
if 'game_length' in flask.request.form:
game_length = flask.request.form['game_length']
else:
game_length = 10
return flask.redirect(f"/fontgame?n={game_length}")