package com.auction; import org.opencv.core.Core; /** * Main entry point for Troostwijk Auction Monitor. * * ARCHITECTURE: * This project focuses on: * 1. Image processing and object detection * 2. Bid monitoring and notifications * 3. Data enrichment * * Auction/Lot scraping is handled by the external ARCHITECTURE-TROOSTWIJK-SCRAPER process. * That process populates the auctions and lots tables in the shared database. * This process reads from those tables and enriches them with: * - Downloaded images * - Object detection labels * - Bid monitoring * - Notifications */ public class Main { public static void main(String[] args) throws Exception { Console.println("=== Troostwijk Auction Monitor ===\n"); // Parse command line arguments String mode = args.length > 0 ? args[0] : "workflow"; // Configuration - Windows paths String databaseFile = System.getenv().getOrDefault("DATABASE_FILE", "C:\\mnt\\okcomputer\\output\\cache.db"); String notificationConfig = System.getenv().getOrDefault("NOTIFICATION_CONFIG", "desktop"); // YOLO model paths (optional - monitor works without object detection) String yoloCfg = "models/yolov4.cfg"; String yoloWeights = "models/yolov4.weights"; String yoloClasses = "models/coco.names"; // Load native OpenCV library (only if models exist) try { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); Console.println("āœ“ OpenCV loaded"); } catch (UnsatisfiedLinkError e) { Console.println("āš ļø OpenCV not available - image detection disabled"); } switch (mode.toLowerCase()) { case "workflow": runWorkflowMode(databaseFile, notificationConfig, yoloCfg, yoloWeights, yoloClasses); break; case "once": runOnceMode(databaseFile, notificationConfig, yoloCfg, yoloWeights, yoloClasses); break; case "legacy": runLegacyMode(databaseFile, notificationConfig, yoloCfg, yoloWeights, yoloClasses); break; case "status": showStatus(databaseFile, notificationConfig, yoloCfg, yoloWeights, yoloClasses); break; default: showUsage(); break; } } /** * WORKFLOW MODE: Run orchestrated scheduled workflows (default) * This is the recommended mode for production use. */ private static void runWorkflowMode(String dbPath, String notifConfig, String yoloCfg, String yoloWeights, String yoloClasses) throws Exception { Console.println("šŸš€ Starting in WORKFLOW MODE (Orchestrated Scheduling)\n"); WorkflowOrchestrator orchestrator = new WorkflowOrchestrator( dbPath, notifConfig, yoloCfg, yoloWeights, yoloClasses ); // Show initial status orchestrator.printStatus(); // Start all scheduled workflows orchestrator.startScheduledWorkflows(); Console.println("āœ“ All workflows are running"); Console.println(" - Scraper import: every 30 min"); Console.println(" - Image processing: every 1 hour"); Console.println(" - Bid monitoring: every 15 min"); Console.println(" - Closing alerts: every 5 min"); Console.println("\nPress Ctrl+C to stop.\n"); // Add shutdown hook Runtime.getRuntime().addShutdownHook(new Thread(() -> { Console.println("\nšŸ›‘ Shutdown signal received..."); orchestrator.shutdown(); })); // Keep application alive try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException e) { Thread.currentThread().interrupt(); orchestrator.shutdown(); } } /** * ONCE MODE: Run complete workflow once and exit * Useful for cron jobs or scheduled tasks. */ private static void runOnceMode(String dbPath, String notifConfig, String yoloCfg, String yoloWeights, String yoloClasses) throws Exception { Console.println("šŸ”„ Starting in ONCE MODE (Single Execution)\n"); WorkflowOrchestrator orchestrator = new WorkflowOrchestrator( dbPath, notifConfig, yoloCfg, yoloWeights, yoloClasses ); orchestrator.runCompleteWorkflowOnce(); Console.println("āœ“ Workflow execution completed. Exiting.\n"); } /** * LEGACY MODE: Original monitoring approach * Kept for backward compatibility. */ private static void runLegacyMode(String dbPath, String notifConfig, String yoloCfg, String yoloWeights, String yoloClasses) throws Exception { Console.println("āš™ļø Starting in LEGACY MODE\n"); var monitor = new TroostwijkMonitor(dbPath, notifConfig, yoloCfg, yoloWeights, yoloClasses); Console.println("\nšŸ“Š Current Database State:"); monitor.printDatabaseStats(); Console.println("\n[1/2] Processing images..."); monitor.processPendingImages(); Console.println("\n[2/2] Starting bid monitoring..."); monitor.scheduleMonitoring(); Console.println("\nāœ“ Monitor is running. Press Ctrl+C to stop.\n"); Console.println("NOTE: This process expects auction/lot data from the external scraper."); Console.println(" Make sure ARCHITECTURE-TROOSTWIJK-SCRAPER is running and populating the database.\n"); try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException e) { Thread.currentThread().interrupt(); Console.println("Monitor interrupted, exiting."); } } /** * STATUS MODE: Show current status and exit */ private static void showStatus(String dbPath, String notifConfig, String yoloCfg, String yoloWeights, String yoloClasses) throws Exception { Console.println("šŸ“Š Checking Status...\n"); WorkflowOrchestrator orchestrator = new WorkflowOrchestrator( dbPath, notifConfig, yoloCfg, yoloWeights, yoloClasses ); orchestrator.printStatus(); } /** * Show usage information */ private static void showUsage() { Console.println("Usage: java -jar troostwijk-monitor.jar [mode]\n"); Console.println("Modes:"); Console.println(" workflow - Run orchestrated scheduled workflows (default)"); Console.println(" once - Run complete workflow once and exit (for cron)"); Console.println(" legacy - Run original monitoring approach"); Console.println(" status - Show current status and exit"); Console.println("\nEnvironment Variables:"); Console.println(" DATABASE_FILE - Path to SQLite database"); Console.println(" (default: C:\\mnt\\okcomputer\\output\\cache.db)"); Console.println(" NOTIFICATION_CONFIG - 'desktop' or 'smtp:user:pass:email'"); Console.println(" (default: desktop)"); Console.println("\nExamples:"); Console.println(" java -jar troostwijk-monitor.jar workflow"); Console.println(" java -jar troostwijk-monitor.jar once"); Console.println(" java -jar troostwijk-monitor.jar status"); IO.println(); } /** * Alternative entry point for container environments. * Simply keeps the container alive for manual commands. */ public static void main2(String[] args) { if (args.length > 0) { Console.println("Command mode - exiting to allow shell commands"); return; } Console.println("Troostwijk Monitor container is running and healthy."); Console.println("Use 'docker exec' or 'dokku run' to execute commands."); try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException e) { Thread.currentThread().interrupt(); Console.println("Container interrupted, exiting."); } } }