281 lines
No EOL
10 KiB
Python
281 lines
No EOL
10 KiB
Python
"""
|
|
Database models and setup for Inventory Service.
|
|
|
|
Normalized schema designed around actual item JSON structure with proper enum translation.
|
|
"""
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy import (
|
|
Column, Integer, String, Float, Boolean, DateTime, BigInteger, Text, JSON,
|
|
ForeignKey, Index, UniqueConstraint, CheckConstraint, create_engine, MetaData
|
|
)
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime
|
|
|
|
Base = declarative_base()
|
|
|
|
class Item(Base):
|
|
"""Core item identification and basic properties."""
|
|
__tablename__ = 'items'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
character_name = Column(String(50), nullable=False, index=True)
|
|
item_id = Column(BigInteger, nullable=False) # Game item instance ID
|
|
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow)
|
|
|
|
# Basic properties (always present)
|
|
name = Column(String(200), nullable=False, index=True)
|
|
icon = Column(Integer, nullable=False)
|
|
object_class = Column(Integer, nullable=False, index=True)
|
|
|
|
# Core stats
|
|
value = Column(Integer, default=0)
|
|
burden = Column(Integer, default=0)
|
|
|
|
# Equipment status
|
|
current_wielded_location = Column(Integer, default=0, index=True) # 0 = not equipped
|
|
|
|
# Item state
|
|
bonded = Column(Integer, default=0) # 0=Normal, 1=Bonded, 2=Sticky, 4=Destroy on drop
|
|
attuned = Column(Integer, default=0) # 0=Normal, 1=Attuned
|
|
unique = Column(Boolean, default=False)
|
|
|
|
# Stack/Container properties
|
|
stack_size = Column(Integer, default=1)
|
|
max_stack_size = Column(Integer, default=1)
|
|
items_capacity = Column(Integer) # For containers
|
|
containers_capacity = Column(Integer) # For containers
|
|
|
|
# Durability
|
|
structure = Column(Integer) # Current durability
|
|
max_structure = Column(Integer) # Maximum durability
|
|
|
|
# Special item flags
|
|
rare_id = Column(Integer) # For rare items
|
|
lifespan = Column(Integer) # Item decay timer
|
|
remaining_lifespan = Column(Integer) # Remaining decay time
|
|
|
|
# Metadata flags
|
|
has_id_data = Column(Boolean, default=False)
|
|
last_id_time = Column(BigInteger, default=0)
|
|
|
|
# Unique constraint per character
|
|
__table_args__ = (
|
|
UniqueConstraint('character_name', 'item_id', name='uq_char_item'),
|
|
Index('ix_items_name_char', 'character_name', 'name'),
|
|
Index('ix_items_class_char', 'character_name', 'object_class'),
|
|
)
|
|
|
|
class ItemCombatStats(Base):
|
|
"""Combat-related properties for weapons and armor."""
|
|
__tablename__ = 'item_combat_stats'
|
|
|
|
item_id = Column(Integer, ForeignKey('items.id'), primary_key=True)
|
|
|
|
# Damage properties
|
|
max_damage = Column(Integer)
|
|
damage = Column(Integer)
|
|
damage_type = Column(Integer)
|
|
damage_bonus = Column(Float)
|
|
elemental_damage_bonus = Column(Integer)
|
|
elemental_damage_vs_monsters = Column(Float)
|
|
variance = Column(Float)
|
|
|
|
# Advanced damage properties
|
|
cleaving = Column(Integer) # Cleaving damage
|
|
crit_damage_rating = Column(Integer) # Critical damage multiplier
|
|
damage_over_time = Column(Integer) # DoT damage
|
|
|
|
# Attack properties
|
|
attack_bonus = Column(Float)
|
|
weapon_time = Column(Integer)
|
|
weapon_skill = Column(Integer)
|
|
|
|
# Defense properties
|
|
armor_level = Column(Integer, index=True)
|
|
shield_value = Column(Integer)
|
|
melee_defense_bonus = Column(Float)
|
|
missile_defense_bonus = Column(Float)
|
|
magic_defense_bonus = Column(Float)
|
|
|
|
# Resistances
|
|
resist_magic = Column(Integer)
|
|
crit_resist_rating = Column(Integer)
|
|
crit_damage_resist_rating = Column(Integer)
|
|
dot_resist_rating = Column(Integer)
|
|
life_resist_rating = Column(Integer)
|
|
nether_resist_rating = Column(Integer)
|
|
|
|
# Healing/Recovery
|
|
heal_over_time = Column(Integer)
|
|
healing_resist_rating = Column(Integer)
|
|
|
|
# Mana properties
|
|
mana_conversion_bonus = Column(Float)
|
|
|
|
# PvP properties
|
|
pk_damage_rating = Column(Integer)
|
|
pk_damage_resist_rating = Column(Integer)
|
|
gear_pk_damage_rating = Column(Integer)
|
|
gear_pk_damage_resist_rating = Column(Integer)
|
|
|
|
class ItemRequirements(Base):
|
|
"""Wield requirements and skill prerequisites."""
|
|
__tablename__ = 'item_requirements'
|
|
|
|
item_id = Column(Integer, ForeignKey('items.id'), primary_key=True)
|
|
|
|
wield_level = Column(Integer, index=True)
|
|
wield_requirement = Column(Integer)
|
|
skill_level = Column(Integer)
|
|
lore_requirement = Column(Integer)
|
|
|
|
# String-based requirements (parsed from StringValues)
|
|
equip_skill = Column(String(50))
|
|
mastery = Column(String(50))
|
|
|
|
class ItemEnhancements(Base):
|
|
"""Enhancements, materials, and modifications."""
|
|
__tablename__ = 'item_enhancements'
|
|
|
|
item_id = Column(Integer, ForeignKey('items.id'), primary_key=True)
|
|
|
|
material = Column(String(50), index=True)
|
|
imbue = Column(String(50))
|
|
tinks = Column(Integer)
|
|
workmanship = Column(Float)
|
|
salvage_workmanship = Column(Float)
|
|
|
|
# Advanced tinkering
|
|
num_times_tinkered = Column(Integer, default=0)
|
|
free_tinkers_bitfield = Column(Integer) # Which tinkers are free
|
|
num_items_in_material = Column(Integer) # Salvage yield
|
|
|
|
# Additional imbue effects
|
|
imbue_attempts = Column(Integer, default=0)
|
|
imbue_successes = Column(Integer, default=0)
|
|
imbued_effect2 = Column(Integer)
|
|
imbued_effect3 = Column(Integer)
|
|
imbued_effect4 = Column(Integer)
|
|
imbued_effect5 = Column(Integer)
|
|
imbue_stacking_bits = Column(Integer) # Which imbues stack
|
|
|
|
# Set information
|
|
item_set = Column(String(100), index=True)
|
|
equipment_set_extra = Column(Integer) # Additional set bonuses
|
|
|
|
# Special properties
|
|
aetheria_bitfield = Column(Integer) # Aetheria slot properties
|
|
heritage_specific_armor = Column(Integer) # Heritage armor type
|
|
|
|
# Cooldowns
|
|
shared_cooldown = Column(Integer) # Cooldown group ID
|
|
|
|
class ItemRatings(Base):
|
|
"""Modern rating system properties."""
|
|
__tablename__ = 'item_ratings'
|
|
|
|
item_id = Column(Integer, ForeignKey('items.id'), primary_key=True)
|
|
|
|
# Damage ratings
|
|
damage_rating = Column(Integer)
|
|
damage_resist_rating = Column(Integer)
|
|
crit_rating = Column(Integer)
|
|
crit_resist_rating = Column(Integer)
|
|
crit_damage_rating = Column(Integer)
|
|
crit_damage_resist_rating = Column(Integer)
|
|
|
|
# Utility ratings
|
|
heal_boost_rating = Column(Integer)
|
|
vitality_rating = Column(Integer)
|
|
healing_rating = Column(Integer) # Healing rating (enum 342)
|
|
mana_conversion_rating = Column(Integer)
|
|
weakness_rating = Column(Integer) # Weakness debuff strength
|
|
nether_over_time = Column(Integer) # Nether DoT
|
|
|
|
# Resist ratings
|
|
healing_resist_rating = Column(Integer) # Healing resist (enum 317)
|
|
nether_resist_rating = Column(Integer) # Nether resist (enum 331)
|
|
dot_resist_rating = Column(Integer) # DoT resist (enum 350)
|
|
life_resist_rating = Column(Integer) # Life resist (enum 351)
|
|
|
|
# Specialized ratings
|
|
sneak_attack_rating = Column(Integer) # Sneak attack (enum 356)
|
|
recklessness_rating = Column(Integer) # Recklessness (enum 357)
|
|
deception_rating = Column(Integer) # Deception (enum 358)
|
|
|
|
# PvP ratings
|
|
pk_damage_rating = Column(Integer) # PvP damage (enum 381)
|
|
pk_damage_resist_rating = Column(Integer) # PvP damage resist (enum 382)
|
|
gear_pk_damage_rating = Column(Integer) # Gear PvP damage (enum 383)
|
|
gear_pk_damage_resist_rating = Column(Integer) # Gear PvP damage resist (enum 384)
|
|
|
|
# Gear totals
|
|
gear_damage = Column(Integer) # Total gear damage
|
|
gear_damage_resist = Column(Integer) # Total gear damage resist
|
|
gear_crit = Column(Integer) # Total gear crit
|
|
gear_crit_resist = Column(Integer) # Total gear crit resist
|
|
gear_crit_damage = Column(Integer) # Total gear crit damage
|
|
gear_crit_damage_resist = Column(Integer) # Total gear crit damage resist
|
|
gear_healing_boost = Column(Integer) # Total gear healing boost
|
|
gear_max_health = Column(Integer) # Total gear max health
|
|
gear_nether_resist = Column(Integer) # Total gear nether resist
|
|
gear_life_resist = Column(Integer) # Total gear life resist
|
|
gear_overpower = Column(Integer) # Total gear overpower
|
|
gear_overpower_resist = Column(Integer) # Total gear overpower resist
|
|
|
|
# Calculated totals
|
|
total_rating = Column(Integer)
|
|
|
|
class ItemSpells(Base):
|
|
"""Spell information for items."""
|
|
__tablename__ = 'item_spells'
|
|
|
|
item_id = Column(Integer, ForeignKey('items.id'), primary_key=True)
|
|
spell_id = Column(Integer, primary_key=True)
|
|
is_active = Column(Boolean, default=False)
|
|
|
|
class ItemRawData(Base):
|
|
"""Preserve original raw enum data for completeness."""
|
|
__tablename__ = 'item_raw_data'
|
|
|
|
item_id = Column(Integer, ForeignKey('items.id'), primary_key=True)
|
|
|
|
# Raw enum collections
|
|
int_values = Column(JSONB)
|
|
double_values = Column(JSONB)
|
|
string_values = Column(JSONB)
|
|
bool_values = Column(JSONB)
|
|
|
|
# Original full JSON for reference
|
|
original_json = Column(JSONB)
|
|
|
|
# Database URL configuration
|
|
import os
|
|
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://inventory_user:inventory_pass@inventory-db:5432/inventory_db")
|
|
|
|
# Create all indexes for performance
|
|
def create_indexes(engine):
|
|
"""Create additional performance indexes."""
|
|
|
|
# Item search indexes
|
|
sa.Index('ix_items_search', Item.character_name, Item.name, Item.object_class).create(engine, checkfirst=True)
|
|
|
|
# Equipment status index for filtering equipped items
|
|
sa.Index('ix_items_equipped', Item.character_name, Item.current_wielded_location).create(engine, checkfirst=True)
|
|
|
|
# Combat stats indexes for filtering
|
|
sa.Index('ix_combat_damage', ItemCombatStats.max_damage).create(engine, checkfirst=True)
|
|
sa.Index('ix_combat_armor', ItemCombatStats.armor_level).create(engine, checkfirst=True)
|
|
|
|
# Requirements indexes for filtering
|
|
sa.Index('ix_req_level', ItemRequirements.wield_level).create(engine, checkfirst=True)
|
|
|
|
# Enhancement indexes
|
|
sa.Index('ix_enh_material_set', ItemEnhancements.material, ItemEnhancements.item_set).create(engine, checkfirst=True)
|
|
|
|
# JSONB indexes for raw data querying
|
|
sa.Index('ix_raw_int_gin', ItemRawData.int_values, postgresql_using='gin').create(engine, checkfirst=True)
|
|
sa.Index('ix_raw_original_gin', ItemRawData.original_json, postgresql_using='gin').create(engine, checkfirst=True) |