diff --git a/ham-test-www.py b/ham-test-www.py new file mode 100644 index 0000000..af46d4f --- /dev/null +++ b/ham-test-www.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +# Description: A Python script that generates a HAM Operator Test in a web browser. +# Usage: python3 ham-test-www.py +# Author: Justin Oros + +import json +import os +import requests +import logging +import webbrowser +from datetime import datetime + +# Logging +logging.basicConfig(level=logging.WARNING, format='[%(levelname)s] %(message)s') + +# Test URLs and local filenames +URLS = { + "Technician": "https://raw.githubusercontent.com/russolsen/ham_radio_question_pool/master/technician-2022-2026/technician.json", + "General": "https://raw.githubusercontent.com/russolsen/ham_radio_question_pool/master/general-2023-2027/general.json", + "Extra": "https://raw.githubusercontent.com/russolsen/ham_radio_question_pool/master/extra-2024-2028/extra.json" +} + +LOCAL_FILES = { + "Technician": "technician.json", + "General": "general.json", + "Extra": "extra.json" +} + +def get_remote_last_modified(url): + try: + r = requests.head(url, timeout=10) + if r.status_code == 200 and 'Last-Modified' in r.headers: + dt = datetime.strptime(r.headers['Last-Modified'], '%a, %d %b %Y %H:%M:%S %Z') + return dt.timestamp() + except Exception as e: + logging.warning(f"Could not fetch Last-Modified for {url}: {e}") + return None + +def download_file(url, local_path): + print(f"Downloading {url} ...") + r = requests.get(url, timeout=20) + r.raise_for_status() + with open(local_path, 'w', encoding='utf-8') as f: + f.write(r.text) + print(f"Saved to {local_path}") + +def sync_files(): + for name, url in URLS.items(): + local = LOCAL_FILES[name] + remote_ts = get_remote_last_modified(url) + if remote_ts is None: + if not os.path.exists(local): + download_file(url, local) + else: + print(f"Skipping update for {name} (no remote timestamp)") + elif not os.path.exists(local) or os.path.getmtime(local) < remote_ts: + download_file(url, local) + else: + print(f"{local} is up to date.") + +def load_all_questions(): + all_questions = {} + for name, path in LOCAL_FILES.items(): + with open(path, 'r', encoding='utf-8') as f: + all_questions[name] = json.load(f) + return all_questions + +def generate_html(questions): + options_html = "\n".join(f'' for name in questions) + data_json = json.dumps(questions) + + html = f""" + + + + HAM Radio Test + + + +

HAM Radio Test

+

Select a test pool:

+ + + + + + + + +""" + return html + +def write_html_file(content, filename="ham-test.html"): + with open(filename, "w", encoding="utf-8") as f: + f.write(content) + print(f"HTML quiz written to: {filename}") + webbrowser.open(f"file://{os.path.abspath(filename)}") + +def main(): + print("Syncing questions...") + sync_files() + print("Loading questions...") + questions = load_all_questions() + html = generate_html(questions) + write_html_file(html) + +if __name__ == "__main__": + main() +