Compare commits
No commits in common. "9b62a141faf41e058d2def50e0dce90fe91ffca9" and "f467e9cbcb03251f11f3816e17ad145792d29ce0" have entirely different histories.
9b62a141fa
...
f467e9cbcb
35
README.md
35
README.md
@ -260,38 +260,3 @@ What? Why would you wanna cite it? What are you even doing?
|
|||||||
year = {2024},
|
year = {2024},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
![NuCon Meme](README_meme.jpg)
|
|
||||||
|
|
||||||
To use you'll need to install the following packages:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install pillow
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from nucon.drake import create_drake_meme
|
|
||||||
|
|
||||||
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"),
|
|
||||||
]
|
|
||||||
|
|
||||||
meme = create_drake_meme(items)
|
|
||||||
meme.save("README_meme.jpg")
|
|
||||||
```
|
|
BIN
README_meme.jpg
BIN
README_meme.jpg
Binary file not shown.
Before Width: | Height: | Size: 753 KiB |
@ -1,99 +0,0 @@
|
|||||||
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")
|
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 44 KiB |
Binary file not shown.
Before Width: | Height: | Size: 49 KiB |
@ -29,12 +29,3 @@ Homepage = "https://git.dominik-roth.eu/dodox/nucon"
|
|||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev = ["pytest"]
|
dev = ["pytest"]
|
||||||
rl = ["gymnasium", "numpy"]
|
|
||||||
model = ["torch", "numpy"]
|
|
||||||
drake = ["Pillow"]
|
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
|
||||||
"nucon" = ["drake_assets/*"]
|
|
||||||
|
|
||||||
[tool.setuptools]
|
|
||||||
include-package-data = true
|
|
Loading…
Reference in New Issue
Block a user