No description
Find a file
Jan-Peter von Hunnius 1a844e7aa8 Address fourth review round: observability, docs accuracy, dep hygiene, tests
- Warn when no timing data was found at all (empty --times-dir previously
  produced empty CSVs without any hint) — best_cars empty + non-empty car
  list now logs a warning in parse_all_times
- Remove the inaccurate "known gap" doc from write_trash_csv: category 1
  (not best on any track) already covers non-final cars, so the
  documented gap never existed
- Gate env_logger behind the bin-logging feature (default-on) and mark
  the records binary as requiring it, so downstream lib consumers do not
  pull env_logger transitively; lib builds clean with --no-default-features
- Switch fetch_car progress output from println! to log::info! so
  RUST_LOG controls it
- atomic_write takes &Path instead of &PathBuf
- Add direct unit tests for is_final_build (sum-8 finals, maxed builds,
  sub-8 non-finals, malformed inputs) and a parsing test covering
  missing/null/non-numeric "t" fields (warn + skip, valid entries still
  parsed)
2026-08-15 20:14:53 +02:00
docs docs: update documentation for normalized config and improve command 2026-05-11 16:58:01 +02:00
src Address fourth review round: observability, docs accuracy, dep hygiene, tests 2026-08-15 20:14:53 +02:00
tests Fix review findings: wishlist qualifying count, improve docs, and lint cleanup 2026-08-15 18:58:12 +02:00
.gitignore Address review findings: const guards, qualifying-count regression test, owned keys 2026-08-15 19:07:03 +02:00
Cargo.lock Address full-codebase review: logging boundary, clone elimination, robustness 2026-08-15 19:29:51 +02:00
Cargo.toml Address fourth review round: observability, docs accuracy, dep hygiene, tests 2026-08-15 20:14:53 +02:00
CHANGELOG.md docs: update documentation for normalized config and improve command 2026-05-11 16:58:01 +02:00
README.md docs: update documentation for normalized config and improve command 2026-05-11 16:58:01 +02:00
rustfmt.toml refactor: modular architecture with unified error handling and DashMap concurrency 2026-05-08 16:19:01 +02:00
track_names.json refactor: extract lib.rs, remove club module, add bounded concurrency 2026-05-06 20:20:15 +02:00

Top Drives Records Analyzer

A comprehensive Rust-based tool for analyzing car performance data in the Top Drives racing game. This tool fetches track times from a community-maintained repository and provides detailed analysis including best cars, trash identification, and wishlist optimization.

🚀 Features

  • Best Car Analysis: Find the best performing cars across all tracks and conditions
  • Wishlist Optimization: Identify cars to add to or remove from your wishlist
  • Collection Cleanup: Identify cars that can be safely removed from your collection
  • Upgrade Prioritization: Find owned cars not yet at their final tune build
  • Track-Specific Analysis: Get detailed performance data for specific tracks and conditions
  • RQ-Based Filtering: Filter results by car rarity (RQ) levels
  • Multiple Surface Types: Support for Dry, Wet, Dirt, Snow, and other track conditions

📋 Table of Contents

🛠️ Installation

Prerequisites

  • Rust (latest stable version)
  • Internet connection for fetching data

Setup

  1. Clone the repository

    git clone <repository-url>
    cd top_drives
    
  2. Build the project

    cargo build --release
    
  3. Run the analyzer

    cargo run --bin records -- fetch
    

🚦 Quick Start

  1. Initial Setup: Fetch the latest car and track data

    cargo run --bin records -- fetch
    
  2. Full Analysis: Generate all output files in a single pass

    cargo run --bin records -- all
    
  3. Best Cars: Find the best cars across all tracks

    cargo run --bin records -- best
    
  4. Collection Cleanup: Identify cars safe to remove

    cargo run --bin records -- trash
    
  5. Wishlist Management: Optimize your wishlist

    cargo run --bin records -- wishlist
    
  6. Upgrade Prioritization: Find cars that need upgrading

    cargo run --bin records -- improve
    

📖 Usage Guide

Basic Commands

Fetch Data

cargo run --bin records -- fetch

Downloads the latest car database and track information from the community repository.

Best Cars Analysis

cargo run --bin records -- best

