top_drives/docs/ARCHITECTURE.md
Jan-Peter von Hunnius 32c4d3c10e Added documentation
Added test cases
Added comments
2025-10-02 17:35:56 +02:00

7.1 KiB

Architecture Documentation

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.

Component Architecture

1. Records Module (src/records.rs)

Primary analysis engine that processes pre-downloaded JSON timing data.

Key Responsibilities

  • Data Fetching: Downloads car and track databases from GitHub repository
  • File Processing: Parses JSON timing files for each car configuration
  • Performance Analysis: Compares timing data across RQ ranges and track conditions
  • Collection Management: Identifies owned cars and optimization opportunities

Data Flow

GitHub Repository
       ↓
cars_repo.json + tracks_repo.json
       ↓
times/*.json (1000+ car files)
       ↓
JSON Parsing → BestCarRecord Analysis
       ↓
User Collection (my_cars.json)
       ↓
Output: CSV/Terminal Results

2. Club Module (src/club.rs)

Alternative data source that scrapes live data from topdrives.club website.

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

Data Flow

topdrives.club Website
       ↓
HTML Content
       ↓
CSS Selector Parsing
       ↓
Car Data Extraction
       ↓
Output: Terminal Results

Data Structures

Core Types

TripletKey

type TripletKey = (String, u8, String);
//   ↓           ↓        ↓
// Track ID    RQ Level  Surface Condition

Purpose: Composite key for uniquely identifying track conditions Usage: HashMap key for storing best car records

Car (Records Module)

struct Car {
    rid: String,        // Repository ID
    brand: String,      // Manufacturer
    only_name: String,  // Model name
    year: u16,         // Model year
    rq: u8,           // Rarity level
    prize: bool,       // Prize car status
    guid: String,      // Game GUID
}

BestCarRecord

struct BestCarRecord {
    car_rid: String,   // Car identifier
    brand: String,     // Manufacturer
    only_name: String, // Model name
    year: u16,        // Year
    rq: u8,           // RQ level
    config: String,    // Tune config (111, 233, etc.)
    time: f64,        // Track time (seconds)
    owned: bool,      // User ownership status
    guid: String,     // Game identifier
}

Car (Club Module)

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

static BEST_CARS: Lazy<Mutex<HashMap<TripletKey, Vec<BestCarRecord>>>>

Thread Safety: Protected by Mutex for concurrent access during parsing Initialization: Uses once_cell::Lazy for one-time setup Structure: HashMap with composite keys for efficient lookups

Algorithm Details

RQ Range Analysis

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)
  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

Time Validation

Multiple validation layers ensure data quality:

  1. Minimum Time: Times below 1.2 seconds are discarded
  2. Downvote Filter: Community-downvoted times are excluded
  3. Special Cases: Test Bowl track uses inverted time calculation (2000.0 / time)

Concurrent Processing

Records Module

  • Task Spawning: One async task per car file
  • Rate Limiting: Semaphore limits concurrent downloads (20 max)
  • Error Isolation: Individual car failures don't stop batch processing

Synchronization

  • Join Handles: Waits for all parsing tasks to complete
  • Mutex Protection: Safe concurrent access to shared BEST_CARS cache

File Organization

Input Files

├── cars_repo.json          # Car database from repository
├── tracks_repo.json        # Track definitions
├── my_cars.json           # User's car collection (game export)
└── times/                 # Individual car timing files
    ├── Ferrari_F40_1987.json
    ├── McLaren_F1_1993.json
    └── ...

Output Files

├── best.csv              # Best cars analysis results
├── missing.csv           # Missing recommended cars
└── details.csv           # Detailed timing data

Performance Characteristics

Records Module

  • Startup Time: Fast (uses cached JSON files)
  • 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

Error Handling Strategy

Graceful Degradation

  • Missing Files: Continue with available data
  • Network Errors: Log errors but don't crash
  • Parse Failures: Use default values or skip invalid entries

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()
  3. Add condition mappings in translate_track_type()

Adding New Analysis Types

  1. Create new output functions (similar to print_best_cars())
  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

Local File Access

  • Read Only: No modification of game files
  • User Data: Only reads exported collection data
  • No Persistence: Analysis results are output-only

Future Enhancements

Potential Improvements

  1. Caching Layer: Cache web scraping results
  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
  5. Export Formats: Multiple output formats (JSON, XML, etc.)

Scalability Considerations

  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