NuCon/nucon/drake.py

100 lines
3.8 KiB
Python
Raw Permalink Normal View History

2024-10-03 23:25:53 +02:00
import os
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
import textwrap
# Get the directory where the script is located
SCRIPT_DIR = Path(__file__).resolve().parent
def get_asset_path(filename):
return str(SCRIPT_DIR / 'drake_assets' / filename)
def fit_text_to_box(draw, text, font, max_width, max_height, line_spacing=1.2):
font_size = 1
while True:
font = ImageFont.truetype(font.path, font_size)
lines = textwrap.wrap(text, width=20)
line_height = font.getbbox("Ay")[3] - font.getbbox("Ay")[1]
total_height = line_height * len(lines) * line_spacing
max_line_width = max(font.getbbox(line)[2] - font.getbbox(line)[0] for line in lines)
if max_line_width > max_width or total_height > max_height:
font_size -= 1
font = ImageFont.truetype(font.path, font_size)
break
font_size += 1
return font, lines
def create_drake_meme(items):
# Load images
no_image = Image.open(get_asset_path('no.jpg'))
yes_image = Image.open(get_asset_path('yes.jpg'))
# Set up meme dimensions
panel_width, panel_height = no_image.size
meme_width = panel_width * 2
meme_height = panel_height * len(items)
# Create meme canvas
meme = Image.new("RGB", (meme_width, meme_height), "white")
# Set up font (use a proper meme font)
font_path = get_asset_path('impact.ttf')
try:
base_font = ImageFont.truetype(font_path, 1)
except OSError:
# Fallback to default font if Impact is not available
base_font = ImageFont.load_default()
for i, (is_yes, text) in enumerate(items):
# Paste the appropriate image
y_offset = i * panel_height
if is_yes:
meme.paste(yes_image, (0, y_offset))
else:
meme.paste(no_image, (0, y_offset))
# Create text panel
text_panel = Image.new("RGB", (panel_width, panel_height), "white")
draw = ImageDraw.Draw(text_panel)
# Fit and draw text
fitted_font, lines = fit_text_to_box(draw, text, base_font, panel_width - 20, panel_height - 20, line_spacing=1.2)
line_height = fitted_font.getbbox("Ay")[3] - fitted_font.getbbox("Ay")[1]
total_height = line_height * len(lines) * 1.2
y_text = (panel_height - total_height) // 2
for line in lines:
bbox = fitted_font.getbbox(line)
text_width = bbox[2] - bbox[0]
x_text = (panel_width - text_width) // 2
draw.text((x_text, y_text), line, font=fitted_font, fill="black")
y_text += line_height * 1.2
# Paste text panel onto meme
meme.paste(text_panel, (panel_width, y_offset))
return meme
default_items = [
(False, "Play Nucleares manually"),
(True, "Automate it with a script"),
(False, "But the web interface is tedious to use"),
(True, "Write an elegant libary to interface with the game and then use that to write the script"),
(False, "But I would still need to write the control policy by hand"),
(True, "Let's extend the libary such that it trains a policy via Reinforcement Learning"),
2024-10-03 23:28:29 +02:00
(False, "But RL takes a huge number of training samples"),
2024-10-03 23:25:53 +02:00
(True, "Extend the libary to also include an efficient simulator"),
(False, "But I don't know what the actual internal dynamics are"),
(True, "Extend the libary once more to also include a neural network dynamics model"),
(True, "And I'm gonna put a drake meme on the README"),
(False, "Online meme generators only support a single yes/no pair"),
(True, "Let's also add a drake meme generator to the libary"),
]
if __name__ == "__main__":
meme = create_drake_meme(default_items)
meme.save("drake_meme.jpg")
print("Meme saved as drake_meme.jpg")