Files
cursebreaker-parser-rust/STATS_IMPLEMENTATION_SUMMARY.md
2026-01-12 03:02:45 +00:00

10 KiB

Item Stats in Database - Implementation Summary

Completed Successfully

Successfully added normalized item stats storage to the database for efficient querying and filtering.


What Was Added

1. Database Migration: add_item_stats

New Table: item_stats

CREATE TABLE item_stats (
    item_id INTEGER NOT NULL,
    stat_type TEXT NOT NULL,
    value REAL NOT NULL,  -- Float/REAL for precise stat values
    PRIMARY KEY (item_id, stat_type),
    FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE
);

Indexes Created:

  • idx_item_stats_stat_type - Find all items with a specific stat
  • idx_item_stats_value - Range queries on stat values
  • idx_item_stats_type_value - Combined queries (type + value range)

Composite Primary Key:

  • (item_id, stat_type) - Ensures each item can only have one value per stat type
  • Prevents duplicate stats for the same item

2. Supported Stat Types

All 20 stat types from the game:

Damage Stats:

  • damage_physical - Physical Damage
  • damage_magical - Magical Damage
  • damage_ranged - Ranged Damage

Accuracy Stats:

  • accuracy_physical - Physical Accuracy
  • accuracy_magical - Magical Accuracy
  • accuracy_ranged - Ranged Accuracy

Resistance Stats:

  • resistance_physical - Physical Resistance
  • resistance_magical - Magical Resistance
  • resistance_ranged - Ranged Resistance

Health & Mana:

  • health - Health
  • mana - Mana
  • health_regen - Health Regeneration
  • mana_regen - Mana Regeneration

Special Stats:

  • critical - Critical
  • healing - Healing
  • movement_speed - Movement Speed

Enemy Type Damage:

  • critter_slaying - Damage against Critters
  • damage_vs_beasts - Damage against Beasts
  • damage_vs_undead - Damage against Undead

3. Code Changes

src/databases/item_database.rs

  • Updated save_to_db_with_images() to also save stats
  • Iterates through item.stats vec and inserts each stat
  • Maps StatType enum to string representation
  • Uses same transaction as item and recipe saving

Results from Test Data

Statistics

✅ Total stat entries: 84
📊 Most common stats:
  - health: 20 items
  - resistance_magical: 9 items
  - resistance_physical: 9 items
  - accuracy_magical: 7 items
  - mana: 7 items
  - mana_regen: 7 items

Example Items with Stats

The Bad Ring (ID: 73) - 12 stats (testing item)

  • All stats maxed at 1000 (accuracy, damage, health, mana, resistances)

Ring of the High Mage (ID: 394) - 5 stats

  • Health: 50
  • Mana: 50
  • Mana Regen: 2
  • Magical Resistance: 35
  • Physical Resistance: 15

Crown of the Tyrant - High health bonus

  • Health: 100

Usage Examples

SQL Queries

-- Find all items with health bonuses
SELECT i.id, i.name, s.value as health
FROM items i
JOIN item_stats s ON i.id = s.item_id
WHERE s.stat_type = 'health'
ORDER BY s.value DESC;

-- Find weapons with high physical damage
SELECT i.id, i.name, s.value as damage
FROM items i
JOIN item_stats s ON i.id = s.item_id
WHERE i.item_type = 'weapon'
  AND s.stat_type = 'damage_physical'
  AND s.value > 50
ORDER BY s.value DESC;

-- Find items with multiple resistance types
SELECT i.id, i.name, COUNT(*) as resistance_count
FROM items i
JOIN item_stats s ON i.id = s.item_id
WHERE s.stat_type LIKE 'resistance_%'
GROUP BY i.id, i.name
HAVING COUNT(*) >= 2;

-- Find balanced items (have both offense and defense)
SELECT i.id, i.name
FROM items i
WHERE EXISTS (
    SELECT 1 FROM item_stats
    WHERE item_id = i.id AND stat_type LIKE 'damage_%'
)
AND EXISTS (
    SELECT 1 FROM item_stats
    WHERE item_id = i.id AND stat_type LIKE 'resistance_%'
);

-- Get all stats for a specific item
SELECT stat_type, value
FROM item_stats
WHERE item_id = 394
ORDER BY stat_type;

-- Find items within a stat range
SELECT i.name, s.value
FROM items i
JOIN item_stats s ON i.id = s.item_id
WHERE s.stat_type = 'health'
  AND s.value BETWEEN 50 AND 100;

Rust Queries

use diesel::prelude::*;
use cursebreaker_parser::schema::{items, item_stats};

// Find items with high health
let high_health_items = item_stats::table
    .inner_join(items::table)
    .filter(item_stats::stat_type.eq("health"))
    .filter(item_stats::value.gt(100.0))
    .select((items::name, item_stats::value))
    .load::<(String, f32)>(&mut conn)?;

// Get all stats for an item
let item_id = 394;
let stats = item_stats::table
    .filter(item_stats::item_id.eq(item_id))
    .select((item_stats::stat_type, item_stats::value))
    .load::<(String, f32)>(&mut conn)?;

Web API Examples

For your interactive map and wiki:

1. Filter Items by Stat

