diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2436c9b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Nividata Consultancy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index f986e2d..30fcf2a 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,104 @@ -# mathgame -A new Flutter application. -## Getting Started + +
+

+ + + -This project is a starting point for a Flutter application. +

Math Matrix : Train Your Brain, Improve Math Skill

-A few resources to get you started if this is your first Flutter project: +

+
+ Train Your Brain + · + Report Bug + · + Request Feature +

+

-- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) +### Math Matrix is a Math Game that tries improvise your math skills in a fun way. -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +[![Product Name Screen Shot][product-screenshot]](https://example.com) + +Simple math games to learn, improve you math skills. This game is easy to play and target everyone from kids to adults. Every level is design in a way to challenge your mind at every step. + +### This game is divided in 3 main categories + +**Math Puzzle** - This category revolves around basic calculation like addition, subtraction, division and multiplication. Each game in this category includes simple calculation with different approach. So you're playing with numbers and signs while fighting with time. + +**Memory Puzzle** - This category focuses on not just calculation but to memorize numbers and signs before applying calculation to them. It tries to engage you in a way to solve this calculation with recalling numbers and signs in gradual manner. + +**Train Your Brain** - Train your Brain tries to enhance your logical thinking with keeping time in mind. There can single or multiple ways to reach your query but you need to find best possible ways to earn best score. + +Overall all this puzzle tries to engage you in a different way to improve your memory, attention, speed, reaction, concentration, logic and more. With each level it becomes more and more complex and try to take best out of you. + +### Games in Math Puzzle +**1) Calculator** : A simple calculation of addition, subtraction, division and multiplication. You'll be given an equation and you need to find correct answer in 5 seconds.
+**2) Guess the sign** : You need to complete equation by placing correct sign between two numbers to reach to the given answer.
+**3) Correct Answer** : You'll be given 4 options and one incomplete equation with answer. You need to place correct number to complete given equation.
+**4) Quick Calculation** : It's same like calculator where you need to perform basic equation but you're racing with time.Faster you answer, more time will be given and more equation you can solve .You need to fight with time to reach to break your own high score. + +### Games in Memory Puzzle +**1) Mental Arithmetic** : Numbers and signs will be shown one by one for few seconds, you need to remember those and give correct answer. This focuses on your memory and calculation at same time.
+**2) Square Root** : You need to find Square root of number for given options. With each increasing level you'll be having tough equation to solve.
+**3) Mathematical pairs** : One card have equation while other card have correct answer, but this will be places randomly in Grid. You need to select equation and correct answer to remove it from Grid. + +### Games in Train Your Brain +**1) Magic Triangle** : This is 3x3 and 4x4 triangle where you need to place 6 number in a way that sum of each side should be equal to given number.
+**2) Math Grid** : You'll be given an answer and a 9x9 grid. You need to select numbers from grid one by one to reach the given number. Find the best possible way to solve max answer from 9x9 grid.
+ + +### Built With +This application built [Flutter](https://flutter.dev/). Flutter is cross-platform open source mobile framework built by Google. Flutter use Dart as a primary language which is highly scalable and easy codebase. +* [Getting started with Flutter](https://flutter.dev/docs). +* [Dart](https://dart.dev/) + + +## Roadmap + +See the [open issues](https://github.com/jaysavsani07/math-metrix/issues) for a list of proposed features (and known issues). + + + +## Contributing + +Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. + +1. Fork the Project +2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) +3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the Branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + + +## License + +Distributed under the MIT License. See [LICENSE](https://github.com/jaysavsani07/math-metrix/blob/master/LICENSE) for more information. + + +## Contact + +[Nividata Consultancy](https://www.nividata.com/contact/) + +## Developers + +### Mehul Makwana +Contact: [LinkedIn](https://www.linkedin.com/in/mehul-makwana-430326b9/) + + +## This app using following awesome open source libraries + +* [Provider](https://pub.dev/packages/provider) +* [Percent Indicator](https://pub.dev/packages/percent_indicator) +* [Provider Architecture](https://pub.dev/packages/provider_architecture) +* [get_it](https://pub.dev/packages/get_it) +* [Shared Preferences](https://pub.dev/packages/shared_preferences) +* [RFlutter Alert](https://pub.dev/packages/rflutter_alert) +* [flutter_svg](https://pub.dev/packages/flutter_svg) + + + +[product-screenshot]: https://github.com/jaysavsani07/math-metrix/blob/master/assets/images/banner.png diff --git a/assets/images/banner.png b/assets/images/banner.png new file mode 100644 index 0000000..f29e186 Binary files /dev/null and b/assets/images/banner.png differ diff --git a/assets/num-pyramid.gif b/assets/num-pyramid.gif new file mode 100644 index 0000000..a4c5e9d Binary files /dev/null and b/assets/num-pyramid.gif differ diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7d7bbc9..0036619 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -78,7 +78,6 @@ 470E1C073221E34E20A8754C /* Pods-Runner.release.xcconfig */, 323F3372D211B410F9ECC62E /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -181,6 +180,7 @@ TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = UJMS4XPZSS; LastSwiftMigration = 1100; }; }; @@ -375,6 +375,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = UJMS4XPZSS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -390,6 +391,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; @@ -509,6 +511,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = UJMS4XPZSS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -525,6 +528,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -536,6 +540,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = UJMS4XPZSS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -551,6 +556,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index dccef0d..86180b7 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -29,8 +29,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/lib/main.dart b/lib/main.dart index 583495b..0d20cb8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,8 +38,10 @@ class MyApp extends StatelessWidget { backgroundColor: Color(0xFFaa0000), brightness: Brightness.dark, primaryColor: Colors.deepPurple, - primaryColorDark: Color(0x673ab7), - primaryColorLight: Color(0x8561c5), + primaryColorDark: Colors.deepPurple[700], + primaryColorLight: Colors.deepPurple[300], + /*primaryColorDark: Color(0x673ab7), + primaryColorLight: Color(0x8561c5),*/ primarySwatch: Colors.yellow, accentColor: Colors.deepOrange[300], scaffoldBackgroundColor: Color(0xFF121212), diff --git a/lib/src/models/numberPyramid/number_pyramid_model.dart b/lib/src/models/numberPyramid/number_pyramid_model.dart new file mode 100644 index 0000000..3ff2f65 --- /dev/null +++ b/lib/src/models/numberPyramid/number_pyramid_model.dart @@ -0,0 +1,37 @@ +class NumberPyramidModel { + int id; + List list; + int remainingCell; + + NumberPyramidModel(this.id, this.list, this.remainingCell); + +} + +class NumPyramidCellModel { + int id; + String text; + int numberOnCell; + bool isActive; + bool isCorrect; + bool isHidden; + bool isHint; + bool isDone; + + NumPyramidCellModel(this.id, this.text, this.numberOnCell, this.isActive, + this.isCorrect, this.isHidden, this.isHint, this.isDone); + + /* @override + String toString() { + return 'MathPairs{text: $text, uid: $uid}'; + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is MathPair && + runtimeType == other.runtimeType && + text == other.text; + + @override + int get hashCode => text.hashCode;*/ +} diff --git a/lib/src/provider/MagicTriangleProvider.dart b/lib/src/provider/MagicTriangleProvider.dart index 7a4c2b5..102d404 100644 --- a/lib/src/provider/MagicTriangleProvider.dart +++ b/lib/src/provider/MagicTriangleProvider.dart @@ -97,6 +97,7 @@ class MagicTriangleProvider with ChangeNotifier { _index = _index + 1; currentScore = currentScore + ScoreUtil.magicTriangleScore; _currentState = _list[_index]; + restartTimer(); notifyListeners(); } } diff --git a/lib/src/provider/dashboardViewModel.dart b/lib/src/provider/dashboardViewModel.dart index fe403e8..5effd6a 100644 --- a/lib/src/provider/dashboardViewModel.dart +++ b/lib/src/provider/dashboardViewModel.dart @@ -103,6 +103,13 @@ class DashboardViewModel extends ChangeNotifier { GameCategoryType.MATH_MACHINE, KeyUtil.MathMachine, getScoreboard("math_machine"))); + list.add(GameCategory( + 10, + "Number Pyramid", + "number_pyramid", + GameCategoryType.NUMBER_PYRAMID, + KeyUtil.NumberPyramid, + getScoreboard("number_pyramid"))); break; } } diff --git a/lib/src/provider/gameViewModel.dart b/lib/src/provider/gameViewModel.dart index 197d38b..e6147d0 100644 --- a/lib/src/provider/gameViewModel.dart +++ b/lib/src/provider/gameViewModel.dart @@ -238,6 +238,8 @@ class GameViewModelImp extends GameViewModel implements TimerAccess { break; case GameCategoryType.PICTURE_PUZZLE: return PicturePuzzleQandSDataProvider.getPicturePuzzleDataList(level); + case GameCategoryType.NUMBER_PYRAMID: + // TODO: Handle this case. break; } } @@ -273,6 +275,8 @@ class GameViewModelImp extends GameViewModel implements TimerAccess { break; case GameCategoryType.PICTURE_PUZZLE: return ScoreUtil.picturePuzzleScore; + case GameCategoryType.NUMBER_PYRAMID: + // TODO: Handle this case. break; } } @@ -308,6 +312,8 @@ class GameViewModelImp extends GameViewModel implements TimerAccess { break; case GameCategoryType.PICTURE_PUZZLE: return ScoreUtil.picturePuzzleScore; + case GameCategoryType.NUMBER_PYRAMID: + // TODO: Handle this case. break; } } @@ -343,6 +349,8 @@ class GameViewModelImp extends GameViewModel implements TimerAccess { break; case GameCategoryType.PICTURE_PUZZLE: return CoinUtil.picturePuzzleCoin; + case GameCategoryType.NUMBER_PYRAMID: + // TODO: Handle this case. break; } } @@ -378,6 +386,8 @@ class GameViewModelImp extends GameViewModel implements TimerAccess { break; case GameCategoryType.PICTURE_PUZZLE: return TimeUtil.picturePuzzleTimeOut; + case GameCategoryType.NUMBER_PYRAMID: + // TODO: Handle this case. break; } } diff --git a/lib/src/provider/mentalArithmeticProvider.dart b/lib/src/provider/mentalArithmeticProvider.dart index a55bcbe..54b0f22 100644 --- a/lib/src/provider/mentalArithmeticProvider.dart +++ b/lib/src/provider/mentalArithmeticProvider.dart @@ -63,7 +63,8 @@ class MentalArithmeticProvider with ChangeNotifier { Future checkResult(String answer) async { if (!timeOut && _localTimeOut && - _result.length < _currentState.answer.toString().length) { + _result.length < _currentState.answer.toString().length && + ((_result.length == 0 && answer == "-") || (answer != "-"))) { _result = _result + answer; notifyListeners(); if (_result != "-" && int.parse(_result) == _currentState.answer) { @@ -81,8 +82,7 @@ class MentalArithmeticProvider with ChangeNotifier { notifyListeners(); } else if (_result.length == _currentState.answer.toString().length) { if (currentScore > 0) { - currentScore = - currentScore + ScoreUtil.mentalArithmeticScoreMinus; + currentScore = currentScore + ScoreUtil.mentalArithmeticScoreMinus; } } } diff --git a/lib/src/provider/numberPyramidProvider.dart b/lib/src/provider/numberPyramidProvider.dart new file mode 100644 index 0000000..be7ab96 --- /dev/null +++ b/lib/src/provider/numberPyramidProvider.dart @@ -0,0 +1,224 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; +import 'package:get_it/get_it.dart'; + +import 'package:mathgame/src/models/numberPyramid/number_pyramid_model.dart'; +import 'package:mathgame/src/resources/dialog_service.dart'; +import 'package:mathgame/src/resources/gameCategoryDataProvider.dart'; + +import 'package:mathgame/src/resources/navigation_service.dart'; +import 'package:mathgame/src/resources/numberPyramid/numberPyramidDataProvider.dart'; +import 'package:mathgame/src/utility/coinUtil.dart'; +import 'package:mathgame/src/provider/dashboardViewModel.dart'; +import 'package:mathgame/src/utility/keyUtil.dart'; +import 'package:mathgame/src/utility/scoreUtil.dart'; +import 'package:mathgame/src/utility/timeUtil.dart'; + +class NumberPyramidProvider with ChangeNotifier { + var homeViewModel = GetIt.I(); + final DialogService _dialogService = GetIt.I(); + + List _list; + NumberPyramidModel _currentState; + int _index = 0; + int first = -1; + int second = -1; + + bool _lock; + bool _timeOut; + int _time; + bool _pause = false; + double currentScore = 0; + + bool get timeOut => _timeOut; + + int get time => _time; + + bool get pause => _pause; + + StreamSubscription timerSubscription; + + NumberPyramidModel get currentState => _currentState; + + NumberPyramidProvider() { + startGame(); + } + + void startGame() { + _list = NumberPyramidDataProvider.getPyramidDataList(1); + _index = 0; + currentScore = 0; + _lock = false; + _currentState = _list[_index]; + _time = TimeUtil.numPyramidTimeOut; + _timeOut = false; + startTimer(); + if (homeViewModel.isFirstTime(GameCategoryType.NUMBER_PYRAMID)) { + showInfoDialogWithDelay(); + } + + } + + void pyramidBoxSelection(NumPyramidCellModel model) { + if (model.isHint) { + // you can't select/edit hint cell + return; + } + //first find previously selected index + var previouslySelectedCell = + _currentState.list.indexWhere((cell) => cell.isActive == true); + if (!previouslySelectedCell.isNegative) { + _currentState.list[previouslySelectedCell].isActive = false; + } + _currentState.list[model.id - 1].isActive = true; + + notifyListeners(); + } + + void pyramidBoxInputValue(String value) { + var currentActiveCellIndex = + _currentState.list.indexWhere((cell) => cell.isActive == true); + if (value == "CLEAR") { + // if clear is pressed then empty existing text value and return + _currentState.list[currentActiveCellIndex].text = ""; + notifyListeners(); + return; + } + var listOfCellWithValues = + _currentState.list.where((cell) => cell.text.isNotEmpty); + if (value == "DONE") { + if (listOfCellWithValues.length > 17) { + checkCorrectValues(); + return; + } else { + return; + } + } + + var currentCellValue = _currentState.list[currentActiveCellIndex].text; + if (currentCellValue.isNotEmpty) { + // check if already have value, then append + var length = _currentState.list[currentActiveCellIndex].text.length; + if (length == 3) { + // can't have more then 3 digits + return; + } + _currentState.list[currentActiveCellIndex].text = + currentCellValue + value; + } else { + // fresh value + _currentState.list[currentActiveCellIndex].text = value; + } + + notifyListeners(); + } + + void checkCorrectValues() { + for (int i = 0; i < _currentState.list.length; i++) { + if (!_currentState.list[i].isHint) { + if (!(_currentState.list[i].numberOnCell == + int.parse(_currentState.list[i].text))) { + _currentState.list[i].isCorrect = false; + _currentState.list[i].isDone = true; + } else { + _currentState.list[i].isCorrect = true; + _currentState.list[i].isDone = true; + } + } + } + var correctVal = _currentState.list.where((cell) => cell.isCorrect == true); + + if (correctVal.length == 18) { + _index = _index + 1; + _currentState = _list[_index]; + + currentScore = currentScore + ScoreUtil.numberPyramidScore; + if (!timeOut) { + restartTimer(); + notifyListeners(); + } + } + } + + void startTimer() { + timerSubscription = Stream.periodic( + Duration(seconds: 1), (x) => TimeUtil.numPyramidTimeOut - x - 1) + .take(TimeUtil.numPyramidTimeOut) + .listen((time) { + _time = time; + notifyListeners(); + }, onDone: () { + this._timeOut = true; + showDialog(); + notifyListeners(); + }); + } + + void restartTimer() { + timerSubscription.cancel(); + startTimer(); + } + + void pauseTimer() { + _pause = true; + timerSubscription.pause(); + notifyListeners(); + showDialog(); + } + + Future showDialog() async { + notifyListeners(); + var dialogResult = await _dialogService.showDialog( + type: KeyUtil.GameOverDialog, + gameCategoryType: GameCategoryType.NUMBER_PYRAMID, + score: currentScore, + coin: _index * CoinUtil.numberPyramidCoin, + isPause: _pause); + + if (dialogResult.exit) { + homeViewModel.updateScoreboard(GameCategoryType.NUMBER_PYRAMID, + currentScore, _index * CoinUtil.numberPyramidCoin); + GetIt.I().goBack(); + } else if (dialogResult.restart) { + homeViewModel.updateScoreboard(GameCategoryType.NUMBER_PYRAMID, + currentScore, _index * CoinUtil.numberPyramidCoin); + timerSubscription.cancel(); + startGame(); + } else if (dialogResult.play) { + timerSubscription.resume(); + _pause = false; + notifyListeners(); + } + notifyListeners(); + } + + Future showInfoDialogWithDelay() async { + await Future.delayed(Duration(milliseconds: 500)); + showInfoDialog(); + } + + Future showInfoDialog() async { + _pause = true; + timerSubscription.pause(); + notifyListeners(); + var dialogResult = await _dialogService.showDialog( + type: KeyUtil.InfoDialog, + gameCategoryType: GameCategoryType.NUMBER_PYRAMID, + score: 0, + coin: 0, + isPause: false); + + if (dialogResult.exit) { + homeViewModel.setFirstTime(GameCategoryType.NUMBER_PYRAMID); + timerSubscription.resume(); + _pause = false; + notifyListeners(); + } + } + + void dispose() { + super.dispose(); + this.timerSubscription.cancel(); + } +} diff --git a/lib/src/resources/gameCategoryDataProvider.dart b/lib/src/resources/gameCategoryDataProvider.dart index bc179e0..3f5b041 100644 --- a/lib/src/resources/gameCategoryDataProvider.dart +++ b/lib/src/resources/gameCategoryDataProvider.dart @@ -8,6 +8,7 @@ enum GameCategoryType { MENTAL_ARITHMETIC, QUICK_CALCULATION, MATH_MACHINE, - PICTURE_PUZZLE + PICTURE_PUZZLE, + NUMBER_PYRAMID } enum PuzzleType { MATH_PUZZLE, MEMORY_PUZZLE, BRAIN_PUZZLE } diff --git a/lib/src/resources/infoDialogDataProvider.dart b/lib/src/resources/infoDialogDataProvider.dart index fd90b26..cb61ce7 100644 --- a/lib/src/resources/infoDialogDataProvider.dart +++ b/lib/src/resources/infoDialogDataProvider.dart @@ -103,6 +103,17 @@ ${ScoreUtil.mathMachineScore.toInt()} for each correct equation ${ScoreUtil.mathMachineScore.toInt()} for each correct equation '''); + case GameCategoryType.NUMBER_PYRAMID: + // TODO: Handle this case. + return GameInfoDialog( + title: "Number Pyramid", + image: "assets/num-pyramid.gif", + dec: ''' +sum of consecutive cell should be placed on top cell. You need to fill all cell correctly to solve Number pyramid. + +${ScoreUtil.numberPyramidScore.toInt()} for each correct equation + ''' + ); break; } } diff --git a/lib/src/resources/numberPyramid/numberPyramidDataProvider.dart b/lib/src/resources/numberPyramid/numberPyramidDataProvider.dart new file mode 100644 index 0000000..a99c2aa --- /dev/null +++ b/lib/src/resources/numberPyramid/numberPyramidDataProvider.dart @@ -0,0 +1,75 @@ +import 'package:mathgame/src/models/numberPyramid/number_pyramid_model.dart'; +import 'package:mathgame/src/utility/mathUtil.dart'; + +class NumberPyramidDataProvider { + static List singlePyramidList = new List(); + static int counter; + + static List getPyramidDataList(int level) { + List pyramidsList = new List(); + + for (int i = 0; i < 10; i++) { + pyramidsList + .add(NumberPyramidModel(i, generateSinglePyramidValues(), 28)); + } + + return pyramidsList; + } + + static List generateSinglePyramidValues() { + singlePyramidList = new List(); + counter = 1; + int min = 1; + int max = 8; + List baseLineList = generateBaseLineOfPyramid( + min, max); // generating bottom line of pyramid + singlePyramidList.addAll(baseLineList); + generateUpperLineOfPyramid(baseLineList, + counter); // generating upper line of pyramid by looping one by one + + var list = new List.generate(27, (int index) => index); // select 8 random number for hint + list.shuffle(); + var finalList = list.sublist(0, 10); + + for (int i = 0; i < finalList.length; i++) { + singlePyramidList[finalList[i]].isHidden = false; + singlePyramidList[finalList[i]].isHint = true; + } + return singlePyramidList; + } + + static generateUpperLineOfPyramid( + List baseLineCellList, int counter) { + makeSumForPyramid(baseLineCellList, 6, counter); + } + + static makeSumForPyramid( + List list, int loopTime, int counter) { + if (loopTime == 0) { + return; + } + List tempList = new List(); + for (int k = 0; k < list.length - 1; k++) { + int sum = list[k].numberOnCell + list[k + 1].numberOnCell; + singlePyramidList + .add(NumPyramidCellModel(counter, "", sum, false, false, true, false, false)); + tempList.add(NumPyramidCellModel(counter, "", sum, false, false, true, false, false)); + counter++; + } + loopTime--; + makeSumForPyramid(tempList, loopTime, counter); + } + + static List generateBaseLineOfPyramid(int min, int max) { + List cellList = new List(); + cellList.clear(); + for (int i = 0; i < 7; i++) { + int randomNum = MathUtil.generateRandomAnswer(min, max); + cellList + .add(NumPyramidCellModel(counter, "", randomNum, false, false, true, false, false)); + counter++; + } + return cellList; + } +} + diff --git a/lib/src/resources/router.dart b/lib/src/resources/router.dart index 12f9acd..fbff5ed 100644 --- a/lib/src/resources/router.dart +++ b/lib/src/resources/router.dart @@ -1,3 +1,5 @@ + + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mathgame/src/resources/gameCategoryDataProvider.dart'; @@ -10,6 +12,7 @@ import 'package:mathgame/src/ui/mathGrid/math_grid.dart'; import 'package:mathgame/src/ui/mathPairs/mathPairs.dart'; import 'package:mathgame/src/ui/mentalArithmetic/mental_arithmetic.dart'; import 'package:mathgame/src/ui/picturePuzzle/picturePuzzle.dart'; +import 'package:mathgame/src/ui/numberPyramid/number_pyramid.dart'; import 'package:mathgame/src/ui/quickCalculation/quickCalculation.dart'; import 'package:mathgame/src/ui/squareRoot/square_root.dart'; import 'package:mathgame/src/ui/whatsTheSign/whats_the_sign.dart'; @@ -50,6 +53,8 @@ Route generateRoute(RouteSettings settings) { return MaterialPageRoute(builder: (context) => MathGrid()); case KeyUtil.PicturePuzzle: return MaterialPageRoute(builder: (context) => PicturePuzzle()); + case KeyUtil.NumberPyramid: + return MaterialPageRoute(builder: (context) => NumberPyramid()); default: return MaterialPageRoute( builder: (context) => Scaffold( diff --git a/lib/src/ui/numberPyramid/number_pyramid.dart b/lib/src/ui/numberPyramid/number_pyramid.dart new file mode 100644 index 0000000..dc040ae --- /dev/null +++ b/lib/src/ui/numberPyramid/number_pyramid.dart @@ -0,0 +1,274 @@ +import 'package:flutter/material.dart'; +import 'package:mathgame/src/provider/numberPyramidProvider.dart'; +import 'package:mathgame/src/resources/gameCategoryDataProvider.dart'; +import 'package:mathgame/src/ui/timer.dart'; +import 'package:mathgame/src/utility/sizeConfig.dart'; +import 'package:provider/provider.dart'; + +import 'number_pyramid_box.dart'; +import 'number_pyramid_button.dart'; + +class NumberPyramid extends StatelessWidget { + @override + Widget build(BuildContext context) { + SizeConfig().init(context); + return ChangeNotifierProvider( + create: (_) => NumberPyramidProvider(), + child: Scaffold( + body: SafeArea( + top: true, + bottom: true, + child: Container( + margin: EdgeInsets.fromLTRB(20, 20, 20, 0), + constraints: BoxConstraints.expand(), + child: Column( + children: [ + Expanded( + flex: 10, + child: Timer(GameCategoryType.NUMBER_PYRAMID), + /*child: Timer(GameCategoryType.NUMBER_PYRAMID)*/ + ), + Expanded( + flex: 40, + child: Consumer( + builder: (context, numberPyramidProvider, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Stack( + children: [ + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[27]), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[26]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[25]) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[24]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[23]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[22]), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[21]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[20]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[19]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[18]), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[17]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[16]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[15]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[14]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[13]), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[12]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[11]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[10]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[9]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[8]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[7]), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[6]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[5]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[4]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[3]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[2]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[1]), + PyramidNumberBox( + "", + numberPyramidProvider.currentState.list[0]), + ], + ), + ], + ); + }), + ), + Expanded( + flex: 40, + child: Align( + alignment: Alignment.center, + child: SizedBox( + height: 300, + width: 300, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Row( + children: [ + PyramidNumberButton( + "7", + BorderRadius.only( + topLeft: Radius.circular(40))), + PyramidNumberButton( + "8", BorderRadius.all(Radius.zero)), + PyramidNumberButton( + "9", + BorderRadius.only( + topRight: Radius.circular(40))) + ], + ), + ), + Expanded( + child: Row( + children: [ + PyramidNumberButton( + "4", BorderRadius.all(Radius.zero)), + PyramidNumberButton( + "5", BorderRadius.all(Radius.zero)), + PyramidNumberButton( + "6", BorderRadius.all(Radius.zero)) + ], + ), + ), + Expanded( + child: Row( + children: [ + PyramidNumberButton( + "1", BorderRadius.all(Radius.zero)), + PyramidNumberButton( + "2", BorderRadius.all(Radius.zero)), + PyramidNumberButton( + "3", BorderRadius.all(Radius.zero)) + ], + ), + ), + Expanded( + child: Row( + children: [ + PyramidNumberButton( + "DONE", + BorderRadius.only( + bottomLeft: Radius.circular(40))), + PyramidNumberButton( + "0", + BorderRadius.all(Radius.zero)), + PyramidNumberButton( + "CLEAR", + BorderRadius.only( + bottomRight: Radius.circular(40))) + ], + ), + ), + ], + ), + ), + ), + ), + ), + Expanded( + flex: 10, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Consumer( + builder: (context, numberPyramidProvider, child) { + return IconButton( + icon: numberPyramidProvider.pause + ? Icon(Icons.play_arrow) + : Icon(Icons.pause), + iconSize: 40, + onPressed: () { + numberPyramidProvider.pauseTimer(); + }, + ); + }), + Consumer( + builder: (context, provider, child) { + return IconButton( + icon: Icon(Icons.info_outline), + iconSize: 40, + onPressed: () { + provider.showInfoDialog(); + }, + ); + }) + ], + ) + ) + ], + ), + ), + )), + ); + } +} diff --git a/lib/src/ui/numberPyramid/number_pyramid_box.dart b/lib/src/ui/numberPyramid/number_pyramid_box.dart new file mode 100644 index 0000000..c28ff5f --- /dev/null +++ b/lib/src/ui/numberPyramid/number_pyramid_box.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:mathgame/src/models/numberPyramid/number_pyramid_model.dart'; +import 'package:mathgame/src/provider/calculatorProvider.dart'; +import 'package:mathgame/src/provider/numberPyramidProvider.dart'; +import 'package:mathgame/src/utility/sizeConfig.dart'; +import 'package:provider/provider.dart'; + +class PyramidNumberBox extends StatelessWidget { + final String text; + +// final String correctVal; + final NumPyramidCellModel numPyramidCellModel; + + PyramidNumberBox(this.text, this.numPyramidCellModel); + + @override + Widget build(BuildContext context) { + SizeConfig().init(context); + double boxHeight = (SizeConfig.screenHeight / 100); + double boxWidth = (SizeConfig.screenWidth / 100); + final numberProvider = Provider.of(context); + return InkWell( + onTap: () { + numberProvider.pyramidBoxSelection(numPyramidCellModel); + }, + child: Container( + height: boxHeight * 4.6, + width: boxWidth * 12, + alignment: Alignment.center, + decoration: BoxDecoration( + color: numPyramidCellModel.isHint + ? Theme.of(context).primaryColorLight + : (numPyramidCellModel.isDone + ? (numPyramidCellModel.isCorrect ? Colors.transparent : Colors.redAccent) + : Colors.transparent), + border: new Border.all( + color: + numPyramidCellModel.isActive ? Colors.yellow : Colors.white, + width: 1, + style: BorderStyle.solid)), + child: Text( + numPyramidCellModel.isHidden + ? numPyramidCellModel.text + : numPyramidCellModel.numberOnCell.toString(), + style: Theme.of(context).textTheme.title, + ), + ), + ); + } +} diff --git a/lib/src/ui/numberPyramid/number_pyramid_button.dart b/lib/src/ui/numberPyramid/number_pyramid_button.dart new file mode 100644 index 0000000..316222a --- /dev/null +++ b/lib/src/ui/numberPyramid/number_pyramid_button.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:mathgame/src/models/numberPyramid/number_pyramid_model.dart'; +import 'package:mathgame/src/provider/calculatorProvider.dart'; +import 'package:mathgame/src/provider/numberPyramidProvider.dart'; +import 'package:provider/provider.dart'; + +class PyramidNumberButton extends StatelessWidget { + final BorderRadius borderRadius; + final String text; +// final NumPyramidCellModel numPyramidCellModel; + PyramidNumberButton(this.text, this.borderRadius); + + @override + Widget build(BuildContext context) { + final numberProvider = Provider.of(context); + + return Expanded( + flex: 1, + child: InkWell( + borderRadius: borderRadius, + onTap: (){ + numberProvider.pyramidBoxInputValue(text); + }, + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).dialogBackgroundColor, + shape: BoxShape.rectangle, + borderRadius: borderRadius, + border: Border.all(color: Theme.of(context).dividerColor, width: 1), + ), + margin: EdgeInsets.all(1), + constraints: BoxConstraints.expand(), + child: Center( + child: Text( + text, + style: Theme.of(context).textTheme.headline, + ), + ), + ), + ), + ); + } +} diff --git a/lib/src/ui/timer.dart b/lib/src/ui/timer.dart index e140446..e205d72 100644 --- a/lib/src/ui/timer.dart +++ b/lib/src/ui/timer.dart @@ -6,6 +6,7 @@ import 'package:mathgame/src/provider/correctAnswerProvider.dart'; import 'package:mathgame/src/provider/mathPairsProvider.dart'; import 'package:mathgame/src/provider/mentalArithmeticProvider.dart'; import 'package:mathgame/src/provider/picturePuzzleProvider.dart'; +import 'package:mathgame/src/provider/numberPyramidProvider.dart'; import 'package:mathgame/src/provider/quickCalculationProvider.dart'; import 'package:mathgame/src/provider/signProvider.dart'; import 'package:mathgame/src/provider/squareRootProvider.dart'; @@ -52,6 +53,9 @@ class Timer extends StatelessWidget { } else if (type == GameCategoryType.PICTURE_PUZZLE) { provider = Provider.of(context); timeConstant = TimeUtil.picturePuzzleTimeOut; + } else if (type == GameCategoryType.NUMBER_PYRAMID) { + provider = Provider.of(context); + timeConstant = TimeUtil.numPyramidTimeOut; } return Container( alignment: Alignment.center, diff --git a/lib/src/utility/coinUtil.dart b/lib/src/utility/coinUtil.dart index 5a7a87b..45bde9b 100644 --- a/lib/src/utility/coinUtil.dart +++ b/lib/src/utility/coinUtil.dart @@ -16,6 +16,8 @@ class CoinUtil { static double magicTriangleCoin = 3; static double mathMachineCoin = 3; - + static double picturePuzzleCoin = 1; + + static double numberPyramidCoin = 3; } diff --git a/lib/src/utility/keyUtil.dart b/lib/src/utility/keyUtil.dart index a91a8ad..e2e57a2 100644 --- a/lib/src/utility/keyUtil.dart +++ b/lib/src/utility/keyUtil.dart @@ -12,6 +12,7 @@ class KeyUtil { static const String MagicTriangle = 'MagicTriangle'; static const String PicturePuzzle = 'PicturePuzzle'; static const String MathMachine = 'MathMachine'; + static const String NumberPyramid = "NumberPyramid"; static const String GameOverDialog = "GameOverDialog"; static const String InfoDialog = "InfoDialog"; diff --git a/lib/src/utility/scoreUtil.dart b/lib/src/utility/scoreUtil.dart index d84fb1a..a315910 100644 --- a/lib/src/utility/scoreUtil.dart +++ b/lib/src/utility/scoreUtil.dart @@ -29,4 +29,5 @@ class ScoreUtil { static double mathMachineScore = 5; static double picturePuzzleScore = 2; + static double numberPyramidScore = 5; } diff --git a/lib/src/utility/timeUtil.dart b/lib/src/utility/timeUtil.dart index 849fb17..7145939 100644 --- a/lib/src/utility/timeUtil.dart +++ b/lib/src/utility/timeUtil.dart @@ -16,8 +16,10 @@ class TimeUtil { static int squareRootTimeOut = 5; static int mathematicalPairsTimeOut = 60; - static int magicTriangleTimeOut = 120; + static int magicTriangleTimeOut = 60; static int mathMachineTimeOut = 120; static int picturePuzzleTimeOut = 300; + static int numPyramidTimeOut = 120; + } diff --git a/pubspec.yaml b/pubspec.yaml index 43c0a0f..350598f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: A new Flutter application. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 +version: 1.0.1+2 environment: sdk: ">=2.2.2 <3.0.0" @@ -29,9 +29,7 @@ dependencies: get_it: ^4.0.1 shared_preferences: ^0.5.6+3 rflutter_alert: ^1.0.3 - flare_flutter: ^2.0.3 flutter_svg: ^0.17.3+1 - intl: ^0.15.7 dev_dependencies: @@ -63,6 +61,7 @@ flutter: - quick-calculation-intro.gif - sqroot-intro.gif - whats-the-sign-intro.gif + - num-pyramid.gif # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see