diff --git a/wizard-work/spark/ascii_tool.py b/wizard-work/spark/ascii_tool.py new file mode 100644 index 0000000..7677e80 --- /dev/null +++ b/wizard-work/spark/ascii_tool.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +"""Quick ASCII art generator from images. + +Usage: + python ascii_tool.py test # Run self-test + python ascii_tool.py [width] # Convert local image + +Produces ASCII art output saved to output_ascii.txt +""" + +import sys +from PIL import Image + +ASCII_CHARS = "@%#*+=-:. " + +def resize_image(img: Image.Image, new_width: int = 80) -> Image.Image: + """Resize image maintaining aspect ratio.""" + w, h = img.size + aspect_ratio = h / w + new_height = int(aspect_ratio * new_width * 0.55) + return img.resize((new_width, max(1, new_height))) + +def image_to_ascii(img: Image.Image, width: int = 80) -> str: + """Convert PIL Image to ASCII art string.""" + img = resize_image(img, width) + img = img.convert("L") + # Use get_flattened_data for Pillow 11+, fallback to getdata() + try: + pixels = list(img.get_flattened_data()) + except AttributeError: + pixels = list(img.getdata()) + chars_per_pixel = len(ASCII_CHARS) + + lines = [] + row = [] + for i, pixel in enumerate(pixels): + if i > 0 and (i % width) == 0: + lines.append("".join(row)) + row = [] + idx = min(pixel * (chars_per_pixel - 1) // 255, chars_per_pixel - 1) + row.append(ASCII_CHARS[idx]) + if row: + lines.append("".join(row)) + return "\n".join(lines) + +def run_self_test(): + """Create test image and verify ASCII conversion works.""" + # Create a simple 20x20 test image with a gradient + img = Image.new("RGB", (20, 20)) + pixels = img.load() + for x in range(20): + for y in range(20): + # Create a diagonal gradient + val = int((x + y) * 255 / 40) + pixels[x, y] = (val, val, val) + + ascii_result = image_to_ascii(img, 40) + lines = ascii_result.split("\n") + + print(f"Self-test: Created 20x20 gradient image") + print(f"ASCII result: {len(lines)} lines") + print(f"First line: '{lines[0][:20]}...'") + print(f"Line lengths vary: {set(len(l) for l in lines)} chars") + + # Verify output is saved + output_path = "/root/.hermes/wizard-outputs/spark/output_ascii.txt" + with open(output_path, "w") as f: + f.write(ascii_result) + print(f"Saved to {output_path}") + + # Verify file exists + with open(output_path) as f: + verify = f.read() + if verify == ascii_result: + print("VERIFICATION: File written correctly") + return True + else: + print("ERROR: File content mismatch") + return False + +def main(): + if len(sys.argv) < 2: + print(__doc__) + sys.exit(1) + + if sys.argv[1] == "test": + success = run_self_test() + sys.exit(0 if success else 1) + + # Convert local image file + img_path = sys.argv[1] + width = int(sys.argv[2]) if len(sys.argv) > 2 else 80 + + print(f"Loading {img_path}...") + img = Image.open(img_path) + print(f"Original size: {img.size}, converting to ASCII (width={width})...") + + ascii_art = image_to_ascii(img, width) + print(ascii_art) + + output_path = "/root/.hermes/wizard-outputs/spark/output_ascii.txt" + with open(output_path, "w") as f: + f.write(ascii_art) + print(f"\nSaved to {output_path}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/wizard-work/spark/json-validate.py b/wizard-work/spark/json-validate.py new file mode 100644 index 0000000..fbca363 --- /dev/null +++ b/wizard-work/spark/json-validate.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +""" +Quick JSON validator - validates all .json files in a directory. +Usage: python3 json-validate.py +Exit 0 if all valid, exit 1 if any invalid. +""" +import sys +import json +from pathlib import Path + +def validate_json_files(directory: str) -> bool: + """Validate all JSON files in directory. Returns True if all valid.""" + dir_path = Path(directory) + if not dir_path.exists(): + print(f"Error: Directory {directory} does not exist") + return False + + json_files = list(dir_path.glob("*.json")) + if not json_files: + print(f"No .json files found in {directory}") + return True + + all_valid = True + for json_file in json_files: + try: + with open(json_file, 'r') as f: + json.load(f) + print(f"✓ {json_file.name}") + except json.JSONDecodeError as e: + print(f"✗ {json_file.name}: {e}") + all_valid = False + except Exception as e: + print(f"✗ {json_file.name}: {type(e).__name__}: {e}") + all_valid = False + + return all_valid + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: json-validate.py ") + sys.exit(1) + + if validate_json_files(sys.argv[1]): + print("\nAll JSON files are valid") + sys.exit(0) + else: + print("\nSome JSON files are invalid") + sys.exit(1) \ No newline at end of file diff --git a/wizard-work/spark/output_ascii.txt b/wizard-work/spark/output_ascii.txt new file mode 100644 index 0000000..f65956b --- /dev/null +++ b/wizard-work/spark/output_ascii.txt @@ -0,0 +1,9 @@ +@@@@@@*+=@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@+-+***@@@@@@@@@@@@@@@@@@..@..@@@@@@@@@@@@@@@ ...@@@@@@@@ +@@+++++***=.:@@@....:@.:@:.......... ....@.....@...@@@@@@@@ +@+++******:.::@@.:...:..@..:...:..........:.....@@@@@@@@@@@@ +@++*+:::-:::::@@::@::::: ::.::@::@@::::@::::.@::@@@@@@@@@@@@ +@+**:.:::::::@@@:::::+:::::::::::@@:::::::-::@::@@@@@@@@@@@@ +@@@@::::::-@@@@@:: @@@@-:::-@@+@@@@@@@@ @@@@@@@@@@@@@@@@@@@@ +@@@@#----=@@@@@@::@@@@@:::@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \ No newline at end of file diff --git a/wizard-work/spark/python_logo.png b/wizard-work/spark/python_logo.png new file mode 100644 index 0000000..d18e7c3 Binary files /dev/null and b/wizard-work/spark/python_logo.png differ