Generates best.csv (all cars best on at least one track) and very_best.csv (cars best on ≥10 tracks). Both files are sorted by RQ.

Output Files:

best.csv        — All cars best on at least one track
very_best.csv   — Cars best on ≥10 tracks (default)

Use --min-count N to change the threshold for very_best.csv:

cargo run --bin records -- best --min-count 5

Trash Analysis

cargo run --bin records -- trash

Generates trash.csv — owned cars that are not best on any track, have RQ < 80, and are not prize cars. Sorted by RQ.

Output File:

trash.csv       — Owned cars safe to remove

Wishlist Management

cargo run --bin records -- wishlist

Generates wishlist.csv (ideal wishlist: very_best unowned cars, capped at 300), add.csv (cars that should be on your wishlist but aren't), and remove.csv (cars on your wishlist that shouldn't be). All sorted by RQ.

Output Files:

wishlist.csv    — Ideal wishlist (very_best unowned, capped)
add.csv         — Cars to add to wishlist
remove.csv      — Cars to remove from wishlist

Use --min-count N to change the threshold for very_best cars (default 10):

cargo run --bin records -- wishlist --min-count 5

Use --max-wishlist M to change the wishlist cap (default 300):

cargo run --bin records -- wishlist --max-wishlist 500

Full Analysis

cargo run --bin records -- all

Generates all 7 CSV files in a single parse pass. Equivalent to running best, trash, wishlist, and improve together, but more efficient.

Output Files:

best.csv        — All cars best on at least one track
very_best.csv   — Cars best on ≥10 tracks
trash.csv       — Owned cars safe to remove
wishlist.csv    — Ideal wishlist (very_best unowned, capped)
add.csv         — Cars to add to wishlist
remove.csv      — Cars to remove from wishlist
improve.csv     — Owned cars not yet at final build config

Supports both --min-count N (default 10) and --max-wishlist M (default 300):

cargo run --bin records -- all --min-count 5 --max-wishlist 500

Detailed Performance Data

cargo run --bin records -- details

Generates details.csv with comprehensive timing data for all tracks and conditions.

Sample Output:

RQ,TrackID,Condition,CarRQ,Brand,Model,Year,Config,Time
85,laguna,Dry,85,McLaren,F1,1993,233,112.45
82,monaco,Dry,82,Ferrari,250 GTO,1962,111,45.23

Track-Specific Analysis

cargo run --bin records -- track "Laguna Seca" "Dry" "85"

Prints the best car for a specific track, condition, and RQ combination to stdout.

Advanced Usage

Multiple RQ Analysis

The tool supports analyzing performance across different RQ ranges. Use the best and wishlist commands to see how cars perform at various rarity levels.

Track Conditions

The analyzer supports multiple track conditions:

  • Dry: Standard asphalt conditions
  • Wet: Rain-affected tracks
  • Dirt: Off-road conditions
  • Snow: Winter conditions
  • Gravel: Loose surface conditions

🗃️ Commands Reference

Command Description Arguments
fetch Download latest car and track data None
best Generate best.csv and very_best.csv [--min-count N]
trash Generate trash.csv (owned cars safe to remove) None
wishlist Generate wishlist.csv, add.csv, remove.csv [--min-count N] [--max-wishlist M]
all Generate all 7 CSV files in a single pass [--min-count N] [--max-wishlist M]
details Print detailed timing data for all tracks (stdout) None
track Print best car for specific track (stdout) <track_name> <condition> <rq>
improve Generate improve.csv (owned cars not at final build) None

Flags

Flag Default Description
--min-count N 10 Minimum number of tracks a car must be best on to qualify as "very best"
--max-wishlist M 300 Maximum number of cars on the ideal wishlist

📅 Daily Workflow

The typical daily workflow uses the all command, which runs all analysis in a single efficient parse pass:

cargo run --bin records -- fetch
cargo run --bin records -- all

Or combine them:

cargo run --bin records -- fetch && cargo run --bin records -- all

This generates the following output files (all sorted by car RQ):

