re factor rog
This commit is contained in:
397
lib/features/data/checkpoint.dart
Normal file
397
lib/features/data/checkpoint.dart
Normal file
@ -0,0 +1,397 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
|
||||
class FeatureCollection {
|
||||
final String type;
|
||||
final List<Feature> features;
|
||||
|
||||
FeatureCollection({required this.type, required this.features});
|
||||
|
||||
factory FeatureCollection.fromJson(Map<String, dynamic> json) {
|
||||
return FeatureCollection(
|
||||
type: json['type'],
|
||||
features:
|
||||
List<Feature>.from(json['features'].map((x) => Feature.fromJson(x))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Feature {
|
||||
final int id;
|
||||
final String type;
|
||||
final Geometry geometry;
|
||||
final Properties properties;
|
||||
|
||||
Feature(
|
||||
{required this.id,
|
||||
required this.type,
|
||||
required this.geometry,
|
||||
required this.properties});
|
||||
|
||||
factory Feature.fromJson(Map<String, dynamic> json) {
|
||||
return Feature(
|
||||
id: json['id'],
|
||||
type: json['type'],
|
||||
geometry: Geometry.fromJson(json['geometry']),
|
||||
properties: Properties.fromJson(json['properties']),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'type': type,
|
||||
'geometry': geometry.toMap(), // Assuming Geometry has a toMap method
|
||||
'properties':
|
||||
properties.toMap(), // Assuming Properties has a toMap method
|
||||
};
|
||||
}
|
||||
|
||||
Feature.fromMap(Map<String, dynamic> map)
|
||||
: id = map['id'],
|
||||
type = map['type'],
|
||||
geometry = Geometry.fromMap(map['geometry']),
|
||||
properties = Properties.fromJson(map['properties']);
|
||||
|
||||
static empty() {}
|
||||
}
|
||||
|
||||
class Geometry {
|
||||
final String type;
|
||||
final List<List<double>> coordinates;
|
||||
|
||||
Geometry({required this.type, required this.coordinates});
|
||||
|
||||
Geometry copyWith({
|
||||
String? type,
|
||||
List<List<double>>? coordinates,
|
||||
}) {
|
||||
return Geometry(
|
||||
type: type ?? this.type,
|
||||
coordinates: coordinates ?? this.coordinates,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
'type': type,
|
||||
'coordinates': coordinates,
|
||||
};
|
||||
}
|
||||
|
||||
factory Geometry.fromMap(Map<String, dynamic> map) {
|
||||
return Geometry(
|
||||
type: map['type'] as String,
|
||||
coordinates: List<List<double>>.from(
|
||||
(map['coordinates'] as List<dynamic>).map<List<double>>(
|
||||
(coordinateList) {
|
||||
// Ensure 'coordinateList' is treated as a List of dynamic elements.
|
||||
// Then, for each element in the list, explicitly cast or convert it to double.
|
||||
return List<double>.from(coordinateList.map((coordinate) {
|
||||
// 'coordinate' is dynamic, needs explicit conversion to double.
|
||||
// The conversion depends on the original data type of 'coordinate';
|
||||
// if it's already a number, you can use .toDouble(); if it's a String, you might need double.parse.
|
||||
return double.parse(coordinate.toString());
|
||||
}));
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory Geometry.fromJson(Map<String, dynamic> source) {
|
||||
final geom = Geometry.fromMap(source);
|
||||
return geom;
|
||||
}
|
||||
|
||||
get latitude => coordinates[0][1];
|
||||
get longitude => coordinates[0][0];
|
||||
}
|
||||
|
||||
class Properties {
|
||||
// Include all properties fields
|
||||
final int locationId;
|
||||
final String subLocId;
|
||||
final double cp;
|
||||
final String? name;
|
||||
final String? address;
|
||||
final String? phone;
|
||||
final String? email;
|
||||
final String? webcontents;
|
||||
final String? videos;
|
||||
final String? category;
|
||||
final int? series;
|
||||
final double? lat;
|
||||
final double? lon;
|
||||
final int? listOrder;
|
||||
final String? photos;
|
||||
final double? checkinRadious;
|
||||
final bool? autoCheckin;
|
||||
bool? selected = false;
|
||||
bool? checkedin = false;
|
||||
final double? checkinPoint;
|
||||
final double? buyPoint;
|
||||
final bool? hiddenLocation;
|
||||
String? checkinImage;
|
||||
String? buypointImage;
|
||||
bool? forcedCheckin = false;
|
||||
final String? tags;
|
||||
|
||||
Properties(
|
||||
{required this.locationId,
|
||||
required this.subLocId,
|
||||
required this.cp,
|
||||
this.name,
|
||||
this.address,
|
||||
this.phone,
|
||||
this.email,
|
||||
this.webcontents,
|
||||
this.videos,
|
||||
this.category,
|
||||
this.series,
|
||||
this.lat,
|
||||
this.lon,
|
||||
this.listOrder,
|
||||
this.photos,
|
||||
this.checkinRadious,
|
||||
this.autoCheckin,
|
||||
this.selected,
|
||||
this.checkedin,
|
||||
this.checkinPoint,
|
||||
this.buyPoint,
|
||||
this.hiddenLocation,
|
||||
this.checkinImage,
|
||||
this.buypointImage,
|
||||
this.forcedCheckin,
|
||||
this.tags});
|
||||
|
||||
factory Properties.fromJson(Map<String, dynamic> json) {
|
||||
Properties prop;
|
||||
try {
|
||||
prop = Properties(
|
||||
locationId: json['location_id'],
|
||||
subLocId: json['sub_loc_id'],
|
||||
cp: json['cp'],
|
||||
name: json['name'] ?? '',
|
||||
address: json['address'] ?? '',
|
||||
phone: json['phone'] ?? '',
|
||||
email: json['email'] ?? '',
|
||||
webcontents: json['webcontents'] ?? '',
|
||||
videos: json['videos'] ?? '',
|
||||
category: json['category'] ?? '',
|
||||
series: json['series'] ?? 0,
|
||||
lat: json['lat'] ?? 0.0,
|
||||
lon: json['lon'] ?? 0.0,
|
||||
listOrder: json['list_order'] ?? 0,
|
||||
photos: json['photos'] ?? '',
|
||||
checkinRadious: json['checkin_radious'] ?? 0.0,
|
||||
autoCheckin: json['auto_checkin'] == 0 ? false : true,
|
||||
selected: json['selected'] == 0 ? false : true,
|
||||
checkedin: json['checkedin'] == 0 ? false : true,
|
||||
checkinPoint: json['checkin_point'] ?? 0.0,
|
||||
buyPoint: json['buy_point'] ?? 0.0,
|
||||
hiddenLocation: json['hidden_location'] == 0 ? false : true,
|
||||
checkinImage: json['checkin_image'] ?? '',
|
||||
buypointImage: json['buypoint_image'] ?? '',
|
||||
forcedCheckin: json['forced_checkin'] == 0 ? false : true,
|
||||
tags: json['tags'] ?? '');
|
||||
//print("from json --- $prop");
|
||||
} catch (e) {
|
||||
//print("from json --- $e");
|
||||
return Properties(locationId: 0, subLocId: '', cp: 0.0, name: '');
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
factory Properties.toJson(Properties prop) {
|
||||
return Properties(
|
||||
locationId: prop.locationId,
|
||||
subLocId: prop.subLocId,
|
||||
cp: prop.cp,
|
||||
name: prop.name,
|
||||
address: prop.address,
|
||||
phone: prop.phone,
|
||||
email: prop.email,
|
||||
webcontents: prop.webcontents,
|
||||
videos: prop.videos,
|
||||
category: prop.category,
|
||||
series: prop.series,
|
||||
lat: prop.lat,
|
||||
lon: prop.lon,
|
||||
listOrder: prop.listOrder,
|
||||
photos: prop.photos,
|
||||
checkinRadious: prop.checkinRadious,
|
||||
autoCheckin: prop.autoCheckin,
|
||||
selected: prop.selected,
|
||||
checkedin: prop.checkedin,
|
||||
checkinPoint: prop.checkinPoint,
|
||||
buyPoint: prop.buyPoint,
|
||||
hiddenLocation: prop.hiddenLocation,
|
||||
checkinImage: prop.checkinImage,
|
||||
buypointImage: prop.buypointImage,
|
||||
forcedCheckin: prop.forcedCheckin,
|
||||
tags: prop.tags);
|
||||
}
|
||||
|
||||
Properties copyWith({
|
||||
int? locationId,
|
||||
String? subLocId,
|
||||
double? cp,
|
||||
String? name,
|
||||
String? address,
|
||||
String? phone,
|
||||
String? email,
|
||||
String? webcontents,
|
||||
String? videos,
|
||||
String? category,
|
||||
int? series,
|
||||
double? lat,
|
||||
double? lon,
|
||||
int? listOrder,
|
||||
String? photos,
|
||||
double? checkinRadious,
|
||||
bool? autoCheckin,
|
||||
bool? selected,
|
||||
bool? checkedin,
|
||||
double? checkinPoint,
|
||||
double? buyPoint,
|
||||
bool? hiddenLocation,
|
||||
String? checkinImage,
|
||||
String? buypointImage,
|
||||
bool? forcedCheckin,
|
||||
String? tags,
|
||||
}) {
|
||||
return Properties(
|
||||
locationId: locationId ?? this.locationId,
|
||||
subLocId: subLocId ?? this.subLocId,
|
||||
cp: cp ?? this.cp,
|
||||
name: name ?? this.name,
|
||||
address: address ?? this.address,
|
||||
phone: phone ?? this.phone,
|
||||
email: email ?? this.email,
|
||||
webcontents: webcontents ?? this.webcontents,
|
||||
videos: videos ?? this.videos,
|
||||
category: category ?? this.category,
|
||||
series: series ?? this.series,
|
||||
lat: lat ?? this.lat,
|
||||
lon: lon ?? this.lon,
|
||||
listOrder: listOrder ?? this.listOrder,
|
||||
photos: photos ?? this.photos,
|
||||
checkinRadious: checkinRadious ?? this.checkinRadious,
|
||||
autoCheckin: autoCheckin ?? this.autoCheckin,
|
||||
selected: selected ?? this.selected,
|
||||
checkedin: checkedin ?? this.checkedin,
|
||||
checkinPoint: checkinPoint ?? this.checkinPoint,
|
||||
buyPoint: buyPoint ?? this.buyPoint,
|
||||
hiddenLocation: hiddenLocation ?? this.hiddenLocation,
|
||||
checkinImage: checkinImage ?? this.checkinImage,
|
||||
buypointImage: buypointImage ?? this.buypointImage,
|
||||
forcedCheckin: forcedCheckin ?? this.forcedCheckin,
|
||||
tags: tags ?? this.tags,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
'locationId': locationId,
|
||||
'subLocId': subLocId,
|
||||
'cp': cp,
|
||||
'name': name,
|
||||
'address': address,
|
||||
'phone': phone,
|
||||
'email': email,
|
||||
'webcontents': webcontents,
|
||||
'videos': videos,
|
||||
'category': category,
|
||||
'series': series,
|
||||
'lat': lat,
|
||||
'lon': lon,
|
||||
'listOrder': listOrder,
|
||||
'photos': photos,
|
||||
'checkinRadious': checkinRadious,
|
||||
'autoCheckin': autoCheckin,
|
||||
'selected': selected,
|
||||
'checkedin': checkedin,
|
||||
'checkinPoint': checkinPoint,
|
||||
'buyPoint': buyPoint,
|
||||
'hiddenLocation': hiddenLocation,
|
||||
'checkinImage': checkinImage,
|
||||
'buypointImage': buypointImage,
|
||||
'forcedCheckin': forcedCheckin,
|
||||
'tags': tags,
|
||||
};
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Properties(locationId: $locationId, subLocId: $subLocId, cp: $cp, name: $name, address: $address, phone: $phone, email: $email, webcontents: $webcontents, videos: $videos, category: $category, series: $series, lat: $lat, lon: $lon, listOrder: $listOrder, photos: $photos, checkinRadious: $checkinRadious, autoCheckin: $autoCheckin, selected: $selected, checkedin: $checkedin, checkinPoint: $checkinPoint, buyPoint: $buyPoint, hiddenLocation: $hiddenLocation, checkinImage: $checkinImage, buypointImage: $buypointImage, forcedCheckin: $forcedCheckin, tags: $tags)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant Properties other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.locationId == locationId &&
|
||||
other.subLocId == subLocId &&
|
||||
other.cp == cp &&
|
||||
other.name == name &&
|
||||
other.address == address &&
|
||||
other.phone == phone &&
|
||||
other.email == email &&
|
||||
other.webcontents == webcontents &&
|
||||
other.videos == videos &&
|
||||
other.category == category &&
|
||||
other.series == series &&
|
||||
other.lat == lat &&
|
||||
other.lon == lon &&
|
||||
other.listOrder == listOrder &&
|
||||
other.photos == photos &&
|
||||
other.checkinRadious == checkinRadious &&
|
||||
other.autoCheckin == autoCheckin &&
|
||||
other.selected == selected &&
|
||||
other.checkedin == checkedin &&
|
||||
other.checkinPoint == checkinPoint &&
|
||||
other.buyPoint == buyPoint &&
|
||||
other.hiddenLocation == hiddenLocation &&
|
||||
other.checkinImage == checkinImage &&
|
||||
other.buypointImage == buypointImage &&
|
||||
other.forcedCheckin == forcedCheckin &&
|
||||
other.tags == tags;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return locationId.hashCode ^
|
||||
subLocId.hashCode ^
|
||||
cp.hashCode ^
|
||||
name.hashCode ^
|
||||
address.hashCode ^
|
||||
phone.hashCode ^
|
||||
email.hashCode ^
|
||||
webcontents.hashCode ^
|
||||
videos.hashCode ^
|
||||
category.hashCode ^
|
||||
series.hashCode ^
|
||||
lat.hashCode ^
|
||||
lon.hashCode ^
|
||||
listOrder.hashCode ^
|
||||
photos.hashCode ^
|
||||
checkinRadious.hashCode ^
|
||||
autoCheckin.hashCode ^
|
||||
selected.hashCode ^
|
||||
checkedin.hashCode ^
|
||||
checkinPoint.hashCode ^
|
||||
buyPoint.hashCode ^
|
||||
hiddenLocation.hashCode ^
|
||||
checkinImage.hashCode ^
|
||||
buypointImage.hashCode ^
|
||||
forcedCheckin.hashCode ^
|
||||
tags.hashCode;
|
||||
}
|
||||
}
|
||||
82
lib/features/data/checkpoint_visitis.dart
Normal file
82
lib/features/data/checkpoint_visitis.dart
Normal file
@ -0,0 +1,82 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class CheckpointVisit {
|
||||
final String id;
|
||||
final String checkpointId;
|
||||
final String teamName;
|
||||
final String userName;
|
||||
final String eventCode;
|
||||
final DateTime visitTime;
|
||||
|
||||
CheckpointVisit({
|
||||
required this.id,
|
||||
required this.checkpointId,
|
||||
required this.teamName,
|
||||
required this.userName,
|
||||
required this.eventCode,
|
||||
required this.visitTime,
|
||||
});
|
||||
|
||||
CheckpointVisit copyWith({
|
||||
String? id,
|
||||
String? checkpointId,
|
||||
String? teamName,
|
||||
String? userName,
|
||||
String? eventCode,
|
||||
DateTime? visitTime,
|
||||
}) {
|
||||
return CheckpointVisit(
|
||||
id: id ?? this.id,
|
||||
checkpointId: checkpointId ?? this.checkpointId,
|
||||
teamName: teamName ?? this.teamName,
|
||||
userName: userName ?? this.userName,
|
||||
eventCode: eventCode ?? this.eventCode,
|
||||
visitTime: visitTime ?? this.visitTime,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'checkpointId': checkpointId,
|
||||
'teamName': teamName,
|
||||
'userName': userName,
|
||||
'eventCode': eventCode,
|
||||
'visitTime': visitTime.millisecondsSinceEpoch,
|
||||
};
|
||||
}
|
||||
|
||||
factory CheckpointVisit.fromMap(Map<String, dynamic> map) {
|
||||
return CheckpointVisit(
|
||||
id: map['id'],
|
||||
checkpointId: map['checkpointId'],
|
||||
teamName: map['teamName'],
|
||||
userName: map['userName'],
|
||||
eventCode: map['eventCode'],
|
||||
visitTime: DateTime.fromMillisecondsSinceEpoch(map['visitTime']),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory CheckpointVisit.fromJson(String source) =>
|
||||
CheckpointVisit.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CheckpointVisit(id: $id, checkpointId: $checkpointId, teamName: $teamName, userName: $userName, eventCode: $eventCode, visitTime: $visitTime)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is CheckpointVisit &&
|
||||
other.id == id &&
|
||||
other.checkpointId == checkpointId &&
|
||||
other.teamName == teamName &&
|
||||
other.userName == userName &&
|
||||
other.eventCode == eventCode &&
|
||||
other.visitTime == visitTime;
|
||||
}
|
||||
}
|
||||
329
lib/features/data/data_provider.dart
Normal file
329
lib/features/data/data_provider.dart
Normal file
@ -0,0 +1,329 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:rogapp/features/data/checkpoint.dart';
|
||||
import 'package:rogapp/features/data/user_location.dart';
|
||||
|
||||
final dataProviderProvider = Provider<DataProvider>((ref) {
|
||||
return DataProvider();
|
||||
});
|
||||
|
||||
// Convert a Feature object to a Map
|
||||
Map<String, dynamic> featureToMap(Feature feature) {
|
||||
var properties = feature.properties;
|
||||
|
||||
try {
|
||||
return {
|
||||
'id': feature.id,
|
||||
'type': feature.type,
|
||||
'name': properties.name ?? '',
|
||||
'address': properties.address ?? '',
|
||||
'phone': properties.phone ?? '',
|
||||
'email': properties.email ?? '',
|
||||
'webcontents': properties.webcontents ?? '',
|
||||
'videos': properties.videos ?? '',
|
||||
'category': properties.category ?? '',
|
||||
'series': properties.series,
|
||||
'lat': feature.geometry.latitude,
|
||||
'lon': feature.geometry.longitude,
|
||||
'list_order': properties.listOrder,
|
||||
'photos': properties.photos ?? '',
|
||||
'checkin_radious': properties.checkinRadious,
|
||||
'sub_loc_id': properties.subLocId,
|
||||
'auto_checkin': properties.autoCheckin! ? 1 : 0,
|
||||
'selected': properties.selected == null
|
||||
? 0
|
||||
: properties.selected!
|
||||
? 1
|
||||
: 0,
|
||||
'checkedin': properties.checkedin == null
|
||||
? 0
|
||||
: properties.checkedin!
|
||||
? 1
|
||||
: 0,
|
||||
'cp': properties.cp,
|
||||
'checkin_point': properties.checkinPoint,
|
||||
'buy_point': properties.buyPoint,
|
||||
'hidden_location': properties.hiddenLocation,
|
||||
'checkin_image': properties.checkinImage,
|
||||
'buypoint_image': properties.buypointImage,
|
||||
'forced_checkin': properties.forcedCheckin == null
|
||||
? 0
|
||||
: properties.forcedCheckin!
|
||||
? 1
|
||||
: 0,
|
||||
'tags': properties.tags ?? '',
|
||||
'location_id': properties.locationId,
|
||||
};
|
||||
} catch (e) {
|
||||
//print("--- feature to map Error: $e");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a Map to a Feature object
|
||||
Feature mapToFeature(Map<String, dynamic> map) {
|
||||
Feature feat;
|
||||
//print("mapToFeature id --- ${Properties.fromJson(map)}");
|
||||
//print("mapToFeature --- ${map['type']}");
|
||||
feat = Feature(
|
||||
id: map['id'],
|
||||
type: map['type'],
|
||||
geometry: Geometry(
|
||||
type: map['type'] ?? 'Point',
|
||||
coordinates: [
|
||||
[map['lon'], map['lat']]
|
||||
],
|
||||
),
|
||||
properties: Properties.fromJson(map),
|
||||
);
|
||||
|
||||
//print("mapToFeature --- $feat");
|
||||
|
||||
return feat;
|
||||
}
|
||||
|
||||
class DataProvider {
|
||||
static Database? _database;
|
||||
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database!;
|
||||
_database = await initDB();
|
||||
return _database!;
|
||||
}
|
||||
|
||||
initDB() async {
|
||||
var documentsDirectory = await getApplicationDocumentsDirectory();
|
||||
String path = join(documentsDirectory.path, "GameDB.db");
|
||||
return await openDatabase(path,
|
||||
version: 1, onOpen: (db) {}, onCreate: _onCreate);
|
||||
}
|
||||
|
||||
_onCreate(Database db, int version) async {
|
||||
await db.execute('''
|
||||
CREATE TABLE Checkpoints (
|
||||
location_id INTEGER PRIMARY KEY,
|
||||
id INTEGER,
|
||||
type TEXT,
|
||||
name TEXT,
|
||||
address TEXT,
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
webcontents TEXT,
|
||||
videos TEXT,
|
||||
category TEXT,
|
||||
series INTEGER,
|
||||
lat REAL,
|
||||
lon REAL,
|
||||
list_order INTEGER,
|
||||
photos TEXT,
|
||||
checkin_radious REAL,
|
||||
sub_loc_id TEXT,
|
||||
auto_checkin INTEGER,
|
||||
selected INTEGER,
|
||||
checkedin INTEGER,
|
||||
cp REAL,
|
||||
checkin_point REAL,
|
||||
buy_point REAL,
|
||||
hidden_location INTEGER,
|
||||
checkin_image TEXT,
|
||||
buypoint_image TEXT,
|
||||
forced_checkin INTEGER,
|
||||
recipt_times INTEGER,
|
||||
tags TEXT
|
||||
)
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE TABLE GPSLocations (
|
||||
timestamp TEXT PRIMARY KEY,
|
||||
latitude REAL,
|
||||
longitude REAL,
|
||||
event_code TEXT,
|
||||
team_name TEXT,
|
||||
user_name TEXT,
|
||||
attempt_count INTEGER
|
||||
)
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE TABLE GameState (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT,
|
||||
event_code TEXT,
|
||||
team_name TEXT,
|
||||
user_name TEXT,
|
||||
attempt_count INTEGER
|
||||
)
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE TABLE CheckpointVisits (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
checkpointId INTEGER,
|
||||
photoTaken BOOLEAN,
|
||||
receiptPhotoTaken BOOLEAN,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
event_code TEXT,
|
||||
team_name TEXT,
|
||||
user_name TEXT,
|
||||
attempt_count INTEGER DEFAULT 1,
|
||||
FOREIGN KEY (checkpointId) REFERENCES Checkpoints(location_id)
|
||||
)
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> recordCheckpointVisit(
|
||||
int locationId, String userName, String teamName, String eventCode,
|
||||
{bool photoTaken = false, bool? receiptPhotoTaken}) async {
|
||||
final db = await database;
|
||||
|
||||
// Fetching buy_point to determine if a receipt is required
|
||||
var checkpointQueryResult = await db.query(
|
||||
'Checkpoints',
|
||||
columns: ['buy_point'],
|
||||
where: 'location_id = ?',
|
||||
whereArgs: [locationId],
|
||||
);
|
||||
|
||||
var buyPoint = checkpointQueryResult.isNotEmpty
|
||||
? checkpointQueryResult.first['buy_point'] as double?
|
||||
: null;
|
||||
var requiresReceipt = buyPoint != null && buyPoint > 0.0;
|
||||
|
||||
await db.insert(
|
||||
'CheckpointVisits',
|
||||
{
|
||||
'checkpointId': locationId,
|
||||
'user_name': userName,
|
||||
'team_name': teamName,
|
||||
'event_code': eventCode,
|
||||
'photoTaken': photoTaken ? 1 : 0,
|
||||
'receiptPhotoTaken':
|
||||
requiresReceipt ? (receiptPhotoTaken == true ? 1 : 0) : null,
|
||||
},
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getIncompleteTasks(int locationId,
|
||||
String userName, String teamName, String eventCode) async {
|
||||
final db = await database;
|
||||
var checkpoint = await db.query(
|
||||
'Checkpoints',
|
||||
where: 'location_id = ?',
|
||||
whereArgs: [locationId],
|
||||
);
|
||||
|
||||
var buyPointValue =
|
||||
checkpoint.isNotEmpty ? checkpoint.first['buy_point'] as double? : null;
|
||||
var requiresReceipt = buyPointValue != null && buyPointValue > 0.0;
|
||||
|
||||
// Fetch visits considering all relevant identifiers
|
||||
List<Map> visits = await db.query(
|
||||
'CheckpointVisits',
|
||||
where:
|
||||
'checkpointId = ? AND user_name = ? AND team_name = ? AND event_code = ?',
|
||||
whereArgs: [locationId, userName, teamName, eventCode],
|
||||
);
|
||||
|
||||
if (visits.isNotEmpty) {
|
||||
var lastVisit = visits.last;
|
||||
return {
|
||||
'photoTaken': lastVisit['photoTaken'] == 1,
|
||||
'receiptPhotoTaken':
|
||||
requiresReceipt ? lastVisit['receiptPhotoTaken'] == 1 : true,
|
||||
};
|
||||
}
|
||||
|
||||
// Default return values when no visits found
|
||||
return {
|
||||
'photoTaken': false,
|
||||
'receiptPhotoTaken': requiresReceipt ? false : true,
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> insertMarker(Feature marker) async {
|
||||
//print("--- inserting ${featureToMap(marker)} ---");
|
||||
final db = await database;
|
||||
try {
|
||||
await db.insert(
|
||||
'Checkpoints',
|
||||
featureToMap(marker),
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
} catch (e) {
|
||||
print("--- ${e.toString()} ---");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Feature>> getMarkers() async {
|
||||
final db = await database;
|
||||
var res = await db.query('Checkpoints');
|
||||
List<Feature> list =
|
||||
res.isNotEmpty ? res.map((c) => mapToFeature(c)).toList() : [];
|
||||
//print("--- checkpoints ${res} ---");
|
||||
return list;
|
||||
}
|
||||
|
||||
Future<int> deleteMarker(int id) async {
|
||||
final db = await database;
|
||||
return db.delete('Checkpoints', where: 'id = ?', whereArgs: [id]);
|
||||
}
|
||||
|
||||
Future<void> insertGPSLocation(UserLocation location) async {
|
||||
final db = await database;
|
||||
await db.insert(
|
||||
'GPSLocations',
|
||||
location
|
||||
.toMap(), // Implement a method in UserLocation to convert the object to a Map
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<UserLocation>> getGPSLocations() async {
|
||||
final db = await database;
|
||||
var res = await db.query('GPSLocations');
|
||||
List<UserLocation> locations =
|
||||
res.isNotEmpty ? res.map((c) => UserLocation.fromMap(c)).toList() : [];
|
||||
return locations;
|
||||
}
|
||||
|
||||
Future<void> updateGameState(
|
||||
String key,
|
||||
String value,
|
||||
String userName,
|
||||
String teamName,
|
||||
String eventCode,
|
||||
) async {
|
||||
final db = await database;
|
||||
await db.insert(
|
||||
'GameState',
|
||||
{
|
||||
'key': key,
|
||||
'value': value,
|
||||
'team_name': teamName,
|
||||
'event_code': eventCode,
|
||||
'user_name': userName,
|
||||
},
|
||||
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<String?> getGameState(
|
||||
String key,
|
||||
String userName,
|
||||
String teamName,
|
||||
String eventCode,
|
||||
) async {
|
||||
final db = await database;
|
||||
List<Map<String, dynamic>> results = await db.query(
|
||||
'GameState',
|
||||
where: 'key = ? AND team_name = ? AND event_code = ? AND user_name = ?',
|
||||
whereArgs: [key, teamName, eventCode, userName],
|
||||
);
|
||||
|
||||
if (results.isNotEmpty) {
|
||||
return results.first['value'] as String?;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
17
lib/features/data/game_event.dart
Normal file
17
lib/features/data/game_event.dart
Normal file
@ -0,0 +1,17 @@
|
||||
enum EventType {
|
||||
atStart,
|
||||
starting,
|
||||
started,
|
||||
inCheckin,
|
||||
checkiningIn,
|
||||
checkedIn,
|
||||
atGoal,
|
||||
finishingGoal,
|
||||
finishedGoal,
|
||||
}
|
||||
|
||||
class GameEvent {
|
||||
final EventType type;
|
||||
final DateTime timestamp;
|
||||
GameEvent({this.type = EventType.atStart, required this.timestamp});
|
||||
}
|
||||
24
lib/features/data/user.dart
Normal file
24
lib/features/data/user.dart
Normal file
@ -0,0 +1,24 @@
|
||||
class User {
|
||||
User.User();
|
||||
|
||||
//AuthUser.from({required this.id, required this.email, required this.is_rogaining, required this.group, required this.zekken_number, required this.event_code, required this.team_name});
|
||||
|
||||
User.fromMap(Map<String, dynamic> map)
|
||||
: id = int.parse(map["id"].toString()),
|
||||
email = map["email"].toString(),
|
||||
is_rogaining = bool.parse(map["is_rogaining"].toString()),
|
||||
group = map["group"].toString(),
|
||||
zekken_number = map["zekken_number"].toString(),
|
||||
event_code = map["event_code"].toString(),
|
||||
team_name = map["team_name"].toString(),
|
||||
auth_token = map["token"];
|
||||
|
||||
int? id;
|
||||
String? email;
|
||||
bool? is_rogaining;
|
||||
String? group;
|
||||
String? zekken_number;
|
||||
String? event_code;
|
||||
String? team_name;
|
||||
String? auth_token;
|
||||
}
|
||||
59
lib/features/data/user_location.dart
Normal file
59
lib/features/data/user_location.dart
Normal file
@ -0,0 +1,59 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
class UserLocation {
|
||||
final double latitude;
|
||||
final double longitude;
|
||||
final DateTime timestamp;
|
||||
UserLocation(
|
||||
{required this.latitude,
|
||||
required this.longitude,
|
||||
required this.timestamp});
|
||||
|
||||
static UserLocation empty() {
|
||||
return UserLocation(
|
||||
latitude: 0.0, longitude: 0.0, timestamp: DateTime.now());
|
||||
}
|
||||
|
||||
factory UserLocation.fromPosition(Position position) {
|
||||
return UserLocation(
|
||||
latitude: position.latitude,
|
||||
longitude: position.longitude,
|
||||
timestamp: position.timestamp);
|
||||
}
|
||||
|
||||
UserLocation copyWith({
|
||||
double? latitude,
|
||||
double? longitude,
|
||||
DateTime? timestamp,
|
||||
}) {
|
||||
return UserLocation(
|
||||
latitude: latitude ?? this.latitude,
|
||||
longitude: longitude ?? this.longitude,
|
||||
timestamp: timestamp ?? this.timestamp,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
'latitude': latitude,
|
||||
'longitude': longitude,
|
||||
'timestamp': timestamp.millisecondsSinceEpoch,
|
||||
};
|
||||
}
|
||||
|
||||
factory UserLocation.fromMap(Map<String, dynamic> map) {
|
||||
return UserLocation(
|
||||
latitude: map['latitude'] as double,
|
||||
longitude: map['longitude'] as double,
|
||||
timestamp: DateTime.fromMillisecondsSinceEpoch(map['timestamp'] as int),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory UserLocation.fromJson(String source) =>
|
||||
UserLocation.fromMap(json.decode(source) as Map<String, dynamic>);
|
||||
}
|
||||
Reference in New Issue
Block a user