# Collection Tracking Feature Plan ## Overview The Collection Tracking feature enables users to maintain a comprehensive inventory of their Granblue Fantasy game items. This system is distinct from the existing grid/party system and focuses on cataloging what items users own rather than how they use them in team compositions. ## Business Requirements ### User Stories 1. **As a user**, I want to record which characters I own so I can keep track of my collection progress. 2. **As a user**, I want to save character customizations (rings, awakenings, transcendence) so I can reference them when building teams. 3. **As a user**, I want to track multiple copies of the same weapon/summon with different properties so I can manage my duplicates. 4. **As a user**, I want to record my job accessories collection so I know which ones I still need to obtain. 5. **As a user**, I want to import/export my collection data so I can backup or share my inventory. 6. **As a user**, I want to see statistics about my collection so I can track my progress. ### Core Concepts #### Collection vs Grid Items - **Grid Items** (GridCharacter, GridWeapon, GridSummon): Represent items configured within a specific party/team - **Collection Items**: Represent the user's overall inventory, independent of any party configuration #### Item Uniqueness Rules - **Characters**: One instance per character (by granblue_id) per user - **Weapons**: Multiple instances of the same weapon allowed, each with unique properties - **Summons**: Multiple instances of the same summon allowed, each with unique properties - **Job Accessories**: One instance per accessory (by granblue_id) per user ## Technical Design ### Database Schema #### users table additions ```sql - collection_privacy: integer (default: 0, not null) # 0 = public (viewable by everyone) # 1 = crew_only (viewable by crew members only) # 2 = private (viewable by owner only) Index: - index on collection_privacy ``` #### collection_characters ```sql - id: uuid (primary key) - user_id: uuid (foreign key to users) - character_id: uuid (foreign key to characters) - uncap_level: integer (0-5) - transcendence_step: integer (0-10) - perpetuity: boolean - awakening_id: uuid (foreign key to awakenings, optional) - awakening_level: integer (1-10) - ring1: jsonb {modifier: integer, strength: float} - ring2: jsonb {modifier: integer, strength: float} - ring3: jsonb {modifier: integer, strength: float} - ring4: jsonb {modifier: integer, strength: float} - earring: jsonb {modifier: integer, strength: float} - created_at: timestamp - updated_at: timestamp Indexes: - unique index on [user_id, character_id] - index on user_id - index on character_id ``` #### collection_weapons ```sql - id: uuid (primary key) - user_id: uuid (foreign key to users) - weapon_id: uuid (foreign key to weapons) - uncap_level: integer (0-5) - transcendence_step: integer (0-10) - weapon_key1_id: uuid (foreign key to weapon_keys, optional) - weapon_key2_id: uuid (foreign key to weapon_keys, optional) - weapon_key3_id: uuid (foreign key to weapon_keys, optional) - weapon_key4_id: uuid (foreign key to weapon_keys, optional) - awakening_id: uuid (foreign key to awakenings, optional) - awakening_level: integer (1-10) - ax_modifier1: integer - ax_strength1: float - ax_modifier2: integer - ax_strength2: float - element: integer (for element-changeable weapons) - created_at: timestamp - updated_at: timestamp Indexes: - index on user_id - index on weapon_id - index on [user_id, weapon_id] ``` #### collection_summons ```sql - id: uuid (primary key) - user_id: uuid (foreign key to users) - summon_id: uuid (foreign key to summons) - uncap_level: integer (0-5) - transcendence_step: integer (0-10) - created_at: timestamp - updated_at: timestamp Indexes: - index on user_id - index on summon_id - index on [user_id, summon_id] ``` #### collection_job_accessories ```sql - id: uuid (primary key) - user_id: uuid (foreign key to users) - job_accessory_id: uuid (foreign key to job_accessories) - created_at: timestamp - updated_at: timestamp Indexes: - unique index on [user_id, job_accessory_id] - index on user_id - index on job_accessory_id ``` ### Model Relationships ```ruby # User model additions has_many :collection_characters, dependent: :destroy has_many :collection_weapons, dependent: :destroy has_many :collection_summons, dependent: :destroy has_many :collection_job_accessories, dependent: :destroy # CollectionCharacter belongs_to :user belongs_to :character belongs_to :awakening, optional: true validates :character_id, uniqueness: { scope: :user_id } # CollectionWeapon belongs_to :user belongs_to :weapon belongs_to :awakening, optional: true belongs_to :weapon_key1, class_name: 'WeaponKey', optional: true belongs_to :weapon_key2, class_name: 'WeaponKey', optional: true belongs_to :weapon_key3, class_name: 'WeaponKey', optional: true belongs_to :weapon_key4, class_name: 'WeaponKey', optional: true # CollectionSummon belongs_to :user belongs_to :summon # CollectionJobAccessory belongs_to :user belongs_to :job_accessory validates :job_accessory_id, uniqueness: { scope: :user_id } ``` ### API Design #### Endpoints ##### Collection Characters ``` GET /api/v1/collection/characters Query params: page, limit Response: Paginated list of user's characters GET /api/v1/collection/characters/:id Response: Single collection character details POST /api/v1/collection/characters Body: character_id, uncap_level, transcendence_step, rings, etc. Response: Created collection character PUT /api/v1/collection/characters/:id Body: Updated fields Response: Updated collection character DELETE /api/v1/collection/characters/:id Response: Success/error status ``` ##### Collection Weapons ``` GET /api/v1/collection/weapons Query params: page, limit, weapon_id (filter) Response: Paginated list of user's weapons GET /api/v1/collection/weapons/:id Response: Single collection weapon details POST /api/v1/collection/weapons Body: weapon_id, uncap_level, keys, ax_modifiers, etc. Response: Created collection weapon PUT /api/v1/collection/weapons/:id Body: Updated fields Response: Updated collection weapon DELETE /api/v1/collection/weapons/:id Response: Success/error status ``` ##### Collection Summons ``` GET /api/v1/collection/summons Query params: page, limit, summon_id (filter) Response: Paginated list of user's summons GET /api/v1/collection/summons/:id Response: Single collection summon details POST /api/v1/collection/summons Body: summon_id, uncap_level, transcendence_step Response: Created collection summon PUT /api/v1/collection/summons/:id Body: Updated fields Response: Updated collection summon DELETE /api/v1/collection/summons/:id Response: Success/error status ``` ##### Collection Job Accessories ``` GET /api/v1/collection/job_accessories Query params: page, limit, job_id (filter) Response: Paginated list of user's job accessories POST /api/v1/collection/job_accessories Body: job_accessory_id Response: Created collection job accessory DELETE /api/v1/collection/job_accessories/:id Response: Success/error status ``` ##### Collection Management ``` GET /api/v1/collection/statistics Response: { total_characters: 150, total_weapons: 500, total_summons: 200, total_job_accessories: 25, breakdown_by_element: {...}, breakdown_by_rarity: {...} } POST /api/v1/collection/import Body: JSON with collection data Response: Import results GET /api/v1/collection/export Response: Complete collection data as JSON ``` ### Error Handling #### Custom Error Classes ```ruby # app/errors/collection_errors.rb module CollectionErrors class CollectionItemNotFound < StandardError; end class DuplicateCharacter < StandardError; end class DuplicateJobAccessory < StandardError; end class InvalidWeaponKey < StandardError; end class InvalidAwakening < StandardError; end class InvalidUncapLevel < StandardError; end class InvalidTranscendenceStep < StandardError; end class CollectionLimitExceeded < StandardError; end end ``` #### Error Responses ```json { "error": { "type": "DuplicateCharacter", "message": "Character already exists in collection", "details": { "character_id": "3040001000", "existing_id": "uuid-here" } } } ``` ### Security Considerations 1. **Authorization**: Collection management endpoints require authentication 2. **Ownership**: Users can only modify their own collection 3. **Privacy Controls**: Three-tier privacy system: - **Public**: Viewable by everyone - **Crew Only**: Viewable by crew members (future feature) - **Private**: Viewable only by the owner 4. **Access Control**: Enforced based on privacy level and viewer relationship 5. **Rate Limiting**: Import/export endpoints have stricter rate limits 6. **Validation**: Strict validation of all input data against game rules ### Performance Considerations 1. **Eager Loading**: Use includes() to avoid N+1 queries 2. **Pagination**: All list endpoints must be paginated 3. **Caching**: Cache statistics and export data (15-minute TTL) 4. **Batch Operations**: Support bulk create/update for imports 5. **Database Indexes**: Proper indexes on foreign keys and common query patterns ## Implementation Phases ### Phase 1: Core Models and Database (Week 1) - Create migrations for all collection tables - Implement collection models with validations - Add model associations and scopes - Write model specs ### Phase 2: API Controllers and Blueprints (Week 2) - Implement CRUD controllers for each collection type - Create blueprint serializers - Add authentication and authorization - Write controller specs ### Phase 3: Import/Export and Statistics (Week 3) - Implement bulk import functionality - Add export endpoints - Create statistics aggregation - Add background job support for large imports ### Phase 4: Frontend Integration (Week 4) - Update frontend models and types - Create collection management UI - Add import/export interface - Implement collection statistics dashboard ## Success Metrics 1. **Performance**: All endpoints respond within 200ms for standard operations 2. **Reliability**: 99.9% uptime for collection services 3. **User Adoption**: 50% of active users use collection tracking within 3 months 4. **Data Integrity**: Zero data loss incidents 5. **User Satisfaction**: 4+ star rating for the feature ## Future Enhancements 1. **Collection Sharing**: Allow users to share their collection publicly 2. **Collection Goals**: Set targets for collection completion 3. **Collection Comparison**: Compare collections between users 4. **Automated Sync**: Sync with game data via API (if available) 5. **Collection Value**: Calculate total collection value/rarity score 6. **Mobile App**: Native mobile app for collection management 7. **Collection History**: Track changes to collection over time