Implements template-based project creation allowing teams to start with
professional example code instead of empty projects.
Features:
- Two templates: 'basic' (minimal) and 'testing' (45-test showcase)
- Template variable substitution ({{PROJECT_NAME}}, etc.)
- Template validation with helpful error messages
- `weevil new --list-templates` command
- Template files embedded in binary at compile time
Technical details:
- Templates stored in templates/basic/ and templates/testing/
- Files ending in .template have variables replaced
- Uses include_dir! macro to embed templates in binary
- Returns file count for user feedback
Testing template includes:
- 3 complete subsystems (MotorCycler, WallApproach, TurnController)
- Hardware abstraction layer with mock implementations
- 45 comprehensive tests (unit, integration, system)
- Professional documentation (DESIGN_AND_TEST_PLAN.md, etc.)
Usage:
weevil new my-robot # basic template
weevil new my-robot --template testing # testing showcase
weevil new --list-templates # show available templates
This enables FTC teams to learn from working code and best practices
rather than starting from scratch.
174 lines
5.0 KiB
Markdown
174 lines
5.0 KiB
Markdown
# 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!**
|