Retrospect - WSU-4110/FindMySpot GitHub Wiki
Sprint 1: Foundation & Core Data Layer
Focus: Sprint 1 established the foundational infrastructure of FindMySpot. The goal was to get the core data pipeline working end-to-end: a camera detects a license plate, the AI processes it, the result is stored in the database, and a user can search for their vehicle and see its location. Everything downstream in Sprint 2 and Sprint 3 depends on this layer being reliable.
What Went Well
- Observer pattern (parking_observer.py) implemented cleanly with 3 concrete observers and a working demo
- Database schema is well-designed with proper foreign keys, indexes, and CASCADE behavior
- Full pipeline works end-to-end: Python OCR → POST to backend → session in PostgreSQL → locate endpoint returns location
- Three migration files created with both PowerShell and Node.js runner; good developer onboarding
- Camera config file (camera_config.json) created with a clear structure mapping 10 cameras to floors/lots
- Vehicle search falls back to the detected_plates table if no session exists; good resilience thinking
- EasyOCR confidence filtering and blocked words list reduce false positive detections significantly
What Didn't Go Well
- camera_config.json was created but never actually read by app.py — floor/lot are assigned randomly.randint(1,5) instead
- cv2.VideoCapture(0) hardcoded in both app.py and ai-service/api/app.py — Multi-camera support is not wired up
- Confidence score hardcoded to 0.98 in send_parking_checkin() — real EasyOCR confidence never passed to backend TR4. UNCATE TABLE parking_spots, parking_sessions CASCADE runs on Every server starts in db.js — all sessions wiped on restart
- parking_sessions uses VARCHAR(16) for vehicle_plate but user_vehicles allows VARCHAR(20) — schema mismatch
- window_detections list grows unbounded within each 5-second window despite deque being imported but unused
- ROI extracted from grayscale frame But EasyOCR performs better on color input; detection quality unnecessarily reduced
- No migration versioning table; migrations can be re-run, causing constraint errors
Start/ Stop/ Continue
Start
- Reading camera_config.json at startup and using the actual floor/lot for each camera instance.
- Passing real EasyOCR confidence to the backend instead of hardcoding 0.98.
- Using color ROI for EasyOCR instead of grayscale.
- Adding a separate reset-db.js script to initializeDatabase() never TRUNCATEs.
- Using deque(maxlen=50) for window_detection -- its already imported.
- Migration version tracking to prevent duplicate runs.
Stop
- Randomly assigning floor and lot; this breaks the core product feature.
- Running TRUNCATE inside initializeDatabase(); destroys all data on every server restart.
- Hardcoding cv2.VideoCapture(0); ignores all other configured cameras.
- Using VARCHAR(16) for plates in parking_sessions; inconsistent with user_vehicles VARCHAR (20)
- Extracting ROI from a grayscale frame reduces OCR accuracy unnecessarily.
Continue
- Well-structured MVC backend architecture --> routes, controllers, modules clearly separated.
- Observer pattern design --> clean and reusable for future notifications.
- Three- migration structure --> clean and maintainable schema evolution.
- Vote consensus detection --> good noise-reduction for OCR results.
- Detection fallback to detected_plates --> good resilience when the session is missing.
- camera_config.json structure --> well-designed, just needs to be actually used.
Sprint 2
Focus: Sprint 2 built the user-facing layer on top of Sprint 1's data foundation. The focus shifted from internal data processing to interactive features: how users check in manually, how they receive feedback, how occupancy is tracked in real time, and how the system handles time. This sprint also introduced the mobile app UI and the notification banner system.
What Went Well
- Full push notification pipeline working: camera detects plate → DB notification record created → mobile banner shows unread alert
- Stale data fallback in getOccupancyStats(); returns last known stats when DB fails rather than crashing
- Auto-checkout timer implemented in both controllers to prevent sessions from staying open indefinitely
- Mobile app UI is clean and polished with a consistent design system (style.css shared across all pages)
- Parking history page (history.html) merges backend data with local storage entries; good resilience
- vehicles.html implements local + backend merge with deduplication via mergeVehicles()
- Notification bell, unread badge, mark-as-read, and mark-all-read are all working correctly
- sidenav navigation implemented consistently across all pages with a hamburger toggle
- Local storage history capped at 500 entries with slice(0, 500) to prevent overflow
What Didn't Go Well
- Manual check-in posts to /api/detection/record (camera endpoint) instead of /api/parking/checkin — wrong endpoint for user input
- appendLocalParkingHistory() and parkingSet() called BEFORE the API request — failed check-ins appear as successful in history
- Two separate autoCheckoutTimers objects in detectionController.js and parkingController.js — cross-controller Checkouts leave stale timers
- No fetch timeout on findVehicle() — The loading spinner can stay forever if backend hangs
- Notification banner has no auto-dismiss — cycles indefinitely during active camera testing
- check_out_time is always stored as null in local history — history always shows 'Active session' even after checkout
- stale: true flag returned from backend but never checked by any frontend code
- clearMessages() does not clear textContent — stale toast text can reappear
- The spot input form allows values 1–5, but camera_config.json only defines lots 1 and 2 per floor
Start/Stops/Continue
Start
- Posting manual check-in to /api/parking/checkin instead of /api/detection/record
- Writing to local storage only AFTER a confirmed API success response
- Centralizing autoCheckoutTimers into a shared timerService.js module
- Adding AbortController with 10-second timeout to findVehicle() fetch calls
- Checking the stale: true flag in the frontend and showing a 'Data may be outdated' warning
- Auto-dismissing the notification banner after 15 seconds
- Updating check_out_time in local history when backend checkout succeeds
- Restricting spot input to lots 1–2 to match camera_config.json
Stop
- Using the camera detection endpoint for user-initiated manual check-ins
- Writing optimistic local state before API confirmation — creates phantom sessions
- Silently ignoring the stale: true flag from the backend
- Leaving toast textContent populated after clearMessages() — stale text resurfaces
- Running unbounded notification polling with no rate limiting during active detection
Continue
- Clean mobile-first UI design system in style.css; consistent and polished
- Merging backend and local storage data for vehicles and history; good offline resilience
- Notification system architecture; the pipeline from detection to bell icon works well
- Auto-checkout timer concept; right idea, needs centralization
- Stale data fallback for occupancy; correct defensive pattern
- Shared sidenav navigation across all mobile-app pages
- Local storage capping at 500 history entries
Sprint 3
Focus: Sprint 3 completed the feature set with analytics reporting, security flagging, cross-platform data sync, and the full parking session lifecycle. It also covered submission preparation — ensuring the repo was correctly set up, documentation was complete, and the system could be demonstrated end-to-end. This was also the sprint where the majority of bug documentation was completed.
What Went Well
- Analytics report endpoint returns total sessions, completed sessions, average duration, peak hours, and live occupancy snapshot in one response
- SecurityFlag.createIfMissing() pattern prevents duplicate flags for the same session, correctly using OPEN status check 3.isExitEvent() handles both explicit eventType='EXIT' and location-string detection — two layers of exit detection
- Auto-checkout timer gives sessions a maximum 10- minute lifespan — prevents indefinitely open sessions in demo environments 5.test_system.py is a comprehensive integration test covering auth, vehicle registration, detection, history, and notifications
- README has complete installation instructions covering Node.js backend, Python AI service, database setup, and mobile app
- Security flag scan correctly joins parking_sessions with user_vehicles to detect unregistered vehicles
- parking_observer.py delivered a clean, standalone Observer pattern demo with three distinct observer types
What Didn't Go Well
- Security scan endpoint (POST /api/parking/security/scan) has no authentication middleware — anyone can trigger it
- OPEN security flags never resolved when a vehicle checks out — flags accumulate indefinitely
- AUTHORIZATION_DATA_MISSING flag created for every anonymous check-in, including all test/demo vehicles — floods security dashboard
- hours Back cap at 720 hours is silent — no requested Hours field in response to indicate truncation occurred
- averageParkingDurationMinutes returns null when no completed sessions exist, instead of defaulting to 0
- occupancySnapshot in the usage report reflects the current live state, not the historical state for the requested window
- EXIT detection relies on a location string containing 'EXIT' — 'Departure Lane' or 'Gate Out Ramp' would be missed
- closeByExitDetection() returns 201 success even when no active session was found to close
- fms_parking in localStorage never learned on vehicle checkout — stale location shown in offline mode after checkout
- root index.html and mobile-app use completely different localStorage schemas — cross-interface sync not complete
- setup-database.ps1 only runs migrations 001 and 002 — 003_security_flags.sql never referenced in the setup scripts
Start/Stop/Continue
Start
- Adding auth middleware to all admin-only routes (/security/scan, /security/flags, /reports/usage)
- Auto-resolving OPEN security flags in ParkingSession.checkout() when a session ends
- Adding requestedHours to getUsageReport() response so callers know if data was capped
- Defaulting averageParkingDurationMinutes to 0 instead of null when no completed sessions exist
- Deleting fms_parking[plate] from localStorage on confirmed checkout success
- Adding 003_security_flags.sql to setup-database.ps1 so it runs as part of the standard setup
- Writing unit tests with Jest for parking.js model methods (create, checkout, locateVehicle)
- Using INTERVAL '1 hour' * $1 instead of ($1::text || 'hours')::interval for safer SQL
- Unifying the localStorage schema between root index.html and mobile-app into a single shared structure
Stop
- Creating AUTHORIZATION_DATA_MISSING flags for every anonymous check-in — use a time threshold (e.g., parked > 2 hours) instead
- Returning 201 success from closeByExitDetection() when no session was actually closed — use 200 with sessionClosed: false
- Silently capping hours back without informing the caller
- Relying solely on location string keywords for EXIT detection — this is fragile for non-standard camera labels
- Leaving the security scan endpoint completely open without any authentication
- Keeping root index.html as a parallel interface with its own incompatible localStorage schema
Continue
- Analytics report endpoint structure — comprehensive response with metrics, peak hours, and occupancy snapshot
- SecurityFlag.createIfMissing() deduplication pattern — prevents duplicate flags cleanly
- test_system.py integration test suite — run it after every major change
- Safe input bounding with Math.min/Math.max for query parameters
- Two-layer EXIT detection (eventType + location string) — good defense-in-depth, just needs better keywords
- README quality — installation instructions are thorough and cover all components
- Auto-checkout concept via setTimeout — correct approach, centralize the timer map in Sprint 2 fixes