Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F81644726
Ac5.dart
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Sep 7, 05:07
Size
28 KB
Mime Type
text/x-c++
Expires
Mon, Sep 9, 05:07 (2 d)
Engine
blob
Format
Raw Data
Handle
20603952
Attached To
R10646 Orchestration
Ac5.dart
View Options
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.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';
import 'package:student/widgets/bezierCurvePainter.dart';
import 'package:bezier/bezier.dart';
import 'package:student/widgets/mapShapeMaker.dart';
import 'package:bezier/bezier.dart';
import "dart:math" as math;
import "package:vector_math/vector_math.dart" as vector;
import 'package:student/widgets/guidegrid.dart';
import 'package:student/widgets/stopdrawer.dart';
class Ac5 extends StatefulWidget {
Ac5({Key key}) : super(key: key);
@override
_Ac5State createState() => _Ac5State();
}
class _Ac5State extends State<Ac5> {
// Activity_Independent
int currentTurn = 1;
var elapseTimer = new Stopwatch();
var timeOutofBorder;
AnimationController controllerRobotPath;
Animation<double> animationRobotPath;
Timer timerCelluloPosition;
Timer timerCelluloPositionPainttoserver;
// Celulo
var celluloxPosition = [0.0, 0.0];
var celluloyPosition = [0.0, 0.0];
var xHaptic;
var yHaptic;
final String mapPath = 'assets/images/Grid_Ac5_Screen.svg';
// Learning
bool gameover = false;
bool startGame = false;
int score = 6;
bool outofborder = false;
bool reachend = false;
bool stopend = false;
double radiuosStart = 45;
List<int> mistakesSlope = [0, 0, 0];
List<int> mistakesIntrepet = [0, 0, 0];
List<int> mistakesInitialPosition = [0, 0, 0];
int tapCounter = 0;
List<int> progress = [0, -2, -2];
List<int> progressElpasedTime = [0, 0, 0];
//Activity Dependent
final double mapSizeWidth = 860;
final double mapSizeHeight = 860;
final List<String> initialpointList = ['0', '1', '2', '3'];
String initialPointXvalue;
String initialPointYvalue;
static List<List<Offset>> pointPosition = [
[
Offset(530, 132),
Offset(125, 525),
],
[
Offset(690, 532),
Offset(125, 135),
],
[
Offset(530, 132),
Offset(125, 735),
],
];
var midddlePoint1 = [
Offset(291.1, 176.2),
Offset(110.2, 632.8),
Offset(610.2, 732.8)
];
var midddlePoint2 = [
Offset(410.2, 532.8),
Offset(356, 357),
Offset(110.2, 232.8)
];
var startPoint = ['A', 'A', 'C'];
var endPoint = ['B', 'D', 'B'];
List<Offset> stopBoxCenter = [
Offset(330, 340),
Offset(520, 490),
Offset(380, 250)
];
Offset origin = new Offset(106, 572.0); // should be calibrated for a new map
var step = 75.0;
var mapShape = [
{
'numCircles': 0,
'originCircles': [Offset(0, 0)],
'radiuosCircles': [0.0],
'numRectangles': 0,
'originRectangles': [
Offset(300, 30),
Offset(100, 560),
Offset(600, 630),
Offset(780, 360),
Offset(300, 300),
Offset(500, 260),
Offset(300, 560)
],
'widthRectangles': [150.0, 100.0, 50.0, 80.0, 150.0, 100.0, 100.0],
'heightRectangles': [70.0, 100.0, 200.0, 300.0, 40.0, 300.0, 200.0],
'numPolygons': 0,
'sidesofPolygon': [0],
'radiusPolygon': [0.0],
'centerPolygon': [Offset(0, 0)],
'startCenter': pointPosition[0][1],
'endCenter': pointPosition[0][0]
},
{
'numCircles': 0,
'originCircles': [Offset(0, 0)],
'radiuosCircles': [0.0],
'numRectangles': 0,
'originRectangles': [
Offset(690, 430),
Offset(500, 560),
Offset(430, 130),
Offset(300, 760),
Offset(100, 230),
Offset(100, 460)
],
'widthRectangles': [150.0, 100.0, 200.0, 100.0, 210.0, 210.0],
'heightRectangles': [150.0, 250.0, 50.0, 250.0, 50.0, 300.0],
'numPolygons': 0,
'sidesofPolygon': [3, 3, 5, 4, 4],
'radiusPolygon': [30.0, 40.0, 40.0, 40.0, 50.0],
'centerPolygon': [
Offset(40, 130),
Offset(700, 90),
Offset(600, 200),
Offset(600, 500),
Offset(780, 400)
],
'startCenter': pointPosition[1][1],
'endCenter': pointPosition[1][0]
},
{
'numCircles': 0,
'originCircles': [Offset(0, 0)],
'radiuosCircles': [0.0],
'numRectangles': 0,
'originRectangles': [
Offset(300, 130),
Offset(500, 460),
Offset(750, 530),
Offset(600, 130),
Offset(600, 730),
Offset(100, 530),
Offset(350, 460)
],
'widthRectangles': [160.0, 90.0, 150.0, 100.0, 150.0, 300.0, 50.0],
'heightRectangles': [130.0, 270.0, 150.0, 250.0, 100.0, 70.0, 250.0],
'numPolygons': 0,
'sidesofPolygon': [0],
'radiusPolygon': [0.0],
'centerPolygon': [Offset(0, 0)],
'startCenter': pointPosition[2][1],
'endCenter': pointPosition[2][0]
},
];
void onDataSend() {
dbRef.child('attempts').push().set(json.encode({
"numAttempts": tapCounter,
"groupID": group.id,
"acID": "Ac5",
"engagementX": group.cellulox.traveledDistance,
"engagementY": group.celluloy.traveledDistance,
"elpasedTime": elapseTimer.elapsedMilliseconds -
progressElpasedTime[currentTurn - 1],
"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 checkCelluloGame() {
Offset beginpath = mapShape[currentTurn - 1]['startCenter'];
Offset endpath = mapShape[currentTurn - 1]['endCenter'];
double celluloXYdistances = math.sqrt(
math.pow((celluloxPosition[0] - celluloyPosition[0]), 2) +
math.pow((celluloxPosition[1] - celluloyPosition[1]), 2));
double distanceThreshold = 120;
//print(score.toString());
//print(enterBorder.toString());
if (celluloXYdistances < distanceThreshold) {
cellulox.robotVibrate(10, 10, 0, 100, 100);
celluloy.robotVibrate(10, 10, 0, 100, 100);
// cellulox.setVelocity(-celluloxVelocity[0], -celluloxVelocity[1]);
// celluloy.setVelocity(-celluloyVelocity[0], -celluloyVelocity[1]);
}
var distancePointCenter = math.sqrt(math.pow(
((celluloxPosition[0] + celluloxPosition[0]) / 2 - beginpath.dx),
2) +
math.pow(
((celluloyPosition[1] + celluloyPosition[1]) / 2 - beginpath.dy),
2));
if (distancePointCenter <= radiuosStart) {
score = 6;
gameover = false;
reachend = false;
startGame = true;
}
if (startGame) {
if (score <= 0 && gameover == false) {
tapCounter = tapCounter + 1;
onDataSend();
gameover = true;
showAlertDialog(context, 'Your Robot does not have energy',
'Tell your friend to go start point to get energy');
}
var distancePointEnd = math.sqrt(math.pow(
((celluloxPosition[0] + celluloxPosition[0]) / 2 - endpath.dx),
2) +
math.pow(
((celluloyPosition[1] + celluloyPosition[1]) / 2 - endpath.dy),
2));
if (distancePointEnd <= radiuosStart && reachend == false) {
// scoreX = -1;
reachend = true;
tapCounter = tapCounter + 1;
onDataSend();
showAlertDialog(context, 'Your Robot reached the goal point',
'Tell your friend to start again or you can go to next turn.');
}
var distancePointStop = math.sqrt(math.pow(
((celluloxPosition[0] + celluloxPosition[0]) / 2 -
stopBoxCenter[currentTurn - 1].dx),
2) +
math.pow(
((celluloyPosition[1] + celluloyPosition[1]) / 2 -
stopBoxCenter[currentTurn - 1].dy),
2));
if (distancePointStop <= radiuosStart && stopend == false) {
// scoreX = -1;
stopend = true;
tapCounter = tapCounter + 1;
onDataSend();
showAlertDialog(context, 'Your Robot reached the middle stop point',
'Put where should red and blue robot should go in continue.');
}
}
colorRobots();
}
void colorRobots() {
for (int i = 0; i < 6; i++) {
cellulox.setColor(0, 0, 0, 0, 0);
}
for (int i = 0; i < score; i++) {
cellulox.setColor(0, 255, 0, 1, i);
}
for (int i = 0; i < 6; i++) {
celluloy.setColor(0, 0, 0, 0, 0);
}
for (int i = 0; i < score; i++) {
celluloy.setColor(0, 0, 255, 1, i);
}
}
void calcHaptic() {
Offset beginpath = mapShape[currentTurn - 1]['startCenter'];
Offset endpath = mapShape[currentTurn - 1]['endCenter'];
final curve = new CubicBezier([
new vector.Vector2(beginpath.dx, beginpath.dy),
new vector.Vector2(
midddlePoint1[currentTurn - 1].dx, midddlePoint1[currentTurn - 1].dy),
new vector.Vector2(
midddlePoint2[currentTurn - 1].dx, midddlePoint2[currentTurn - 1].dy),
new vector.Vector2(endpath.dx, endpath.dy)
]);
var tHaptic = curve.nearestTValue(new vector.Vector2(
(celluloxPosition[0] + celluloxPosition[0]) / 2,
(celluloyPosition[1] + celluloyPosition[1]) / 2));
var xyHaptic = curve.pointAt(tHaptic);
// print('thaptic' + tHaptic.toString());
//print('xyhaptic' + xyHaptic.toString());
cellulox.setGoalPosition(xyHaptic[0].toDouble(), 800, 150);
celluloy.setGoalPosition(60, xyHaptic[1].toDouble(), 150);
var distancePointCurve = math.sqrt(math.pow(
((celluloxPosition[0] + celluloxPosition[0]) / 2 - xyHaptic[0]),
2) +
math.pow(
((celluloyPosition[1] + celluloyPosition[1]) / 2 - xyHaptic[1]),
2));
if (distancePointCurve > 50 && outofborder == false) {
outofborder = true;
timeOutofBorder = elapseTimer.elapsedMilliseconds;
// console.log(timeStart)
}
var timeNow = elapseTimer.elapsedMilliseconds;
//console.log( timeNow- timeStart)
if (outofborder == true &&
timeNow - timeOutofBorder < 3000 &&
distancePointCurve < 10) {
outofborder = false;
// console.log("outofbordrfalse")
}
if (outofborder == true && timeNow - timeOutofBorder > 3000) {
outofborder = false;
score = score - 1;
//console.log("battey reduced")
}
}
@override
void initState() {
super.initState();
cellulox.setColor(0, 255, 0, 0, 0);
timerCelluloPositionPainttoserver =
new Timer.periodic(new Duration(milliseconds: 1800), (time) {
if (true) {
dbRef.child("celluloPosition").push().set(json.encode({
"x": celluloxPosition[0],
"y": celluloyPosition[1],
"xx": celluloxPosition[0],
"xy": celluloxPosition[1],
"yx": celluloyPosition[0],
"yy": celluloyPosition[1],
"acID": "Ac5",
"turn": currentTurn,
"groupID": group.id,
}));
}
});
celluloy.setColor(0, 0, 255, 0, 0);
dbRef.child('groups').child(group.id).child('tabletStatus').set("YES");
dbRef.child('groups').child(group.id).child('currentActivity').set("Ac5");
timerCelluloPosition =
new Timer.periodic(new Duration(milliseconds: 500), (time) {
var xxprev = celluloxPosition[0];
var xyprev = celluloxPosition[1];
var yxprev = celluloyPosition[0];
var yyprev = celluloyPosition[1];
if (totalRobots() > 1) {
// print(cellulox.getrobotKidnapped().toString());
// print(celluloy.getrobotKidnapped().toString());
cellulox.getrobotx().then((val) => setState(() {
if (val != null) {
group.cellulox.traveledDistance =
group.cellulox.traveledDistance +
(val - celluloxPosition[0]);
celluloxPosition[0] = val;
// print(celluloxPosition[0]);
// if (addtoprint == true) celluloxPositiontopaint.add(val);
}
// print(addtoprint.toString());
}));
cellulox.getroboty().then((val) => setState(() {
if (val != null) {
celluloxPosition[1] = val;
group.cellulox.traveledDistance =
group.cellulox.traveledDistance +
math.sqrt(math.pow((xxprev - celluloxPosition[0]), 2) +
math.pow((xyprev - celluloxPosition[1]), 2)) /
20;
}
}));
celluloy.getrobotx().then((val) => setState(() {
if (val != null) {
celluloyPosition[0] = val;
}
}));
celluloy.getroboty().then((val) => setState(() {
if (val != null) {
group.celluloy.traveledDistance =
group.celluloy.traveledDistance +
math.sqrt(math.pow((yxprev - celluloyPosition[0]), 2) +
math.pow((yyprev - celluloyPosition[1]), 2)) /
20;
celluloyPosition[1] = val;
// if (addtoprint == true) celluloyPositiontopaint.add(val);
}
}));
if (celluloxPosition[0] > 800 || celluloyPosition[1] > 800) {
cellulox.setVelocity(0, 0);
celluloy.setVelocity(0, 0);
}
}
//if (runHaptic == true) {
calcHaptic();
checkCelluloGame();
});
elapseTimer.start();
onDataSend();
}
@override
void dispose() {
elapseTimer.stop();
timerCelluloPosition.cancel();
//
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Follow the Curve'),
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () {
group.prevActivity = 'Ac5';
group.currentActivity = 'Ac61';
group.navigatorKeygame.currentState.pushReplacementNamed(
group.currentActivity,
);
// print('ff');
},
child: Icon(Icons.help),
)),
],
),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(children: <Widget>[
Row(
//mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: 70,
width: 600,
child: Card(
color: Colors.lightBlue,
child: ListTile(
title: Text(
startGame
? ('Follow the curve from Point ' +
'A' +
' to ' +
'B')
: ('Move the prurple robot to point A'),
style: new TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(
width: 25,
),
// SizedBox(width: 20),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(100)),
color: reachend ? Colors.blue : Colors.grey),
child: FlatButton(
disabledColor: Colors.grey,
child: Text(
"Next Turn",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 18),
),
onPressed: () => {
reachend
? {
tapCounter = 0,
startGame = false,
if (currentTurn <= 2)
{
setState(() {
currentTurn = currentTurn + 1;
}),
progress[currentTurn - 2] = 1,
// controller.reset(),
progress[currentTurn - 1] = 0,
onDataSend(),
}
else
{
progress[2] = 1,
onDataSend(),
showAlertDialog(context, 'Wait for teacher',
'Game has finished! '),
},
}
: null
},
),
)
]),
SizedBox(
height: 30,
),
(stopend)
? Row(
// crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 290,
child: ListTile(
title: Text(
'Where the purple robot should go to reach point B:'),
)),
Container(
width: 200,
child: DropdownButton<String>(
hint: Text('RED robot goes to: '),
value: initialPointXvalue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
onChanged: (String newValue) {
setState(() {
initialPointXvalue = newValue;
});
},
items: initialpointList
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)),
SizedBox(width: 38),
Container(
width: 200,
child: DropdownButton<String>(
hint: Text('BLUE robot goes to: '),
value: initialPointYvalue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
onChanged: (String newValue) {
setState(() {
initialPointYvalue = newValue;
});
},
items: initialpointList
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)),
])
: SizedBox(
height: 10,
),
(reachend && stopend)
? Row(
// crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 290,
child: ListTile(
title: Text('Did you guess correctly?'),
)),
Container(
width: 200,
child: DropdownButton<String>(
hint: Text(''),
value: initialPointXvalue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
onChanged: (String newValue) {
setState(() {
initialPointXvalue = newValue;
});
},
items: ['Yes', 'No']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)),
SizedBox(width: 38),
])
: SizedBox(
height: 1,
),
SizedBox(
height: 10,
),
Container(
width: MediaQuery.of(context).size.width * 0.9,
height: MediaQuery.of(context).size.height * 0.65,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(100)),
// color: Colors.blue
),
child: Stack(
children: <Widget>[
CustomPaint(
//size: Size(200, 200),
painter:
//LinePainter2(celluloxPositiontopaint, celluloyPositiontopaint),
MapShapeMaker2(
pointPosition[currentTurn - 1],
MediaQuery.of(context).size.width *
0.9 /
mapSizeWidth,
MediaQuery.of(context).size.height *
0.65 /
mapSizeHeight,
mapShape[currentTurn - 1]['numRectangles'],
mapShape[currentTurn - 1]['originRectangles'],
mapShape[currentTurn - 1]['widthRectangles'],
mapShape[currentTurn - 1]['heightRectangles'],
mapShape[currentTurn - 1]['numCircles'],
mapShape[currentTurn - 1]['originCircles'],
mapShape[currentTurn - 1]['radiuosCircles'],
mapShape[currentTurn - 1]['numPolygons'],
mapShape[currentTurn - 1]['sidesofPolygon'],
mapShape[currentTurn - 1]['radiusPolygon'],
mapShape[currentTurn - 1]['centerPolygon'],
mapShape[currentTurn - 1]['startCenter'],
mapShape[currentTurn - 1]['endCenter']),
),
Container(
width: MediaQuery.of(context).size.width * 0.9,
height: MediaQuery.of(context).size.height * 0.65,
child: SvgPicture.asset(
mapPath,
),
),
CustomPaint(
//size: Size(200, 200),
painter: GuideGrid(
origin,
step,
MediaQuery.of(context).size.width * 0.9 / mapSizeWidth,
MediaQuery.of(context).size.height * 0.65 / mapSizeHeight,
celluloxPosition,
celluloyPosition,
)
//LinePainter2(celluloxPositiontopaint, celluloyPositiontopaint),
),
CustomPaint(
//size: Size(200, 200),
painter: StopDrawer(
MediaQuery.of(context).size.width * 0.9 / mapSizeWidth,
MediaQuery.of(context).size.height * 0.65 / mapSizeHeight,
stopBoxCenter[currentTurn - 1],
)
//LinePainter2(celluloxPositiontopaint, celluloyPositiontopaint),
),
Container(
width: MediaQuery.of(context).size.width * 0.9,
height: MediaQuery.of(context).size.height * 0.65,
child: Align(
alignment: Alignment(
2 * ((celluloxPosition[0]) / mapSizeWidth) - 1,
2 * ((celluloxPosition[1]) / mapSizeHeight) - 1),
child: Card(
child: SvgPicture.asset("assets/images/celluloRed.svg",
height: 60, width: 60),
),
),
),
Container(
width: MediaQuery.of(context).size.width * 0.9,
height: MediaQuery.of(context).size.height * 0.65,
child: Align(
alignment: Alignment(
2 * ((celluloyPosition[0]) / mapSizeWidth) - 1,
2 * ((celluloyPosition[1]) / mapSizeHeight) - 1),
child: Card(
child: SvgPicture.asset("assets/images/celluloBlue.svg",
height: 60, width: 60),
),
),
),
CustomPaint(
//size: Size(200, 200),
painter: BezierCurvePainter(
mapShape[currentTurn - 1]['startCenter'],
mapShape[currentTurn - 1]['endCenter'],
MediaQuery.of(context).size.width *
0.9 /
mapSizeWidth,
MediaQuery.of(context).size.height *
0.65 /
mapSizeHeight,
currentTurn,
5)
//LinePainter2(celluloxPositiontopaint, celluloyPositiontopaint),
),
Container(
width: MediaQuery.of(context).size.width * 0.9,
height: MediaQuery.of(context).size.height * 0.65,
child: Align(
alignment: Alignment(
2 *
((celluloxPosition[0] + celluloxPosition[0]) /
2 /
mapSizeWidth) -
1,
2 *
((celluloyPosition[1] + celluloyPosition[1]) /
2 /
mapSizeHeight) -
1),
child: Card(
child: SvgPicture.asset(
"assets/images/celluloPurple.svg",
height: 60,
width: 60),
),
),
),
],
)),
SizedBox(
height: 15,
),
MembersBar(
curTurn: currentTurn,
),
])));
}
}
Event Timeline
Log In to Comment