Public Access
feat(classes): implement initiation, start work on dbHelper
This commit is contained in:
+2
-2
@@ -6,7 +6,7 @@ import 'transport_helper.dart';
|
|||||||
void main() async {
|
void main() async {
|
||||||
await dotenv.load();
|
await dotenv.load();
|
||||||
const String dbName = "oeffimasterTransportDb";
|
const String dbName = "oeffimasterTransportDb";
|
||||||
initDB(dbName);
|
DbHelper.initDb(dbName);
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,4 +145,4 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+176
-51
@@ -1,48 +1,151 @@
|
|||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:sqflite/sqflite.dart';
|
||||||
|
// import './state_helper.dart';
|
||||||
|
// import './db_helper.dart';
|
||||||
|
|
||||||
void initDB(dbName) async {
|
// TODO: get access to DB
|
||||||
var databasesPath = await getDatabasesPath();
|
|
||||||
var path = databasesPath + dbName;
|
|
||||||
var db = await openDatabase(path);
|
|
||||||
// var db = await openDatabase('/var/db/oeffimaster/transport_db.db');
|
|
||||||
|
|
||||||
// TODO: Make sure the directory exists
|
class DbHelper {
|
||||||
|
static late Database db;
|
||||||
|
static String dbName = "";
|
||||||
|
|
||||||
// TODO: future optimisation: batch transactions
|
// DbHelper({
|
||||||
|
// required this.db,
|
||||||
|
// required this.dbName,
|
||||||
|
// });
|
||||||
|
|
||||||
// TODO: create tables for all classes
|
// remnant from when DB was not static
|
||||||
// - [] route
|
// factory DbHelper._openDb(Database database, String dbName) => DbHelper(
|
||||||
// - [] segment
|
// db: database,
|
||||||
// - [] station
|
// dbName: dbName,
|
||||||
// - [] vehicle
|
// );
|
||||||
// - [] line
|
|
||||||
// - [] departure
|
static void initDb(String dbName) async {
|
||||||
|
// var db = await openDatabase('/var/db/oeffimaster/transport_db.db');
|
||||||
|
var databasesPath = await getDatabasesPath();
|
||||||
|
var path = databasesPath + dbName;
|
||||||
|
// var newDb = await openDatabase(path);
|
||||||
|
// var dbHelper = DbHelper._openDb(newDb, dbName);
|
||||||
|
db = await openDatabase(path);
|
||||||
|
dbName = dbName;
|
||||||
|
|
||||||
|
// TODO: Make sure the directory exists
|
||||||
|
|
||||||
|
// TODO: future optimisation: batch transactions
|
||||||
|
|
||||||
|
Route.initRouteTable();
|
||||||
|
Segment.initSegmentTable();
|
||||||
|
Station.initStationTable();
|
||||||
|
Vehicle.initVehicleTable();
|
||||||
|
Departure.initDepartureTable();
|
||||||
|
Route.updateHighestId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Route {
|
class Route {
|
||||||
|
static int highestId = 0;
|
||||||
|
static const String tableName = "route";
|
||||||
|
|
||||||
|
int id;
|
||||||
List<Segment> segments = List.empty();
|
List<Segment> segments = List.empty();
|
||||||
Duration duration = Duration(minutes: 0);
|
Duration duration = Duration(minutes: 0);
|
||||||
|
|
||||||
Route({
|
Route({
|
||||||
|
required this.id,
|
||||||
required this.segments,
|
required this.segments,
|
||||||
required this.duration,
|
required this.duration,
|
||||||
});
|
});
|
||||||
|
|
||||||
// from trip API request
|
// from trip API request
|
||||||
factory Route.fromJson(Map<String, dynamic> json) => Route(
|
// TODO: how to connect this best with the database for read/write?
|
||||||
segments: json["LegList"]["Leg"].map((leg) => Segment.fromJson(leg)),
|
factory Route.fromJson(Map<String, dynamic> json) {
|
||||||
duration:
|
Route newRoute = Route(
|
||||||
json["LegList"]["Leg"][-1]["Origin"]["time"] -
|
id: highestId,
|
||||||
json["LegList"]["Leg"][0]["Origin"]["time"],
|
segments: json["LegList"]["Leg"].map((leg) => Segment.fromJson(leg)),
|
||||||
);
|
duration:
|
||||||
|
json["LegList"]["Leg"][-1]["Origin"]["time"] -
|
||||||
|
json["LegList"]["Leg"][0]["Origin"]["time"],
|
||||||
|
);
|
||||||
|
highestId += 1;
|
||||||
|
return newRoute;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: do we need route in the database???? // what beyond and ID is needed?
|
// rowids will give us new ids for every route-segment connection, but routeid
|
||||||
void initRouteTable(Database database) async {
|
// is needed as well, so how do we create these - query highest existing routeid? I think so
|
||||||
database.execute("CREATE TABLE IF NOT EXISTS route();");
|
// TODO: get highest routeid in route table (fast)
|
||||||
|
static void initRouteTable() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
|
database.execute("""CREATE TABLE IF NOT EXISTS routesegments(
|
||||||
|
id TEXT,
|
||||||
|
segmentid INTEGER,
|
||||||
|
segmentorder INTEGER, -- TODO: implement sorting
|
||||||
|
FOREIGN KEY(segmentid) REFERENCES segment(id)
|
||||||
|
);
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateHighestId() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
|
int newHigh = await getHighestId();
|
||||||
|
highestId = newHigh + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: better separation between production db and test db
|
||||||
|
* they share the highestId field regardless, which wont do
|
||||||
|
* so is an attribut for database needed?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// parse the highest id from the database to continue with ongoing ids but
|
||||||
|
/// create the db entry after the class, for now
|
||||||
|
|
||||||
|
// -- this might be making it more complicated than it needs to be
|
||||||
|
static Future<int> getHighestId() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
|
try {
|
||||||
|
var tmp = await database.query(
|
||||||
|
"routesegments",
|
||||||
|
columns: ["id"],
|
||||||
|
distinct: true,
|
||||||
|
orderBy: "id",
|
||||||
|
whereArgs: ["id"],
|
||||||
|
limit: 1,
|
||||||
|
);
|
||||||
|
if (tmp.isEmpty) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (tmp[0].isEmpty) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// entry "routeid" should definitely exist
|
||||||
|
assert(tmp[0]["id"] != null);
|
||||||
|
|
||||||
|
// Source - https://stackoverflow.com/a/52632172
|
||||||
|
// Posted by Günter Zöchbauer, modified by community. See post 'Timeline' for change history
|
||||||
|
// Retrieved 2026-06-08, License - CC BY-SA 4.0
|
||||||
|
T? cast<T>(x) => x is T ? x : null;
|
||||||
|
// --
|
||||||
|
//doing this in two steps go deal with nullability
|
||||||
|
String highestId = cast<String>(tmp[0]["routeid"]) ?? "0";
|
||||||
|
return int.parse(highestId);
|
||||||
|
} catch (e) {
|
||||||
|
print('Error: Could not get id: $e'); // TODO: use logging
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeNewToTable(Route route) async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
|
for (var i = 0; i < route.segments.length; i++) {
|
||||||
|
database.insert("routesegments", {
|
||||||
|
"id": route.id,
|
||||||
|
"segmentid": route.segments[i].id,
|
||||||
|
"segmentorder": i,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Segment {
|
class Segment {
|
||||||
|
final int id = 0;
|
||||||
final Station startPoint;
|
final Station startPoint;
|
||||||
final Station endPoint;
|
final Station endPoint;
|
||||||
final DateTime startTime;
|
final DateTime startTime;
|
||||||
@@ -57,15 +160,21 @@ class Segment {
|
|||||||
required this.vehicle,
|
required this.vehicle,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Segment.fromJson(Map<String, dynamic> json) => Segment(
|
factory Segment.fromJson(Map<String, dynamic> json) {
|
||||||
startPoint: Station.fromJson(json["Origin"]),
|
Database database = DbHelper.db;
|
||||||
endPoint: Station.fromJson(json["Destination"]),
|
Segment tmp = Segment(
|
||||||
startTime: json["Origin"]["rtTime"],
|
startPoint: Station.fromJson(json["Origin"]),
|
||||||
endTime: json["Destination"]["rtTime"],
|
endPoint: Station.fromJson(json["Destination"]),
|
||||||
vehicle: Vehicle.fromJson(json["Product"]),
|
startTime: json["Origin"]["rtTime"],
|
||||||
);
|
endTime: json["Destination"]["rtTime"],
|
||||||
|
vehicle: Vehicle.fromJson(json["Product"]),
|
||||||
|
);
|
||||||
|
tmp.writeNewToTable(); // TODO: we need to write to db and get the ID!!!!!!!
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
void initSegmentTable(Database database) async {
|
static void initSegmentTable() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
database.execute("""
|
database.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS segment(
|
CREATE TABLE IF NOT EXISTS segment(
|
||||||
startpoint TEXT,
|
startpoint TEXT,
|
||||||
@@ -74,26 +183,38 @@ class Segment {
|
|||||||
endtime TEXT,
|
endtime TEXT,
|
||||||
vehicle INTEGER,
|
vehicle INTEGER,
|
||||||
FOREIGN KEY(startpoint) REFERENCES station(stationid),
|
FOREIGN KEY(startpoint) REFERENCES station(stationid),
|
||||||
FOREIGN KEY(endpoint) REFERENCES station(stationid)
|
FOREIGN KEY(endpoint) REFERENCES station(stationid),
|
||||||
FOREIGN KEY(vehicle) REFERENCES vehicle(vehicleid)
|
FOREIGN KEY(vehicle) REFERENCES vehicle(vehicleid)
|
||||||
);
|
);
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> writeNewToTable() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
|
int id = await database.insert("segment", {
|
||||||
|
"startpoint": startPoint.id,
|
||||||
|
"endpoint": startPoint.id,
|
||||||
|
"startTime": startTime,
|
||||||
|
"endTime": endTime,
|
||||||
|
"vehicle": vehicle.id,
|
||||||
|
});
|
||||||
|
return id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Station {
|
class Station {
|
||||||
final String stationId;
|
final String id;
|
||||||
final String name;
|
final String name;
|
||||||
List<Line>? transportLines; // could be normalized away
|
List<Line>? transportLines; // could be normalized away
|
||||||
|
|
||||||
Station({
|
Station({
|
||||||
required this.stationId,
|
required this.id,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.transportLines, //TODO: make extra db table
|
required this.transportLines, //TODO: make extra db table
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Station.fromJson(Map<String, dynamic> json) => Station(
|
factory Station.fromJson(Map<String, dynamic> json) => Station(
|
||||||
stationId: json["id"] as String? ?? json["extId"] as String,
|
id: json["id"] as String? ?? json["extId"] as String,
|
||||||
name: json["name"],
|
name: json["name"],
|
||||||
transportLines: json.containsKey("productAtStop")
|
transportLines: json.containsKey("productAtStop")
|
||||||
? json["productAtStop"].map(
|
? json["productAtStop"].map(
|
||||||
@@ -102,9 +223,10 @@ class Station {
|
|||||||
: const [],
|
: const [],
|
||||||
);
|
);
|
||||||
|
|
||||||
void initStationTable(Database database) async {
|
static void initStationTable() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
database.execute("""CREATE TABLE IF NOT EXISTS station(
|
database.execute("""CREATE TABLE IF NOT EXISTS station(
|
||||||
stationid TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
name TEXT
|
name TEXT
|
||||||
);
|
);
|
||||||
""");
|
""");
|
||||||
@@ -112,24 +234,25 @@ class Station {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Vehicle {
|
class Vehicle {
|
||||||
final String vehicleId;
|
final String id;
|
||||||
final Line line;
|
final Line line;
|
||||||
|
|
||||||
Vehicle({
|
Vehicle({
|
||||||
required this.vehicleId,
|
required this.id,
|
||||||
required this.line,
|
required this.line,
|
||||||
});
|
});
|
||||||
|
|
||||||
// we can use the "product" class from within any JSON response
|
// we can use the "product" class from within any JSON response
|
||||||
// (within hafas API, on the appropriate level)
|
// (within hafas API, on the appropriate level)
|
||||||
factory Vehicle.fromJson(Map<String, dynamic> json) => Vehicle(
|
factory Vehicle.fromJson(Map<String, dynamic> json) => Vehicle(
|
||||||
vehicleId: json["matchId"],
|
id: json["matchId"],
|
||||||
line: Line.fromJson(json),
|
line: Line.fromJson(json),
|
||||||
);
|
);
|
||||||
|
|
||||||
void initVehicleTable(Database database) async {
|
static void initVehicleTable() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
database.execute("""CREATE TABLE IF NOT EXISTS vehicle(
|
database.execute("""CREATE TABLE IF NOT EXISTS vehicle(
|
||||||
vehicleid TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
line TEXT,
|
line TEXT,
|
||||||
FOREIGN KEY(line) REFERENCES line(lineid)
|
FOREIGN KEY(line) REFERENCES line(lineid)
|
||||||
);
|
);
|
||||||
@@ -138,7 +261,7 @@ class Vehicle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Line {
|
class Line {
|
||||||
final String lineId;
|
final String id;
|
||||||
Station? destination;
|
Station? destination;
|
||||||
Station? direction;
|
Station? direction;
|
||||||
final VehicleType mode;
|
final VehicleType mode;
|
||||||
@@ -147,7 +270,7 @@ class Line {
|
|||||||
Color? bgColor;
|
Color? bgColor;
|
||||||
|
|
||||||
Line({
|
Line({
|
||||||
required this.lineId,
|
required this.id,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.mode,
|
required this.mode,
|
||||||
this.fgColor,
|
this.fgColor,
|
||||||
@@ -163,7 +286,7 @@ class Line {
|
|||||||
];
|
];
|
||||||
|
|
||||||
factory Line.fromJson(Map<String, dynamic> json) => Line(
|
factory Line.fromJson(Map<String, dynamic> json) => Line(
|
||||||
lineId: json["lineId"],
|
id: json["lineId"],
|
||||||
name: json["name"],
|
name: json["name"],
|
||||||
mode: _vehicleTypeAsCatCode[int.parse(json["catCode"])],
|
mode: _vehicleTypeAsCatCode[int.parse(json["catCode"])],
|
||||||
fgColor:
|
fgColor:
|
||||||
@@ -173,7 +296,8 @@ class Line {
|
|||||||
Color.fromJson(json["backgroundColor"]) as Color? ??
|
Color.fromJson(json["backgroundColor"]) as Color? ??
|
||||||
Color(r: 50, g: 50, b: 50), // fallback
|
Color(r: 50, g: 50, b: 50), // fallback
|
||||||
);
|
);
|
||||||
void initLineTable(Database database) async {
|
static void initLineTable() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
database.execute("""CREATE TABLE IF NOT EXISTS line(
|
database.execute("""CREATE TABLE IF NOT EXISTS line(
|
||||||
lineid TEXT PRIMARY KEY,
|
lineid TEXT PRIMARY KEY,
|
||||||
destination TEXT,
|
destination TEXT,
|
||||||
@@ -199,14 +323,15 @@ class Departure {
|
|||||||
required this.departureTime,
|
required this.departureTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
void initDepartureTable(Database database) async {
|
static void initDepartureTable() async {
|
||||||
|
Database database = DbHelper.db;
|
||||||
database.execute("""CREATE TABLE IF NOT EXISTS departure(
|
database.execute("""CREATE TABLE IF NOT EXISTS departure(
|
||||||
departureid INTEGER,
|
id INTEGER,
|
||||||
vehicle TEXT,
|
vehicle TEXT,
|
||||||
station TEXT,
|
station TEXT,
|
||||||
departuretime TEXT
|
departuretime TEXT,
|
||||||
FOREIGN KEY(vehicle) REFERENCES vehicle(vehicleid),
|
FOREIGN KEY(vehicle) REFERENCES vehicle(id),
|
||||||
FOREIGN KEY(station) REFERENCES station(stationid)
|
FOREIGN KEY(station) REFERENCES station(id)
|
||||||
);
|
);
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user