NEW: MIH MineSweeper Package pt2
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihMineSweeperLeaderBoard extends StatefulWidget {
|
||||
const MihMineSweeperLeaderBoard({super.key});
|
||||
|
||||
@override
|
||||
State<MihMineSweeperLeaderBoard> createState() =>
|
||||
_MihMineSweeperLeaderBoardState();
|
||||
}
|
||||
|
||||
class _MihMineSweeperLeaderBoardState extends State<MihMineSweeperLeaderBoard> {
|
||||
TextEditingController filterController = TextEditingController();
|
||||
|
||||
Future<void> initialiseLeaderboard() async {
|
||||
MihMineSweeperProvider mineSweeperProvider =
|
||||
context.read<MihMineSweeperProvider>();
|
||||
filterController.text = mineSweeperProvider.difficulty;
|
||||
if (mineSweeperProvider.leaderboard == null ||
|
||||
mineSweeperProvider.leaderboard!.isEmpty) {
|
||||
KenLogger.success("getting data");
|
||||
await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider);
|
||||
List<ImageProvider<Object>?> userPictures = [];
|
||||
String userPicUrl = "";
|
||||
for (final ranking in mineSweeperProvider.leaderboard!) {
|
||||
userPicUrl =
|
||||
await MihFileApi.getMinioFileUrl(ranking.proPicUrl, context);
|
||||
userPictures.add(NetworkImage(userPicUrl));
|
||||
}
|
||||
mineSweeperProvider.setLeaderboardUserPictures(
|
||||
leaderboardUserPictures: userPictures);
|
||||
}
|
||||
}
|
||||
|
||||
void refreshLeaderBoard(
|
||||
MihMineSweeperProvider mineSweeperProvider, String difficulty) {
|
||||
mineSweeperProvider.setDifficulty(difficulty);
|
||||
mineSweeperProvider.setLeaderboard(leaderboard: null);
|
||||
mineSweeperProvider.setMyScoreboard(myScoreboard: null);
|
||||
initialiseLeaderboard();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await initialiseLeaderboard();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.sizeOf(context).width;
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
refreshLeaderBoard(mineSweeperProvider, filterController.text);
|
||||
},
|
||||
child: MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
if (mineSweeperProvider.leaderboard == null) {
|
||||
return Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
} else {
|
||||
return SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihDropdownField(
|
||||
controller: filterController,
|
||||
hintText: "Leaderboards",
|
||||
dropdownOptions: const [
|
||||
"Very Easy",
|
||||
"Easy",
|
||||
"Intermediate",
|
||||
"Hard",
|
||||
],
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
onSelected: (selection) {
|
||||
refreshLeaderBoard(mineSweeperProvider, selection!);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
mineSweeperProvider.leaderboard!.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mineSweeper,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Be the first on the leaderboard.",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
FontAwesomeIcons.bomb,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " and start a new game"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: BuildMinesweeperLeaderboardList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,26 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/board_square.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/mih_mine_sweeper_start_game_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/mine_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MineSweeperGame extends StatefulWidget {
|
||||
@@ -27,92 +31,115 @@ class MineSweeperGame extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
TextEditingController modeController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
List<List<BoardSquare>> board = [];
|
||||
bool isGameOver = false;
|
||||
bool isGameWon = false;
|
||||
int squaresLeft = -1;
|
||||
bool _isFirstLoad = true;
|
||||
Timer? _timer;
|
||||
int _milliseconds = 0;
|
||||
bool _isRunning = false;
|
||||
static const int millisecondsPerUpdate = 10;
|
||||
|
||||
String getModeConfig() {
|
||||
switch (modeController.text) {
|
||||
case ("Easy"):
|
||||
return "Columns: 10\nRows: 10\nBomds: 15";
|
||||
case ("Normal"):
|
||||
return "Columns: 10\nRows: 15\nBomds: 23";
|
||||
case ("Hard"):
|
||||
return "Columns: 10\nRows: 20\nBomds: 30";
|
||||
default:
|
||||
return "Error";
|
||||
double timeStringToTotalSeconds(String timeString) {
|
||||
try {
|
||||
List<String> parts = timeString.split(':');
|
||||
if (parts.length < 4) {
|
||||
return 0.0;
|
||||
}
|
||||
double hours = double.parse(parts[0]);
|
||||
double minutes = double.parse(parts[1]);
|
||||
double seconds = double.parse(parts[2]);
|
||||
double milliseconds = double.parse(parts[3]);
|
||||
double totalSeconds =
|
||||
(hours * 3600) + (minutes * 60) + seconds + (milliseconds / 1000);
|
||||
return totalSeconds;
|
||||
} catch (e) {
|
||||
print("Error parsing time string: $e");
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void showStartGameWindow(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
double calculateGameScore(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
int scoreConst = 10000;
|
||||
double dificusltyMultiplier;
|
||||
switch (mihMineSweeperProvider.difficulty) {
|
||||
case ("Very Easy"):
|
||||
dificusltyMultiplier = 0.5;
|
||||
break;
|
||||
case ("Easy"):
|
||||
dificusltyMultiplier = 1.0;
|
||||
break;
|
||||
case ("Intermediate"):
|
||||
dificusltyMultiplier = 2.5;
|
||||
break;
|
||||
case ("Hard"):
|
||||
dificusltyMultiplier = 5.0;
|
||||
break;
|
||||
default:
|
||||
dificusltyMultiplier = 0.0;
|
||||
break;
|
||||
}
|
||||
double rawScore = (scoreConst * dificusltyMultiplier) /
|
||||
timeStringToTotalSeconds(_formatTime());
|
||||
|
||||
String scoreString = rawScore.toStringAsFixed(5);
|
||||
return double.parse(scoreString);
|
||||
}
|
||||
|
||||
void startTimer() {
|
||||
if (_isRunning) return;
|
||||
_isRunning = true;
|
||||
_timer = Timer.periodic(const Duration(milliseconds: millisecondsPerUpdate),
|
||||
(timer) {
|
||||
setState(() {
|
||||
_milliseconds += millisecondsPerUpdate; // Increment by the interval
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void stopTimer() {
|
||||
_timer?.cancel();
|
||||
setState(() {
|
||||
_isRunning = false;
|
||||
});
|
||||
}
|
||||
|
||||
void resetTimer() {
|
||||
stopTimer(); // Stop the timer first
|
||||
setState(() {
|
||||
_milliseconds = 0; // Reset the time to zero
|
||||
});
|
||||
}
|
||||
|
||||
String _formatTime() {
|
||||
Duration duration = Duration(milliseconds: _milliseconds);
|
||||
final int hours = duration.inHours.remainder(60);
|
||||
final int minutes = duration.inMinutes.remainder(60);
|
||||
final int seconds = duration.inSeconds.remainder(60);
|
||||
final int centiseconds = (duration.inMilliseconds.remainder(1000)) ~/ 10;
|
||||
String hoursStr = hours.toString().padLeft(2, '0');
|
||||
String minutesStr = minutes.toString().padLeft(2, '0');
|
||||
String secondsStr = seconds.toString().padLeft(2, '0');
|
||||
String centiStr = centiseconds.toString().padLeft(2, '0');
|
||||
return '$hoursStr:$minutesStr:$secondsStr:$centiStr';
|
||||
}
|
||||
|
||||
void showStartGameWindow(MihMineSweeperProvider mihMineSweeperProvider,
|
||||
MihBannerAdProvider addProvider) {
|
||||
// easy - 10 * 10 & 15 bombs
|
||||
// Normal - 10 * 15 & 23 bombs
|
||||
// Intermediate - 10 * 15 & 23 bombs
|
||||
// Hard - 10 * 20 & 30 bombs
|
||||
addProvider.loadBannerAd();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "New Game Settings",
|
||||
onWindowTapClose: () {
|
||||
context.pop();
|
||||
return MihMineSweeperStartGameWindow(
|
||||
onPressed: () {
|
||||
resetTimer();
|
||||
mihMineSweeperProvider
|
||||
.setDifficulty(mihMineSweeperProvider.difficulty);
|
||||
setState(() => initializeBoard(mihMineSweeperProvider));
|
||||
},
|
||||
windowBody: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihDropdownField(
|
||||
controller: modeController,
|
||||
hintText: "Difficulty",
|
||||
dropdownOptions: ["Easy", "Normal", "Hard"],
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: false,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
getModeConfig(),
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
setState(
|
||||
() => initializeBoard(mihMineSweeperProvider));
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Start Game",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -137,6 +164,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
isGameOver = false;
|
||||
isGameWon = false;
|
||||
// You'd typically add a call to setState here, but it's in initState.
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void placeBombs(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
@@ -213,12 +241,18 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
}
|
||||
}
|
||||
|
||||
void handleTap(MihMineSweeperProvider mihMineSweeperProvider, int r, int c) {
|
||||
Future<void> handleTap(
|
||||
MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mihMineSweeperProvider,
|
||||
MihBannerAdProvider adProvider,
|
||||
int r,
|
||||
int c) async {
|
||||
if (isGameOver || board[r][c].isOpened || board[r][c].isFlagged) {
|
||||
return;
|
||||
}
|
||||
// 1. Check for bomb (LOSS)
|
||||
if (board[r][c].hasBomb) {
|
||||
stopTimer();
|
||||
setState(() {
|
||||
board[r][c].isOpened = true;
|
||||
isGameOver = true;
|
||||
@@ -227,19 +261,34 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MihPackageAlert(
|
||||
alertIcon: Icon(
|
||||
FontAwesomeIcons.bomb,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 100,
|
||||
alertIcon: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Icon(
|
||||
FontAwesomeIcons.bomb,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 100,
|
||||
),
|
||||
),
|
||||
alertTitle: "Better Luck Next Time",
|
||||
alertBody: Column(
|
||||
children: [
|
||||
Text(
|
||||
"Your lost this game of MIH MineSweeper!!!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontSize: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Please feel free to start a New Game or check out the Leader Board to find out who's the best in Mzansi.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
@@ -254,9 +303,9 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
setState(
|
||||
() => initializeBoard(mihMineSweeperProvider));
|
||||
Navigator.of(context).pop();
|
||||
context.pop();
|
||||
showStartGameWindow(
|
||||
mihMineSweeperProvider, adProvider);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
@@ -273,6 +322,26 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
mihMineSweeperProvider.setToolIndex(1);
|
||||
},
|
||||
buttonColor: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Leader Board",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -295,7 +364,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
squaresLeft--;
|
||||
}
|
||||
// 3. Check for win
|
||||
_checkWinCondition(mihMineSweeperProvider);
|
||||
_checkWinCondition(profileProvider, mihMineSweeperProvider, adProvider);
|
||||
// Update the UI
|
||||
setState(() {});
|
||||
}
|
||||
@@ -311,9 +380,14 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
}
|
||||
|
||||
// --- GAME ACTION LOGIC ---
|
||||
void _checkWinCondition(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
Future<void> _checkWinCondition(
|
||||
MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mihMineSweeperProvider,
|
||||
MihBannerAdProvider adProvider,
|
||||
) async {
|
||||
// Game is won if all non-mine squares are opened.
|
||||
if (squaresLeft <= mihMineSweeperProvider.totalMines) {
|
||||
stopTimer();
|
||||
isGameWon = true;
|
||||
isGameOver = true;
|
||||
// win alert
|
||||
@@ -327,13 +401,41 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 100,
|
||||
),
|
||||
alertTitle: "Congradulations",
|
||||
alertTitle: "Congratulations",
|
||||
alertBody: Column(
|
||||
children: [
|
||||
Text(
|
||||
"Your won this game of MIH MineSweeper!!!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontSize: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// Text(
|
||||
// "You took ${_formatTime()} to complete the game on ${mihMineSweeperProvider.difficulty} mode.",
|
||||
// style: TextStyle(
|
||||
// fontSize: 15,
|
||||
// color: MihColors.getSecondaryColor(
|
||||
// MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 10),
|
||||
Text(
|
||||
"Time Taken: ${_formatTime().replaceAll("00:", "")}",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Score: ${calculateGameScore(mihMineSweeperProvider)}",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
@@ -347,8 +449,8 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
setState(() => initializeBoard(mihMineSweeperProvider));
|
||||
Navigator.of(context).pop();
|
||||
context.pop();
|
||||
showStartGameWindow(mihMineSweeperProvider, adProvider);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
@@ -365,6 +467,26 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
mihMineSweeperProvider.setToolIndex(1);
|
||||
},
|
||||
buttonColor: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Leader Board",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -374,17 +496,35 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
);
|
||||
},
|
||||
);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return Mihloadingcircle(
|
||||
message: "Uploading your score",
|
||||
);
|
||||
});
|
||||
await MihMinesweeperServices().addPlayerScore(
|
||||
profileProvider,
|
||||
mihMineSweeperProvider,
|
||||
_formatTime().replaceAll("00:", ""),
|
||||
calculateGameScore(mihMineSweeperProvider),
|
||||
);
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
Color? getDifficultyColor() {
|
||||
String mode = modeController.text;
|
||||
Color? getDifficultyColor(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
String mode = mihMineSweeperProvider.difficulty;
|
||||
switch (mode) {
|
||||
case "Easy":
|
||||
case "Very Easy":
|
||||
return MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
);
|
||||
case "Normal":
|
||||
case "Easy":
|
||||
return MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
);
|
||||
case "Intermediate":
|
||||
return MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
);
|
||||
@@ -398,42 +538,33 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
modeController.text = "Easy";
|
||||
// showStartGameWindow(context.read<MihMineSweeperProvider>());
|
||||
// initializeBoard();
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
// This method is safe for calling showDialog or reading provider values.
|
||||
if (_isFirstLoad) {
|
||||
// 1. Get the provider safely.
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final mihMineSweeperProvider = context.read<MihMineSweeperProvider>();
|
||||
// board = List.generate(
|
||||
// mihMineSweeperProvider.rowCount,
|
||||
// (i) => List.generate(
|
||||
// mihMineSweeperProvider.columnCount,
|
||||
// (j) => BoardSquare(),
|
||||
// ),
|
||||
// );
|
||||
// 2. Show the dialog to get initial game settings.
|
||||
// The user selection in the dialog will call initializeBoard().
|
||||
showStartGameWindow(mihMineSweeperProvider);
|
||||
});
|
||||
// 3. Set flag to prevent showing the dialog on subsequent dependency changes
|
||||
_isFirstLoad = false;
|
||||
}
|
||||
void initState() {
|
||||
// UBongani was here during the MIH Live
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
return Consumer3<MzansiProfileProvider, MihMineSweeperProvider,
|
||||
MihBannerAdProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mihMineSweeperProvider, Widget? child) {
|
||||
MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mihMineSweeperProvider,
|
||||
MihBannerAdProvider adProvider,
|
||||
Widget? child) {
|
||||
return Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
@@ -456,7 +587,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Welcom to MIH MineSweeper, the first game of MIH.",
|
||||
"Welcom to Minesweeper, the first game of MIH.",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
@@ -495,7 +626,9 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " to start a new game."),
|
||||
TextSpan(
|
||||
text:
|
||||
" to start a new game or learn how to play the minesweeper."),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -514,7 +647,8 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10.0),
|
||||
child: Text(
|
||||
'Mines: ${mihMineSweeperProvider.totalMines}',
|
||||
textAlign: TextAlign.left,
|
||||
@@ -526,20 +660,29 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10.0),
|
||||
child: Text(
|
||||
modeController.text,
|
||||
_formatTime().replaceAll("00:", ""),
|
||||
textAlign: TextAlign.right,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: getDifficultyColor(),
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
mihMineSweeperProvider.difficulty,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: getDifficultyColor(mihMineSweeperProvider),
|
||||
),
|
||||
),
|
||||
|
||||
// const SizedBox(
|
||||
// height: 30,
|
||||
// ),
|
||||
@@ -571,13 +714,16 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
|
||||
return MineTile(
|
||||
square: board[r][c],
|
||||
onTap: () =>
|
||||
handleTap(mihMineSweeperProvider, r, c),
|
||||
onTap: () => handleTap(profileProvider,
|
||||
mihMineSweeperProvider, adProvider, r, c),
|
||||
onLongPress: () => handleLongPress(r, c),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
MihBannerAd(),
|
||||
// const SizedBox(height: 100),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -587,6 +733,30 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
child: MihFloatingMenu(
|
||||
animatedIcon: AnimatedIcons.menu_close,
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
label: "Learn how to play",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onTap: () {
|
||||
mihMineSweeperProvider.setToolIndex(2);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
@@ -610,9 +780,9 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onTap: () {
|
||||
showStartGameWindow(mihMineSweeperProvider);
|
||||
showStartGameWindow(mihMineSweeperProvider, adProvider);
|
||||
},
|
||||
)
|
||||
),
|
||||
]),
|
||||
)
|
||||
],
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MineSweeperQuickStartGuide extends StatefulWidget {
|
||||
const MineSweeperQuickStartGuide({super.key});
|
||||
|
||||
@override
|
||||
State<MineSweeperQuickStartGuide> createState() =>
|
||||
_MineSweeperQuickStartGuideState();
|
||||
}
|
||||
|
||||
class _MineSweeperQuickStartGuideState
|
||||
extends State<MineSweeperQuickStartGuide> {
|
||||
Widget _buildSectionTitle(String title) {
|
||||
return Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSubSectionTitle(String title) {
|
||||
return Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRulePoint({
|
||||
required String title,
|
||||
required List<String> points,
|
||||
required Color color,
|
||||
}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0, top: 4.0, bottom: 4.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
...points
|
||||
.map((point) => Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: Text(
|
||||
'• $point',
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNumberClue(String clue, String explanation) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0, bottom: 4.0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const Text('• ',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
Expanded(
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark")),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: 'If you see a $clue: ',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextSpan(text: explanation),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStrategyPoint(String title, String explanation,
|
||||
{bool isAction = false}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0, bottom: 4.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: title,
|
||||
style: TextStyle(
|
||||
fontWeight: isAction ? FontWeight.bold : FontWeight.normal,
|
||||
color: isAction
|
||||
? MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark")
|
||||
: MihColors.getPurpleColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: isAction ? ' $explanation' : ': $explanation'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTipPoint(String title, String explanation) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0, bottom: 4.0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text('• ',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
|
||||
fontWeight: FontWeight.bold)),
|
||||
Expanded(
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: title,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextSpan(text: explanation),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Simple Rules and Strategy',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'Minesweeper is a puzzle game where you use numbers to figure out where the hidden bombs (mines) are located.',
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
const Divider(height: 30),
|
||||
|
||||
// --- 1. Two Main Actions ---
|
||||
_buildSectionTitle('1. Two Main Actions (Your Controls)'),
|
||||
const SizedBox(height: 8),
|
||||
_buildRulePoint(
|
||||
title: 'Quick Tap (or Click): This is the Dig action.',
|
||||
points: [
|
||||
'Goal: To uncover a square and see a number clue.',
|
||||
'Risk: If you click a mine, the game ends!',
|
||||
],
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
|
||||
),
|
||||
_buildRulePoint(
|
||||
title:
|
||||
'Tap and Hold (or Long Press): This is the Flag action (🚩).',
|
||||
points: [
|
||||
'Goal: To safely mark a square that you are **certain** is a mine.',
|
||||
'Benefit: You cannot accidentally click a square that is flagged.',
|
||||
],
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
|
||||
),
|
||||
const Divider(height: 30),
|
||||
|
||||
// --- 2. The Golden Rule: Reading the Numbers ---
|
||||
_buildSectionTitle('2. The Golden Rule: Reading the Numbers'),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'The number tells you exactly how many mines are touching that square (including sides and corners).',
|
||||
style: TextStyle(fontSize: 18, fontStyle: FontStyle.italic),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_buildNumberClue('Blank Space (a \'0\')',
|
||||
'Zero (0) mines are touching it. All surrounding squares are safe, and the game will open them for you automatically.'),
|
||||
_buildNumberClue('\'1\'',
|
||||
'Only **one** mine is touching this square. You must find and flag that single mine.'),
|
||||
_buildNumberClue('\'3\'',
|
||||
'Three mines are touching this square. You must find and flag all three.'),
|
||||
const Divider(height: 30),
|
||||
|
||||
// --- 3. The Winning Strategy ---
|
||||
_buildSectionTitle('3. The Winning Strategy (The Deduction Loop)'),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'The game is won by uncovering every single safe square and correctly flagging all the mines. Use this two-step loop to clear the board:',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
_buildSubSectionTitle('A. Find the Mines (Where to Flag 🚩)'),
|
||||
_buildStrategyPoint(
|
||||
'Look for a number that only has one choice for a mine.',
|
||||
'Example: If a \'1\' is touching only one hidden square, that hidden square **must** be the mine.'),
|
||||
_buildStrategyPoint('Action:',
|
||||
'Tap and Hold to place a **Flag** on the square you are sure is a mine.',
|
||||
isAction: true),
|
||||
|
||||
const SizedBox(height: 12),
|
||||
|
||||
_buildSubSectionTitle('B. Find the Safe Squares (Where to Dig)'),
|
||||
_buildStrategyPoint(
|
||||
'Look for a number that has been \'satisfied\' by your flags.',
|
||||
'Example: You see a \'2\'. You have already placed two 🚩 flags touching it. The \'2\' is satisfied.'),
|
||||
_buildStrategyPoint('Action:',
|
||||
'Quick Tap any of the remaining hidden squares touching that \'satisfied\' number. They **must be safe** because the mine requirement has already been met.',
|
||||
isAction: true),
|
||||
|
||||
const Divider(height: 30),
|
||||
|
||||
// --- Key Beginner Tip ---
|
||||
_buildSectionTitle('✨ Key Beginner Tips'),
|
||||
_buildTipPoint('Start on the Edges and Corners:',
|
||||
'Numbers on the edge or corner of the board are easier to solve because they have fewer surrounding squares to check.'),
|
||||
_buildTipPoint('Don\'t Guess:',
|
||||
'If you are down to two squares and either one could be the mine, look somewhere else on the board for a guaranteed, safe move.'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_my_scoreboard_list.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MyScoreBoard extends StatefulWidget {
|
||||
const MyScoreBoard({super.key});
|
||||
|
||||
@override
|
||||
State<MyScoreBoard> createState() => _MihMineSweeperLeaderBoardState();
|
||||
}
|
||||
|
||||
class _MihMineSweeperLeaderBoardState extends State<MyScoreBoard> {
|
||||
TextEditingController filterController = TextEditingController();
|
||||
|
||||
Future<void> initialiseLeaderboard() async {
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
MihMineSweeperProvider mineSweeperProvider =
|
||||
context.read<MihMineSweeperProvider>();
|
||||
filterController.text = mineSweeperProvider.difficulty;
|
||||
if (mineSweeperProvider.myScoreboard == null ||
|
||||
mineSweeperProvider.myScoreboard!.isEmpty) {
|
||||
KenLogger.success("getting data");
|
||||
await MihMinesweeperServices()
|
||||
.getMyScoreboard(profileProvider, mineSweeperProvider);
|
||||
KenLogger.success("${mineSweeperProvider.myScoreboard}");
|
||||
}
|
||||
}
|
||||
|
||||
void refreshLeaderBoard(
|
||||
MihMineSweeperProvider mineSweeperProvider, String difficulty) {
|
||||
mineSweeperProvider.setDifficulty(difficulty);
|
||||
mineSweeperProvider.setLeaderboard(leaderboard: null);
|
||||
mineSweeperProvider.setMyScoreboard(myScoreboard: null);
|
||||
initialiseLeaderboard();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await initialiseLeaderboard();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.sizeOf(context).width;
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
refreshLeaderBoard(mineSweeperProvider, filterController.text);
|
||||
},
|
||||
child: MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
if (mineSweeperProvider.myScoreboard == null) {
|
||||
return Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
} else {
|
||||
return SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
imageFile: profileProvider.userProfilePicture,
|
||||
width: 150,
|
||||
editable: false,
|
||||
fileNameController: null,
|
||||
userSelectedfile: null,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onChange: (selectedImage) {},
|
||||
key: ValueKey(profileProvider.userProfilePicUrl),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihDropdownField(
|
||||
controller: filterController,
|
||||
hintText: "Scoreboards",
|
||||
dropdownOptions: const [
|
||||
"Very Easy",
|
||||
"Easy",
|
||||
"Intermediate",
|
||||
"Hard",
|
||||
],
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
onSelected: (selection) {
|
||||
refreshLeaderBoard(mineSweeperProvider, selection!);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
mineSweeperProvider.myScoreboard!.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mineSweeper,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"You have played and ${mineSweeperProvider.difficulty} yet.",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
FontAwesomeIcons.bomb,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " and start a new game"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: BuildMyScoreBoardList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user