# Imperial Units Implementation ## Overview The application automatically selects between metric and imperial (USCS) units based on the request context, matching the behavior of the original Python implementation. ## Unit Selection Priority The system determines which units to use in the following priority order: 1. **Explicit query parameter** (highest priority) - `?u` - Force imperial units (°F, mph, inches, inHg) - `?m` - Force metric units (°C, km/h, mm, hPa) 2. **Language parameter** - `?lang=us` - Use imperial units (for us.wttr.in subdomain) 3. **Client IP geolocation** - Requests from US IP addresses automatically use imperial units - Uses GeoIP database to detect country code 4. **Default** - Metric units for all other cases ## Implementation Details ### Code Changes 1. **GeoIP Module** (`src/location/geoip.zig`) - Added `isUSIP()` method to detect US IP addresses - Queries MaxMind database for country ISO code - Returns `true` if country code is "US" 2. **Handler** (`src/http/handler.zig`) - Added `geoip` to `HandleWeatherOptions` - Implements priority logic for unit selection - Extracts client IP from headers (X-Forwarded-For, X-Real-IP) - Passes `use_imperial` flag to all renderers 3. **Renderers** (all updated to support imperial units) - `ansi.zig` - Shows °F instead of °C - `line.zig` - Shows °F and mph for formats 1-4 - `custom.zig` - Converts all units (temp, wind, precip, pressure) - `v2.zig` - Shows imperial units in detailed format - `json.zig` - Already outputs both units (no changes needed) ### Conversions - Temperature: `°F = °C × 9/5 + 32` - Wind speed: `mph = km/h × 0.621371` - Precipitation: `inches = mm × 0.0393701` - Pressure: `inHg = hPa × 0.02953` ## Testing ### Unit Tests All renderers have unit tests verifying imperial units: - `test "render with imperial units"` in ansi.zig - `test "format 2 with imperial units"` in line.zig - `test "render custom format with imperial units"` in custom.zig - `test "render v2 format with imperial units"` in v2.zig - `test "imperial units selection logic"` in handler.zig - `test "isUSIP detects US IPs"` in geoip.zig ### Integration Testing ```bash # Test with lang=us curl "http://localhost:8002/London?lang=us&format=2" # Output: 51.5074,-0.1278: ☁️ 54°F 🌬️SW19mph # Test with explicit ?u curl "http://localhost:8002/London?format=2&u" # Output: 51.5074,-0.1278: ☁️ 54°F 🌬️SW19mph # Test metric override curl "http://localhost:8002/London?lang=us&format=2&m" # Output: 51.5074,-0.1278: ☁️ 12°C 🌬️SW30km/h # Test from US IP (automatic detection) curl -H "X-Forwarded-For: 1.1.1.1" "http://localhost:8002/London?format=2" # Output: Uses imperial as 1.1.1.1 is detected as US IP ``` ## Documentation Updates - **API_ENDPOINTS.md** - Added "Unit System Defaults" section explaining priority - **README.md** - Updated "Implemented Features" to mention auto-detection - **IMPERIAL_UNITS.md** - This document ## Compatibility This implementation matches the original Python behavior in `lib/parse_query.py`: - Same priority order - Same detection logic - Same unit conversions - Compatible with existing clients and scripts