#!/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.basicConfig(level=logging.WARNING, format='[%(levelname)s] %(message)s') 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"""
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()