diff --git a/Dashboard/lib/model/Cellulo.dart b/Dashboard/lib/model/Cellulo.dart index e69de29..d517a06 100644 --- a/Dashboard/lib/model/Cellulo.dart +++ b/Dashboard/lib/model/Cellulo.dart @@ -0,0 +1,25 @@ +import 'package:firebase_database/firebase_database.dart'; +import 'package:flutter/rendering.dart'; + +Activity ac7 = new Activity("Ac7"); + +Activity ac8 = new Activity("Ac8"); + +List acList = ['Ac7', 'Ac8']; + +class Activity { + String id; +// String _title; + // String _description; + int numAttempts = 0; + int currentTurn = 1; + int elapsedTime = 0; + List progress = [-2, -2, -2]; + int expectedDuration; + int expectedNumTrials; + var mistakes = { + "slope": [0, 0, 0], + "initialPoint": [0, 0, 0], + }; + Activity(this.id); +} diff --git a/Dashboard/lib/model/Group.dart b/Dashboard/lib/model/Group.dart index 0848d3d..1d3258e 100644 --- a/Dashboard/lib/model/Group.dart +++ b/Dashboard/lib/model/Group.dart @@ -1,44 +1,47 @@ +import 'package:Teacher_Dashboard/model/cellulo.dart'; import 'package:firebase_database/firebase_database.dart'; import 'package:flutter/rendering.dart'; import 'package:Teacher_Dashboard/model/activities/activity.Dart'; Group group = new Group("1"); class Group { String id = "1"; // String _title; // String _description; int curinactivity; + Cellulo cellulox = new Cellulo(); + Cellulo celluloy = new Cellulo(); List inactivity = new List.generate(50, (index) => -1); String member1name; String member2name; String member3name; String robot1code; String robot2code; String tabletStatus; bool ispaused; int numAttempts; String currentActivity = ''; List activities = [ac7, ac8]; Group(this.id); toJson() { return { "userId": member1name, "subject": member1name, "completed": member1name, }; } Group.fromSnapshot(DataSnapshot snapshot) { // _id = snapshot.key; member1name = snapshot.value['member1name']; member2name = snapshot.value['member2name']; member3name = snapshot.value['member3name']; id = snapshot.value['id']; // numCurrentActivity = snapshot.value['numCurrentActivity']; numAttempts = snapshot.value['numAttempts']; // member3name = snapshot.value['inactivity']; } } diff --git a/Dashboard/lib/model/activities/activity.Dart b/Dashboard/lib/model/activities/activity.Dart index d517a06..b846b75 100644 --- a/Dashboard/lib/model/activities/activity.Dart +++ b/Dashboard/lib/model/activities/activity.Dart @@ -1,25 +1,28 @@ import 'package:firebase_database/firebase_database.dart'; import 'package:flutter/rendering.dart'; +import 'package:Teacher_Dashboard/model/cellulo.dart'; +import 'package:Teacher_Dashboard/model/turn.dart'; Activity ac7 = new Activity("Ac7"); Activity ac8 = new Activity("Ac8"); List acList = ['Ac7', 'Ac8']; class Activity { String id; // String _title; // String _description; int numAttempts = 0; int currentTurn = 1; int elapsedTime = 0; List progress = [-2, -2, -2]; + List turns = [turn1, turn2, turn3]; int expectedDuration; int expectedNumTrials; var mistakes = { "slope": [0, 0, 0], "initialPoint": [0, 0, 0], }; Activity(this.id); } diff --git a/Dashboard/lib/model/cellulo.dart b/Dashboard/lib/model/cellulo.dart new file mode 100644 index 0000000..8532051 --- /dev/null +++ b/Dashboard/lib/model/cellulo.dart @@ -0,0 +1,21 @@ +import 'package:firebase_database/firebase_database.dart'; +import 'package:flutter/rendering.dart'; + +//Activity ac7 = new Activity("Ac7"); + +//Activity ac8 = new Activity("Ac8"); + +//List acList = ['Ac7', 'Ac8']; + +class Cellulo { + String id; +// String _title; + // String _description; + int numAttempts = 0; + int currentTurn = 1; + int elapsedTime = 0; + List x = [0.0]; + List y = [0.0]; + + Cellulo(); +} diff --git a/Dashboard/lib/model/turn.dart b/Dashboard/lib/model/turn.dart new file mode 100644 index 0000000..1b802b1 --- /dev/null +++ b/Dashboard/lib/model/turn.dart @@ -0,0 +1,16 @@ +import 'package:firebase_database/firebase_database.dart'; +import 'package:flutter/rendering.dart'; +import 'package:Teacher_Dashboard/model/cellulo.dart'; + +Turn turn1 = new Turn(); +Turn turn2 = new Turn(); +Turn turn3 = new Turn(); + +class Turn { + String id; +// String _title; + // String _description; + Cellulo cellulox = new Cellulo(); + Cellulo celluloy = new Cellulo(); + Turn(); +} diff --git a/Dashboard/lib/screens/Debriefing.dart b/Dashboard/lib/screens/Debriefing.dart index 083f33d..635c773 100644 --- a/Dashboard/lib/screens/Debriefing.dart +++ b/Dashboard/lib/screens/Debriefing.dart @@ -1,374 +1,410 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:Teacher_Dashboard/widgets/custom_app_bar.dart'; import 'package:Teacher_Dashboard/SoCKet.dart'; import 'dart:convert'; import 'package:Teacher_Dashboard/config/palette.dart'; import 'package:Teacher_Dashboard/config/styles.dart'; import 'package:Teacher_Dashboard/data/data.dart'; import 'dart:async'; import 'package:Teacher_Dashboard/Database.dart'; import 'package:Teacher_Dashboard/model/Class.dart'; import 'package:Teacher_Dashboard/model/Group.dart'; import 'package:firebase_database/firebase_database.dart'; import 'package:Teacher_Dashboard/model/activities/activity.Dart'; import 'package:step_progress_indicator/step_progress_indicator.dart'; import 'package:Teacher_Dashboard/widgets/hexagonPainter.Dart'; import 'package:Teacher_Dashboard/widgets/celluloMap.Dart'; import 'package:flutter/scheduler.dart' show timeDilation; class Debriefing extends StatefulWidget { @override DebriefingState createState() => DebriefingState(); } class DebriefingState extends State { final FirebaseDatabase _database = FirebaseDatabase.instance; StreamSubscription _ongroupAddedSubscription; StreamSubscription _ongroupChangedSubscription; StreamSubscription _onattemptAddedSubscription; StreamSubscription _oninactivityAddedSubscription; + StreamSubscription _onrobotpositionAddedSubscription; int numofgroups = 0; int currentstepActivation = 0; @override void initState() { super.initState(); _ongroupAddedSubscription = _database.reference().child("groups").onChildAdded.listen(onGroupAdded); _ongroupChangedSubscription = _database .reference() .child("groups") .onChildChanged .listen(onGroupChanged); _onattemptAddedSubscription = _database .reference() .child("attempts") .onChildAdded .listen(onAttemptAdded); _oninactivityAddedSubscription = _database .reference() - .child("activation") + .child("celluloPosition") .onChildAdded - .listen(onInactivityAdded); + .listen(oncelluloPositionAdded); /// /// Ask to be notified when messages related to the game /// are sent by the server /// } onGroupAdded(Event event) { // print(event.snapshot.value); thisClass.groups.add(Group.fromSnapshot(event.snapshot)); thisClass.groupIDs.add(event.snapshot.value['id']); setState(() { numofgroups = thisClass.groups.length; }); // mem1Name = thisClass.groups[0].member1name; // mem2Name = thisClass.groups[0].member2name; // mem3Name = thisClass.groups[0].member3name; // print(thisClass.groups.length); // print(thisClass.groupIDs); } onGroupChanged(Event event) { //thisClass.groups.add(Group.fromSnapshot(event.snapshot)); int currentGroup = thisClass.groupIDs.indexOf(event.snapshot.key); thisClass.groups[currentGroup].currentActivity = (event.snapshot.value)['currentActivity'].toString(); thisClass.groups[currentGroup].tabletStatus = (event.snapshot.value)['tabletStatus'].toString(); setState(() {}); //print(thisClass.groups[currentGroup].currentActivity.toString()); } onAttemptAdded(Event event) { // print(jsonDecode(event.snapshot.value)['acID'].toString()); int currentGroup = thisClass.groupIDs.indexOf(jsonDecode(event.snapshot.value)['groupID']); int currentActivity = acList.indexOf(jsonDecode(event.snapshot.value)['acID'].toString()); thisClass.groups[currentGroup].activities[currentActivity].numAttempts = jsonDecode(event.snapshot.value)['numAttempts']; thisClass.groups[currentGroup].activities[currentActivity].elapsedTime = jsonDecode(event.snapshot.value)['elpasedTime']; var progressmsg = jsonDecode((event.snapshot.value))['progress']; thisClass.groups[currentGroup].activities[currentActivity].progress[0] = progressmsg['turn1']; thisClass.groups[currentGroup].activities[currentActivity].progress[1] = progressmsg['turn2']; thisClass.groups[currentGroup].activities[currentActivity].progress[2] = progressmsg['turn3']; var mistakemsg = jsonDecode(event.snapshot.value)['mistakes']; var mistakemsgturn1 = (mistakemsg['turn1']); var mistakemsgturn2 = (mistakemsg['turn2']); var mistakemsgturn3 = (mistakemsg['turn3']); thisClass.groups[currentGroup].activities[currentActivity].mistakes['slope'] [0] = mistakemsgturn1['slope']; thisClass.groups[currentGroup].activities[currentActivity] .mistakes['initialPoint'][0] = mistakemsgturn1['initialPoint']; thisClass.groups[currentGroup].activities[currentActivity].mistakes['slope'] [1] = mistakemsgturn2['slope']; thisClass.groups[currentGroup].activities[currentActivity] .mistakes['initialPoint'][1] = mistakemsgturn2['initialPoint']; thisClass.groups[currentGroup].activities[currentActivity].mistakes['slope'] [2] = mistakemsgturn3['slope']; thisClass.groups[currentGroup].activities[currentActivity] .mistakes['initialPoint'][2] = mistakemsgturn3['initialPoint']; - var elapsemsg = jsonDecode(event.snapshot.value)['progressElpasedTime']; + var elapsemsg = (event.snapshot.value)['progressElpasedTime']; print(elapsemsg.toString()); // print(thisClass // .groups[currentGroup].activities[currentActivity].); setState(() {}); } onInactivityAdded(Event event) { // print(jsonDecode(event.snapshot.value)['acID'].toString()); int currentGroup = thisClass.groupIDs.indexOf(jsonDecode(event.snapshot.value)['groupID']); // int currentActivity = // acList.indexOf(jsonDecode(event.snapshot.value)['acID'].toString()); thisClass.groups[currentGroup].inactivity[currentstepActivation] = (jsonDecode(event.snapshot.value)['inactivity']); //print(thisClass.groups[currentGroup].inactivity); currentstepActivation = currentstepActivation + 1; setState(() {}); } + oncelluloPositionAdded(Event event) { + int currentGroup = + thisClass.groupIDs.indexOf(jsonDecode(event.snapshot.value)['groupID']); + + int currentActivity = + acList.indexOf(jsonDecode(event.snapshot.value)['acID'].toString()); + int currentTurn = 0; + + if (jsonDecode(event.snapshot.value)['turn'].toString() == '1') + currentTurn = 1; + if (jsonDecode(event.snapshot.value)['turn'].toString() == '2') + currentTurn = 2; + if (jsonDecode(event.snapshot.value)['turn'].toString() == '3') + currentTurn = 3; + print(currentTurn); + // int currentActivity = + // acList.indexOf(jsonDecode(event.snapshot.value)['acID'].toString()); + print((jsonDecode(event.snapshot.value)['x'])); + thisClass.groups[currentGroup].activities[currentActivity] + .turns[currentTurn - 1].cellulox.x + .add((jsonDecode(event.snapshot.value)['x'] * 90 / 860)); + print((jsonDecode(event.snapshot.value)['y'])); + thisClass.groups[currentGroup].activities[currentActivity] + .turns[currentTurn - 1].celluloy.y + .add((jsonDecode(event.snapshot.value)['y'] * 90 / 860)); +// thisClass.groups[currentGroup].celluloy.y + // .add((jsonDecode(event.snapshot.value)['y'] / 40)) + setState(() {}); + } + @override void dispose() { _ongroupAddedSubscription.cancel(); _ongroupChangedSubscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: CustomAppBar(), body: Column(children: [ SizedBox( height: 670, child: ListView.builder( itemCount: numofgroups, itemBuilder: (context, int position) { return Card( child: ListTile( title: Column(children: [ Row(children: [ Container( width: 100, height: 100, child: Stack(children: [ CustomPaint( painter: HexagonPainter( Offset(50, 50), 50, thisClass.groups[position].tabletStatus == 'YES' ? Colors.green : Colors.red), ), CustomPaint( painter: HexagonPainter( Offset(50, 50), 40, Colors.white), ), Center( child: Text( thisClass.groups[position].id, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 13), )), ]), ), SizedBox(width: 17), Stack(children: [ CircularStepProgressIndicator( totalSteps: 3, // currentStep: // thisClass.groups[position].activities[0].progress, width: 100, customColor: (index) => thisClass.groups[position] .activities[0].progress[index] > -2 ? (thisClass.groups[position].activities[0] .progress[index] > -1 ? (thisClass.groups[position].activities[0] .progress[index] > 0 ? Colors.green : Colors.blue) : Colors.red) : Colors.grey, ), Positioned( bottom: 45, right: 18, child: Text( thisClass.groups[position].currentActivity, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15), )), ]), SizedBox(width: 25), minituare(position, 1), SizedBox( width: 25, ), minituare(position, 2), SizedBox( width: 25, ), minituare(position, 3) ]), SizedBox(height: 20), ]), trailing: Icon(Icons.more_vert), )); }, )), Row( // mainAxisSize: MainAxisSize.min, children: [ Text('Show Students Mistakes'), - SizedBox(width: 10), + SizedBox(width: 5), Checkbox( //title: const Text('Animate Slowly'), value: timeDilation != 1.0, onChanged: (bool value) { setState(() { timeDilation = value ? 10.0 : 1.0; }); }, // secondary: const Icon(Icons.hourglass_empty), ), - SizedBox(width: 50), + SizedBox(width: 30), Text('Show Students Activity Time'), - SizedBox(width: 10), + SizedBox(width: 5), Checkbox( //title: const Text('Animate Slowly'), value: timeDilation != 1.0, onChanged: (bool value) { setState(() { timeDilation = value ? 10.0 : 1.0; }); }, // secondary: const Icon(Icons.hourglass_empty), ), - SizedBox(width: 50), + SizedBox(width: 30), Text('Show Students attempts timeline'), - SizedBox(width: 10), + SizedBox(width: 5), Checkbox( //title: const Text('Animate Slowly'), value: timeDilation != 1.0, onChanged: (bool value) { setState(() { timeDilation = value ? 10.0 : 1.0; }); }, // secondary: const Icon(Icons.hourglass_empty), ), ]), Row( // mainAxisSize: MainAxisSize.min, children: [ Expanded( child: MaterialButton( color: Colors.deepOrange, elevation: 0, onPressed: () { dbRef.child("1").child("isPaused").set(true); }, child: Container( padding: EdgeInsets.all(15.0), child: Text( "Pause All", textAlign: TextAlign.center, style: TextStyle( fontSize: 20.0, color: Colors.white, fontWeight: FontWeight.w500), ), ), ), ), Expanded( child: MaterialButton( color: Colors.black54, elevation: 0, onPressed: () {}, child: Container( padding: EdgeInsets.all(15.0), child: Text( "Next Activity", textAlign: TextAlign.center, style: TextStyle( fontSize: 20.0, color: Colors.white, fontWeight: FontWeight.w500), ), ), ), ), ], ), ])); } } Widget minituare(int position, int turn) { var colors = [Colors.grey, Colors.red, Colors.blue, Colors.green]; return Container( width: 130, height: 180, decoration: BoxDecoration( border: Border.all( width: 0.5, color: colors[ thisClass.groups[position].activities[0].progress[turn - 1] + 2])), child: Stack(children: [ Positioned( bottom: 65, right: 30, width: 90, height: 90, - child: celluloMap(turn)), + child: celluloMap( + turn, + thisClass + .groups[position].activities[0].turns[turn - 1].cellulox.x, + thisClass.groups[position].activities[0].turns[turn - 1] + .celluloy.y)), Positioned( bottom: 155, right: 50, child: Text("Turn " + turn.toString())), Positioned(bottom: 4, right: 50, child: Text("")), Positioned( bottom: 25, right: 6, child: Text( thisClass.groups[position].activities[0].progress[turn - 1] > -2 ? (thisClass.groups[position].activities[0].mistakes['slope'][turn - 1] == 0 && thisClass.groups[position].activities[0].mistakes['initialPoint'][turn - 1] == 0 ? 'No Mistakes' : (thisClass.groups[position].activities[0].mistakes['slope'][turn - 1] > 0 && thisClass.groups[position].activities[0] .mistakes['initialPoint'][turn - 1] > 0 ? 'Mistakes in finding\n Slope and\n Initial Points' : (thisClass.groups[position].activities[0].mistakes['slope'][turn - 1] > 0 && thisClass.groups[position].activities[0] .mistakes['initialPoint'][turn - 1] == 0 ? 'Mistakes in finding\n slope' : 'Mistakes in finding\n initial points'))) : '', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ), ) ])); } diff --git a/Dashboard/lib/widgets/celluloMap.Dart b/Dashboard/lib/widgets/celluloMap.Dart index e4608c1..4d8adaf 100644 --- a/Dashboard/lib/widgets/celluloMap.Dart +++ b/Dashboard/lib/widgets/celluloMap.Dart @@ -1,21 +1,27 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:Teacher_Dashboard/widgets/linePainter.Dart'; -Widget celluloMap(int turn) { +Widget celluloMap(int turn, List celluloxPositiontopaint, + List celluloyPositiontopaint) { var imagespath = [ 'assets/images/function1.svg', 'assets/images/function2.svg', 'assets/images/function3.svg', 'assets/images/GridOnlyPositive.svg', ]; final double mapSizeWidth = 860; final double mapSizeHeight = 860; - final double mapSizeScreenWidth = 30; - final double mapSizeScreenHeight = 30; + final double mapSizeScreenWidth = 90; + final double mapSizeScreenHeight = 90; final double scaleWidth = mapSizeScreenWidth / mapSizeWidth; final double scaleHeight = mapSizeScreenHeight / mapSizeHeight; return Stack(children: [ SvgPicture.asset(imagespath[turn - 1]), SvgPicture.asset("assets/images/GridOnlyPositive.svg"), + CustomPaint( + size: Size(mapSizeScreenWidth, mapSizeScreenHeight), + painter: LinePainter2(celluloxPositiontopaint, celluloyPositiontopaint), + ), ]); } diff --git a/Dashboard/lib/widgets/linePainter.Dart b/Dashboard/lib/widgets/linePainter.Dart index f47e531..ec6abb2 100644 --- a/Dashboard/lib/widgets/linePainter.Dart +++ b/Dashboard/lib/widgets/linePainter.Dart @@ -1,27 +1,37 @@ import 'package:flutter/material.dart'; -class LinePainter extends CustomPainter { +class LinePainter2 extends CustomPainter { Paint _paint; - double _progress; - Offset beginpath; - Offset endpath; - LinePainter(this._progress, this.beginpath, this.endpath) { + + List x; + List y; + var path = Path(); + //var patendpathh=path(); + LinePainter2(this.x, this.y) { _paint = Paint() - ..color = Colors.green - ..strokeWidth = 6.0; + ..color = Colors.blue + ..strokeWidth = 3.0 + ..style = PaintingStyle.stroke; } @override void paint(Canvas canvas, Size size) { - canvas.drawLine( - beginpath, - Offset(beginpath.dx + _progress * (endpath.dx - beginpath.dx), - beginpath.dy + _progress * (endpath.dy - beginpath.dy)), - _paint); + // path.moveTo(0, 0); + //canvas.restore(); + // print(x); + for (int i = 3; i < x.length - 3; i++) { + path.moveTo(x[i - 2], y[i - 2]); + path.lineTo(x[i - 1], y[i - 1]); + canvas.drawPath(path, _paint); + // canvas.save(); + } + // path.moveTo(0, 0); + //path.lineTo(20, 20); + //canvas.drawPath(path, _paint); } @override - bool shouldRepaint(LinePainter oldDelegate) { - return oldDelegate._progress != _progress; + bool shouldRepaint(LinePainter2 oldDelegate) { + return true; } } diff --git a/student/lib/Activities/Ac7.Dart b/student/lib/Activities/Ac7.Dart index 7a50a23..11b4e1a 100644 --- a/student/lib/Activities/Ac7.Dart +++ b/student/lib/Activities/Ac7.Dart @@ -1,774 +1,796 @@ import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:student/widgets/onlineRobotMap.Dart'; import 'dart:async'; import 'dart:convert'; import 'package:student/Database.dart'; import 'package:student/model/Group.dart'; import 'package:student/model/Cellulo.dart'; import 'package:student/widgets/showAlertDialog.Dart'; import 'package:student/widgets/membersBar.Dart'; import 'package:student/widgets/inactivityDetector.Dart'; import 'package:flutter_appavailability/flutter_appavailability.dart'; class Ac7 extends StatefulWidget { Ac7({Key key}) : super(key: key); @override _Ac7State createState() => _Ac7State(); } class _Ac7State extends State with SingleTickerProviderStateMixin, WidgetsBindingObserver { Timer timerCelluloPosition; Timer timerslopedetection; Timer timercleartracking; Timer timerprevCelluloPosition; Timer timerInactivityDetector; + Timer timerprevCelluloPositiontoserver; final acID = 7; bool celluloxSwitch1 = true; bool celluloySwitch1 = false; bool celluloxSwitch2 = true; bool celluloySwitch2 = false; var onStop = false; bool mode = false; int wrongcounts = 0; double _progress = 0.0; final celluloSize = 60; final ScrollController _scrollController = ScrollController(); final functionFormulas = ['X ⟼ Y', 'X+1 ⟼ Y', 'X+2 ⟼ Y', '2*X ⟼ Y', '-X ⟼ Y']; Offset beginpath = Offset(0, 0); Offset endpath = Offset(10, 100); AnimationController controller; Animation animation; TextEditingController controllerinitialX = TextEditingController(); TextEditingController controllerinitialY = TextEditingController(); TextEditingController controllerXslope = TextEditingController(); TextEditingController controllerYslope = TextEditingController(); var counterfunctionImage = 0; var imagespath = [ 'assets/images/Ac7_function1.svg', 'assets/images/Ac7_function2.svg', 'assets/images/Ac7_function3.svg', 'assets/images/GridOnlyPositive.svg', ]; var onTap = [false, false, false, false, false]; // var onTap=[false,false,false,false,false]; final double mapSizeWidth = 860; final double mapSizeHeight = 860; var currentTurn = 1; var currentTap = 0; var tapCounter = 0; List progress = [0, -2, -2]; // zero: undergoing, -1: not accomplished, 1: accomplished bool waitforanimation = false; List mistakesSlope = [0, 0, 0]; List mistakesIntrepet = [0, 0, 0]; List mistakesInitialPosition = [0, 0, 0]; List progressElpasedTime = [0, 0, 0]; var inactivity = 0; var prevcelluloxPositionSlope = 0.0; var prevcelluloyPositionSlope = 0.0; // robot related var elapseTimer = new Stopwatch(); bool setRun = false; var celluloxPosition = [0.0, 0.0]; var celluloyPosition = [0.0, 0.0]; List celluloxPositiontopaint = [0.0, 0.0]; List celluloyPositiontopaint = [0.0, 0.0]; var prevcelluloxPosition = [0.0, 0.0]; var prevcelluloyPosition = [0.0, 0.0]; var initialPositionCellulox = [0.0, 0.0]; var initialPositionCelluloy = [0.0, 0.0]; // screen-related var originCoordinates = [303.08, 563.08]; var avgActivation = 0; int prevtotalTaps = 0; var correctAnswer = [ {"initialPointX": 0, "initialPointY": 0, "slope": 1}, {"initialPointX": 0, "initialPointY": 1, "slope": 1}, {"initialPointX": 0, "initialPointY": 0, "slope": 2} ]; Future getApps() async { List> _installedApps; _installedApps = await AppAvailability.getInstalledApps(); print(await AppAvailability.checkAvailability("com.android.chrome")); // Returns: Map{app_name: Chrome, package_name: com.android.chrome, versionCode: null, version_name: 55.0.2883.91} print(await AppAvailability.isAppEnabled("com.android.chrome")); // Returns: true } @override void initState() { WidgetsBinding.instance.addObserver(this); dbRef.child('groups').child(group.id).child('tabletStatus').set("YES"); dbRef .child('groups') .child(group.id) .child('currentActivity') .set("Activity 7"); elapseTimer.start(); onDataSend(); // getApps(); super.initState(); // group.numCurrentActivity = 7; cellulox.resetrobot(); celluloy.resetrobot(); timerCelluloPosition = new Timer.periodic(new Duration(milliseconds: 100), (time) { cellulox.getrobotx().then((val) => setState(() { celluloxPosition[0] = val; if (setRun == true) celluloxPositiontopaint.add(val * 500 / 860); + // print(setRun.toString()); })); cellulox.getroboty().then((val) => setState(() { celluloxPosition[1] = val; if (setRun == true) prevcelluloxPosition[1] = celluloxPosition[1]; })); celluloy.getrobotx().then((val) => setState(() { celluloyPosition[0] = val; if (setRun == true) prevcelluloyPosition[0] = celluloyPosition[0]; })); celluloy.getroboty().then((val) => setState(() { celluloyPosition[1] = val; if (setRun == true) celluloyPositiontopaint.add(val * 500 / 860); })); if (celluloxPosition[0] > 800 || celluloyPosition[1] > 800) { cellulox.resetrobot(); celluloy.resetrobot(); } + /* dbRef .child(group.id) .child("activity 8") .child("inactivity") .push() .set(inactivity); dbRef .child(group.id) .child("cellulox") .child("x") .push() .set(celluloxPosition); dbRef .child(group.id) .child("cellulox") .child("y") .push() .set(celluloxPosition); dbRef .child(group.id) .child("celluloy") .child("x") .push() .set(celluloyPosition); dbRef .child(group.id) .child("celluloy") .child("y") .push() .set(celluloyPosition); */ }); + + timerprevCelluloPositiontoserver = + new Timer.periodic(new Duration(milliseconds: 400), (time) { + if (setRun == true) { + dbRef.child("celluloPosition").push().set(json.encode({ + "x": celluloxPosition[0], + "y": celluloyPosition[1], + "acID": "Ac7", + "turn": currentTurn, + "groupID": group.id, + })); + } + }); + timerprevCelluloPosition = new Timer.periodic(new Duration(seconds: 40), (time) { setState(() { if (setRun == true) { prevcelluloxPosition[0] = celluloxPosition[0]; prevcelluloxPosition[1] = celluloxPosition[1]; prevcelluloyPosition[0] = celluloyPosition[0]; prevcelluloyPosition[1] = celluloyPosition[1]; } }); /* dbRef .child(group.id) .child("activity 8") .child("inactivity") .push() .set(inactivity); dbRef .child(group.id) .child("cellulox") .child("x") .push() .set(celluloxPosition); dbRef .child(group.id) .child("cellulox") .child("y") .push() .set(celluloxPosition); dbRef .child(group.id) .child("celluloy") .child("x") .push() .set(celluloyPosition); dbRef .child(group.id) .child("celluloy") .child("y") .push() .set(celluloyPosition); */ }); timerInactivityDetector = new Timer.periodic(new Duration(seconds: 60), (time) { onInactivityTimer(); }); controller = AnimationController( duration: Duration(milliseconds: 10000), vsync: this); /// /// Ask to be notified when messages related to the game /// are sent by the server /// } AppLifecycleState _notification; @override void didChangeAppLifecycleState(AppLifecycleState state) { print(state); if (state == AppLifecycleState.resumed) { dbRef.child('groups').child(group.id).child('tabletStatus').set("YES"); } else { dbRef.child('groups').child(group.id).child('tabletStatus').set("NO"); } setState(() { _notification = state; }); } void onDataSend() { dbRef.child('attempts').push().set(json.encode({ "numAttempts": tapCounter, "groupID": group.id, "acID": "Ac7", "elpasedTime": elapseTimer.elapsedMilliseconds, "progress": { "turn1": progress[0], "turn2": progress[1], "turn3": progress[2] }, "progressElpasedTime": { "turn1": progressElpasedTime[0], "turn2": progressElpasedTime[1], "turn3": progressElpasedTime[2], }, "currentTurn": currentTurn, "inactivity": inactivity, "mistakes": { "turn1": { "slope": mistakesSlope[0], "initialPoint": mistakesInitialPosition[0] }, "turn2": { "slope": mistakesSlope[1], "initialPoint": mistakesInitialPosition[1] }, "turn3": { "slope": mistakesSlope[2], "initialPoint": mistakesInitialPosition[2] }, } })); } void slopeDtectionTimer() { timerslopedetection = new Timer.periodic(new Duration(seconds: 1), (time) { print("prev" + (((celluloxPosition[0] - prevcelluloxPositionSlope).roundToDouble() > 0) .toString())); // print("currwnt" + celluloxPosition[0].toString()); controllerXslope.text = 1.0.toString(); if ((celluloxPosition[0] - prevcelluloxPositionSlope).abs() < 10) { controllerYslope.text = "You sould move the RED robot faster"; } else { controllerYslope.text = (((prevcelluloyPositionSlope - celluloyPosition[1])) / (celluloxPosition[0] - prevcelluloxPositionSlope)) .roundToDouble() .toString(); } prevcelluloxPositionSlope = celluloxPosition[0]; prevcelluloyPositionSlope = celluloyPosition[1]; // print(int.parse(controllerXslope.text) > 0); print("cur" + (((celluloxPosition[0] - prevcelluloxPositionSlope).roundToDouble() > 0) .toString())); if ((celluloxPosition[0] - prevcelluloxPositionSlope).roundToDouble() > 1) { setState(() { celluloxSwitch2 = true; print(celluloxSwitch2); }); } if (((celluloxPosition[0] - prevcelluloxPositionSlope) / 100) .roundToDouble() < -1) { setState(() { celluloxSwitch2 = false; print(celluloxSwitch2); }); } if (celluloyPosition[1] - prevcelluloyPositionSlope > 0) { setState(() { celluloySwitch2 = true; print(celluloySwitch2); }); } if (celluloyPosition[1] - prevcelluloyPositionSlope < 1.0) { setState(() { celluloySwitch2 = false; print(celluloySwitch2); }); } }); } void clearTrackingTimer() { timercleartracking = new Timer.periodic(new Duration(seconds: 5), (time) { cellulox.resetrobot(); celluloy.resetrobot(); setState(() { setRun = true; }); timercleartracking.cancel(); }); } void onInactivityTimer() { group.inactivity = group.inactivity + 1; dbRef.child('activation').push().set(json.encode({ "groupID": group.id, "acID": "Ac7", "elpasedTime": elapseTimer.elapsedMilliseconds, "inactivity": tapCounter - prevtotalTaps, })); prevtotalTaps = tapCounter; } @override void dispose() { WidgetsBinding.instance.removeObserver(this); timer.cancel(); super.dispose(); } void nextPLayer() { setState(() { currentTurn = currentTurn + 1; // celluloyPositiontopaint = [0.0, 0.0]; // celluloxPositiontopaint = [0.0, 0.0]; }); } void animationRunner(progress) { print(progress); if (progress < 0.4) { cellulox.setGoalPosition( originCoordinates[0] + 100 * int.parse(controllerinitialX.text), 600); celluloy.setGoalPosition( 100, originCoordinates[1] - 100 * int.parse(controllerinitialY.text)); } setState(() { setRun = true; }); if (progress > 0.6) { cellulox.setGoalPosition( originCoordinates[0] + 100 * int.parse(controllerinitialX.text) + 500, 600); celluloy.setGoalPosition( 100, originCoordinates[1] - 100 * int.parse(controllerinitialY.text) - 500); } if (celluloxPosition[0] > 800 || celluloyPosition[1] > 800) { cellulox.resetrobot(); celluloy.resetrobot(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Activity 7: Semi-Mathematical Control'), ), backgroundColor: Colors.white, body: SingleChildScrollView( child: Column(children: [ Card( child: ListTile( title: Text( 'Choose the two points that your robots start from there and also how much the blue robot should move. '), ), ), Container( margin: const EdgeInsets.all(15.0), padding: const EdgeInsets.all(10.0), decoration: BoxDecoration( border: Border.all(color: Colors.blueAccent), borderRadius: new BorderRadius.circular(25.0), ), height: 230.0, child: Column(children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container( width: 250, child: new TextFormField( controller: controllerinitialX, decoration: new InputDecoration( labelText: "RED starts at this position:", fillColor: Colors.red, border: new OutlineInputBorder( borderRadius: new BorderRadius.circular(25.0), borderSide: new BorderSide(), ), //fillColor: Colors.green ), validator: (val) { if (val.length == 0) { return "Email cannot be empty"; } else { return null; } }, keyboardType: TextInputType.text, style: new TextStyle( fontFamily: "Poppins", ), ), ), SizedBox(height: 10), Row(children: [ Container( width: 250, child: new TextFormField( enabled: false, // controller: controllerXslope, decoration: new InputDecoration( labelText: "When RED moves by 1", fillColor: Colors.red, border: new OutlineInputBorder( borderRadius: new BorderRadius.circular(25.0), borderSide: new BorderSide(), ), //fillColor: Colors.green ), validator: (val) { if (val.length == 0) { return "Email cannot be empty"; } else { return null; } }, keyboardType: TextInputType.text, style: new TextStyle( fontFamily: "Poppins", ), ), ), Column(children: [ Container( child: Switch( value: celluloxSwitch1, onChanged: (value) { setState(() { // celluloxSwitch1 = value; }); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, inactiveTrackColor: Colors.lightGreenAccent, inactiveThumbColor: Colors.green, )), Text(celluloxSwitch1 ? 'Right' : 'Left') ]), ]), ]), SizedBox( width: 8, ), Column( // mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 250, child: new TextFormField( controller: controllerinitialY, decoration: new InputDecoration( labelText: "BLUE starts at this position:", fillColor: Colors.blue, border: new OutlineInputBorder( borderRadius: new BorderRadius.circular(25.0), borderSide: new BorderSide(), ), //fillColor: Colors.green ), validator: (val) { if (val.length == 0) { return "Email cannot be empty"; } else { return null; } }, keyboardType: TextInputType.text, style: new TextStyle( fontFamily: "Poppins", ), ), ), SizedBox(height: 10), Row(children: [ Container( width: 250, child: new TextFormField( controller: controllerYslope, decoration: new InputDecoration( labelText: "Then Blue should move by:", fillColor: Colors.blue, border: new OutlineInputBorder( borderRadius: new BorderRadius.circular(25.0), borderSide: new BorderSide(), ), //fillColor: Colors.green ), validator: (val) { if (val.length == 0) { return "Email cannot be empty"; } else { return null; } }, keyboardType: TextInputType.text, style: new TextStyle( fontFamily: "Poppins", ), )), Column(children: [ RotatedBox( quarterTurns: 1, child: Switch( value: celluloySwitch1, onChanged: (value) { setState(() { celluloySwitch1 = value; }); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, inactiveTrackColor: Colors.lightGreenAccent, inactiveThumbColor: Colors.green, )), Text(celluloySwitch1 ? 'Down' : 'Up') ]), ]) ]), ]), SizedBox( height: 5, ), Row(mainAxisAlignment: MainAxisAlignment.center, children: < Widget>[ FloatingActionButton( heroTag: "btn2", tooltip: 'Run the Robots', onPressed: () => { tapCounter = tapCounter + 1, // avgActivation= if (controllerinitialX.text != correctAnswer[currentTurn - 1]['initialPointX'] .toString() || controllerinitialY.text != correctAnswer[currentTurn - 1]['initialPointY'] .toString()) { mistakesInitialPosition[currentTurn - 1] = mistakesInitialPosition[currentTurn - 1] + 1, }, if (controllerYslope.text != correctAnswer[currentTurn - 1]['slope'].toString()) { mistakesSlope[currentTurn - 1] = mistakesSlope[currentTurn - 1] + 1, }, if (controllerinitialX.text == correctAnswer[currentTurn - 1] ['initialPointX'] .toString() && controllerinitialY.text == correctAnswer[currentTurn - 1]['initialPointY'] .toString() && controllerYslope.text == correctAnswer[currentTurn - 1]['slope'] .toString()) { progress[currentTurn - 1] = 1, }, onDataSend(), + controller.reset(), animation = Tween(begin: 0.0, end: 1.0).animate( controller) ..addListener(() { _progress = animation.value; if (_progress < 0.4) { cellulox.setGoalPosition( originCoordinates[0] + 100 * int.parse(controllerinitialX.text), 600); celluloy.setGoalPosition( 100, originCoordinates[1] - 100 * int.parse(controllerinitialY.text)); } if (_progress > 0.6) { setState(() { setRun = true; }); cellulox.setGoalPosition( originCoordinates[0] + 100 * int.parse(controllerinitialX.text) + 300, 600); celluloy.setGoalPosition( 100, originCoordinates[1] - 100 * int.parse(controllerinitialY.text) - 150); } if (celluloxPosition[0] > 800 || celluloyPosition[1] > 800) { cellulox.resetrobot(); celluloy.resetrobot(); } }), controller.forward(), }, child: Icon(Icons.play_circle_outline), ), SizedBox(width: 20), FloatingActionButton( heroTag: "btn1", tooltip: 'Next Turn', onPressed: () => { setState(() { currentTurn = currentTurn + 1; if (currentTurn == 2) { progressElpasedTime[0] = elapseTimer.elapsedMilliseconds; } else { progressElpasedTime[currentTurn - 2] = elapseTimer.elapsedMilliseconds - progressElpasedTime[currentTurn - 3]; } }), if (progress[currentTurn - 2] == 0) progress[currentTurn - 2] = -1, if (currentTurn < 4) { + celluloxPositiontopaint = [0, 0], + celluloyPositiontopaint = [0, 0], + controller.reset(), + setRun = false, progress[currentTurn - 1] = 0, onDataSend(), } // _ackAlert, // showAlertDialog(context, '', 'Now its next player turn'), }, child: Icon(Icons.navigate_next), ), ]), ])), SizedBox( height: 5, ), celluloMap(context), SizedBox( height: 15, ), MembersBar(), ]))); } Widget celluloMap(BuildContext context) { final double mapSizeScreenWidth = 500; final double mapSizeScreenHeight = 500; final double scaleWidth = mapSizeScreenWidth / mapSizeWidth; final double scaleHeight = mapSizeScreenHeight / mapSizeHeight; return Container( height: mapSizeScreenWidth, width: mapSizeScreenHeight, decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)), child: Stack(children: [ Container( height: mapSizeScreenWidth, width: mapSizeScreenHeight, child: SvgPicture.asset(imagespath[currentTurn - 1])), Container( height: mapSizeScreenWidth, width: mapSizeScreenHeight, child: SvgPicture.asset("assets/images/GridOnlyPositive.svg")), Align( alignment: Alignment( 2 * (celluloxPosition[0] * scaleWidth / mapSizeScreenWidth) - 1, 1), child: Card( child: SvgPicture.asset("assets/images/cellulox.svg", height: 60, width: 60), ), ), Align( alignment: Alignment( -1, 2 * (celluloyPosition[1] * scaleHeight / mapSizeScreenHeight) - 1), child: Card( child: SvgPicture.asset("assets/images/celluloy.svg", height: 60, width: 60), ), ), CustomPaint( size: Size(mapSizeScreenWidth, mapSizeScreenHeight), painter: LinePainter2(celluloxPositiontopaint, celluloyPositiontopaint), ), ])); } } diff --git a/student/lib/widgets/onlineRobotMap.Dart b/student/lib/widgets/onlineRobotMap.Dart index 56d0481..c73580c 100644 --- a/student/lib/widgets/onlineRobotMap.Dart +++ b/student/lib/widgets/onlineRobotMap.Dart @@ -1,63 +1,63 @@ import 'package:flutter/material.dart'; class LinePainter extends CustomPainter { Paint _paint; Offset beginpath; Offset endpath; var path = Path(); //var patendpathh=path(); LinePainter(this.beginpath, this.endpath) { _paint = Paint() ..color = Colors.blue ..strokeWidth = 8.0 ..style = PaintingStyle.stroke; } @override void paint(Canvas canvas, Size size) { // path.moveTo(0, 0); path.moveTo(beginpath.dx, beginpath.dy); path.lineTo(endpath.dx, endpath.dy); canvas.drawPath(path, _paint); - canvas.save(); + // canvas.saveLayer(bounds, paint); } @override bool shouldRepaint(LinePainter oldDelegate) { return true; } } class LinePainter2 extends CustomPainter { Paint _paint; double _progress; List x; List y; var path = Path(); //var patendpathh=path(); LinePainter2(this.x, this.y) { _paint = Paint() ..color = Colors.blue ..strokeWidth = 8.0 ..style = PaintingStyle.stroke; } @override void paint(Canvas canvas, Size size) { // path.moveTo(0, 0); for (int i = 4; i < x.length; i++) { path.moveTo(x[i - 2], y[i - 2]); path.lineTo(x[i - 1], y[i - 1]); canvas.drawPath(path, _paint); } } @override bool shouldRepaint(LinePainter2 oldDelegate) { return true; } } LinePainter linepainter = new LinePainter(Offset(0, 0), Offset(0, 10));