refactor: extract lib.rs, remove club module, add bounded concurrency
- Extract shared types (Car, BestCarRecord, AnalysisContext) into src/lib.rs - Replace global static BEST_CARS with injected AnalysisContext for testability - Add semaphore-bounded concurrency (limit 20) in parse_all_times() - Replace hardcoded track name match with track_names.json loaded via include_str! - Replace magic number 115 with const MAX_RQ: u8 = 113 - Improve floating-point tie comparison with TIME_TOLERANCE (5ms) constant - Remove src/club.rs binary (topdrives.club no longer maintained) - Remove scraper dependency from Cargo.toml - Remove tracks.txt (replaced by track_names.json) - Remove empty/placeholder test bodies - Improve error handling in get_file() for response body read - Add load_my_cars_data() combining owned + wishlist extraction in one I/O - Update CHANGELOG, README, and all docs to reflect changes
This commit is contained in:
parent
6a68469239
commit
89fa69e3c8
14 changed files with 874 additions and 2037 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## System Overview
|
||||
|
||||
The Top Drives Records Analyzer consists of two main components working together to provide comprehensive car performance analysis for the Top Drives racing game.
|
||||
The Top Drives Records Analyzer consists of a main analysis binary and a shared library working together to provide comprehensive car performance analysis for the Top Drives racing game.
|
||||
|
||||
## Component Architecture
|
||||
|
||||
|
|
@ -16,6 +16,9 @@ The Top Drives Records Analyzer consists of two main components working together
|
|||
- **Performance Analysis**: Compares timing data across RQ ranges and track conditions
|
||||
- **Collection Management**: Identifies owned cars and optimization opportunities
|
||||
|
||||
#### Key Constants
|
||||
- `MAX_RQ: u8 = 113` — Maximum RQ level used for range analysis (replaces former magic number 115)
|
||||
|
||||
#### Data Flow
|
||||
|
||||
```
|
||||
|
|
@ -32,28 +35,17 @@ User Collection (my_cars.json)
|
|||
Output: CSV/Terminal Results
|
||||
```
|
||||
|
||||
### 2. Club Module (`src/club.rs`)
|
||||
### 2. Shared Library (`src/lib.rs`)
|
||||
|
||||
**Alternative data source** that scrapes live data from topdrives.club website.
|
||||
**Common utilities** shared across the project.
|
||||
|
||||
#### Key Responsibilities
|
||||
- **Web Scraping**: Fetches HTML content from topdrives.club
|
||||
- **HTML Parsing**: Extracts car performance data using CSS selectors
|
||||
- **Real-time Data**: Provides fresh data without pre-downloaded files
|
||||
- **Track Name Translation**: Converts track codes to human-readable names via `translate_track_name()`
|
||||
- **Track Type Translation**: Converts condition codes to surface descriptions via `translate_track_type()`
|
||||
|
||||
#### Data Flow
|
||||
|
||||
```
|
||||
topdrives.club Website
|
||||
↓
|
||||
HTML Content
|
||||
↓
|
||||
CSS Selector Parsing
|
||||
↓
|
||||
Car Data Extraction
|
||||
↓
|
||||
Output: Terminal Results
|
||||
```
|
||||
#### Configuration
|
||||
- Track name mappings are loaded from `track_names.json` at compile time using `include_str!`
|
||||
- This external config file maps track codes (e.g., `"laguna"`) to human-readable names (e.g., `"Laguna Seca"`)
|
||||
|
||||
## Data Structures
|
||||
|
||||
|
|
@ -69,7 +61,7 @@ type TripletKey = (String, u8, String);
|
|||
**Purpose**: Composite key for uniquely identifying track conditions
|
||||
**Usage**: HashMap key for storing best car records
|
||||
|
||||
#### Car (Records Module)
|
||||
#### Car
|
||||
```rust
|
||||
struct Car {
|
||||
rid: String, // Repository ID
|
||||
|
|
@ -97,18 +89,6 @@ struct BestCarRecord {
|
|||
}
|
||||
```
|
||||
|
||||
#### Car (Club Module)
|
||||
```rust
|
||||
struct Car {
|
||||
class: String, // Class letter (S, A, B, etc.)
|
||||
rq: u8, // Rarity level
|
||||
manufacturer: String, // Brand
|
||||
model: String, // Model
|
||||
year: u16, // Year
|
||||
upgrade: String, // Upgrade config
|
||||
}
|
||||
```
|
||||
|
||||
## Global State Management
|
||||
|
||||
### BEST_CARS Cache
|
||||
|
|
@ -127,7 +107,7 @@ static BEST_CARS: Lazy<Mutex<HashMap<TripletKey, Vec<BestCarRecord>>>>
|
|||
The system analyzes car performance across multiple RQ brackets:
|
||||
|
||||
1. **Base RQ**: Car's natural rarity level
|
||||
2. **RQ Range**: Tests from car's RQ up to maximum (115)
|
||||
2. **RQ Range**: Tests from car's RQ up to `MAX_RQ` (113)
|
||||
3. **Cross-RQ Competition**: Allows cars to compete above their base level
|
||||
|
||||
**Example**: A RQ 85 car might perform well at RQ 90-95 levels against higher-rated cars
|
||||
|
|
@ -142,9 +122,9 @@ Multiple validation layers ensure data quality:
|
|||
|
||||
### Concurrent Processing
|
||||
|
||||
#### Records Module
|
||||
#### Bounded Concurrency Pattern
|
||||
- **Task Spawning**: One async task per car file
|
||||
- **Rate Limiting**: Semaphore limits concurrent downloads (20 max)
|
||||
- **Semaphore**: Limits concurrent operations to 20 (bounded concurrency)
|
||||
- **Error Isolation**: Individual car failures don't stop batch processing
|
||||
|
||||
#### Synchronization
|
||||
|
|
@ -157,6 +137,7 @@ Multiple validation layers ensure data quality:
|
|||
```
|
||||
├── cars_repo.json # Car database from repository
|
||||
├── tracks_repo.json # Track definitions
|
||||
├── track_names.json # Track code → name mappings (compiled in)
|
||||
├── my_cars.json # User's car collection (game export)
|
||||
└── times/ # Individual car timing files
|
||||
├── Ferrari_F40_1987.json
|
||||
|
|
@ -167,8 +148,13 @@ Multiple validation layers ensure data quality:
|
|||
### Output Files
|
||||
```
|
||||
├── best.csv # Best cars analysis results
|
||||
├── missing.csv # Missing recommended cars
|
||||
└── details.csv # Detailed timing data
|
||||
├── details.csv # Detailed timing data
|
||||
├── add.csv # Cars to add to wishlist
|
||||
├── remove.csv # Cars to remove from wishlist
|
||||
├── trash.csv # Owned cars safe to remove
|
||||
├── sorted.csv # Best cars sorted by count
|
||||
├── very_best.csv # Best cars with count ≥ 10
|
||||
└── wishlist.csv # Missing cars already on wishlist
|
||||
```
|
||||
|
||||
## Performance Characteristics
|
||||
|
|
@ -178,12 +164,7 @@ Multiple validation layers ensure data quality:
|
|||
- **Memory Usage**: Moderate (loads all timing data into memory)
|
||||
- **Accuracy**: High (comprehensive dataset)
|
||||
- **Update Frequency**: Manual refresh required
|
||||
|
||||
### Club Module
|
||||
- **Startup Time**: Slow (web scraping required)
|
||||
- **Memory Usage**: Low (processes one track at a time)
|
||||
- **Accuracy**: Variable (depends on website structure)
|
||||
- **Update Frequency**: Real-time on each run
|
||||
- **Concurrency**: Bounded at 20 simultaneous operations via semaphore
|
||||
|
||||
## Error Handling Strategy
|
||||
|
||||
|
|
@ -195,13 +176,12 @@ Multiple validation layers ensure data quality:
|
|||
### User Feedback
|
||||
- **Progress Indication**: Shows fetching/download progress
|
||||
- **Error Messages**: Clear descriptions of what went wrong
|
||||
- **Fallback Options**: Multiple data sources available
|
||||
|
||||
## Extension Points
|
||||
|
||||
### Adding New Tracks
|
||||
1. Update `tracks_repo.json` with new track definitions
|
||||
2. Add track name mappings in `translate_track_name()`
|
||||
2. Add track name mapping in `track_names.json`
|
||||
3. Add condition mappings in `translate_track_type()`
|
||||
|
||||
### Adding New Analysis Types
|
||||
|
|
@ -209,17 +189,12 @@ Multiple validation layers ensure data quality:
|
|||
2. Add command parsing in main function
|
||||
3. Update help text and documentation
|
||||
|
||||
### Custom Data Sources
|
||||
1. Implement new scraping module (similar to club.rs)
|
||||
2. Add data source selection logic
|
||||
3. Update configuration system
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Network Access
|
||||
- **HTTPS Only**: All external requests use HTTPS
|
||||
- **Certificate Validation**: Accepts invalid certificates for compatibility
|
||||
- **Rate Limiting**: Respects server limits with controlled concurrency
|
||||
- **Rate Limiting**: Respects server limits with controlled concurrency (semaphore limit of 20)
|
||||
|
||||
### Local File Access
|
||||
- **Read Only**: No modification of game files
|
||||
|
|
@ -229,7 +204,7 @@ Multiple validation layers ensure data quality:
|
|||
## Future Enhancements
|
||||
|
||||
### Potential Improvements
|
||||
1. **Caching Layer**: Cache web scraping results
|
||||
1. **Caching Layer**: Cache parsed results between runs
|
||||
2. **Database Backend**: Replace in-memory HashMap with persistent storage
|
||||
3. **Configuration Files**: External configuration for analysis parameters
|
||||
4. **GUI Interface**: Web-based interface for non-technical users
|
||||
|
|
@ -239,4 +214,4 @@ Multiple validation layers ensure data quality:
|
|||
1. **Pagination**: Handle large datasets with pagination
|
||||
2. **Incremental Updates**: Only fetch changed data
|
||||
3. **Compression**: Compress large timing files
|
||||
4. **Streaming**: Process data without loading everything into memory
|
||||
4. **Streaming**: Process data without loading everything into memory
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue