added game status

This commit is contained in:
2024-02-04 19:14:41 +05:30
parent eda5f77e2d
commit 494b27bf9e
16 changed files with 691 additions and 137 deletions

View File

@ -14,6 +14,7 @@ import 'package:rogapp/model/gps_data.dart';
import 'package:rogapp/pages/camera/camera_page.dart';
import 'package:rogapp/pages/index/index_controller.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/services/DatabaseService.dart';
import 'package:rogapp/services/destination_service.dart';
import 'package:rogapp/services/external_service.dart';
import 'package:rogapp/services/location_service.dart';
@ -77,6 +78,7 @@ class DestinationController extends GetxController {
final IndexController indexController = Get.find<IndexController>();
final LocationController locationController = Get.put(LocationController());
final DatabaseService dbService = DatabaseService();
int _start = 0;
int chekcs = 0;
@ -433,6 +435,7 @@ class DestinationController extends GetxController {
lastGoalAt = DateTime.fromMicrosecondsSinceEpoch(latgoal);
//print("===== last goal : $last_goal_at =====");
}
dbService.updateDatabase();
}
void deleteAllDestinations() {
@ -564,6 +567,7 @@ class DestinationController extends GetxController {
Future<void> checkForCheckin() async {
//print("--- Start of checkForCheckin function ---");
dbService.updateDatabase();
await Future.delayed(const Duration(milliseconds: 3000));
game_started = true;
@ -718,15 +722,16 @@ class DestinationController extends GetxController {
// print("------Ext service check point $value ------");
});
}
dbService.updateDatabase();
}
Future<void> removeCheckin(int cp) {
dbService.updateDatabase();
return ExternalService().removeCheckin(cp);
}
Future<void> startGame() async {
//print("------ starting game ------");
if (game_started == false) {
await checkForCheckin();
}
@ -776,6 +781,9 @@ class DestinationController extends GetxController {
}
double distanceToStart() {
if (indexController.locations.isEmpty) {
return 1000000000;
}
//print("=== gfs len == ${indexController.locations[0].collection.length}");
double distanceToDest = double.infinity;
if (indexController.locations[0].features.isEmpty) {
@ -959,6 +967,7 @@ class DestinationController extends GetxController {
db.deleteDestination(d.location_id!).then((value) {
populateDestinations();
});
dbService.updateDatabase();
}
void deleteDBDestinations() {
@ -966,6 +975,7 @@ class DestinationController extends GetxController {
db.deleteAllDestinations().then((value) {
populateDestinations();
});
dbService.updateDatabase();
}
// ---------- database ------------------///
@ -988,6 +998,7 @@ class DestinationController extends GetxController {
});
}
});
dbService.updateDatabase();
}
void toggleSelection(Destination dest) async {

View File

@ -1,11 +1,14 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/model/destination.dart';
import 'package:rogapp/model/gps_data.dart';
import 'package:rogapp/pages/destination/destination_controller.dart';
import 'package:rogapp/pages/drawer/drawer_page.dart';
import 'package:rogapp/pages/index/index_controller.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/services/DatabaseService.dart';
import 'package:rogapp/utils/database_gps.dart';
import 'package:rogapp/utils/database_helper.dart';
import 'package:rogapp/widgets/list_widget.dart';
import 'package:rogapp/widgets/map_widget.dart';
@ -25,6 +28,13 @@ class IndexPage extends GetView<IndexController> {
appBar: AppBar(
title: Text("add_location".tr),
actions: [
IconButton(
onPressed: () {
DatabaseService ds = DatabaseService();
ds.updateDatabase();
},
icon: const Icon(Icons.ten_k_sharp)),
IconButton(
onPressed: () async {
// GpsDatabaseHelper db = GpsDatabaseHelper.instance;

View File

@ -0,0 +1,55 @@
import 'dart:async';
import 'package:rogapp/model/destination.dart';
import 'package:rogapp/utils/database_helper.dart';
class DatabaseService {
// Private constructor
DatabaseService._privateConstructor();
// Static instance
static final DatabaseService _instance =
DatabaseService._privateConstructor();
// Factory constructor to return the instance
factory DatabaseService() {
return _instance;
}
// StreamController for updates
final StreamController<List<Destination>> _dbUpdateController =
StreamController<List<Destination>>.broadcast();
// Getter for the stream
Stream<List<Destination>> get destinationUpdatesStream =>
_dbUpdateController.stream;
// Method to fetch destinations
Future<List<Destination>> fetchDestinations() async {
// Your database fetch logic here
List<Destination> destinations = await _fetchFromDb();
_dbUpdateController.add(destinations);
return destinations;
}
// Method to update the database and emit an update through the stream
Future<void> updateDatabase() async {
// Your update logic here
// After updating, fetch the updated list and add it to the stream
fetchDestinations();
}
// Method to fetch data from the database (placeholder)
Future<List<Destination>> _fetchFromDb() async {
// Simulate fetching data with a delay
DatabaseHelper db = DatabaseHelper.instance;
List<Destination> destinations = await db.getDestinations();
return destinations; // Replace with your actual fetch operation
}
// Dispose method to close the stream controller
void dispose() {
_dbUpdateController.close();
}
}

View File

@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
import 'package:rogapp/widgets/GameState/Colors.dart';
class LocationVisitedWidget extends StatelessWidget {
final int count;
final bool minimized;
const LocationVisitedWidget(
{Key? key, required this.count, this.minimized = false})
: super(key: key);
@override
Widget build(BuildContext context) {
if (minimized) {
return Container(
height: 40,
width: 40,
decoration: BoxDecoration(
color: JapaneseColors.mizu,
shape: BoxShape.circle,
),
child: Center(
child: Text(
'$count',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
),
);
} else {
return Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: JapaneseColors.matcha,
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.check_circle_outline, color: Colors.white, size: 24),
SizedBox(width: 8),
Text(
'$count チェックイン', // "X Check-ins" in Japanese
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16),
),
],
),
);
}
}
}

View File

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
class JapaneseColors {
static const Color mizu = Color(0xFFA4DDED); // Mizu (light blue)
static const Color matcha = Color(0xFFC5E1A5);
static const Color ume = Color(0xFFE1A8A8); // Ume (plum)
static const Color take = Color(0xFF7B8D42); // Take (bamboo)
static const Color sora = Color(0xFFA1CAF1);
static const Color indigo = Color(0xFF264653); // Aizome
static const Color sakuraPink = Color(0xFFFAD2E1); // Sakura-iro
/// Matcha (green tea)
}

View File

@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:rogapp/widgets/GameState/Colors.dart';
enum ConnectionStatus { none, mobile, wifi }
class ConnectionStatusIndicator extends StatelessWidget {
final ConnectionStatus connectionStatus;
final bool minimized;
const ConnectionStatusIndicator({
Key? key,
required this.connectionStatus,
this.minimized = false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Color backgroundColor;
IconData iconData;
String text;
switch (connectionStatus) {
case ConnectionStatus.none:
backgroundColor = JapaneseColors.ume;
iconData = Icons.signal_cellular_off;
text = 'No Connection';
break;
case ConnectionStatus.mobile:
backgroundColor = JapaneseColors.take;
iconData = Icons.signal_cellular_alt;
text = 'Mobile Data';
break;
case ConnectionStatus.wifi:
backgroundColor = JapaneseColors.sora;
iconData = Icons.wifi;
text = 'Wi-Fi';
break;
default:
backgroundColor = Colors.grey; // Fallback color
iconData = Icons.device_unknown;
text = 'Unknown';
}
return Container(
height: minimized ? 40 : null,
width: minimized ? 40 : null,
padding:
minimized ? null : EdgeInsets.symmetric(vertical: 8, horizontal: 16),
decoration: BoxDecoration(
color: backgroundColor,
shape: minimized ? BoxShape.circle : BoxShape.rectangle,
borderRadius: minimized ? null : BorderRadius.circular(10),
),
child: minimized
? Center(
child: Icon(iconData, color: Colors.white, size: 24),
)
: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(iconData, color: Colors.white),
SizedBox(width: 8),
Text(
text,
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
],
),
);
}
}

View File

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:rogapp/widgets/GameState/CheckinState.dart';
import 'package:rogapp/widgets/GameState/game_on_off.dart';
class DashboardWidget extends StatelessWidget {
final bool gameStarted;
final int locationsVisited;
final bool isMinimized;
const DashboardWidget({
Key? key,
required this.gameStarted,
required this.locationsVisited,
this.isMinimized = false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
List<Widget> widgets = [
GameStatusIndicator(gameStarted: gameStarted, minimized: isMinimized),
SizedBox(
height: isMinimized ? 0 : 8, width: isMinimized ? 8 : 0), // Spacing
LocationVisitedWidget(count: locationsVisited, minimized: isMinimized),
];
return Container(
padding: EdgeInsets.all(isMinimized ? 8 : 16),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3),
),
],
borderRadius: BorderRadius.circular(10),
),
child: isMinimized
? Row(
mainAxisSize: MainAxisSize.min,
children: widgets,
)
: Column(
mainAxisSize: MainAxisSize.min,
children: widgets,
),
);
}
}

View File

@ -0,0 +1,55 @@
import 'package:flutter/material.dart';
import 'package:rogapp/widgets/GameState/Colors.dart';
class GameStatusIndicator extends StatelessWidget {
final bool gameStarted;
final bool minimized;
const GameStatusIndicator(
{Key? key, required this.gameStarted, this.minimized = true})
: super(key: key);
@override
Widget build(BuildContext context) {
// Icons to show based on the game status
IconData iconData =
gameStarted ? Icons.stop_circle : Icons.play_circle_filled;
// Text to show based on the game status
String text = gameStarted ? 'ゲーム開始' : 'ゲーム未開始';
// Layout for minimized view
if (minimized) {
return Container(
height: 40, // Square size
width: 40, // Square size
decoration: BoxDecoration(
color:
gameStarted ? JapaneseColors.indigo : JapaneseColors.sakuraPink,
shape: BoxShape
.circle, // Making it circle when minimized for a more distinct look
),
child: Icon(iconData, color: Colors.white),
);
}
// Layout for expanded view
return Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: gameStarted ? JapaneseColors.indigo : JapaneseColors.sakuraPink,
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(iconData, color: Colors.white),
SizedBox(width: 8),
Text(
text,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
],
),
);
}
}

View File

@ -0,0 +1,200 @@
import 'dart:ffi';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/model/destination.dart';
import 'package:rogapp/pages/destination/destination_controller.dart';
import 'package:rogapp/pages/index/index_controller.dart';
import 'package:rogapp/services/DatabaseService.dart';
import 'package:rogapp/utils/database_helper.dart';
import 'package:rogapp/widgets/GameState/CheckinState.dart';
import 'package:rogapp/widgets/GameState/ConnectionStatus.dart';
import 'package:rogapp/widgets/GameState/DashboardWidget.dart';
import 'package:rogapp/widgets/GameState/game_on_off.dart';
class GameStateManager {
static final GameStateManager _instance = GameStateManager._internal();
factory GameStateManager() {
return _instance;
}
GameStateManager._internal();
List<String> _logs = [];
List<VoidCallback> _listeners = [];
List<String> get logs => _logs;
void addLog(String log) {
_logs.add(log);
_notifyListeners(); // Notify all listeners
}
void clearLogs() {
_logs.clear();
_notifyListeners(); // Notify all listeners
}
void addListener(VoidCallback listener) {
_listeners.add(listener);
}
void removeListener(VoidCallback listener) {
_listeners.remove(listener);
}
void _notifyListeners() {
for (var listener in _listeners) {
listener();
}
}
}
class GameStateWidget extends StatefulWidget {
const GameStateWidget({super.key});
@override
State<GameStateWidget> createState() => _GameStateWidgetState();
}
class _GameStateWidgetState extends State<GameStateWidget> {
final GameStateManager gameStateManager = GameStateManager();
final IndexController indexController = Get.find<IndexController>();
final DestinationController destinationController =
Get.find<DestinationController>();
@override
void initState() {
super.initState();
gameStateManager.addListener(_updateLogs);
}
@override
void dispose() {
gameStateManager.removeListener(_updateLogs);
super.dispose();
}
void _updateLogs() {
Future.delayed(Duration.zero, () {
if (mounted) {
setState(() {});
}
});
}
void toggleExpanded() {
setState(() {
isExpanded = !isExpanded;
});
}
void clearLogs() {
gameStateManager.clearLogs();
}
bool isExpanded = false;
@override
Widget build(BuildContext context) {
final DatabaseService dbService = DatabaseService();
return Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(color: Colors.black12),
child: GestureDetector(
onTap: toggleExpanded,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
color: isExpanded ? Colors.black54 : Colors.black12,
height: isExpanded ? 160.0 : 48.0, // Adjust sizes as needed
child: Column(
children: [
// Top bar with clear button
if (isExpanded)
Container(
padding: EdgeInsets.symmetric(horizontal: 10.0),
color: Colors.blueGrey, // Adjust color as needed
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('ゲームステータス', style: TextStyle(color: Colors.white)),
IconButton(
icon: Icon(Icons.clear, color: Colors.white),
onPressed: toggleExpanded,
),
],
),
),
// Log messages
Expanded(
child: SingleChildScrollView(
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
children: [
Obx(() => Padding(
padding: const EdgeInsets.all(4.0),
child: GameStatusIndicator(
gameStarted: destinationController.isInRog.value,
minimized: !isExpanded,
),
)),
Padding(
padding: const EdgeInsets.all(4.0),
child: StreamBuilder<List<Destination>>(
stream: dbService.destinationUpdatesStream,
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return LocationVisitedWidget(
count: 0,
minimized: !isExpanded,
);
} else if (snapshot.hasData) {
return LocationVisitedWidget(
count: snapshot.data!.length,
minimized: !isExpanded,
);
} else {
return LocationVisitedWidget(
count: 0,
minimized: !isExpanded,
);
}
},
),
// child: LocationVisitedWidget(
// count:
// minimized: !isExpanded,
// ),
),
Padding(
padding: const EdgeInsets.all(4.0),
child: ConnectionStatusIndicator(
connectionStatus: ConnectionStatus.wifi,
minimized: !isExpanded),
) // Expanded view
],
),
// child: Obx(
// () => DashboardWidget(
// gameStarted: destinationController.isInRog.value,
// locationsVisited: 3,
// isMinimized: false,
// ),
),
),
],
),
),
),
);
}
}

View File

@ -14,7 +14,7 @@ import 'package:rogapp/utils/database_helper.dart';
import 'package:rogapp/utils/text_util.dart';
import 'package:rogapp/widgets/base_layer_widget.dart';
import 'package:rogapp/widgets/bottom_sheet_new.dart';
import 'package:rogapp/widgets/debug_widget.dart';
import 'package:rogapp/widgets/game_state_view.dart';
class MapWidget extends StatelessWidget {
final IndexController indexController = Get.find<IndexController>();
@ -249,6 +249,7 @@ class MapWidget extends StatelessWidget {
: const Center(child: CircularProgressIndicator()),
],
)),
const Positioned(top: 0, left: 0, child: GameStateWidget()),
// const Positioned(
// bottom: 10,
// left: 0,