Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ Unless explicitly stated otherwise, the repository license applies to the source
- Optional X-Ray opening mechanic
- Souvenir packages with tournament-based dates
- Skin pattern seed and finish variant support, including phase-aware finishes
- Persistent collection tracking with a saved inventory and recent activity
- Collection-aware glossary browsing with per-item collected counts
- Collection progress and per-source stats across containers and collections
- Major tournament section covering CS:GO and CS2 eras
- Major teams and players browsing
- Operation and Armory reward collections
Expand Down Expand Up @@ -145,23 +148,21 @@ The source code in this repository is licensed under `AGPL-3.0`.

The project is actively evolving, with current work focused on:

- expanding the simulation layer beyond basic opening flows with deeper item metadata
- polishing the collection layer with stronger progress tracking across containers, collections, and collectibles
- improving long-term data quality for tournaments, teams, and players
- continuing UI/codebase refactoring to reduce duplicated screen logic
- preparing larger progression features such as collection tracking and ownership history
- hardening the simulator around long-term product polish rather than major missing content

## Roadmap

### v0.13
### v0.14

- Inventory or item ownership tracking in some form
- Opening and Trade-Up history with per-container and per-item stats
- Better collection browsing around owned items, seen drops, and completion progress
- Better automated test coverage for core simulator and collection logic
- Deeper collection analytics across items, duplicates, sessions, and finishing variants
- Cleaner navigation and final UI consistency pass across major app sections

### Future

- Cleaner navigation across containers, collections, and collectibles
- Better automated test coverage beyond basic smoke checks
- Music Kit preview playback if a reliable audio source is available
- Optional China / Perfect World visual mode if a reliable alternate asset source is available
- Music Kit preview playback if a maintainable preview-audio import pipeline becomes available
- Optional China / Perfect World visual mode once a reliable alternate asset source is available

84 changes: 84 additions & 0 deletions lib/core/collection/collection_entry.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
class CollectionEntry {
final String entryId;
final String category;
final String filterCategory;
final String itemId;
final String stackKey;
final String title;
final String subtitle;
final String imagePath;
final String rarity;
final String sourceName;
final String sourceType;
final DateTime acquiredAt;
final bool isStatTrak;
final bool isSouvenir;
final double? floatValue;
final String? exterior;
final int? patternSeed;

const CollectionEntry({
required this.entryId,
required this.category,
required this.filterCategory,
required this.itemId,
required this.stackKey,
required this.title,
required this.subtitle,
required this.imagePath,
required this.rarity,
required this.sourceName,
required this.sourceType,
required this.acquiredAt,
required this.isStatTrak,
required this.isSouvenir,
required this.floatValue,
required this.exterior,
required this.patternSeed,
});

factory CollectionEntry.fromJson(Map<String, dynamic> json) {
return CollectionEntry(
entryId: json['entryId'] as String,
category: json['category'] as String,
filterCategory:
(json['filterCategory'] as String?) ?? (json['category'] as String),
itemId: json['itemId'] as String,
stackKey: json['stackKey'] as String,
title: json['title'] as String,
subtitle: json['subtitle'] as String,
imagePath: json['imagePath'] as String,
rarity: json['rarity'] as String,
sourceName: json['sourceName'] as String? ?? '',
sourceType: json['sourceType'] as String? ?? '',
acquiredAt: DateTime.parse(json['acquiredAt'] as String),
isStatTrak: json['isStatTrak'] as bool? ?? false,
isSouvenir: json['isSouvenir'] as bool? ?? false,
floatValue: (json['floatValue'] as num?)?.toDouble(),
exterior: json['exterior'] as String?,
patternSeed: json['patternSeed'] as int?,
);
}

Map<String, dynamic> toJson() {
return {
'entryId': entryId,
'category': category,
'filterCategory': filterCategory,
'itemId': itemId,
'stackKey': stackKey,
'title': title,
'subtitle': subtitle,
'imagePath': imagePath,
'rarity': rarity,
'sourceName': sourceName,
'sourceType': sourceType,
'acquiredAt': acquiredAt.toIso8601String(),
'isStatTrak': isStatTrak,
'isSouvenir': isSouvenir,
'floatValue': floatValue,
'exterior': exterior,
'patternSeed': patternSeed,
};
}
}
33 changes: 33 additions & 0 deletions lib/core/collection/collection_summary.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'collection_entry.dart';

class CollectionSummary {
final String stackKey;
final String category;
final String filterCategory;
final String title;
final String subtitle;
final String imagePath;
final String rarity;
final int count;
final DateTime latestAcquiredAt;
final double? bestFloat;
final bool hasStatTrak;
final bool hasSouvenir;
final CollectionEntry latestEntry;

const CollectionSummary({
required this.stackKey,
required this.category,
required this.filterCategory,
required this.title,
required this.subtitle,
required this.imagePath,
required this.rarity,
required this.count,
required this.latestAcquiredAt,
required this.bestFloat,
required this.hasStatTrak,
required this.hasSouvenir,
required this.latestEntry,
});
}
Loading
Loading