_getDataRowsForCompletedExerciseSets(workoutId) async {
try {
List listOfExercises = await FirebaseFirestore.instance
.collection('users')
.doc(currentUser!.uid)
.collection("workouts")
.doc(workoutId)
.collection("exercises")
.get()
.then((snapShot) => snapShot.docs);
for (int i = 0; i < listOfExercises.length; i++) {
FirebaseFirestore.instance
.collection('users')
.doc(currentUser!.uid)
.collection("workouts")
.doc(workoutId)
.collection("exercises")
.doc(listOfExercises[i].doc.id.toString())
.collection("sets")
.snapshots()
.listen(_createListOfExerciseSets);
}
setState(() {
for (ExerciseSet set in listOfExerciseSets) {
//print(set.weight);
completedExerciseSetRows.add(DataRow(cells: [
DataCell(Text(setCount.toString())),
//const DataCell(VerticalDivider(thickness: 5)),
DataCell(Text(set.weight.toString())),
//const DataCell(VerticalDivider(thickness: 5)),
DataCell(Text(set.reps.toString())),
//const DataCell(VerticalDivider(thickness: 5)),
DataCell((isSetToFailure == true) ? Icon(Icons.check) : Icon(null))
//const DataCell(VerticalDivider(thickness: 5)),
]));
}
});
} on Exception catch (_, e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(e.toString()),
duration: Duration(milliseconds: 1000),
),
);
}
return Container();
}
_createListOfExerciseSets(QuerySnapshot snapshot) {
var docs = snapshot.docs;
for (var doc in docs) {
listOfExerciseSets.add(ExerciseSet.fromFireStore(doc));
}
print('EXERCISE SETS = ' + listOfExerciseSets.toString());
}
I have the following db structure:
users-->{id}-->workouts-->{id}-->exercises-->{id}-->sets-->{id}--fields
I am trying to get the exercises for a particular workout(id) along with the sets(including fields) for each exercise.
The listOfExercises is always empty (0 items). There are no errors showing either.
Here is what I have right now:
Widget build(BuildContext context) {
var exercisesRef = usersRef
.doc(currentUser!.uid)
.collection('workouts')
.doc(workoutId)
.collection('exercises');
return FutureBuilder<QuerySnapshot>(
future: exercisesRef.get(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
return const Center(
child: kCPI,
);
case ConnectionState.waiting:
return const Center(
child: kCPI,
);
case ConnectionState.none:
return const Center(
child: kCPI,
);
case ConnectionState.done:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else if (!snapshot.hasData) {
//print('WORKOUTID = ' + workoutId);
return const Text("Document does not exist");
} else if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
final exercises = snapshot.data!.docs;
List<Widget> completedExercisesWidgetsList = [];
final _controller = ScrollController();
// for loop - loop through all the exercises for the current workout
for (var doc in exercises) {
bool isRowsGeneratedForPreviousExercises = false;
dataRowsForCompletedExercises = [];
var setList = [];
Map<String, dynamic> exercise;
var exerciseName = '';
exercise = doc.data() as Map<String, dynamic>;
setList = exercise['sets'];
exerciseName = exercise['name'];
//loop through the sets for the exercise
for (var set in setList) {
var setNumber = 0;
var weight = '';
var reps = '';
var isToFailure = false;
setNumber = setList.indexOf(set) + 1;
weight = set['weight'].toString();
reps = set['reps'].toString();
isToFailure = set['isToFailure'];
if (isRowsGeneratedForPreviousExercises == false) {
_generateDataTableRowsForCompletedExercises(
setNumber,
weight,
reps,
isToFailure,
);
}
}
isRowsGeneratedForPreviousExercises = true;
completedExercisesWidgetsList
.add(_completedExercisesDataTableWidget(exerciseName));
} //for loop ends
///Return list of widgets - one widget for each completed exercise for the current workout
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(
dragDevices: {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
},
),
child: ListView(
shrinkWrap: true,
controller: _controller,
physics: const AlwaysScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
children: completedExercisesWidgetsList,
),
),
),
],
);
}
}
return const Text("There was a problem loading content.");
},
);
}
And then simply generating DataTable rows from the data:
void _generateDataTableRowsForCompletedExercises(
setNumber, weight, reps, isToFailure) {
dataRowsForCompletedExercises.add(
DataRow(cells: [
DataCell(Text(setNumber.toString())),
DataCell(Text(weight)),
DataCell(Text(reps)),
DataCell(
(isToFailure == true) ? const Icon(Icons.check) : const Icon(null)),
]),
);
}
I believe your problem is where you use 'then'
Try this code and see the print output
var test = await FirebaseFirestore.instance
.collection('users')
.doc(currentUser!.uid)
.collection("workouts")
.doc(workoutId)
.collection("exercises")
.get()
print(test);
Related
I am trying to filter items from an array and create a new one out of it. When a user taps on one of the tabs, the list sorts the products into its categories(ie: When the dinner tab is selected, all products labeled as category "Dinner" will show) from there organize into sub categories (Chicken, Beef, Oxtail). I am not sure where I am going wrong here. Here is what I have so far:
Tab Bar
TabBar(
onTap: _changedDropDownItem,
indicatorColor: buddiesGreen,
labelColor: buddiesPurple,
unselectedLabelColor: Colors.grey,
// isScrollable: true,
tabs: [
Tab(icon: Icon(FontAwesomeIcons.medkit), text: "Dinner"),
Tab(icon: Icon(FontAwesomeIcons.heart), text: "Desserts"),
Tab(icon: Icon(Icons.info), text: "Taste"),
Tab(
icon: Icon(FontAwesomeIcons.home),
text: "More",
),
],
),
Then I use these methods to get the categories from the tab bar:
void _tabBarItemsTapped(int newValue) {
setState(() {
_selectedCustomerType = newValue;
});
_tabBarFilterSwitch(newValue);
print(_selectedCustomerType);
}
void _tabBarFilterSwitch(filterNumb) {
if (filterNumb == 0) {
_dropdownList = _usage;
} else if (filterNumb == 1) {
_dropdownList = _productType;
} else if (filterNumb == 2) {
_dropdownList = _productType;
} else if (filterNumb == 3) {
_dropdownList = _productType;
}
print(_dropdownList);
}
Here is a data model I'm pulling down:
{
"resId":123,
“image”: “ 'assets/ChocolateCake.jpg',
“productType”: “Dinner”
“type”: “main”
“sizes” :
[
{“size”:1,
“price”:$2.99},
{“size”:3,
"quantity”: $4.99}
]
}
I am trying to tap the tab that would trigger a switch case. This switch chase will update the list:
void _filterProductList(int value, productList, filter) {
List tempProducts = [];
switch (value) {
case 0:
for (int i = 0; i < productList.length; i++) {
tempProducts.add(productList[i].category.contains(filter[i]));
// tempProducts = productList
// tempProducts.
productList =[];
productList = tempProducts;
print(tempProducts[i].name);
}
break;
case 1:
for (int i = 0; i < productList.length; i++) {
tempProducts.add(productList[i].category.contains(filter[i]));
// tempProducts = productList
// tempProducts.
productList =[];
productList = tempProducts;
print(tempProducts[i].name);
}
break;
case 2:
for (int i = 0; i < productList.length; i++) {
tempProducts.add(productList[i].category.contains(filter[i]));
// tempProducts = productList
// tempProducts.
productList =[];
productList = tempProducts;
print(tempProducts[i].name);
}
break;
case 3:
for (int i = 0; i < productList.length; i++) {
tempProducts.add(productList[i].category.contains(filter[i]));
// tempProducts = productList
// tempProducts.
productList =[];
productList = tempProducts;
print(tempProducts[i].name);
}
break;
}
return;
}
And presents like:
Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: _prodType.length,
shrinkWrap: true,
itemBuilder: (context, ii) {
_filterProductList(filterNumb, productList, _dropdownList);
return Container(child: _buildProduct(context, ii));
},
)),
Instead of updating the list with every tap, it just seems like nothing is happening.
To refresh the hi you need to use setState.
productList = tempProducts should be:
setState(()=>productList = tempProducts);
Also, the widget should be a stateful widget.
trying to extend a chart, so that i can draw lines up to the data point, but this is happening before the default animation. it would look smoother if it applied after.
i have got most of it to work.. but how do i get this to apply after chart animation.
var originalLineDraw = Chart.controllers.line.prototype.draw;
Chart.helpers.extend(Chart.controllers.line.prototype, {
draw: function () {
originalLineDraw.apply(this, arguments);
var chart = this.chart;
var ctx = chart.chart.ctx;
var index = chart.config.data.lineAtIndex;
if (index) {
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-1']
var points = this.chart.getDatasetMeta(this.index).data;
for (var i = 0; i < points.length; i++) {
// var point_x = points[i]._model.x;
var point_y = points[i]._model.y;
ctx.beginPath();
ctx.setLineDash([5, 5]);/*dashes are 5px and spaces are 3px*/
ctx.moveTo(xaxis.getPixelForValue(undefined, i), point_y);
ctx.strokeStyle = '#fff';
ctx.lineTo(xaxis.getPixelForValue(undefined, i), yaxis.bottom);
ctx.stroke();
}
}
}
});
Update...
altho the darw is incorrect it still is playing after animation
var verticalLinePlugin = {
renderVerticalLine: function (chartInstance) {
var chart = chartInstance;
var ctx = chart.chart.ctx;
var maxpoint = [];
//loop the datasets
for (var y = 0; y < chart.config.data.datasets.length; y++) {
var dataset = chart.config.data.datasets[y];
if (dataset.hidden)
continue;
var points = chart.getDatasetMeta(y).data;
for (var i = 0; i < points.length; i++) {
var point_y = points[i]._model.y;
if (point_y < 0)
continue;
var point = maxpoint[i];
if (point == undefined) {
maxpoint.push({ id: i, y: point_y });
} else {
if (point.y > point_y) {
point.y = point_y;
}
}
}
}
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-1']
chart.data.datasets.forEach(function (dataset, i) {
var ds = dataset;
var meta = chart.getDatasetMeta(i);
meta.data.forEach(function (element, index) {
var value = maxpoint[i];
ctx.beginPath();
ctx.setLineDash([5, 5]);
ctx.moveTo(xaxis.getPixelForValue(undefined, i), value.y);
ctx.strokeStyle = '#fff';
ctx.lineTo(xaxis.getPixelForValue(undefined, i), yaxis.bottom);
ctx.stroke();
});
});
},
afterRender: function (chart) {
this.renderVerticalLine(chart);
}
};
Chart.plugins.register(verticalLinePlugin);
I made some small changes (non-intuitive!), and the vertical lines now appear after the animation.
Get the x values from the metadata instead of the data.
Either:
var x_point = element._model.x;
or:
var position = element.tooltipPosition();
var x_point = position.x;
Wrap the drawing in if(!hidden){}, then the vertical lines will disapear and reappear with the data. (The ternary assignment fixes a clash if the data starts hidden)
Do you need the value=max[i]? If just drawing the line up to the points, can get the y_point the same as for x.
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-1'];
chart.data.datasets.forEach(function (dataset, i) {
var meta = chart.getDatasetMeta(i);
var hidden = (meta.hidden != undefined) ? meta.hidden : dataset.hidden
if(!hidden){
meta.data.forEach(function (element, index) {
//var value = maxpoint[i];
var x_point = element._model.x;
var y_point = element._model.y;
ctx.beginPath();
ctx.save();
ctx.setLineDash([5, 5])
ctx.strokeStyle = '#fff';
ctx.moveTo(x_point, y_point); // or value.y
ctx.lineTo(x_point, yaxis.bottom)
ctx.stroke();
ctx.restore();
});
}
});
I have a method to skip to the next list item, which works fine, but the method to display the previous list item doesn't seem to re-render.
When I print to console, the list item index it goes down by 1, but the text widget doesn't update like it does when it increases by 1.
I have shown the 2x methods below and an excerpt from the build. Help! :)
void _skipFlashcard () {
setState(() {
int currentIndex = allFlashcards.indexOf(widget.flashcardToShow);
var nextFlashcard = allFlashcards[currentIndex + 1];
widget.flashcardToShow = nextFlashcard;
print(widget.flashcardToShow.flashcardId);
});
}
void _previousFlashcard () {
int currentIndex = allFlashcards.indexOf(widget.flashcardToShow);
var previousFlashcard = allFlashcards[currentIndex - 1];
widget.flashcardToShow = previousFlashcard;
print(widget.flashcardToShow.flashcardId);
}
-------------------------
Container(
child: Row(
children: <Widget>[
Text(widget.flashcardToShow.flashcardId.toString()),
Wrap your code in setState, that's all that is missed :-)
void _previousFlashcard () {
setState() {
int currentIndex = allFlashcards.indexOf(widget.flashcardToShow);
var previousFlashcard = allFlashcards[currentIndex - 1];
widget.flashcardToShow = previousFlashcard;
print(widget.flashcardToShow.flashcardId);
}
}
If I have some bodies that are repulsed and also have a distance. Right now they bounce back and forth endlessly. Is there a way to add a resistance to the physics engine so that they may come to rest?
var context = Engine.createContext();
var contextSize = context.getSize();
var handler = new EventHandler();
var physicsEngine = new PhysicsEngine();
function addBall(color, i) {
var ball = new Surface ({
size: [50,50],
properties: {
backgroundColor: color,
borderRadius: '100px'
}
});
ball.state = new StateModifier({origin:[0.5,0.5]});
ball.particle = new Circle({radius:50, mass: 20 + i * 1});
return ball;
}
var leftWall = new Wall({normal : [1,0,0], distance : contextSize[0]/2.0, restitution : 0.7});
var rightWall = new Wall({normal : [-1,0,0], distance : contextSize[0]/2.0, restitution : 0.7});
var topWall = new Wall({normal : [0,1,0], distance : contextSize[1]/2.0, restitution : 0.7});
var bottomWall = new Wall({normal : [0,-1,0], distance : contextSize[1]/2.0, restitution : 0.7});
var walls = [leftWall,rightWall,bottomWall,topWall];
var bodies = [];
_.each(['yellow', 'blue','green', 'red', 'orange', 'purple','gray', 'black'],function(color, index) {
var body = addBall(color, index);
bodies.push(body);
});
_.each(bodies, function (body) {
physicsEngine.addBody(body.particle);
context.add(body.state).add(body);
});
var particles = _.map(bodies, function(body){
return body.particle;
});
_.each(particles, function(particle, index){
var r = new Repulsion({strength: 61});
var d = new Distance({length: 80, minLength: 0});
physicsEngine.attach(r, [particles[(index + 4) % 8]], particle);
physicsEngine.attach(r, [particle], particles[(index + 4) % 8]);
physicsEngine.attach(d, [particles[(index + 1) % 8]], particle);
if (index == 0) {
physicsEngine.attach(d, [particle], particles[7]);
} else {
physicsEngine.attach(d, [particle], particles[(index - 1) % 8]);
}
particle.setVelocity([0.004101*index,0.004101*index,0 ]);
});
_.each(walls, function(wall) {
physicsEngine.attach(wall);
});
Engine.on('prerender', function(){
_.each(bodies, function(body) {
body.state.setTransform(body.particle.getTransform());
});
});
I was looking for Drag!
var drag = new Drag({strength: 0.1})
physicsEngine.attach(drag, [particle]);
Sorry if this is a newbie question but I have just started using cocos2d-html and I am having some issues creating a ccmenu with an image. Here is my code:
var ActionLayer = cc.Layer.extend({
getTexture: function (name) {
return cc.TextureCache.getInstance()
.addImage('./images/' + name + '.png');
},
addObject: function (desc) {
var sprite = cc.Sprite.createWithTexture(this.getTexture(desc.name));
sprite.setAnchorPoint(desc.anchor || cc.p(0.5, 0.5));
sprite.setScaleX(desc.scaleX || desc.scale || 1);
sprite.setScaleY(desc.scaleY || desc.scale || 1);
sprite.setRotation(desc.rotation || 0);
sprite.setPosition(cc.p(desc.x || 0, desc.y || 0));
this.addChild(sprite, desc.z || 0);
return sprite;
},
checkAnswer:function(){
alert('yay');
},
init: function () {
this._super();
this.removeAllChildrenWithCleanup(true);
this.setTouchEnabled(true);
var layer1 = cc.LayerColor.create(
new cc.Color4B(00, 185, 214, 255), 1024, 768);
layer1.setPosition(new cc.Point(0.0,0.0));
this.addChild(layer1,-2);
var director = cc.Director.getInstance(),
self = this,
winSize = director.getWinSize();
var bgSprite = this.addObject({
name: "GenericBG",
scaleY: 1,
anchor: cc.p(0, 0),
z: 0
});
var closeItem = cc.MenuItemImage.create('./images/sign.png','./images/sign.png',this,'checkAnswer');
closeItem.setAnchorPoint(cc.p(0.5, 0.5));
var menu = cc.Menu.create(closeItem);
menu.setPosition(500,300);
this.addChild(menu, 5);
}
}); //end ActionLayer
//--------------------- Scene ---------------------
var ActionLayerScene = cc.Scene.extend({
onEnter: function () {
this._super();
var layer = new ActionLayer();
layer.init();
this.addChild(layer);
}
});
The menu is displayed on the screen but when I click on the menuitem, nothing happens
There is no javascript error on the console so I really don't know how to debug this.
Thanks
Cyril
Your parameter for cc.MenuItemImage.create() is wrong. Instead of:
var closeItem = cc.MenuItemImage.create('./images/sign.png','./images/sign.png',this,'checkAnswer');
it should be:
var closeItem = cc.MenuItemImage.create('./images/sign.png','./images/sign.png','checkAnswer', this);
for(var i=0; i<5; i++){
var colorImg = cc.MenuItemImage.create(color_list[i], color_list[i], "colorAction", this);
colorImg.setPosition(new cc.Point(40+i*70, 38));
colorImg.tag = i+100;
this.colorImageArray.push(colorImg);
colorMenu.addChild(colorImg);
}
colorAction:function(event)
{
var colorTag = event.tag;
switch(colorTag)
{
case 1:
break;
case 2:
break;
case 3:
break;
}
}