diff --git a/nucon/drake.py b/nucon/drake.py new file mode 100644 index 0000000..634853b --- /dev/null +++ b/nucon/drake.py @@ -0,0 +1,99 @@ +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"), + (False, "But RL is takes a huge number of training samples"), + (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") diff --git a/nucon/drake_assets/impact.ttf b/nucon/drake_assets/impact.ttf new file mode 100644 index 0000000..114e6c1 Binary files /dev/null and b/nucon/drake_assets/impact.ttf differ diff --git a/nucon/drake_assets/no.jpg b/nucon/drake_assets/no.jpg new file mode 100644 index 0000000..7c6cdf0 Binary files /dev/null and b/nucon/drake_assets/no.jpg differ diff --git a/nucon/drake_assets/yes.jpg b/nucon/drake_assets/yes.jpg new file mode 100644 index 0000000..bb2fcc7 Binary files /dev/null and b/nucon/drake_assets/yes.jpg differ