# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a novelty Garmin Connect IQ watchface that displays time as decimal day progress (French Revolutionary Time style) instead of traditional 12/24 hour format. The day is divided into 10 equal parts, with time displayed as a decimal from 0.0 to 10.0. **Key Concept**: The watchface converts standard time to decimal using the formula: ``` decimalTime = (hours + minutes/60 + seconds/3600) / 24 * 10 ``` This means: - Midnight (00:00) → 0.0 - 6:00 AM → 2.5 - Noon (12:00) → 5.0 - 6:00 PM → 7.5 - End of day → 10.0 ## Development Commands ### Building the Watchface The project uses the Garmin Connect IQ SDK. You need the SDK installed with `$SDK_PATH` environment variable set. **Build for simulator:** ```bash $SDK_PATH/bin/monkeyc \ -o bin/MetricWatchFace.prg \ -f monkey.jungle \ -y $SDK_PATH/bin/developer_key ``` **Run in simulator:** ```bash $SDK_PATH/bin/connectiq # Then load the generated .prg file in the simulator ``` **Build for specific device (example for Fenix 7):** ```bash $SDK_PATH/bin/monkeyc \ -o bin/MetricWatchFace.prg \ -f monkey.jungle \ -d fenix7 \ -y $SDK_PATH/bin/developer_key ``` **Note**: The project uses `monkey.jungle` for build configuration, which references `manifest.xml` for project settings. ## Architecture ### Core Components **DecimalWatchFaceApp.mc** (`source/DecimalWatchFaceApp.mc:4-23`) - Application entry point extending `Application.AppBase` - Minimal setup - primarily returns the watchface view - No complex application state management **DecimalWatchFaceView.mc** (`source/DecimalWatchFaceView.mc:8-201`) - Main watchface implementation extending `WatchUi.WatchFace` - Handles all rendering and time calculation logic - Key methods: - `onUpdate(dc)` - Main render loop, called every second when active - `computeDecimalTime(clockTime)` - Converts standard time to decimal (0.0-10.0) - `drawWatchFace(dc)` - Renders the analog face with 10 divisions, tick marks, and numbers - `drawHand(dc, decimalTime)` - Draws both hour and minute hands - `drawSingleHand(...)` - Helper for rendering individual hands as filled polygons - `drawDigitalTime(dc, decimalTime)` - Displays decimal time as text ### Rendering Architecture The watchface uses programmatic drawing (no XML layouts). All graphics are drawn using Monkey C Graphics API: 1. **Watchface Circle**: 100 tick marks drawn in a loop (10 major at whole numbers 0-9, 90 minor at 0.1 intervals) 2. **Two Hands**: - **Hour hand** (red, shorter, wider): Shows which decimal unit (0-9), completes one rotation per day - **Minute hand** (white, longer, thinner): Shows fractional part within current decimal unit, completes 10 rotations per day 3. **Digital Display**: Shows exact decimal time at bottom (formatted to 2 decimal places) The hand rotation uses trigonometry with angles calculated from decimal time, offset by -90° to start at top (12 o'clock position). ### Device Support The manifest (`manifest.xml`) targets 57 modern Garmin devices including: - Fenix series (6, 7, 8, Epix 2) - Forerunner series (255, 265, 645, 945, 955, 965, 970) - Vivoactive series (3, 4, 5, 6) - Venu series (2 Plus, 3, 4) All devices require Connect IQ API level 3.2.0 or higher. ## Project Structure ``` MetricWatchFace/ ├── manifest.xml # App metadata, device compatibility ├── monkey.jungle # Build configuration ├── source/ │ ├── DecimalWatchFaceApp.mc # Application entry point │ └── DecimalWatchFaceView.mc # Main watchface view and rendering └── resources/ ├── drawables/ │ ├── drawables.xml # Drawable resource definitions │ └── launcher_icon.png # App icon (placeholder) └── strings/ └── strings.xml # Localized strings ``` ## Important Implementation Details ### Time Calculation Edge Cases - The decimal time formula ensures smooth progression from 0.0 to 10.0 - The fractional part extraction (`decimalTime - decimalTime.toNumber()`) is used for the minute hand - Both hands update every second when the watchface is active ### Drawing Performance - The watchface redraws completely on each `onUpdate()` call - 100 tick marks are drawn in every frame (major optimization opportunity) - Hands are drawn as filled polygons using triangle geometry - Center dot is redrawn after hands to ensure it's on top ### Sleep Mode Handling - `onEnterSleep()` and `onExitSleep()` are currently empty - In sleep mode, the system reduces update frequency automatically - Consider implementing reduced complexity rendering for sleep mode ## Known Technical Debt From IMPROVEMENT_IDEAS.md: - Launcher icon is currently a placeholder PNG - No screen type optimization (MIP vs AMOLED) - No low power mode implementation - Hand polygon drawing could be optimized - No error handling for edge cases - No unit tests for time conversion ## Monkey C Specifics **Language**: Monkey C (Garmin's proprietary language, similar to Java/C) **Key APIs used**: - `Toybox.WatchUi.WatchFace` - Base class for watchfaces - `Toybox.Graphics` - Drawing primitives (drawLine, fillPolygon, drawText, etc.) - `Toybox.System` - System functions (getClockTime) - `Toybox.Time` / `Toybox.Time.Gregorian` - Time utilities - `Toybox.Lang` / `Toybox.Math` - Language and math utilities **Common patterns**: - Drawing context (`dc`) is passed to all render methods - Colors use `Graphics.COLOR_*` constants - Coordinates are in pixels, origin at top-left - All trigonometry uses radians (convert with `Math.toRadians()`)