feat: refactor code
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
// موجودیتهای وضعیت بازی (نگاشت از پیامهای WebSocket سرور).
|
||||
|
||||
class GamePlayer {
|
||||
final int seat;
|
||||
final String name;
|
||||
final bool bot;
|
||||
final bool connected;
|
||||
|
||||
GamePlayer.fromJson(Map<String, dynamic> j)
|
||||
: seat = (j['seat'] ?? 0) as int,
|
||||
name = (j['name'] ?? '') as String,
|
||||
bot = (j['bot'] ?? false) as bool,
|
||||
connected = (j['connected'] ?? false) as bool;
|
||||
}
|
||||
|
||||
class TrickCard {
|
||||
final int seat;
|
||||
final String card;
|
||||
TrickCard(this.seat, this.card);
|
||||
factory TrickCard.fromJson(Map<String, dynamic> j) =>
|
||||
TrickCard((j['seat'] ?? 0) as int, (j['card'] ?? '') as String);
|
||||
}
|
||||
|
||||
/// نمای وضعیت بازی برای بازیکن جاری (پیام type=state).
|
||||
class GameState {
|
||||
final String room;
|
||||
final String phase; // choose_trump | playing | hand_over | game_over
|
||||
final int yourSeat;
|
||||
final int hakem;
|
||||
final int turn;
|
||||
final String? trump;
|
||||
final bool trickDone;
|
||||
final List<String> yourHand;
|
||||
final List<int> handCounts;
|
||||
final List<TrickCard> trick;
|
||||
final String? leadSuit;
|
||||
final List<int> tricksWon;
|
||||
final List<int> scores;
|
||||
final int targetScore;
|
||||
final List<GamePlayer> players;
|
||||
|
||||
GameState({
|
||||
required this.room,
|
||||
required this.phase,
|
||||
required this.yourSeat,
|
||||
required this.hakem,
|
||||
required this.turn,
|
||||
required this.trump,
|
||||
required this.trickDone,
|
||||
required this.yourHand,
|
||||
required this.handCounts,
|
||||
required this.trick,
|
||||
required this.leadSuit,
|
||||
required this.tricksWon,
|
||||
required this.scores,
|
||||
required this.targetScore,
|
||||
required this.players,
|
||||
});
|
||||
|
||||
factory GameState.fromJson(Map<String, dynamic> j) {
|
||||
List<int> ints(dynamic v) =>
|
||||
((v as List?) ?? []).map((e) => (e as num).toInt()).toList();
|
||||
return GameState(
|
||||
room: (j['room'] ?? '') as String,
|
||||
phase: (j['phase'] ?? '') as String,
|
||||
yourSeat: (j['your_seat'] ?? 0) as int,
|
||||
hakem: (j['hakem'] ?? 0) as int,
|
||||
turn: (j['turn'] ?? 0) as int,
|
||||
trump: j['trump'] as String?,
|
||||
trickDone: (j['trick_done'] ?? false) as bool,
|
||||
yourHand:
|
||||
((j['your_hand'] as List?) ?? []).map((e) => e as String).toList(),
|
||||
handCounts: ints(j['hand_counts']),
|
||||
trick: ((j['trick'] as List?) ?? [])
|
||||
.map((e) => TrickCard.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||
.toList(),
|
||||
leadSuit: j['lead_suit'] as String?,
|
||||
tricksWon: ints(j['tricks_won']),
|
||||
scores: ints(j['scores']),
|
||||
targetScore: (j['target_score'] ?? 7) as int,
|
||||
players: ((j['players'] as List?) ?? [])
|
||||
.map((e) => GamePlayer.fromJson(Map<String, dynamic>.from(e as Map)))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
bool get isMyTurn => turn == yourSeat;
|
||||
bool get amHakem => hakem == yourSeat;
|
||||
GamePlayer? playerAt(int seat) =>
|
||||
players.where((p) => p.seat == seat).cast<GamePlayer?>().firstOrNull;
|
||||
}
|
||||
|
||||
/// نتیجهی یک هَند (پیام type=hand_over).
|
||||
class HandResult {
|
||||
final int winnerTeam;
|
||||
final bool kot;
|
||||
final bool hakemKot;
|
||||
final int points;
|
||||
final List<int> scores;
|
||||
HandResult.fromJson(Map<String, dynamic> j)
|
||||
: winnerTeam = (j['winner_team'] ?? 0) as int,
|
||||
kot = (j['kot'] ?? false) as bool,
|
||||
hakemKot = (j['hakem_kot'] ?? false) as bool,
|
||||
points = (j['points'] ?? 0) as int,
|
||||
scores =
|
||||
((j['scores'] as List?) ?? []).map((e) => (e as num).toInt()).toList();
|
||||
}
|
||||
|
||||
/// نتیجهی پایان بازی (پیام type=game_over).
|
||||
class GameOver {
|
||||
final int winnerTeam;
|
||||
final List<int> scores;
|
||||
GameOver.fromJson(Map<String, dynamic> j)
|
||||
: winnerTeam = (j['winner_team'] ?? 0) as int,
|
||||
scores =
|
||||
((j['scores'] as List?) ?? []).map((e) => (e as num).toInt()).toList();
|
||||
}
|
||||
|
||||
extension FirstOrNullExt<E> on Iterable<E> {
|
||||
E? get firstOrNull {
|
||||
final it = iterator;
|
||||
return it.moveNext() ? it.current : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/// نوع میز (از catalog.table_tiers در GET /api/shop).
|
||||
class TableTier {
|
||||
final String id;
|
||||
final String title;
|
||||
final int hands;
|
||||
final int entry;
|
||||
final int prize;
|
||||
final int xp;
|
||||
final int trophy;
|
||||
|
||||
const TableTier({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.hands,
|
||||
required this.entry,
|
||||
required this.prize,
|
||||
required this.xp,
|
||||
required this.trophy,
|
||||
});
|
||||
|
||||
factory TableTier.fromJson(Map<String, dynamic> j) => TableTier(
|
||||
id: j['id'] as String,
|
||||
title: j['title'] as String,
|
||||
hands: (j['hands'] ?? 0) as int,
|
||||
entry: (j['entry'] ?? 0) as int,
|
||||
prize: (j['prize'] ?? 0) as int,
|
||||
xp: (j['xp'] ?? 0) as int,
|
||||
trophy: (j['trophy'] ?? 0) as int,
|
||||
);
|
||||
}
|
||||
|
||||
/// اطلاعات سهمیهی میزهای خصوصی (GET /api/tables/info).
|
||||
class TablesInfo {
|
||||
final int remaining;
|
||||
final bool unlimited;
|
||||
const TablesInfo(this.remaining, this.unlimited);
|
||||
|
||||
factory TablesInfo.fromJson(Map<String, dynamic> j) => TablesInfo(
|
||||
(j['remaining'] ?? 0) as int,
|
||||
(j['unlimited'] ?? false) as bool,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import '../../../../core/network/ws_client.dart';
|
||||
import '../../../../core/resources/data_state.dart';
|
||||
import '../entities/table_entities.dart';
|
||||
|
||||
/// قرارداد دادهٔ بازی: بخش realtime (سوکت) + بخش HTTP (میزها/سهمیه).
|
||||
abstract class GameRepository {
|
||||
// --- realtime ---
|
||||
Stream<Map<String, dynamic>> get messages;
|
||||
Stream<WsStatus> get status;
|
||||
Future<void> connect();
|
||||
void send(Map<String, dynamic> msg);
|
||||
Future<void> disconnect();
|
||||
|
||||
// --- HTTP ---
|
||||
Future<DataState<List<TableTier>>> getTiers();
|
||||
Future<DataState<TablesInfo>> getTablesInfo();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import '../../../../core/resources/data_state.dart';
|
||||
import '../../../../core/usecase/use_case.dart';
|
||||
import '../entities/table_entities.dart';
|
||||
import '../repository/game_repository.dart';
|
||||
|
||||
class GetTablesInfoUseCase
|
||||
implements UseCase<DataState<TablesInfo>, NoParams> {
|
||||
final GameRepository repository;
|
||||
GetTablesInfoUseCase(this.repository);
|
||||
|
||||
@override
|
||||
Future<DataState<TablesInfo>> call(NoParams params) =>
|
||||
repository.getTablesInfo();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import '../../../../core/resources/data_state.dart';
|
||||
import '../../../../core/usecase/use_case.dart';
|
||||
import '../entities/table_entities.dart';
|
||||
import '../repository/game_repository.dart';
|
||||
|
||||
class GetTiersUseCase
|
||||
implements UseCase<DataState<List<TableTier>>, NoParams> {
|
||||
final GameRepository repository;
|
||||
GetTiersUseCase(this.repository);
|
||||
|
||||
@override
|
||||
Future<DataState<List<TableTier>>> call(NoParams params) =>
|
||||
repository.getTiers();
|
||||
}
|
||||
Reference in New Issue
Block a user