From 0e265bbead3357b8965634db3c32b9f2551c6067 Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Tue, 21 Mar 2023 11:51:48 +0100 Subject: [PATCH 1/7] Readjust the LocalManager of louison and new functions in the UserManager :white_check_mark: --- .idea/Bowl_in.iml | 1 - .../bowlin_project/lib/model/IManager.dart | 2 - .../lib/model/LocalManager/AuthManager.dart | 16 ++++ .../lib/model/LocalManager/GameManager.dart | 59 ++++++++++++++ .../lib/model/LocalManager/LocalData.dart | 19 +++++ .../lib/model/LocalManager/UserManager.dart | 78 +++++++++++++++++++ .../lib/model/StubManager/AuthManager.dart | 4 +- .../lib/model/StubManager/StubData.dart | 70 ++--------------- Sources/bowlin_project/pubspec.lock | 8 ++ Sources/bowlin_project/pubspec.yaml | 1 + 10 files changed, 191 insertions(+), 67 deletions(-) create mode 100644 Sources/bowlin_project/lib/model/LocalManager/AuthManager.dart create mode 100644 Sources/bowlin_project/lib/model/LocalManager/GameManager.dart create mode 100644 Sources/bowlin_project/lib/model/LocalManager/LocalData.dart create mode 100644 Sources/bowlin_project/lib/model/LocalManager/UserManager.dart diff --git a/.idea/Bowl_in.iml b/.idea/Bowl_in.iml index f1b2d07..01dd66f 100644 --- a/.idea/Bowl_in.iml +++ b/.idea/Bowl_in.iml @@ -10,6 +10,5 @@ - \ No newline at end of file diff --git a/Sources/bowlin_project/lib/model/IManager.dart b/Sources/bowlin_project/lib/model/IManager.dart index 00ecb8c..3b1932f 100644 --- a/Sources/bowlin_project/lib/model/IManager.dart +++ b/Sources/bowlin_project/lib/model/IManager.dart @@ -2,10 +2,8 @@ import 'package:bowl_in/model/GameDetail.dart'; import 'package:bowl_in/model/GamePlayer.dart'; import 'User.dart'; -import 'Game.dart'; import 'IUserManager.dart'; import 'IGameManager.dart'; -import 'Game.dart'; abstract class IManager { late User _userCurrent; diff --git a/Sources/bowlin_project/lib/model/LocalManager/AuthManager.dart b/Sources/bowlin_project/lib/model/LocalManager/AuthManager.dart new file mode 100644 index 0000000..e97923f --- /dev/null +++ b/Sources/bowlin_project/lib/model/LocalManager/AuthManager.dart @@ -0,0 +1,16 @@ +import 'package:bowl_in/model/IAuthManager.dart'; +import 'package:bowl_in/model/LocalManager/LocalData.dart'; + +class AuthManager extends IAuthManager { + final LocalData parent; + + // Constructor + AuthManager(this.parent); + + @override + bool verifiedUser(String mail, String password) { + // TODO: implement verifiedUser + throw UnimplementedError(); + } + +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart b/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart new file mode 100644 index 0000000..b93f3a0 --- /dev/null +++ b/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart @@ -0,0 +1,59 @@ +import 'package:bowl_in/model/GameDetail.dart'; +import 'package:bowl_in/model/IGameManager.dart'; +import 'package:bowl_in/model/LocalManager/LocalData.dart'; +import 'package:bowl_in/model/Player.dart'; + +class GameManager extends IGameManager { + final LocalData parent; + + // Constructor + GameManager(this.parent); + + @override + addGame(GameDetail gd) { + // TODO: implement addGame + throw UnimplementedError(); + } + + @override + GameDetail getGameById(int id) { + // TODO: implement getGameById + throw UnimplementedError(); + } + + @override + List getGamesByPlayer(Player user) { + // TODO: implement getGamesByPlayer + throw UnimplementedError(); + } + + @override + List getGamesByPlayerId(int id) { + // TODO: implement getGamesByPlayerId + throw UnimplementedError(); + } + + @override + List getGamesByPlayers(List users) { + // TODO: implement getGamesByPlayers + throw UnimplementedError(); + } + + @override + int getNextId() { + // TODO: implement getNextId + throw UnimplementedError(); + } + + @override + List getPlayersByIdGame(int id) { + // TODO: implement getPlayersByIdGame + throw UnimplementedError(); + } + + @override + Map getRankByIdGame(int id) { + // TODO: implement getRankByIdGame + throw UnimplementedError(); + } +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart new file mode 100644 index 0000000..ebef5aa --- /dev/null +++ b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart @@ -0,0 +1,19 @@ +import 'package:bowl_in/model/IManager.dart'; +import 'package:localstorage/localstorage.dart'; + +import '../IGameManager.dart'; +import '../IUserManager.dart'; +import 'GameManager.dart'; +import 'UserManager.dart'; + +class LocalData extends IManager{ + late IUserManager _userMgr; + late IGameManager _gameMgr; + + final LocalStorage storage = LocalStorage('local_key'); + + LocalData() { + _userMgr = UserManager(this); + _gameMgr = GameManager(this); + } +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart new file mode 100644 index 0000000..b025fc7 --- /dev/null +++ b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart @@ -0,0 +1,78 @@ +import 'dart:convert'; + +import 'package:bowl_in/model/IUserManager.dart'; +import 'package:bowl_in/model/LocalManager/LocalData.dart'; +import 'package:bowl_in/model/Player.dart'; +import 'package:bowl_in/model/User.dart'; + +import '../Stat.dart'; +import 'AuthManager.dart'; + +class UserManager extends IUserManager { + final LocalData parent; + + // Constructor + UserManager(this.parent) : super(AuthManager(parent)) { + _initUser(); + } + + _initUser() { + String userJson = parent.storage.getItem('user'); + + if (userJson != null) { + Map userMap = json.decode(userJson); + User user = User( + userMap['_id'], + userMap['name'], + userMap['image'], + userMap['_mail'], + [], + [], + new Stat(0, 0, 0, 0, 0, 0, 2.0, 3.0), + ); + parent.userCurrent = user; + } else { + parent.userCurrent = new User( + 1, + "Unknown", + "./assets/images/image_user_cyan.png", + "david.d_almeida@etu.uca.fr", + [], + [], + Stat(0, 0, 0, 0, 0, 0, 0, 0)); + } + } + + saveUser(User user) { + String userJson = json.encode(userToMap(user)); + + parent.storage.setItem('user', userJson); + } + + Map userToMap(User user) { + return { + '_id': user.id, + 'name': user.name, + 'image': user.image, + '_mail': user.mail, + }; + } + + @override + List getRankingWithFriends() { + // TODO: implement getRankingWithFriends + throw UnimplementedError(); + } + + @override + Player getUserById(int id) { + // TODO: implement getUserById + throw UnimplementedError(); + } + + @override + List getUsersByName(String name) { + // TODO: implement getUsersByName + throw UnimplementedError(); + } +} diff --git a/Sources/bowlin_project/lib/model/StubManager/AuthManager.dart b/Sources/bowlin_project/lib/model/StubManager/AuthManager.dart index fc93912..bb63f3f 100644 --- a/Sources/bowlin_project/lib/model/StubManager/AuthManager.dart +++ b/Sources/bowlin_project/lib/model/StubManager/AuthManager.dart @@ -1,4 +1,5 @@ library StubLib; + import '../IAuthManager.dart'; import '../User.dart'; import 'StubData.dart'; @@ -8,6 +9,7 @@ class AuthManager extends IAuthManager { // Constructor AuthManager(this.parent); + // Methods bool verifiedUser(String mail, String password) { for (var user in parent.players) { @@ -18,4 +20,4 @@ class AuthManager extends IAuthManager { } return false; } -} \ No newline at end of file +} diff --git a/Sources/bowlin_project/lib/model/StubManager/StubData.dart b/Sources/bowlin_project/lib/model/StubManager/StubData.dart index 001b928..81afb95 100644 --- a/Sources/bowlin_project/lib/model/StubManager/StubData.dart +++ b/Sources/bowlin_project/lib/model/StubManager/StubData.dart @@ -51,15 +51,7 @@ class StubData extends IManager { Achievement("Win a game") ], [], - Stat( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0)), + Stat(0, 0, 0, 0, 0, 0, 0, 0)), User( 9, "Dave", @@ -82,15 +74,7 @@ class StubData extends IManager { Achievement("Win a game") ], [], - Stat( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0)), + Stat(0, 0, 0, 0, 0, 0, 0, 0)), User( 22, "Louison", @@ -102,15 +86,7 @@ class StubData extends IManager { Achievement("Win a game") ], [], - Stat( - 10, - 12, - 150, - 7, - 6, - 700, - 58.33, - 30.2)), + Stat(10, 12, 150, 7, 6, 700, 58.33, 30.2)), User( 23, "Owen", @@ -122,15 +98,7 @@ class StubData extends IManager { Achievement("Win a game") ], [], - Stat( - 10, - 12, - 10, - 7, - 6, - 700, - 58.33, - 30.2)), + Stat(10, 12, 10, 7, 6, 700, 58.33, 30.2)), User( 24, "LULU", @@ -142,15 +110,7 @@ class StubData extends IManager { Achievement("Win a game") ], [], - Stat( - 10, - 12, - 40, - 7, - 6, - 700, - 58.33, - 30.2)), + Stat(10, 12, 40, 7, 6, 700, 58.33, 30.2)), User( 25, "Raphael", @@ -162,25 +122,9 @@ class StubData extends IManager { Achievement("Win a game") ], [], - Stat( - 10, - 12, - 76, - 7, - 6, - 700, - 58.33, - 30.2)), + Stat(10, 12, 76, 7, 6, 700, 58.33, 30.2)), ], - Stat( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0)) + Stat(0, 0, 0, 0, 0, 0, 0, 0)) ]; List _gameDetails = []; diff --git a/Sources/bowlin_project/pubspec.lock b/Sources/bowlin_project/pubspec.lock index ee6d354..27cb5bf 100644 --- a/Sources/bowlin_project/pubspec.lock +++ b/Sources/bowlin_project/pubspec.lock @@ -224,6 +224,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + localstorage: + dependency: "direct main" + description: + name: localstorage + sha256: "1b5304491c85250b90807e0e2b3a6217d2739caea4871b820d42782572f880f4" + url: "https://pub.dev" + source: hosted + version: "4.0.1+2" logging: dependency: transitive description: diff --git a/Sources/bowlin_project/pubspec.yaml b/Sources/bowlin_project/pubspec.yaml index d4df740..45ba99c 100644 --- a/Sources/bowlin_project/pubspec.yaml +++ b/Sources/bowlin_project/pubspec.yaml @@ -40,6 +40,7 @@ dependencies: google_fonts: ^3.0.1 go_router: ^6.0.1 uuid: ^3.0.7 + localstorage: ^4.0.0+1 intl: ^0.18.0 -- 2.36.3 From 7d02d4747a0ab1cd958473a81f57aaaf05b7e8ce Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Wed, 22 Mar 2023 20:28:05 +0100 Subject: [PATCH 2/7] Adding sqflite and creating the database, mappers and User Field :hammer: --- .../lib/database/fields/StatFields.dart | 4 + .../lib/database/fields/UserFields.dart | 12 +++ .../lib/database/mappers/UserMapper.dart | 26 +++++++ .../lib/database/sqlflite/UserDataBase.dart | 75 +++++++++++++++++++ Sources/bowlin_project/lib/main.dart | 3 +- .../lib/model/LocalManager/LocalData.dart | 5 ++ .../lib/model/LocalManager/UserManager.dart | 28 +++---- Sources/bowlin_project/lib/model/Stat.dart | 13 ++++ .../lib/model/StubManager/StubData.dart | 1 - Sources/bowlin_project/lib/model/User.dart | 3 + Sources/bowlin_project/pubspec.lock | 56 ++++++++++---- Sources/bowlin_project/pubspec.yaml | 1 + 12 files changed, 196 insertions(+), 31 deletions(-) create mode 100644 Sources/bowlin_project/lib/database/fields/StatFields.dart create mode 100644 Sources/bowlin_project/lib/database/fields/UserFields.dart create mode 100644 Sources/bowlin_project/lib/database/mappers/UserMapper.dart create mode 100644 Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart diff --git a/Sources/bowlin_project/lib/database/fields/StatFields.dart b/Sources/bowlin_project/lib/database/fields/StatFields.dart new file mode 100644 index 0000000..554ba52 --- /dev/null +++ b/Sources/bowlin_project/lib/database/fields/StatFields.dart @@ -0,0 +1,4 @@ +class StatFields { + + +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/database/fields/UserFields.dart b/Sources/bowlin_project/lib/database/fields/UserFields.dart new file mode 100644 index 0000000..5999827 --- /dev/null +++ b/Sources/bowlin_project/lib/database/fields/UserFields.dart @@ -0,0 +1,12 @@ +class UserFields { + static final List values = [ + id, name, image, mail + ]; + + static final String id = '_id'; + static final String name = '_name'; + static final String image = '_image'; + static final String mail = '_mail'; + +} + diff --git a/Sources/bowlin_project/lib/database/mappers/UserMapper.dart b/Sources/bowlin_project/lib/database/mappers/UserMapper.dart new file mode 100644 index 0000000..97e313c --- /dev/null +++ b/Sources/bowlin_project/lib/database/mappers/UserMapper.dart @@ -0,0 +1,26 @@ +import '../../model/Stat.dart'; +import '../../model/User.dart'; +import '../fields/StatFields.dart'; + +class UserMapper { + static Map toJson(User user) { + return { + UserFields.id: user.id, + UserFields.name: user.name, + UserFields.image: user.image, + UserFields.mail: user.mail, + }; + } + + static User toModel(Map json) { + return User( + json[UserFields.id], + json[UserFields.name], + json[UserFields.image], + json[UserFields.mail], + [], + [], + Stat(0,0,0,0,0,0,0,0) + ); + } +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart b/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart new file mode 100644 index 0000000..b58fc78 --- /dev/null +++ b/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart @@ -0,0 +1,75 @@ +import 'package:bowl_in/model/User.dart'; +import 'package:path/path.dart'; +import 'package:sqflite/sqflite.dart'; + +import '../fields/UserFields.dart'; +import '../mappers/UserMapper.dart'; + +class UserDatabase { + static final UserDatabase instance = UserDatabase._init(); + + static Database? _database; + + UserDatabase._init(); + + Future get database async { + if (_database != null) return _database!; + + _database = await _initDB('user.db'); + return _database!; + } + + Future _initDB(String filePath) async { + final dbPath = await getDatabasesPath(); + final path = join(dbPath, filePath); + + return await openDatabase(path, version: 1, onCreate: _createDB); + } + + Future _createDB(Database db, int version) async { + final idType = 'INTEGER PRIMARY KEY AUTOINCREMENT'; + final textType = 'TEXT NOT NULL'; + final boolType = 'BOOLEAN NOT NULL'; + final integerType = 'INTEGER NOT NULL'; + + await db.execute(''' +CREATE TABLE $tableUser ( + ${UserFields.id} $idType, + ${UserFields.name} $boolType, + ${UserFields.image} $integerType, + ${UserFields.mail} $textType, + ) +'''); + } + + Future createUser(User user) async { + final db = await instance.database; + await db.insert(tableUser, UserMapper.toJson(user)); + } + + Future readUser(int id) async { + final db = await instance.database; + final result = await db.query( + tableUser, + where: '${UserFields.id} = ?', + whereArgs: [id]); + return result.isNotEmpty ? UserMapper.toModel(result.first) : null; + + } + + Future deleteUser(int id) async { + final db = await instance.database; + + return await db.delete( + tableUser, + where: '${UserFields.id} = ?', + whereArgs: [id], + ); + } + + Future close() async { + final db = await instance.database; + + db.close(); + } +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/main.dart b/Sources/bowlin_project/lib/main.dart index 1046f67..34c31fe 100644 --- a/Sources/bowlin_project/lib/main.dart +++ b/Sources/bowlin_project/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:bowl_in/model/LocalManager/LocalData.dart'; import 'package:bowl_in/views/game_screen.dart'; import 'package:bowl_in/views/ingame_screen.dart'; import 'package:bowl_in/views/main_screen.dart'; @@ -16,7 +17,7 @@ void main() { } class MyApp extends StatelessWidget { - static IManager controller = StubData(); + static IManager controller = LocalData(); const MyApp({super.key}); @override Widget build(BuildContext context) { diff --git a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart index ebef5aa..ad3ef50 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart @@ -16,4 +16,9 @@ class LocalData extends IManager{ _userMgr = UserManager(this); _gameMgr = GameManager(this); } + + IUserManager get userMgr => _userMgr; + + IGameManager get gameMgr => _gameMgr; + } \ No newline at end of file diff --git a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart index b025fc7..962ea22 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart @@ -16,10 +16,21 @@ class UserManager extends IUserManager { _initUser(); } - _initUser() { - String userJson = parent.storage.getItem('user'); + _initUser() async { + var userJson = await parent.storage.getItem('user'); + if (userJson == null || userJson =='') { + User user2 = User( + 1, + "Unknown", + "./assets/images/image_user_cyan.png", + "", + [], + [], + Stat(0, 0, 0, 0, 0, 0, 0, 0)); + parent.userCurrent = user2; - if (userJson != null) { + + } else { Map userMap = json.decode(userJson); User user = User( userMap['_id'], @@ -28,18 +39,9 @@ class UserManager extends IUserManager { userMap['_mail'], [], [], - new Stat(0, 0, 0, 0, 0, 0, 2.0, 3.0), + Stat(0, 0, 0, 0, 0, 0, 2.0, 3.0), ); parent.userCurrent = user; - } else { - parent.userCurrent = new User( - 1, - "Unknown", - "./assets/images/image_user_cyan.png", - "david.d_almeida@etu.uca.fr", - [], - [], - Stat(0, 0, 0, 0, 0, 0, 0, 0)); } } diff --git a/Sources/bowlin_project/lib/model/Stat.dart b/Sources/bowlin_project/lib/model/Stat.dart index d68fa57..6cf57b4 100644 --- a/Sources/bowlin_project/lib/model/Stat.dart +++ b/Sources/bowlin_project/lib/model/Stat.dart @@ -96,4 +96,17 @@ class Stat { avgPinsPerRound = ((avgPinsPerRound * (nbGames-1)) + (totalpins/10))/nbGames; } + + + // Serialize to JSON + Map toJson() => { + 'nbVictory': nbVictory, + 'nbGames': nbGames, + 'highscore': highscore, + 'nbStrikes': nbStrikes, + 'nbSpares': nbSpares, + 'nbScore': nbScore, + 'avgScore': avgScore, + 'avgPinsPerRound': avgPinsPerRound, + }; } diff --git a/Sources/bowlin_project/lib/model/StubManager/StubData.dart b/Sources/bowlin_project/lib/model/StubManager/StubData.dart index 81afb95..ae95609 100644 --- a/Sources/bowlin_project/lib/model/StubManager/StubData.dart +++ b/Sources/bowlin_project/lib/model/StubManager/StubData.dart @@ -25,7 +25,6 @@ class StubData extends IManager { _initGameDetails(); _initGame(); userCurrent = players[8] as User; - userCurrent.games = []; } IUserManager get userMgr => _userMgr; diff --git a/Sources/bowlin_project/lib/model/User.dart b/Sources/bowlin_project/lib/model/User.dart index b1740aa..0b0a8b9 100644 --- a/Sources/bowlin_project/lib/model/User.dart +++ b/Sources/bowlin_project/lib/model/User.dart @@ -1,3 +1,5 @@ +import 'package:bowl_in/database/fields/UserFields.dart'; + import 'Achievement.dart'; import 'Game.dart'; import 'Player.dart'; @@ -42,4 +44,5 @@ class User extends Player { set stat(Stat value) { _stat = value; } + } diff --git a/Sources/bowlin_project/pubspec.lock b/Sources/bowlin_project/pubspec.lock index 27cb5bf..248abaf 100644 --- a/Sources/bowlin_project/pubspec.lock +++ b/Sources/bowlin_project/pubspec.lock @@ -156,10 +156,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: b4bb06205ec607278b6fc23db238278417bca84a3905779cc68d1eb7afae37e2 + sha256: e2a90e1d4eed378ea12e0771be9e32766a2f8d2de3064e42f3a55f1b04fb8af8 url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.4.1" google_fonts: dependency: "direct main" description: @@ -276,34 +276,34 @@ packages: dependency: transitive description: name: path_provider - sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" + sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4 url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.0.14" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e" + sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" url: "https://pub.dev" source: hosted - version: "2.0.23" + version: "2.0.24" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972 + sha256: "12eee51abdf4d34c590f043f45073adbb45514a108bd9db4491547a2fd891059" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.2.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" url: "https://pub.dev" source: hosted - version: "2.1.9" + version: "2.1.10" path_provider_platform_interface: dependency: transitive description: @@ -316,10 +316,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" petitparser: dependency: transitive description: @@ -348,10 +348,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: ae73e842cdd27a3467a71d70cefd9b198538aab4fc7dde1d0e8c78c96225abf0 url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.1" process: dependency: transitive description: @@ -381,6 +381,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + sqflite: + dependency: "direct main" + description: + name: sqflite + sha256: "500d6fec583d2c021f2d25a056d96654f910662c64f836cd2063167b8f1fa758" + url: "https://pub.dev" + source: hosted + version: "2.2.6" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "963dad8c4aa2f814ce7d2d5b1da2f36f31bd1a439d8f27e3dc189bb9d26bc684" + url: "https://pub.dev" + source: hosted + version: "2.4.3" stack_trace: dependency: transitive description: @@ -405,6 +421,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" + url: "https://pub.dev" + source: hosted + version: "3.0.1" term_glyph: dependency: transitive description: @@ -465,10 +489,10 @@ packages: dependency: transitive description: name: xml - sha256: ac0e3f4bf00ba2708c33fbabbbe766300e509f8c82dbd4ab6525039813f7e2fb + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.2" yaml: dependency: transitive description: diff --git a/Sources/bowlin_project/pubspec.yaml b/Sources/bowlin_project/pubspec.yaml index 45ba99c..04e4716 100644 --- a/Sources/bowlin_project/pubspec.yaml +++ b/Sources/bowlin_project/pubspec.yaml @@ -42,6 +42,7 @@ dependencies: uuid: ^3.0.7 localstorage: ^4.0.0+1 intl: ^0.18.0 + sqflite: ^2.0.0+3 dev_dependencies: -- 2.36.3 From 73204ba03a5b2a76bb9e8c448ca1227a4eec69d3 Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Thu, 23 Mar 2023 18:57:32 +0100 Subject: [PATCH 3/7] Addition of the Game table and modifications of the ReadUser and UpdateUser functions :hammer: --- .../lib/database/fields/GameFields.dart | 10 +++ .../lib/database/mappers/GameMapper.dart | 24 ++++++++ .../lib/database/sqlflite/UserDataBase.dart | 61 ++++++++++++++++--- .../lib/model/LocalManager/UserManager.dart | 9 +-- Sources/bowlin_project/lib/model/User.dart | 2 - Sources/bowlin_project/pubspec.lock | 12 +--- Sources/bowlin_project/pubspec.yaml | 1 - 7 files changed, 93 insertions(+), 26 deletions(-) create mode 100644 Sources/bowlin_project/lib/database/fields/GameFields.dart create mode 100644 Sources/bowlin_project/lib/database/mappers/GameMapper.dart diff --git a/Sources/bowlin_project/lib/database/fields/GameFields.dart b/Sources/bowlin_project/lib/database/fields/GameFields.dart new file mode 100644 index 0000000..327d16a --- /dev/null +++ b/Sources/bowlin_project/lib/database/fields/GameFields.dart @@ -0,0 +1,10 @@ +class GameFields { + static final List values = [ + id, date, pointsCurrentUser, userId + ]; + + static final String id = '_id'; + static final String date = '_date'; + static final String pointsCurrentUser = '_points_current_user'; + static final String userId = '_user_id'; +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/database/mappers/GameMapper.dart b/Sources/bowlin_project/lib/database/mappers/GameMapper.dart new file mode 100644 index 0000000..0367e64 --- /dev/null +++ b/Sources/bowlin_project/lib/database/mappers/GameMapper.dart @@ -0,0 +1,24 @@ +import 'package:bowl_in/database/mappers/UserMapper.dart'; +import 'package:bowl_in/model/Game.dart'; +import '../../model/User.dart'; +import '../fields/GameFields.dart'; + +class GameMapper { + static Map toJson(Game game, User user) { + return { + GameFields.id: game.id, + GameFields.date: game.date.toIso8601String(), + GameFields.pointsCurrentUser: game.pointsCurrentUser, + GameFields.userId: user.id, + }; + } + + static Game toModel(Map json) { + return Game( + json[GameFields.id], + DateTime.parse(json[GameFields.date]), + json[GameFields.pointsCurrentUser], + [], + ); + } +} diff --git a/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart b/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart index 9b5393a..12cdd5b 100644 --- a/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart +++ b/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart @@ -1,12 +1,13 @@ +import 'package:bowl_in/database/mappers/GameMapper.dart'; import 'package:bowl_in/model/User.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; +import '../fields/GameFields.dart'; import '../fields/UserFields.dart'; import '../mappers/UserMapper.dart'; class UserDatabase { - UserDatabase(); static final UserDatabase instance = UserDatabase._init(); @@ -16,6 +17,7 @@ class UserDatabase { UserDatabase._init(); static const String tableUser = 'users'; + static const String tableGame = 'games'; Future get database async { if (_database != null) return _database!; @@ -28,14 +30,14 @@ class UserDatabase { final dbPath = await getDatabasesPath(); final path = join(dbPath, filePath); - return await openDatabase(path, version: 1, onCreate: _createDB); + return await openDatabase(path, version: 4, onCreate: _createDB, onUpgrade: _upgradeDB); } Future _createDB(Database db, int version) async { const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT'; const textType = 'TEXT NOT NULL'; const boolType = 'BOOLEAN NOT NULL'; - const integerType = 'INTEGER NOT NULL'; + final integerType = 'INTEGER NOT NULL'; await db.execute(''' CREATE TABLE $tableUser ( @@ -45,6 +47,24 @@ CREATE TABLE $tableUser ( ${UserFields.mail} $textType ) '''); + + await db.execute(''' +CREATE TABLE $tableGame ( + ${GameFields.id} $idType, + ${GameFields.date} $textType, + ${GameFields.pointsCurrentUser} $integerType, + ${GameFields.userId} $integerType, + FOREIGN KEY(${GameFields.userId}) REFERENCES $tableUser(${UserFields.id}) +) +'''); + } + + Future _upgradeDB(Database db, int oldVersion, int newVersion) async { + if (oldVersion < 4) { + await db.execute('DROP TABLE IF EXISTS $tableUser'); + await db.execute('DROP TABLE IF EXISTS $tableGame'); + await _createDB(db, newVersion); + } } Future createUser(User user) async { @@ -54,12 +74,35 @@ CREATE TABLE $tableUser ( Future readUser(int id) async { final db = await instance.database; - final result = await db.query( - tableUser, - where: '${UserFields.id} = ?', - whereArgs: [id]); - return result.isNotEmpty ? UserMapper.toModel(result.first) : null; + final result = await db + .query(tableUser, where: '${UserFields.id} = ?', whereArgs: [id]); + + if (result.isNotEmpty) { + User user = UserMapper.toModel(result.first); + final games = await db + .query(tableGame, where: '${GameFields.userId} = ?', whereArgs: [user.id]); + for (var game in games) { + user.games.add(GameMapper.toModel(game)); + } + return user; + } + else { + return null; + } + } + + Future updateUser(User user) async { + final db = await instance.database; + + await db.transaction((txn) async { + await txn.update(tableUser, UserMapper.toJson(user), + where: '${UserFields.id} = ?', whereArgs: [user.id]); + // Insert new games for the user + for (var game in user.games) { + await txn.insert(tableGame, GameMapper.toJson(game, user)); + } + }); } Future deleteUser(int id) async { @@ -77,4 +120,4 @@ CREATE TABLE $tableUser ( db.close(); } -} \ No newline at end of file +} diff --git a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart index 1386929..c88f5ec 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart @@ -2,6 +2,7 @@ import 'package:bowl_in/model/IUserManager.dart'; import 'package:bowl_in/model/LocalManager/LocalData.dart'; import 'package:bowl_in/model/Player.dart'; import 'package:bowl_in/model/User.dart'; +import '../Game.dart'; import 'AuthManager.dart'; class UserManager extends IUserManager { @@ -9,8 +10,9 @@ class UserManager extends IUserManager { // Constructor UserManager(this.parent) : super(AuthManager(parent)) { - saveUser( - User(0, "Lucas", "./assets/images/image_user_red.png", "", [], [])); + User user = User(0, "Dave", "./assets/images/image_user_red.png", "", [], []); + user.games.add(Game(0,DateTime.now(), 30, [])); + saveUser(user); _initUser(); } @@ -26,8 +28,7 @@ class UserManager extends IUserManager { } saveUser(User user) { - parent.userDatabase.deleteUser(0); - parent.userDatabase.createUser(user); + parent.userDatabase.updateUser(user); } Map userToMap(User user) { diff --git a/Sources/bowlin_project/lib/model/User.dart b/Sources/bowlin_project/lib/model/User.dart index fb1c2ac..7bcd9f9 100644 --- a/Sources/bowlin_project/lib/model/User.dart +++ b/Sources/bowlin_project/lib/model/User.dart @@ -1,5 +1,3 @@ -import 'package:bowl_in/database/fields/UserFields.dart'; - import 'Achievement.dart'; import 'Game.dart'; import 'Player.dart'; diff --git a/Sources/bowlin_project/pubspec.lock b/Sources/bowlin_project/pubspec.lock index 17478e3..e04bffe 100644 --- a/Sources/bowlin_project/pubspec.lock +++ b/Sources/bowlin_project/pubspec.lock @@ -156,10 +156,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: b90b9aaa7723ca7159a81c0cd3be8108c74c986c3fbc41d413fd82ea164733ea + sha256: e2a90e1d4eed378ea12e0771be9e32766a2f8d2de3064e42f3a55f1b04fb8af8 url: "https://pub.dev" source: hosted - version: "6.4.0" + version: "6.4.1" google_fonts: dependency: "direct main" description: @@ -224,14 +224,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" - localstorage: - dependency: "direct main" - description: - name: localstorage - sha256: "1b5304491c85250b90807e0e2b3a6217d2739caea4871b820d42782572f880f4" - url: "https://pub.dev" - source: hosted - version: "4.0.1+2" logging: dependency: transitive description: diff --git a/Sources/bowlin_project/pubspec.yaml b/Sources/bowlin_project/pubspec.yaml index 04e4716..a2e33e3 100644 --- a/Sources/bowlin_project/pubspec.yaml +++ b/Sources/bowlin_project/pubspec.yaml @@ -40,7 +40,6 @@ dependencies: google_fonts: ^3.0.1 go_router: ^6.0.1 uuid: ^3.0.7 - localstorage: ^4.0.0+1 intl: ^0.18.0 sqflite: ^2.0.0+3 -- 2.36.3 From b4b031f7dd4456e38a36b3cf78d1788efa4085eb Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Thu, 23 Mar 2023 21:17:44 +0100 Subject: [PATCH 4/7] Create Mapper and Field for GameDetails :white_check_mark: --- .../lib/database/fields/GameDetailFields.dart | 10 ++++++++ .../database/mappers/GameDetailMapper.dart | 25 +++++++++++++++++++ .../lib/database/mappers/GameMapper.dart | 1 - .../lib/database/sqlflite/UserDataBase.dart | 20 ++++++++++++--- Sources/bowlin_project/lib/main.dart | 3 ++- .../lib/model/LocalManager/LocalData.dart | 4 +-- 6 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 Sources/bowlin_project/lib/database/fields/GameDetailFields.dart create mode 100644 Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart diff --git a/Sources/bowlin_project/lib/database/fields/GameDetailFields.dart b/Sources/bowlin_project/lib/database/fields/GameDetailFields.dart new file mode 100644 index 0000000..8d30c01 --- /dev/null +++ b/Sources/bowlin_project/lib/database/fields/GameDetailFields.dart @@ -0,0 +1,10 @@ +class GameDetailFields { + static final List values = [ + id, date, nameWinner, host + ]; + + static final String id = '_id'; + static final String date = '_date'; + static final String nameWinner = '_winner_id'; + static final String host = '_host'; +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart b/Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart new file mode 100644 index 0000000..a185d20 --- /dev/null +++ b/Sources/bowlin_project/lib/database/mappers/GameDetailMapper.dart @@ -0,0 +1,25 @@ +import 'package:bowl_in/model/GameDetail.dart'; + +import '../../model/User.dart'; +import '../fields/GameDetailFields.dart'; + +class GameDetailMapper { + static Map toJson(GameDetail gameDetail) { + return { + GameDetailFields.id: gameDetail.id, + GameDetailFields.date: gameDetail.time.toIso8601String(), + GameDetailFields.nameWinner: gameDetail.winner?.name, + GameDetailFields.host: gameDetail.host + }; + } + + static GameDetail toModel(Map json, User winner) { + return GameDetail( + json[GameDetailFields.id], + json[GameDetailFields.date], + json[winner], + json[GameDetailFields.host], + [], + ); + } +} diff --git a/Sources/bowlin_project/lib/database/mappers/GameMapper.dart b/Sources/bowlin_project/lib/database/mappers/GameMapper.dart index 0367e64..44aef95 100644 --- a/Sources/bowlin_project/lib/database/mappers/GameMapper.dart +++ b/Sources/bowlin_project/lib/database/mappers/GameMapper.dart @@ -1,4 +1,3 @@ -import 'package:bowl_in/database/mappers/UserMapper.dart'; import 'package:bowl_in/model/Game.dart'; import '../../model/User.dart'; import '../fields/GameFields.dart'; diff --git a/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart b/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart index 12cdd5b..5104443 100644 --- a/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart +++ b/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart @@ -3,21 +3,23 @@ import 'package:bowl_in/model/User.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; +import '../fields/GameDetailFields.dart'; import '../fields/GameFields.dart'; import '../fields/UserFields.dart'; import '../mappers/UserMapper.dart'; -class UserDatabase { - UserDatabase(); +class BowlInDatabase { + BowlInDatabase(); - static final UserDatabase instance = UserDatabase._init(); + static final BowlInDatabase instance = BowlInDatabase._init(); static Database? _database; - UserDatabase._init(); + BowlInDatabase._init(); static const String tableUser = 'users'; static const String tableGame = 'games'; + static const String tableGameDetail = 'gameDetails'; Future get database async { if (_database != null) return _database!; @@ -56,6 +58,15 @@ CREATE TABLE $tableGame ( ${GameFields.userId} $integerType, FOREIGN KEY(${GameFields.userId}) REFERENCES $tableUser(${UserFields.id}) ) +'''); + + await db.execute(''' +CREATE TABLE $tableGameDetail ( + ${GameDetailFields.id} $idType, + ${GameDetailFields.date} $textType, + ${GameDetailFields.nameWinner} $textType, + ${GameDetailFields.host} $textType, +) '''); } @@ -63,6 +74,7 @@ CREATE TABLE $tableGame ( if (oldVersion < 4) { 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 _createDB(db, newVersion); } } diff --git a/Sources/bowlin_project/lib/main.dart b/Sources/bowlin_project/lib/main.dart index d6faae1..56cd39a 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'; @@ -10,7 +11,7 @@ void main() { } class MyApp extends StatelessWidget { - static IManager controller = LocalData(); + static IManager controller = StubData(); const MyApp({super.key}); diff --git a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart index a10fc94..eb840b5 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart @@ -1,10 +1,10 @@ +import 'package:bowl_in/database/sqlflite/UserDataBase.dart'; import 'package:bowl_in/model/IManager.dart'; -import '../../database/sqlflite/UserDataBase.dart'; import 'GameManager.dart'; import 'UserManager.dart'; class LocalData extends IManager { - final UserDatabase userDatabase = UserDatabase(); + final BowlInDatabase userDatabase = BowlInDatabase(); LocalData() { userMgr = UserManager(this); -- 2.36.3 From af233c821b4aafecf25a5996216746554cb8144d Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Mon, 27 Mar 2023 15:42:32 +0200 Subject: [PATCH 5/7] Storing stats done :white_check_mark: --- .../lib/database/fields/FriendFields.dart | 10 + .../lib/database/fields/StatFields.dart | 12 + .../lib/database/mappers/StatMapper.dart | 32 +++ .../lib/database/mappers/UserMapper.dart | 8 +- .../lib/database/sqlflite/BowlInDatabase.dart | 251 ++++++++++++++++++ .../lib/database/sqlflite/UserDataBase.dart | 135 ---------- Sources/bowlin_project/lib/main.dart | 3 +- .../bowlin_project/lib/model/GamePlayer.dart | 1 + .../lib/model/IUserManager.dart | 1 + .../lib/model/LocalManager/GameManager.dart | 94 ++++--- .../lib/model/LocalManager/LocalData.dart | 10 +- .../lib/model/LocalManager/UserManager.dart | 24 +- .../lib/model/StubManager/StubData.dart | 1 + .../lib/model/StubManager/UserManager.dart | 5 + Sources/bowlin_project/lib/model/User.dart | 8 +- 15 files changed, 412 insertions(+), 183 deletions(-) create mode 100644 Sources/bowlin_project/lib/database/fields/FriendFields.dart create mode 100644 Sources/bowlin_project/lib/database/mappers/StatMapper.dart create mode 100644 Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart delete mode 100644 Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart diff --git a/Sources/bowlin_project/lib/database/fields/FriendFields.dart b/Sources/bowlin_project/lib/database/fields/FriendFields.dart new file mode 100644 index 0000000..327d16a --- /dev/null +++ b/Sources/bowlin_project/lib/database/fields/FriendFields.dart @@ -0,0 +1,10 @@ +class GameFields { + static final List values = [ + id, date, pointsCurrentUser, userId + ]; + + static final String id = '_id'; + static final String date = '_date'; + static final String pointsCurrentUser = '_points_current_user'; + static final String userId = '_user_id'; +} \ No newline at end of file diff --git a/Sources/bowlin_project/lib/database/fields/StatFields.dart b/Sources/bowlin_project/lib/database/fields/StatFields.dart index 554ba52..e6bed82 100644 --- a/Sources/bowlin_project/lib/database/fields/StatFields.dart +++ b/Sources/bowlin_project/lib/database/fields/StatFields.dart @@ -1,4 +1,16 @@ class StatFields { + static final List values = [ + idUser, nbVictory, nbGames, highscore, nbStrikes, nbSpares, nbScore, avgScore, avgPinsPerRound + ]; + static final String nbVictory = '_nbVictory'; + static final String nbGames = '_nbGames'; + static final String highscore = '_highscore'; + static final String nbStrikes = '_nbStrikes'; + static final String nbSpares = '_nbSpares'; + static final String nbScore = '_nbScore'; + static final String avgScore = '_avgScore'; + static final String avgPinsPerRound = '_avgPinsPerRound'; + static final String idUser = '_idUser'; } \ No newline at end of file diff --git a/Sources/bowlin_project/lib/database/mappers/StatMapper.dart b/Sources/bowlin_project/lib/database/mappers/StatMapper.dart new file mode 100644 index 0000000..d668541 --- /dev/null +++ b/Sources/bowlin_project/lib/database/mappers/StatMapper.dart @@ -0,0 +1,32 @@ +import 'package:bowl_in/database/fields/StatFields.dart'; +import '../../model/Stat.dart'; +import '../../model/User.dart'; + +class StatMapper { + static Map toJson(Stat stat, User user) { + return { + StatFields.idUser: user.id, + StatFields.nbVictory: stat.nbVictory, + StatFields.nbGames: stat.nbGames, + StatFields.highscore: stat.highscore, + StatFields.nbStrikes: stat.nbStrikes, + StatFields.nbSpares: stat.nbSpares, + StatFields.nbScore: stat.nbScore, + StatFields.avgScore: stat.avgScore, + StatFields.avgPinsPerRound: stat.avgPinsPerRound + }; + } + + static Stat toModel(Map json) { + return Stat( + json[StatFields.nbVictory], + json[StatFields.nbGames], + json[StatFields.highscore], + json[StatFields.nbStrikes], + json[StatFields.nbSpares], + json[StatFields.nbScore], + json[StatFields.avgScore], + json[StatFields.avgPinsPerRound] + ); + } +} diff --git a/Sources/bowlin_project/lib/database/mappers/UserMapper.dart b/Sources/bowlin_project/lib/database/mappers/UserMapper.dart index 225753e..7aa14a8 100644 --- a/Sources/bowlin_project/lib/database/mappers/UserMapper.dart +++ b/Sources/bowlin_project/lib/database/mappers/UserMapper.dart @@ -1,3 +1,4 @@ +import '../../model/Stat.dart'; import '../../model/User.dart'; import '../fields/UserFields.dart'; @@ -11,14 +12,15 @@ class UserMapper { }; } - static User toModel(Map json) { - return User( + static User toModel(Map json, Stat stat) { + return User.withStat( json[UserFields.id], json[UserFields.name], json[UserFields.image], json[UserFields.mail], [], [], + stat ); } -} \ No newline at end of file +} diff --git a/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart b/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart new file mode 100644 index 0000000..b79d556 --- /dev/null +++ b/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart @@ -0,0 +1,251 @@ +import 'package:bowl_in/database/mappers/GameMapper.dart'; +import 'package:bowl_in/database/mappers/StatMapper.dart'; +import 'package:bowl_in/model/Game.dart'; +import 'package:bowl_in/model/User.dart'; +import 'package:path/path.dart'; +import 'package:sqflite/sqflite.dart'; + +import '../../model/Stat.dart'; +import '../fields/GameDetailFields.dart'; +import '../fields/GameFields.dart'; +import '../fields/StatFields.dart'; +import '../fields/UserFields.dart'; +import '../mappers/UserMapper.dart'; + +class BowlInDatabase { + BowlInDatabase(); + + static final BowlInDatabase instance = BowlInDatabase._init(); + + static Database? _database; + + BowlInDatabase._init(); + + static const String tableUser = 'users'; + static const String tableGame = 'games'; + static const String tableGameDetail = 'gameDetails'; + static const String tableStat = 'stats'; + + Future get database async { + if (_database != null) return _database!; + + _database = await _initDB('user.db'); + return _database!; + } + + Future _initDB(String filePath) async { + final dbPath = await getDatabasesPath(); + final path = join(dbPath, filePath); + + return await openDatabase(path, + version: 1, onCreate: _createDB, onUpgrade: _upgradeDB); + } + + Future _createDB(Database db, int version) async { + const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT'; + const textType = 'TEXT NOT NULL'; + const boolType = 'BOOLEAN NOT NULL'; + const integerType = 'INTEGER NOT NULL'; + const realType = 'REAL NOT NULL'; + + await db.execute(''' +CREATE TABLE $tableUser ( + ${UserFields.id} $idType, + ${UserFields.name} $boolType, + ${UserFields.image} $textType, + ${UserFields.mail} $textType + ) +'''); + + await db.execute(''' +CREATE TABLE $tableGame ( + ${GameFields.id} $idType, + ${GameFields.date} $textType, + ${GameFields.pointsCurrentUser} $integerType, + ${GameFields.userId} $integerType, + FOREIGN KEY(${GameFields.userId}) REFERENCES $tableUser(${UserFields.id}) +) +'''); + + await db.execute(''' +CREATE TABLE $tableGameDetail ( + ${GameDetailFields.id} $idType, + ${GameDetailFields.date} $textType, + ${GameDetailFields.nameWinner} $textType, + ${GameDetailFields.host} $textType +) +'''); + + await db.execute(''' +CREATE TABLE $tableStat ( + ${StatFields.idUser} $integerType, + ${StatFields.nbVictory} $integerType, + ${StatFields.nbGames} $integerType, + ${StatFields.highscore} $integerType, + ${StatFields.nbStrikes} $integerType, + ${StatFields.nbSpares} $integerType, + ${StatFields.nbScore} $integerType, + ${StatFields.avgScore} $realType, + ${StatFields.avgPinsPerRound} $realType, + FOREIGN KEY(${StatFields.idUser}) REFERENCES $tableUser(${UserFields.id}) +) +'''); + } + + Future _upgradeDB(Database db, int oldVersion, int newVersion) async { + if (oldVersion == 5) { + 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 _createDB(db, newVersion); + } + } + + // User + + Future createUser(User user) async { + final db = await instance.database; + await db.insert(tableUser, UserMapper.toJson(user)); + await createStat(user); + } + + Future readUser(int id) async { + final db = await instance.database; + final result = await db + .query(tableUser, where: '${UserFields.id} = ?', whereArgs: [id]); + + if (result.isNotEmpty) { + final stat = await readStat(id); + + User user; + if (stat != null) { + user = UserMapper.toModel(result.first, stat); + } + else { + user = UserMapper.toModel(result.first, Stat.empty()); + } + //final games = await readGame(id); + //for (var game in games!) { + //user.games.add(game); + //} + return user; + } else { + return null; + } + } + + Future updateUser(User user) async { + final db = await instance.database; + + await db.transaction((txn) async { + await txn.update(tableUser, UserMapper.toJson(user), + where: '${UserFields.id} = ?', whereArgs: [user.id]); + + await txn.update(tableStat, StatMapper.toJson(user.stat, user), + where: '${StatFields.idUser} = ?', whereArgs: [user.id]); + + // Insert new games for the user + //await createGame(user); + }); + } + + Future deleteUser(int id) async { + final db = await instance.database; + + await deleteGame(id); + + await deleteStat(id); + + return await db.delete( + tableUser, + where: '${UserFields.id} = ?', + whereArgs: [id], + ); + } + + // GameDetail + + // Game + + Future createGame(User user) async { + final db = await instance.database; + + await db.transaction((txn) async { + for (var game in user.games) { + await txn.insert(tableGame, GameMapper.toJson(game, user)); + } + }); + } + + Future?> readGame(int id) async { + final db = await instance.database; + 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)); + } + return games; + } else { + return null; + } + } + + Future deleteGame(int id) async { + final db = await instance.database; + + return await db.delete( + tableGame, + where: '${GameFields.userId} = ?', + whereArgs: [id], + ); + } + + // Stat + + Future createStat(User user) async { + final db = await instance.database; + await db.insert(tableStat, StatMapper.toJson(Stat.empty(), user)); + } + + Future readStat(int id) async { + final db = await instance.database; + final result = await db.query(tableStat, + where: '${StatFields.idUser} = ?', whereArgs: [id]); + + if (result.isNotEmpty) { + Stat stat = StatMapper.toModel(result.first); + return stat; + } else { + return null; + } + } + + Future updateStat(User user) async { + final db = await instance.database; + await db.transaction((txn) async { + await txn.update(tableStat, StatMapper.toJson(user.stat, user), + where: '${StatFields.idUser} = ?', whereArgs: [user.id]); + }); + } + + Future deleteStat(int id) async { + final db = await instance.database; + + return await db.delete( + tableStat, + where: '${StatFields.idUser} = ?', + whereArgs: [id], + ); + + } + + Future close() async { + final db = await instance.database; + + db.close(); + } +} diff --git a/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart b/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart deleted file mode 100644 index 5104443..0000000 --- a/Sources/bowlin_project/lib/database/sqlflite/UserDataBase.dart +++ /dev/null @@ -1,135 +0,0 @@ -import 'package:bowl_in/database/mappers/GameMapper.dart'; -import 'package:bowl_in/model/User.dart'; -import 'package:path/path.dart'; -import 'package:sqflite/sqflite.dart'; - -import '../fields/GameDetailFields.dart'; -import '../fields/GameFields.dart'; -import '../fields/UserFields.dart'; -import '../mappers/UserMapper.dart'; - -class BowlInDatabase { - BowlInDatabase(); - - static final BowlInDatabase instance = BowlInDatabase._init(); - - static Database? _database; - - BowlInDatabase._init(); - - static const String tableUser = 'users'; - static const String tableGame = 'games'; - static const String tableGameDetail = 'gameDetails'; - - Future get database async { - if (_database != null) return _database!; - - _database = await _initDB('user.db'); - return _database!; - } - - Future _initDB(String filePath) async { - final dbPath = await getDatabasesPath(); - final path = join(dbPath, filePath); - - return await openDatabase(path, version: 4, onCreate: _createDB, onUpgrade: _upgradeDB); - } - - Future _createDB(Database db, int version) async { - const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT'; - const textType = 'TEXT NOT NULL'; - const boolType = 'BOOLEAN NOT NULL'; - final integerType = 'INTEGER NOT NULL'; - - await db.execute(''' -CREATE TABLE $tableUser ( - ${UserFields.id} $idType, - ${UserFields.name} $boolType, - ${UserFields.image} $textType, - ${UserFields.mail} $textType - ) -'''); - - await db.execute(''' -CREATE TABLE $tableGame ( - ${GameFields.id} $idType, - ${GameFields.date} $textType, - ${GameFields.pointsCurrentUser} $integerType, - ${GameFields.userId} $integerType, - FOREIGN KEY(${GameFields.userId}) REFERENCES $tableUser(${UserFields.id}) -) -'''); - - await db.execute(''' -CREATE TABLE $tableGameDetail ( - ${GameDetailFields.id} $idType, - ${GameDetailFields.date} $textType, - ${GameDetailFields.nameWinner} $textType, - ${GameDetailFields.host} $textType, -) -'''); - } - - Future _upgradeDB(Database db, int oldVersion, int newVersion) async { - if (oldVersion < 4) { - 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 _createDB(db, newVersion); - } - } - - Future createUser(User user) async { - final db = await instance.database; - await db.insert(tableUser, UserMapper.toJson(user)); - } - - Future readUser(int id) async { - final db = await instance.database; - final result = await db - .query(tableUser, where: '${UserFields.id} = ?', whereArgs: [id]); - - if (result.isNotEmpty) { - User user = UserMapper.toModel(result.first); - final games = await db - .query(tableGame, where: '${GameFields.userId} = ?', whereArgs: [user.id]); - for (var game in games) { - user.games.add(GameMapper.toModel(game)); - } - return user; - } - else { - return null; - } - } - - Future updateUser(User user) async { - final db = await instance.database; - - await db.transaction((txn) async { - await txn.update(tableUser, UserMapper.toJson(user), - where: '${UserFields.id} = ?', whereArgs: [user.id]); - - // Insert new games for the user - for (var game in user.games) { - await txn.insert(tableGame, GameMapper.toJson(game, user)); - } - }); - } - - Future deleteUser(int id) async { - final db = await instance.database; - - return await db.delete( - tableUser, - where: '${UserFields.id} = ?', - whereArgs: [id], - ); - } - - Future close() async { - final db = await instance.database; - - db.close(); - } -} diff --git a/Sources/bowlin_project/lib/main.dart b/Sources/bowlin_project/lib/main.dart index 56cd39a..d6faae1 100644 --- a/Sources/bowlin_project/lib/main.dart +++ b/Sources/bowlin_project/lib/main.dart @@ -1,5 +1,4 @@ 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'; @@ -11,7 +10,7 @@ void main() { } class MyApp extends StatelessWidget { - static IManager controller = StubData(); + static IManager controller = LocalData(); const MyApp({super.key}); diff --git a/Sources/bowlin_project/lib/model/GamePlayer.dart b/Sources/bowlin_project/lib/model/GamePlayer.dart index 61af1ad..7eb41df 100644 --- a/Sources/bowlin_project/lib/model/GamePlayer.dart +++ b/Sources/bowlin_project/lib/model/GamePlayer.dart @@ -40,6 +40,7 @@ class GamePlayer { _parent.gameMgr.addGame(game); game.computeScores(); + _parent.userMgr.saveUser(_parent.userCurrent); context?.go("/scoreboard", extra: game); } else { print("IN GAME : " + currentRoundIndex.toString()); diff --git a/Sources/bowlin_project/lib/model/IUserManager.dart b/Sources/bowlin_project/lib/model/IUserManager.dart index b9d5ed6..e5a7e89 100644 --- a/Sources/bowlin_project/lib/model/IUserManager.dart +++ b/Sources/bowlin_project/lib/model/IUserManager.dart @@ -12,5 +12,6 @@ abstract class IUserManager { IAuthManager get authMgr => _authMgr; List getUsersByName(String name); Player getUserById(int id); + saveUser(User user); List getRankingWithFriends(); } diff --git a/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart b/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart index b93f3a0..dc111f7 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/GameManager.dart @@ -3,57 +3,89 @@ import 'package:bowl_in/model/IGameManager.dart'; import 'package:bowl_in/model/LocalManager/LocalData.dart'; import 'package:bowl_in/model/Player.dart'; +import '../User.dart'; + class GameManager extends IGameManager { final LocalData parent; - + // Constructor GameManager(this.parent); - @override - addGame(GameDetail gd) { - // TODO: implement addGame - throw UnimplementedError(); + // Methods + GameDetail getGameById(int id) { + for (var element in parent.gameDetails) { + if (element.id == id) { + return element; + } + } + throw Exception("Game not found."); } - @override - GameDetail getGameById(int id) { - // TODO: implement getGameById - throw UnimplementedError(); + List getGamesByPlayerId(int id) { + List games = []; + for (var element in parent.gameDetails) { + for (Player player in element.players) { + if (player is User && player.id == id) { + games.add(element); + break; + } + } + } + return games; } - @override List getGamesByPlayer(Player user) { - // TODO: implement getGamesByPlayer - throw UnimplementedError(); + List games = []; + for (var element in parent.gameDetails) { + for (Player player in element.players) { + if (player is User && user is User && player.id == user.id) { + games.add(element); + break; + } + } + } + return games; } - @override - List getGamesByPlayerId(int id) { - // TODO: implement getGamesByPlayerId - throw UnimplementedError(); + List getGamesByPlayers(List users) { + List games = []; + for (var element in parent.gameDetails) { + if (element.players.toSet().containsAll(users.toSet())) { + games.add(element); + } + } + return games; } - @override - List getGamesByPlayers(List users) { - // TODO: implement getGamesByPlayers - throw UnimplementedError(); + List getPlayersByIdGame(int id) { + List players = []; + for (var element in parent.gameDetails) { + if (element.id == id) { + for (var player in element.players) { + players.add(player); + } + return players; + } + } + throw Exception("Game not found."); } - @override - int getNextId() { - // TODO: implement getNextId - throw UnimplementedError(); + Map getRankByIdGame(int id) { + for (var game in parent.gameDetails) { + if (game.id == id) { + return game.getRank(); + } + } + throw Exception("Game not found."); } @override - List getPlayersByIdGame(int id) { - // TODO: implement getPlayersByIdGame - throw UnimplementedError(); + addGame(GameDetail gd) { + parent.gameDetails.add(gd); } @override - Map getRankByIdGame(int id) { - // TODO: implement getRankByIdGame - throw UnimplementedError(); + int getNextId() { + return parent.gameDetails.length; } -} \ No newline at end of file +} diff --git a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart index eb840b5..3dfb52d 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/LocalData.dart @@ -1,13 +1,19 @@ -import 'package:bowl_in/database/sqlflite/UserDataBase.dart'; +import 'package:bowl_in/database/sqlflite/BowlInDatabase.dart'; import 'package:bowl_in/model/IManager.dart'; +import '../GameDetail.dart'; import 'GameManager.dart'; import 'UserManager.dart'; class LocalData extends IManager { - final BowlInDatabase userDatabase = BowlInDatabase(); + final BowlInDatabase database = BowlInDatabase(); LocalData() { userMgr = UserManager(this); gameMgr = GameManager(this); } + + List _gameDetails = []; + + List get gameDetails => _gameDetails; + } diff --git a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart index c88f5ec..250fc30 100644 --- a/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart +++ b/Sources/bowlin_project/lib/model/LocalManager/UserManager.dart @@ -2,7 +2,6 @@ import 'package:bowl_in/model/IUserManager.dart'; import 'package:bowl_in/model/LocalManager/LocalData.dart'; import 'package:bowl_in/model/Player.dart'; import 'package:bowl_in/model/User.dart'; -import '../Game.dart'; import 'AuthManager.dart'; class UserManager extends IUserManager { @@ -10,14 +9,15 @@ class UserManager extends IUserManager { // Constructor UserManager(this.parent) : super(AuthManager(parent)) { - User user = User(0, "Dave", "./assets/images/image_user_red.png", "", [], []); - user.games.add(Game(0,DateTime.now(), 30, [])); - saveUser(user); + //User user = User(0, "Victor", "./assets/images/image_user_red.png", "", [], []); + //saveUser(user); + //parent.database.deleteUser(0); + //test(); _initUser(); } _initUser() async { - var user = await parent.userDatabase.readUser(0); + var user = await parent.database.readUser(0); if (user == null) { User user2 = User(1, "Unknown", "./assets/images/image_user_cyan.png", "", [], []); @@ -27,8 +27,13 @@ class UserManager extends IUserManager { } } - saveUser(User user) { - parent.userDatabase.updateUser(user); + saveUser(User user) async { + var result = await parent.database.readUser(0); + if (result == null) { + await parent.database.createUser(user); + } else { + await parent.database.updateUser(user); + } } Map userToMap(User user) { @@ -42,8 +47,9 @@ class UserManager extends IUserManager { @override List getRankingWithFriends() { - // TODO: implement getRankingWithFriends - throw UnimplementedError(); + List sortedPlayers = List.from(parent.userCurrent.friends); + sortedPlayers.sort((a, b) => b.stat.highscore.compareTo(a.stat.highscore)); + return sortedPlayers; } @override diff --git a/Sources/bowlin_project/lib/model/StubManager/StubData.dart b/Sources/bowlin_project/lib/model/StubManager/StubData.dart index d5d36f8..8499b82 100644 --- a/Sources/bowlin_project/lib/model/StubManager/StubData.dart +++ b/Sources/bowlin_project/lib/model/StubManager/StubData.dart @@ -11,6 +11,7 @@ import 'UserManager.dart'; import 'GameManager.dart'; class StubData extends IManager { + StubData() { userMgr = UserManager(this); gameMgr = GameManager(this); diff --git a/Sources/bowlin_project/lib/model/StubManager/UserManager.dart b/Sources/bowlin_project/lib/model/StubManager/UserManager.dart index fd8d9e9..e016c60 100644 --- a/Sources/bowlin_project/lib/model/StubManager/UserManager.dart +++ b/Sources/bowlin_project/lib/model/StubManager/UserManager.dart @@ -38,4 +38,9 @@ class UserManager extends IUserManager { sortedPlayers.sort((a, b) => b.stat.highscore.compareTo(a.stat.highscore)); return sortedPlayers; } + + @override + saveUser(User user) { + return ; + } } diff --git a/Sources/bowlin_project/lib/model/User.dart b/Sources/bowlin_project/lib/model/User.dart index 7bcd9f9..582785c 100644 --- a/Sources/bowlin_project/lib/model/User.dart +++ b/Sources/bowlin_project/lib/model/User.dart @@ -8,12 +8,18 @@ class User extends Player { String _mail; List _achievements = []; List _friends = []; - final Stat _stat = Stat.empty(); + late final Stat _stat; List games = []; // Constructor User(this._id, String name, String image, this._mail, this._achievements, this._friends) + : super(name, image){ + _stat = Stat.empty(); + } + + User.withStat(this._id, String name, String image, this._mail, this._achievements, + this._friends, this._stat) : super(name, image); int get id => _id; -- 2.36.3 From 8dc7454e263a3a1f5c49b8569ea7e05f72eecf92 Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Tue, 28 Mar 2023 19:09:35 +0200 Subject: [PATCH 6/7] 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) { -- 2.36.3 From 0150ab963672d66f3947618fe6a9c8212440dd7c Mon Sep 17 00:00:00 2001 From: emkartal1 Date: Tue, 28 Mar 2023 19:17:19 +0200 Subject: [PATCH 7/7] Correct code smells :bug: --- Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart | 1 - Sources/bowlin_project/lib/main.dart | 1 - 2 files changed, 2 deletions(-) diff --git a/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart b/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart index b0c418f..817b5d0 100644 --- a/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart +++ b/Sources/bowlin_project/lib/database/sqlflite/BowlInDatabase.dart @@ -217,7 +217,6 @@ CREATE TABLE $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]) { diff --git a/Sources/bowlin_project/lib/main.dart b/Sources/bowlin_project/lib/main.dart index e4c08fa..d6faae1 100644 --- a/Sources/bowlin_project/lib/main.dart +++ b/Sources/bowlin_project/lib/main.dart @@ -1,5 +1,4 @@ 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'; -- 2.36.3