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
View File
@@ -0,0 +1,5 @@
points:7
i:10
game_length:10
images:WCQU,WD2r,WDcX,WDm+,WDwV,WDHM,WDSo,WE0V,WEb2,WElr
fonts:Akzidenz-Grotesk,Helvetica,Futura,Helvetica,Futura,Calibri,Akzidenz-Grotesk,Calibri,Helvetica,Roboto
+5
View File
@@ -0,0 +1,5 @@
points:10
i:10
game_length:10
images:7g1k,7geK,7gps,7gzz,7gKk,7gTP,7h0A,7h9Y,7hkN,7hzd
fonts:Roboto,Roboto,Calibri,Helvetica,Roboto,Akzidenz-Grotesk,Futura,Calibri,Arial,Arial
+5
View File
@@ -0,0 +1,5 @@
points:4
i:6
game_length:10
images:cUCv,cUOb,cUYI,cV6T,cVgK,cVqA,cVBc,cVLa,cVUo,cW1_
fonts:Futura,Roboto,Arial,Akzidenz-Grotesk,Futura,Calibri,Helvetica,Akzidenz-Grotesk,Arial,Futura
+29
View File
@@ -0,0 +1,29 @@
Akzidenz Grotesk
Arial
#Baskerville
#Bembo
#Bodoni
#Cambria
Calibri
#Clarendon
#DaxPro
#Didot
#Franklin Gothic
#Frutiger
Futura
#Garamond
#Georgia
#Gill Sans
#Gotham
Helvetica
#Minion
#Mrs Eaves
#Myriad
#News Gothic
Roboto
#Roboto Slab
#Rockwell
#Sabon
#Segoe UI
#Times New Roman
#Verdana
+5
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
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
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
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
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}")
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
from font_game.web import app
if __name__ == "__main__":
app.run()
+34
View File
@@ -0,0 +1,34 @@
.mainpage, .stats {
display: flex;
}
.mainpage img {
width: 600pt;
}
.rounds, .points {
font-size: 15pt;
font-weight: bold;
margin: 10pt;
}
.finalpage, .menupage {
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
align-items: center;
justify-items: center;
}
.finalpage .finalscore {
margin-bottom: 30pt;
margin-top: 60pt;
font-weight: bold;
font-size: 20pt;
}
.menupage form .number {
width: 50pt;
text-align: right;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+15
View File
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/css/stylesheet.css">
</head>
<body class="finalpage">
<div class="finalscore">
Final Score:
{{ points }}/{{ game_length }}
</div>
<form action="/">
<input type="submit" value="Try again" />
</form>
</body>
</html>
+28
View File
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/css/stylesheet.css">
</head>
<body class="mainpage">
<img src="{{ url }}" >
<div class="right">
<div class="stats">
<div class="rounds">
Round {{ i }} of {{ game_length }}
</div>
<div class="points">
{{ points }}/{{ round_n }} points.
</div>
</div>
<form method="post" action="/fontgame?id={{ id }}">
<select name="font">
{% for font in fonts %}
<option>{{ font }}</option>
{% endfor %}
</select>
<input type="hidden" name="id" value="{{ id }}">
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/css/stylesheet.css">
</head>
<body class="menupage">
<h1>Font Game</h1>
<form method="post" action="/startgame">
<label for="game_length">Game rounds:</label>
<input type="number" name="game_length" min=1 class="number" value=10>
<input type="submit" value="Start">
</form>
</body>
</html>