| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- import 'dart:io';
- import 'package:sqflite/sqflite.dart';
- import 'package:path/path.dart';
- import '../models/palm_record.dart';
- import '../models/palm_correction.dart';
- class DatabaseHelper {
- static final DatabaseHelper _instance = DatabaseHelper._internal();
- factory DatabaseHelper() => _instance;
- DatabaseHelper._internal();
- static Database? _database;
- Future<Database> get database async {
- if (_database != null) return _database!;
- _database = await _initDatabase();
- return _database!;
- }
- Future<Database> _initDatabase() async {
- String path = join(await getDatabasesPath(), 'palm_oil_history.db');
- return await openDatabase(
- path,
- version: 4,
- onCreate: _onCreate,
- onUpgrade: _onUpgrade,
- );
- }
- Future<void> _onCreate(Database db, int version) async {
- await db.execute('''
- CREATE TABLE history (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- image_path TEXT,
- ripeness_class TEXT,
- confidence REAL,
- timestamp TEXT,
- x1 REAL,
- y1 REAL,
- x2 REAL,
- y2 REAL,
- detections TEXT,
- batch_id TEXT,
- inference_ms INTEGER
- )
- ''');
- await db.execute('CREATE INDEX idx_history_batch_id ON history(batch_id)');
- await _createCorrectionsTable(db);
- }
- Future<void> _createCorrectionsTable(Database db) async {
- await db.execute('''
- CREATE TABLE corrections (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- original_record_id INTEGER,
- corrected_class TEXT,
- corrected_detections TEXT,
- timestamp TEXT
- )
- ''');
- await db.execute('CREATE INDEX idx_corrections_original_record_id ON corrections(original_record_id)');
- }
- Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
- if (oldVersion < 2) {
- await db.execute('ALTER TABLE history ADD COLUMN detections TEXT');
- }
- if (oldVersion < 3) {
- await db.execute('ALTER TABLE history ADD COLUMN batch_id TEXT');
- await db.execute('ALTER TABLE history ADD COLUMN inference_ms INTEGER');
- await db.execute('CREATE INDEX idx_history_batch_id ON history(batch_id)');
- }
- if (oldVersion < 4) {
- await _createCorrectionsTable(db);
- }
- }
- Future<int> insertRecord(PalmRecord record) async {
- Database db = await database;
- return await db.insert('history', record.toMap());
- }
- Future<List<PalmRecord>> getAllRecords() async {
- Database db = await database;
- List<Map<String, dynamic>> maps = await db.query('history', orderBy: 'timestamp DESC');
- return List.generate(maps.length, (i) {
- return PalmRecord.fromMap(maps[i]);
- });
- }
- Future<List<PalmRecord>> getRecordsByBatch(String batchId) async {
- Database db = await database;
- List<Map<String, dynamic>> maps = await db.query(
- 'history',
- where: 'batch_id = ?',
- whereArgs: [batchId],
- orderBy: 'timestamp ASC',
- );
- return List.generate(maps.length, (i) {
- return PalmRecord.fromMap(maps[i]);
- });
- }
- Future<int> deleteRecord(PalmRecord record) async {
- Database db = await database;
- await _deleteImageFile(record.imagePath);
- return await db.delete('history', where: 'id = ?', whereArgs: [record.id]);
- }
- Future<int> deleteBatch(String batchId) async {
- Database db = await database;
- final records = await getRecordsByBatch(batchId);
- for (final record in records) {
- await _deleteImageFile(record.imagePath);
- }
- return await db.delete('history', where: 'batch_id = ?', whereArgs: [batchId]);
- }
- Future<int> clearAllRecords() async {
- Database db = await database;
- final records = await getAllRecords();
- for (final record in records) {
- await _deleteImageFile(record.imagePath);
- }
- return await db.delete('history');
- }
- Future<int> insertCorrection(PalmCorrection correction) async {
- Database db = await database;
- return await db.insert('corrections', correction.toMap());
- }
- Future<int> deleteCorrectionsForRecord(int recordId) async {
- Database db = await database;
- return await db.delete('corrections', where: 'original_record_id = ?', whereArgs: [recordId]);
- }
- Future<PalmCorrection?> getLatestCorrection(int recordId) async {
- Database db = await database;
- List<Map<String, dynamic>> maps = await db.query(
- 'corrections',
- where: 'original_record_id = ?',
- whereArgs: [recordId],
- orderBy: 'timestamp DESC',
- limit: 1,
- );
- if (maps.isEmpty) return null;
- return PalmCorrection.fromMap(maps.first);
- }
- Future<void> _deleteImageFile(String imagePath) async {
- try {
- final file = File(imagePath);
- if (await file.exists()) {
- await file.delete();
- }
- } catch (_) {
- // A missing/locked file shouldn't block the DB delete.
- }
- }
- }
|