# Quick Reference Guide ## Project Commands ### Testing (Windows JRE - No Robot Needed) ```bash gradlew test # Run all tests gradlew test --tests MotorCyclerTest # Run specific test ``` ### Building for Robot ```bash build.bat # Build APK (Windows) ./build.sh # Build APK (Linux/Mac) ``` ### Deployment ```bash deploy.bat # Deploy to robot (Windows) ./deploy.sh # Deploy to robot (Linux/Mac) ``` ## Project Structure Quick View ``` my-robot/ │ ├── src/main/java/robot/ │ ├── hardware/ # Hardware abstractions │ │ ├── MotorController.java [Interface - No FTC deps] │ │ └── FtcMotorController.java [FTC SDK wrapper] │ │ │ ├── subsystems/ # Business logic │ │ └── MotorCycler.java [Pure Java - Testable!] │ │ │ └── opmodes/ # FTC integration │ └── MotorCycleOpMode.java [Glue code] │ ├── src/test/java/robot/ │ ├── hardware/ │ │ └── MockMotorController.java [Test mock] │ └── subsystems/ │ └── MotorCyclerTest.java [Unit tests] │ ├── build.gradle.kts # Build configuration ├── build.bat / build.sh # Build scripts └── deploy.bat / deploy.sh # Deploy scripts ``` ## Code Flow 1. **OpMode starts** → Creates FtcMotorController from hardware map 2. **OpMode.init()** → Creates MotorCycler, passes controller 3. **OpMode.loop()** → Calls motorCycler.update(currentTime) 4. **MotorCycler** → Updates state, controls motor via interface 5. **MotorController** → Abstraction hides whether it's real or mock ## Testing Flow 1. **Test creates** → MockMotorController 2. **Test creates** → MotorCycler with mock 3. **Test calls** → motorCycler.init() 4. **Test calls** → motorCycler.update() with simulated time 5. **Test verifies** → Mock motor received correct commands ## Key Design Patterns ### Dependency Injection ```java // Good: Pass dependencies in constructor MotorCycler cycler = new MotorCycler(motorController, 2000, 1000); // Bad: Create dependencies internally // class MotorCycler { // DcMotor motor = hardwareMap.get(...); // Hard to test! // } ``` ### Interface Abstraction ```java // Good: Program to interface MotorController motor = new FtcMotorController(dcMotor); // Bad: Program to implementation // FtcMotorController motor = new FtcMotorController(dcMotor); ``` ### Time-Based State Machine ```java // Good: Pass time as parameter (testable) void update(long currentTimeMs) { ... } // Bad: Read time internally (hard to test) // void update() { // long time = System.currentTimeMillis(); // } ``` ## Common Tasks ### Add a New Subsystem 1. Create interface in `hardware/` (e.g., `ServoController.java`) 2. Create FTC implementation (e.g., `FtcServoController.java`) 3. Create business logic in `subsystems/` (e.g., `ClawController.java`) 4. Create mock in `test/hardware/` (e.g., `MockServoController.java`) 5. Create tests in `test/subsystems/` (e.g., `ClawControllerTest.java`) 6. Wire into OpMode ### Run a Specific Test ```bash gradlew test --tests "MotorCyclerTest.testFullCycle" ``` ### Debug Test Failure 1. Look at test output (shows which assertion failed) 2. Check expected vs actual values 3. Add println() to MotorCycler if needed 4. Re-run test instantly (no robot deploy needed!) ### Modify Timing Edit MotorCycleOpMode.java line 20: ```java // Change from 2000, 1000 to whatever you want motorCycler = new MotorCycler(motorController, 2000, 1000, 0.5); // ^^^^ ^^^^ ^^^ // on-ms off-ms power ``` ## Hardware Configuration Your FTC Robot Configuration needs: - **One DC Motor** named `"motor"` (exact spelling matters!) ## Troubleshooting ### "Could not find motor" → Check hardware configuration has motor named "motor" ### "Tests won't run" → Make sure you're using `gradlew test` not `gradlew build` → Tests run on PC, build needs FTC SDK ### "Build can't find FTC SDK" → Check `.weevil.toml` has correct `ftc_sdk_path` → Run `weevil init` if SDK is missing ### "Motor not cycling" → Check OpMode is selected and started on Driver Station → Verify motor is plugged in and configured correctly ## Learning More - Read `ARCHITECTURE.md` for deep dive into design decisions - Read `README.md` for overview - Look at tests to see how each component works - Modify values and re-run tests to see behavior change ## Best Practices ✓ Write tests first (they're fast!) ✓ Keep subsystems independent ✓ Use interfaces for hardware ✓ Pass time as parameters ✓ Mock everything external ✗ Don't put hardware maps in subsystems ✗ Don't read System.currentTimeMillis() in logic ✗ Don't skip tests ✗ Don't mix hardware and logic code --- **Remember: Test locally, deploy confidently!**