From 8dc7454e263a3a1f5c49b8569ea7e05f72eecf92 Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Tue, 28 Mar 2023 19:09:35 +0200 Subject: [PATCH] Storage of gameDetails and players in it done :white_check_mark: --- .../lib/database/fields/PlayerFields.dart | 10 ++ .../database/mappers/GameDetailMapper.dart | 17 +-- .../lib/database/mappers/GameMapper.dart | 5 +- .../lib/database/mappers/PlayerMapper.dart | 21 +++ .../lib/database/sqlflite/BowlInDatabase.dart | 132 +++++++++++++++--- Sources/bowlin_project/lib/main.dart | 1 + .../bowlin_project/lib/model/GamePlayer.dart | 1 + .../lib/model/IGameManager.dart | 1 + .../lib/model/LocalManager/GameManager.dart | 12 +- .../lib/model/LocalManager/LocalData.dart | 4 + .../lib/model/LocalManager/UserManager.dart | 10 +- .../lib/model/StubManager/GameManager.dart | 4 + 12 files changed, 179 insertions(+), 39 deletions(-) create mode 100644 Sources/bowlin_project/lib/database/fields/PlayerFields.dart create mode 100644 Sources/bowlin_project/lib/database/mappers/PlayerMapper.dart diff --git a/Sources/bowlin_project/lib/database/fields/PlayerFields.dart b/Sources/bowlin_project/lib/database/fields/PlayerFields.dart new file mode 100644 index 0000000..b927bef --- /dev/null +++ b/Sources/bowlin_project/lib/database/fields/PlayerFields.dart @@ -0,0 +1,10 @@ +class PlayerFields { + static final List values = [ + idGame, name, image + ]; + + static final String idGame = '_idGame'; + static final String name = '_name'; + static final String image = '_image'; +} + diff --git a/Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart b/Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart index a185d20..abeaa3b 100644 --- a/Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart +++ b/Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart @@ -1,6 +1,6 @@ import 'package:bowl_in/model/GameDetail.dart'; -import '../../model/User.dart'; +import '../../model/Player.dart'; import '../fields/GameDetailFields.dart'; class GameDetailMapper { @@ -13,13 +13,14 @@ class GameDetailMapper { }; } - static GameDetail toModel(Map json, User winner) { + static GameDetail toModel( + Map json, Player? winner, List players) { + String dateString = json[GameDetailFields.date]; return GameDetail( - json[GameDetailFields.id], - json[GameDetailFields.date], - json[winner], - json[GameDetailFields.host], - [], - ); + json[GameDetailFields.id], + DateTime.parse(dateString), + winner, + json[GameDetailFields.host], + players); } } diff --git a/Sources/bowlin_project/lib/database/mappers/GameMapper.dart b/Sources/bowlin_project/lib/database/mappers/GameMapper.dart index 44aef95..1191460 100644 --- a/Sources/bowlin_project/lib/database/mappers/GameMapper.dart +++ b/Sources/bowlin_project/lib/database/mappers/GameMapper.dart @@ -1,4 +1,5 @@ import 'package:bowl_in/model/Game.dart'; +import '../../model/Player.dart'; import '../../model/User.dart'; import '../fields/GameFields.dart'; @@ -12,12 +13,12 @@ class GameMapper { }; } - static Game toModel(Map json) { + static Game toModel(Map json, List players) { return Game( json[GameFields.id], DateTime.parse(json[GameFields.date]), json[GameFields.pointsCurrentUser], - [], + players ); } } diff --git a/Sources/bowlin_project/lib/database/mappers/PlayerMapper.dart b/Sources/bowlin_project/lib/database/mappers/PlayerMapper.dart new file mode 100644 index 0000000..d6ca2f2 --- /dev/null +++ b/Sources/bowlin_project/lib/database/mappers/PlayerMapper.dart @@ -0,0 +1,21 @@ +import 'package:bowl_in/database/fields/PlayerFields.dart'; + +import '../../model/Game.dart'; +import '../../model/Player.dart'; + +class PlayerMapper { + static Map toJson(Player player, Game game) { + return { + PlayerFields.idGame: game.id, + PlayerFields.name: player.name, + PlayerFields.image: player.image, + }; + } + + static Player toModel(Map json) { + return Player( + json[PlayerFields.name], + json[PlayerFields.image] + ); + } +} diff --git a/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart b/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart index b79d556..b0c418f 100644 --- a/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart +++ b/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart @@ -1,15 +1,20 @@ +import 'package:bowl_in/database/fields/PlayerFields.dart'; import 'package:bowl_in/database/mappers/GameMapper.dart'; +import 'package:bowl_in/database/mappers/PlayerMapper.dart'; import 'package:bowl_in/database/mappers/StatMapper.dart'; import 'package:bowl_in/model/Game.dart'; +import 'package:bowl_in/model/GameDetail.dart'; import 'package:bowl_in/model/User.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; +import '../../model/Player.dart'; import '../../model/Stat.dart'; import '../fields/GameDetailFields.dart'; import '../fields/GameFields.dart'; import '../fields/StatFields.dart'; import '../fields/UserFields.dart'; +import '../mappers/GameDetailMapper.dart'; import '../mappers/UserMapper.dart'; class BowlInDatabase { @@ -25,6 +30,7 @@ class BowlInDatabase { static const String tableGame = 'games'; static const String tableGameDetail = 'gameDetails'; static const String tableStat = 'stats'; + static const String tablePlayer = 'players'; Future get database async { if (_database != null) return _database!; @@ -38,7 +44,7 @@ class BowlInDatabase { final path = join(dbPath, filePath); return await openDatabase(path, - version: 1, onCreate: _createDB, onUpgrade: _upgradeDB); + version: 6, onCreate: _createDB, onUpgrade: _upgradeDB); } Future _createDB(Database db, int version) async { @@ -72,7 +78,7 @@ CREATE TABLE $tableGameDetail ( ${GameDetailFields.id} $idType, ${GameDetailFields.date} $textType, ${GameDetailFields.nameWinner} $textType, - ${GameDetailFields.host} $textType + ${GameDetailFields.host} $integerType ) '''); @@ -89,15 +95,26 @@ CREATE TABLE $tableStat ( ${StatFields.avgPinsPerRound} $realType, FOREIGN KEY(${StatFields.idUser}) REFERENCES $tableUser(${UserFields.id}) ) +'''); + + await db.execute(''' +CREATE TABLE $tablePlayer ( + id $idType, + ${PlayerFields.name} $textType, + ${PlayerFields.image} $textType, + ${PlayerFields.idGame} $integerType, + FOREIGN KEY(${PlayerFields.idGame}) REFERENCES $tableGame(${GameFields.id}) +) '''); } Future _upgradeDB(Database db, int oldVersion, int newVersion) async { - if (oldVersion == 5) { + if (oldVersion < 6 ) { await db.execute('DROP TABLE IF EXISTS $tableUser'); await db.execute('DROP TABLE IF EXISTS $tableGame'); await db.execute('DROP TABLE IF EXISTS $tableGameDetail'); await db.execute('DROP TABLE IF EXISTS $tableStat'); + await db.execute('DROP TABLE IF EXISTS $tablePlayer'); await _createDB(db, newVersion); } } @@ -121,14 +138,13 @@ CREATE TABLE $tableStat ( User user; if (stat != null) { user = UserMapper.toModel(result.first, stat); - } - else { + } else { user = UserMapper.toModel(result.first, Stat.empty()); } - //final games = await readGame(id); - //for (var game in games!) { - //user.games.add(game); - //} + final games = await readGame(id); + for (var game in games) { + user.games.add(game); + } return user; } else { return null; @@ -146,7 +162,21 @@ CREATE TABLE $tableStat ( where: '${StatFields.idUser} = ?', whereArgs: [user.id]); // Insert new games for the user - //await createGame(user); + for (var game in user.games) { + var result = await txn.query(tableGame, + where: '${GameFields.id} = ? AND ${GameFields.userId} = ?', + whereArgs: [game.id, user.id]); + if (result.isNotEmpty) { + await txn.update(tableGame, GameMapper.toJson(game, user), + where: '${GameFields.id} = ? AND ${GameFields.userId} = ?', + whereArgs: [game.id, user.id]); + } else { + await txn.insert(tableGame, GameMapper.toJson(game, user)); + for (var player in game.players) { + await txn.insert(tablePlayer, PlayerMapper.toJson(player, game)); + } + } + } }); } @@ -166,6 +196,48 @@ CREATE TABLE $tableStat ( // GameDetail + Future createGameDetail(GameDetail gameDetail) async { + final db = await instance.database; + + await db.transaction((txn) async { + await txn.insert(tableGameDetail, GameDetailMapper.toJson(gameDetail)); + }); + } + + Future> readGameDetail() async { + final db = await instance.database; + final result = await db.query(tableGameDetail); + + if (result.isNotEmpty) { + List gameDetails = []; + for (var gameDetail in result) { + List players = []; + Player? winner = null; + final resultPlayer = await db.query(tablePlayer, + where: '${PlayerFields.idGame} = ?', + whereArgs: [gameDetail[GameDetailFields.id]]); + for (var player in resultPlayer) { + var winner; + var rPlayer = PlayerMapper.toModel(player); + players.add(rPlayer); + if (rPlayer.name == gameDetail[GameDetailFields.nameWinner]) { + winner = rPlayer; + } + } + gameDetails.add(GameDetailMapper.toModel(gameDetail, winner, players)); + } + return gameDetails; + } else { + return []; + } + } + + Future deleteGameDetail() async { + final db = await instance.database; + + return await db.delete(tableGameDetail); + } + // Game Future createGame(User user) async { @@ -178,30 +250,45 @@ CREATE TABLE $tableStat ( }); } - Future?> readGame(int id) async { + Future> readGame(int id) async { final db = await instance.database; - final result = await db.query(tableGame, - where: '${GameFields.userId} = ?', whereArgs: [id]); + final result = await db + .query(tableGame, where: '${GameFields.userId} = ?', whereArgs: [id]); if (result.isNotEmpty) { List games = []; for (var game in result) { - games.add(GameMapper.toModel(game)); + List players = []; + final resultPlayer = await db.query(tablePlayer, + where: '${PlayerFields.idGame} = ?', whereArgs: [game[GameFields.id]]); + for (var player in resultPlayer) { + players.add(PlayerMapper.toModel(player)); + } + games.add(GameMapper.toModel(game, players)); + players = []; } return games; } else { - return null; + return []; } } Future deleteGame(int id) async { final db = await instance.database; - return await db.delete( - tableGame, - where: '${GameFields.userId} = ?', - whereArgs: [id], - ); + return await db.transaction((txn) async { + await txn.delete( + tablePlayer, + where: '${PlayerFields.idGame} IN (SELECT ${GameFields.id} FROM $tableGame WHERE ${GameFields.userId} = ?)', + whereArgs: [id], + ); + + return await txn.delete( + tableGame, + where: '${GameFields.userId} = ?', + whereArgs: [id], + ); + }); } // Stat @@ -213,8 +300,8 @@ CREATE TABLE $tableStat ( Future readStat(int id) async { final db = await instance.database; - final result = await db.query(tableStat, - where: '${StatFields.idUser} = ?', whereArgs: [id]); + final result = await db + .query(tableStat, where: '${StatFields.idUser} = ?', whereArgs: [id]); if (result.isNotEmpty) { Stat stat = StatMapper.toModel(result.first); @@ -240,7 +327,6 @@ CREATE TABLE $tableStat ( where: '${StatFields.idUser} = ?', whereArgs: [id], ); - } Future close() async { diff --git a/Sources/bowlin_project/lib/main.dart b/Sources/bowlin_project/lib/main.dart index d6faae1..e4c08fa 100644 --- a/Sources/bowlin_project/lib/main.dart +++ b/Sources/bowlin_project/lib/main.dart @@ -1,4 +1,5 @@ import 'package:bowl_in/model/LocalManager/LocalData.dart'; +import 'package:bowl_in/model/StubManager/StubData.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:bowl_in/config/app_router.dart'; diff --git a/Sources/bowlin_project/lib/model/GamePlayer.dart b/Sources/bowlin_project/lib/model/GamePlayer.dart index 7eb41df..ec4d40e 100644 --- a/Sources/bowlin_project/lib/model/GamePlayer.dart +++ b/Sources/bowlin_project/lib/model/GamePlayer.dart @@ -41,6 +41,7 @@ class GamePlayer { game.computeScores(); _parent.userMgr.saveUser(_parent.userCurrent); + _parent.gameMgr.saveGame(_game); context?.go("/scoreboard", extra: game); } else { print("IN GAME : " + currentRoundIndex.toString()); diff --git a/Sources/bowlin_project/lib/model/IGameManager.dart b/Sources/bowlin_project/lib/model/IGameManager.dart index 2b4eff8..c0ee256 100644 --- a/Sources/bowlin_project/lib/model/IGameManager.dart +++ b/Sources/bowlin_project/lib/model/IGameManager.dart @@ -3,6 +3,7 @@ import 'Player.dart'; abstract class IGameManager { GameDetail getGameById(int id); + saveGame(GameDetail gameDetail); List getGamesByPlayerId(int id); List getGamesByPlayer(Player user); List getGamesByPlayers(List users); diff --git a/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart b/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart index dc111f7..e2f7b70 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart @@ -9,9 +9,15 @@ class GameManager extends IGameManager { final LocalData parent; // Constructor - GameManager(this.parent); + GameManager(this.parent){ + _initGame(); + } // Methods + _initGame() async { + parent.gameDetails = await parent.database.readGameDetail(); + } + GameDetail getGameById(int id) { for (var element in parent.gameDetails) { if (element.id == id) { @@ -21,6 +27,10 @@ class GameManager extends IGameManager { throw Exception("Game not found."); } + saveGame(GameDetail gameDetail) async { + await parent.database.createGameDetail(gameDetail); + } + List getGamesByPlayerId(int id) { List games = []; for (var element in parent.gameDetails) { diff --git a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart index 3dfb52d..b548dd9 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart @@ -16,4 +16,8 @@ class LocalData extends IManager { List get gameDetails => _gameDetails; + set gameDetails(List gameDetails) { + _gameDetails = gameDetails; + } + } diff --git a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart index 250fc30..acb8d37 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart @@ -9,18 +9,18 @@ class UserManager extends IUserManager { // Constructor UserManager(this.parent) : super(AuthManager(parent)) { - //User user = User(0, "Victor", "./assets/images/image_user_red.png", "", [], []); - //saveUser(user); - //parent.database.deleteUser(0); - //test(); _initUser(); } _initUser() async { + //await parent.database.deleteGameDetail(); + //await parent.database.deleteUser(0); + //User crUser = User(0, "Lucas", "./assets/images/image_user_red.png", "", [], []); + //await saveUser(crUser); var user = await parent.database.readUser(0); if (user == null) { User user2 = - User(1, "Unknown", "./assets/images/image_user_cyan.png", "", [], []); + User(0, "Unknown", "./assets/images/image_user_pink.png", "", [], []); parent.userCurrent = user2; } else { parent.userCurrent = user; diff --git a/Sources/bowlin_project/lib/model/StubManager/GameManager.dart b/Sources/bowlin_project/lib/model/StubManager/GameManager.dart index 63c878e..96aacaf 100644 --- a/Sources/bowlin_project/lib/model/StubManager/GameManager.dart +++ b/Sources/bowlin_project/lib/model/StubManager/GameManager.dart @@ -22,6 +22,10 @@ class GameManager extends IGameManager { throw Exception("Game not found."); } + saveGame(GameDetail gameDetail) { + return ; + } + List getGamesByPlayerId(int id) { List games = []; for (var element in parent.gameDetails) {