// GET /api/items?stat=health&min=50&max=100
pub async fn filter_items_by_stat(
    stat: String,
    min: f32,
    max: f32,
) -> Result<Vec<Item>> {
    let items = item_stats::table
        .inner_join(items::table)
        .filter(item_stats::stat_type.eq(stat))
        .filter(item_stats::value.between(min, max))
        .select(items::all_columns)
        .load(&mut conn)?;

    Ok(items)
}

2. Item Comparison Tool

// GET /api/items/compare?ids=394,340,179
pub async fn compare_items(item_ids: Vec<i32>) -> Result<ItemComparison> {
    let stats = item_stats::table
        .filter(item_stats::item_id.eq_any(item_ids))
        .load::<(i32, String, f32)>(&mut conn)?;

    // Group by item and return comparison table
    Ok(build_comparison(stats))
}

3. Best Items for Stat

// GET /api/items/best?stat=damage_physical&limit=10
pub async fn best_items_for_stat(
    stat: String,
    limit: i64,
) -> Result<Vec<ItemWithStat>> {
    let items = item_stats::table
        .inner_join(items::table)
        .filter(item_stats::stat_type.eq(stat))
        .order_by(item_stats::value.desc())
        .limit(limit)
        .select((items::all_columns, item_stats::value))
        .load(&mut conn)?;

    Ok(items)
}

4. Item Build Suggestions

// GET /api/builds?focus=mage
pub async fn suggest_build(focus: String) -> Result<Build> {
    // For mage build: high mana, mana_regen, magical damage/accuracy
    let stats_to_prioritize = match focus.as_str() {
        "mage" => vec!["mana", "mana_regen", "damage_magical", "accuracy_magical"],
        "warrior" => vec!["health", "damage_physical", "resistance_physical"],
        "archer" => vec!["damage_ranged", "accuracy_ranged", "critical"],
        _ => vec![]
    };

    // Find best items for each slot with those stats
    // ...
}

Benefits

Efficient Filtering - Query items by stat without parsing JSON Range Queries - Find items within stat value ranges Comparative Analysis - Easy item comparisons Build Optimization - Find best items for specific builds Indexed - Fast queries on stat types and values Normalized - No data duplication, consistent values Type-Safe - Composite PK prevents duplicate stats


Performance Considerations

Query Optimization

Fast Queries (uses indexes):

-- Single stat lookup
WHERE stat_type = 'health'  -- Uses idx_item_stats_stat_type

-- Range query
WHERE value > 50  -- Uses idx_item_stats_value

-- Combined
WHERE stat_type = 'health' AND value > 50  -- Uses idx_item_stats_type_value

Slower Queries (may need optimization):

-- Multiple stat requirements (requires multiple joins)
-- Consider caching or denormalizing for frequently accessed combinations

Storage Impact

  • 84 stat entries currently
  • Average ~3-4 stats per item with stats
  • Minimal storage: ~8 bytes per entry (int + text + float)
  • Total: < 1 KB for current data

As more items with stats are added, storage remains efficient due to normalization.


Wiki Feature Ideas

1. Item Comparison Tool

Show side-by-side comparison of multiple items with all their stats.

2. Best-in-Slot Lists

  • Best weapons for physical damage
  • Best armor for magical resistance
  • Best accessories for health/mana

3. Build Guides

  • "Mage Build" - show items with high mana/magical stats
  • "Tank Build" - show items with high health/resistances
  • "DPS Build" - show items with high damage/critical

4. Stat Distribution Charts

  • Visualize stat value distributions
  • Show which stats are rare vs common
  • Identify stat "sweet spots"

5. Upgrade Paths

  • Show progression of items by stat values
  • "From 50 health → 100 health → 150 health"

Future Enhancements

Optional Additions:

  1. Stat Ranges Table - For items with variable stats

    CREATE TABLE item_stat_ranges (
        item_id INTEGER,
        stat_type TEXT,
        min_value REAL,
        max_value REAL,
        PRIMARY KEY (item_id, stat_type)
    );
    
  2. Derived Stats - Calculate total stats for equipment sets

    -- Sum up stats across multiple equipped items
    SELECT stat_type, SUM(value) as total
    FROM item_stats
    WHERE item_id IN (/* equipped item IDs */)
    GROUP BY stat_type;
    
  3. Stat Scaling - Track how stats scale with item level

    SELECT i.level, AVG(s.value) as avg_damage
    FROM items i
    JOIN item_stats s ON i.id = s.item_id
    WHERE s.stat_type = 'damage_physical'
    GROUP BY i.level;
    
  4. Stat Categories - Group related stats

    CREATE TABLE stat_categories (
        stat_type TEXT PRIMARY KEY,
        category TEXT  -- 'offense', 'defense', 'utility', etc.
    );
    

Verification

Run the verification script anytime:

cargo run --bin verify-stats

Shows:

  • Total stat entries
  • Breakdown by stat type
  • Items with most stats
  • Example queries (high damage, health bonuses)

Ready for Production

Your item stats are now:

  • Stored in normalized table
  • Efficiently queryable
  • Properly indexed
  • Ready for filtering and comparison
  • Available for build optimization
  • Perfect for wiki features

The database now contains complete item data with:

  • Metadata (type, level, price, etc.)
  • Images (3 sizes, WebP)
  • Crafting recipes (normalized)
  • Stats (normalized, queryable)

Your interactive map and wiki have everything needed for a rich item browsing experience! 🎮