/// یک تورنومنتِ امتیازی (از GET /api/tournaments). class Tournament { final int id; final String title; final String description; final int entryFee; final List prizes; final int prizePool; final String status; // upcoming | active | ended final String startsAt; final String endsAt; final String startsLocal; // به وقتِ تهران (نمایشی) final String endsLocal; final int players; final bool joined; final int myPoints; final int myRank; // ۰ یعنی رتبه‌ای ندارد const Tournament({ required this.id, required this.title, required this.description, required this.entryFee, required this.prizes, required this.prizePool, required this.status, required this.startsAt, required this.endsAt, required this.startsLocal, required this.endsLocal, required this.players, required this.joined, required this.myPoints, required this.myRank, }); bool get isActive => status == 'active'; bool get isUpcoming => status == 'upcoming'; bool get isEnded => status == 'ended'; bool get canJoin => !joined && !isEnded; factory Tournament.fromJson(Map j) => Tournament( id: (j['id'] ?? 0) as int, title: (j['title'] ?? '') as String, description: (j['description'] ?? '') as String, entryFee: (j['entry_fee'] ?? 0) as int, prizes: ((j['prizes'] as List?) ?? const []) .map((e) => (e ?? 0) as int) .toList(), prizePool: (j['prize_pool'] ?? 0) as int, status: (j['status'] ?? 'ended') as String, startsAt: (j['starts_at'] ?? '') as String, endsAt: (j['ends_at'] ?? '') as String, startsLocal: (j['starts_local'] ?? '') as String, endsLocal: (j['ends_local'] ?? '') as String, players: (j['players'] ?? 0) as int, joined: (j['joined'] ?? false) as bool, myPoints: (j['my_points'] ?? 0) as int, myRank: (j['my_rank'] ?? 0) as int, ); } /// یک ردیفِ جدولِ رده‌بندیِ تورنومنت. class TournamentStanding { final int rank; final int userId; final String name; final String avatar; final int points; final int wins; final int games; final int prize; const TournamentStanding({ required this.rank, required this.userId, required this.name, required this.avatar, required this.points, required this.wins, required this.games, required this.prize, }); /// seedِ آواتار: آواتارِ انتخابی، وگرنه نام. String get avatarSeed => avatar.isNotEmpty ? avatar : name; factory TournamentStanding.fromJson(Map j) => TournamentStanding( rank: (j['rank'] ?? 0) as int, userId: (j['user_id'] ?? 0) as int, name: (j['name'] ?? '') as String, avatar: (j['avatar'] ?? '') as String, points: (j['points'] ?? 0) as int, wins: (j['wins'] ?? 0) as int, games: (j['games'] ?? 0) as int, prize: (j['prize'] ?? 0) as int, ); }