import 'dart:async'; import 'dart:core'; import 'package:ohthatsa/pages/practice/PracticeAnswer.dart'; import 'package:ohthatsa/pages/practice/PracticeType.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class PracticeDatabase { static _onCreate(Database database, int version) async { String types = PracticeType.values.map((type) => "'${type.toString().split(".").last}'").join(", "); await database.execute(''' CREATE TABLE PracticeSession ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT CHECK( type IN ($types) ) NOT NULL ); '''); await database.execute(''' CREATE TABLE PracticeAnswer ( id INTEGER PRIMARY KEY AUTOINCREMENT, sessionId INTEGER NOT NULL, question INTEGER NOT NULL, answer INTEGER NOT NULL, time DATETIME NOT NULL, correct BOOLEAN NOT NULL, FOREIGN KEY(sessionId) REFERENCES PracticeSession(id) ); '''); await database.execute(''' CREATE VIEW AnswersView AS SELECT PracticeSession.id as practice_id, PracticeAnswer.id as answer_id, PracticeSession.type as type, PracticeAnswer.question as question, PracticeAnswer.answer as answer, PracticeAnswer.correct as correct, PracticeAnswer.time as time FROM PracticeSession INNER JOIN PracticeAnswer on PracticeSession.id = PracticeAnswer.sessionId; '''); await database.execute(''' CREATE VIEW AnswersCorrectByTypeViewAll AS SELECT type, SUM(correct = 1)*1.0 AS correct, SUM(correct = 0)*1.0 AS incorrect, COUNT(*) AS total FROM AnswersView GROUP BY type; '''); await database.execute(''' CREATE VIEW AnswersCorrectByTypeView7d AS SELECT type, SUM(correct = 1)*1.0 AS correct, SUM(correct = 0)*1.0 AS incorrect, COUNT(*) AS total, CAST( strftime('%s', time) AS INTEGER ) as s_time, CAST( strftime("%s", DATETIME('now', '-7 day')) AS INTEGER ) as before FROM AnswersView WHERE s_time > before GROUP BY type; '''); await database.execute(''' CREATE VIEW AnswersCorrectByTypeView30d AS SELECT type, SUM(correct = 1)*1.0 AS correct, SUM(correct = 0)*1.0 AS incorrect, COUNT(*) AS total, CAST( strftime('%s', time) AS INTEGER ) as s_time, CAST( strftime("%s", DATETIME('now', '-1 month')) AS INTEGER ) as before FROM AnswersView WHERE s_time > before GROUP BY type; '''); } static Future getDatabase() async { var databasesPath = await getDatabasesPath(); final databaseName = "answers.db"; return await openDatabase( join(databasesPath, databaseName), version: 1, onCreate: _onCreate ); } static insertAnswers(List answers, PracticeType practiceType) async { var db = await getDatabase(); int sessionId = await db.insert("PracticeSession", { "type": practiceType.toString().split(".").last } ); var batch = db.batch(); answers.forEach((answer) { answer.sessionId = sessionId; batch.insert("PracticeAnswer", answer.toMap()); }); await batch.commit(noResult: true); } // TODO test the database static Future> getStats() async { var db = await getDatabase(); List> answers = await db.rawQuery(''' SELECT "All" AS range, type, correct, incorrect, total, ROUND((correct / total) * 100, 1) AS ratio FROM AnswersCorrectByTypeViewAll UNION ALL SELECT "7d" AS range, type, correct, incorrect, total, ROUND((correct / total) * 100, 1) AS ratio FROM AnswersCorrectByTypeView7d UNION ALL SELECT "30d" AS range, type, correct, incorrect, total, ROUND((correct / total) * 100, 1) AS ratio FROM AnswersCorrectByTypeView30d; '''); Map stats = Map(); for(var stat in answers){ var typeRange = "${stat['range']} ${stat['type']}"; stats[typeRange] = stat['ratio'] as double; } return stats; } }