From 26a313c3bfee5b28883a46b16a58551f9a7316ba Mon Sep 17 00:00:00 2001 From: spark Date: Tue, 27 Oct 2026 03:11:16 +0000 Subject: [PATCH] spark: add json-validate.py utility script --- wizard-work/spark/ascii_tool.py | 107 +++++++++++++++++++++++++++++ wizard-work/spark/json-validate.py | 48 +++++++++++++ wizard-work/spark/output_ascii.txt | 9 +++ wizard-work/spark/python_logo.png | Bin 0 -> 15770 bytes 4 files changed, 164 insertions(+) create mode 100644 wizard-work/spark/ascii_tool.py create mode 100644 wizard-work/spark/json-validate.py create mode 100644 wizard-work/spark/output_ascii.txt create mode 100644 wizard-work/spark/python_logo.png 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 0000000000000000000000000000000000000000..d18e7c33a08c7de70fea8fba6c95e03b58c445d6 GIT binary patch literal 15770 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

%%vo>h^nI{q^Tvp@>sLm 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 aguMYVB#h{ks|J>>LDJ$1kZMuGp#KBCRVvQ_ literal 0 HcmV?d00001