Storing stats done ✅
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
b4b031f7dd
commit
af233c821b
@ -0,0 +1,10 @@
|
|||||||
|
class GameFields {
|
||||||
|
static final List<String> 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';
|
||||||
|
}
|
@ -1,4 +1,16 @@
|
|||||||
class StatFields {
|
class StatFields {
|
||||||
|
static final List<String> 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';
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
import 'package:bowl_in/database/fields/StatFields.dart';
|
||||||
|
import '../../model/Stat.dart';
|
||||||
|
import '../../model/User.dart';
|
||||||
|
|
||||||
|
class StatMapper {
|
||||||
|
static Map<String, dynamic> 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<String, dynamic> 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]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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<Database> get database async {
|
||||||
|
if (_database != null) return _database!;
|
||||||
|
|
||||||
|
_database = await _initDB('user.db');
|
||||||
|
return _database!;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Database> _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<void> _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<void> createUser(User user) async {
|
||||||
|
final db = await instance.database;
|
||||||
|
await db.insert(tableUser, UserMapper.toJson(user));
|
||||||
|
await createStat(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<User?> 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<void> 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<int> 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<void> 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<List<Game>?> readGame(int id) async {
|
||||||
|
final db = await instance.database;
|
||||||
|
final result = await db.query(tableGame,
|
||||||
|
where: '${GameFields.userId} = ?', whereArgs: [id]);
|
||||||
|
|
||||||
|
if (result.isNotEmpty) {
|
||||||
|
List<Game> games = [];
|
||||||
|
for (var game in result) {
|
||||||
|
games.add(GameMapper.toModel(game));
|
||||||
|
}
|
||||||
|
return games;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> deleteGame(int id) async {
|
||||||
|
final db = await instance.database;
|
||||||
|
|
||||||
|
return await db.delete(
|
||||||
|
tableGame,
|
||||||
|
where: '${GameFields.userId} = ?',
|
||||||
|
whereArgs: [id],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat
|
||||||
|
|
||||||
|
Future<void> createStat(User user) async {
|
||||||
|
final db = await instance.database;
|
||||||
|
await db.insert(tableStat, StatMapper.toJson(Stat.empty(), user));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Stat?> 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<void> 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<int> 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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<Database> get database async {
|
|
||||||
if (_database != null) return _database!;
|
|
||||||
|
|
||||||
_database = await _initDB('user.db');
|
|
||||||
return _database!;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Database> _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<void> _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<void> createUser(User user) async {
|
|
||||||
final db = await instance.database;
|
|
||||||
await db.insert(tableUser, UserMapper.toJson(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<User?> 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<void> 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<int> 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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 'package:bowl_in/model/IManager.dart';
|
||||||
|
import '../GameDetail.dart';
|
||||||
import 'GameManager.dart';
|
import 'GameManager.dart';
|
||||||
import 'UserManager.dart';
|
import 'UserManager.dart';
|
||||||
|
|
||||||
class LocalData extends IManager {
|
class LocalData extends IManager {
|
||||||
final BowlInDatabase userDatabase = BowlInDatabase();
|
final BowlInDatabase database = BowlInDatabase();
|
||||||
|
|
||||||
LocalData() {
|
LocalData() {
|
||||||
userMgr = UserManager(this);
|
userMgr = UserManager(this);
|
||||||
gameMgr = GameManager(this);
|
gameMgr = GameManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<GameDetail> _gameDetails = [];
|
||||||
|
|
||||||
|
List<GameDetail> get gameDetails => _gameDetails;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in new issue