File Format Description
best.csv RQ,Brand,Model,Year,FinalBuild,Count All cars best on at least one track
very_best.csv RQ,Brand,Model,Year,FinalBuild,Count Cars best on ≥ min_count tracks
trash.csv RQ,Brand,Model,Year Owned cars not best on any track (RQ<80, not prize)
wishlist.csv RQ,Brand,Model,Year,FinalBuild,Count Ideal wishlist (very_best unowned, capped)
add.csv RQ,Brand,Model,Year,FinalBuild,Count Cars to add to wishlist
remove.csv RQ,Brand,Model,Year,FinalBuild,Count Cars to remove from wishlist
improve.csv RQ,Brand,Model,Year,Target,Count Owned cars not yet at final build config

Workflow Steps

  1. Fetch fresh data from the community repository
  2. Analyze your collection with all to generate all CSV files
  3. Review best.csv to see how your cars rank
  4. Check add.csv for cars worth adding to your wishlist
  5. Clean up remove.csv entries from your wishlist
  6. Sell cars listed in trash.csv that are no longer useful
  7. Upgrade cars listed in improve.csv to their target final build

📊 Data Sources

Car Data

  • Source: Community-maintained GitHub repository
  • Format: JSON files with performance data per car
  • Update Frequency: Regular updates from community contributors

Track Data

  • Source: Same community repository
  • Coverage: All tracks and conditions in Top Drives
  • Format: Structured track definitions with conditions

Track Names

  • Source: track_names.json (included in repository)
  • Format: JSON mapping track codes to human-readable names
  • Loaded: At compile time via include_str!

User Collection

  • File: my_cars.json
  • Format: Top Drives game export format
  • Usage: Identifies owned cars for analysis

⚙️ Configuration

Files Structure

top_drives/
├── src/
│   ├── records.rs      # Main analyzer binary
│   └── lib.rs          # Shared library (track name translations)
├── times/              # Car performance data (1000+ files)
├── cars_repo.json      # Car database
├── tracks_repo.json    # Track definitions
├── track_names.json    # Track code → name mappings
├── my_cars.json        # Your car collection
└── Cargo.toml          # Rust project configuration

Dependencies

  • reqwest: HTTP client for data fetching
  • serde / serde_json: JSON parsing and serialization (with serde::Deserialize derive for Car)
  • tokio: Asynchronous runtime (rt-multi-thread, macros, fs, sync, io-util)
  • futures: Async utility combinators
  • clap: CLI argument parsing (with derive macros)
  • thiserror: Ergonomic error type definitions

🔧 Development

Project Structure

The project consists of a single binary with a shared library:

  1. records: Primary analysis tool using JSON data (src/records.rs)
  2. lib: Shared library with track name translations (src/lib.rs)

Key Constants

  • MAX_RQ: u8 = 113 — Maximum RQ level used in analysis (defined in records.rs)

Key Data Structures

Car Information

struct Car {
    rid: String,        // Unique car identifier
    brand: String,      // Manufacturer name
    only_name: String,  // Model name
    year: u16,         // Model year
    rq: u8,            // Rarity level (10-113)
    prize: bool,       // Whether car is prize-only
    guid: String,      // Game-specific identifier
}

Performance Records

struct BestCarRecord {
    car_rid: String,           // Car identifier
    brand: String,             // Manufacturer
    only_name: String,         // Model name
    year: u16,                 // Year
    rq: u8,                    // Rarity level
    config: String,            // Original tune config from JSON
    normalized_config: String, // Normalized final build (323, 233, or 332)
    time: f64,                 // Track time
    owned: bool,               // Whether you own this car
    prize: bool,               // Whether this is a prize car
    guid: String,              // Game identifier
}

Building

# Debug build
cargo build

# Release build
cargo build --release

# Run the analyzer
cargo run --bin records

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

Adding New Tracks

Track definitions are stored in tracks_repo.json. Each track includes:

  • Unique identifier
  • Display name
  • Supported conditions
  • Track type classification

Track name mappings are stored in track_names.json and loaded at compile time.

Adding Car Data

New car performance data should be submitted to the upstream repository following their contribution guidelines.

📄 License

This project is open source. Please check the upstream data repositories for their respective licenses.

🆘 Support

For issues and questions:

  1. Check existing documentation
  2. Review open issues
  3. Create new issue with detailed description

🔄 Updates

The tool fetches fresh data each time you run the fetch command. Keep your local data updated for best results.


Built with ❤️ for the Top Drives community