main
Vicctic 2023-02-06 03:12:39 +01:00
parent 3a3b7841a6
commit 13d3a48d06
11 changed files with 237 additions and 191 deletions

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,4 +1,4 @@
import 'package:cpd_2022_energy/widgets/input_card_widget.dart'; import 'package:cpd_2022_energy/widgets/input_widget.dart';
import 'package:cpd_2022_energy/widgets/output_card_widget.dart'; import 'package:cpd_2022_energy/widgets/output_card_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -36,7 +36,7 @@ class EnergyCalculation extends StatelessWidget {
create: (context) => EnergyModel(), create: (context) => EnergyModel(),
child: Column( child: Column(
children: const [ children: const [
InputCardWidget(), InputWidget(),
OutputCardWidget(), OutputCardWidget(),
], ],
), ),

View File

@ -1,18 +1,64 @@
import 'package:cpd_2022_energy/widgets/input_card_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class EnergyModel with ChangeNotifier { class EnergyModel with ChangeNotifier {
final double weightForce = 9.81;
final double _waterStartTemp = 20.0;
final double _waterEndTemp = 100.0;
final double _waterHeatCapacity = 4.183;
final double _ironStartTemp = 20.0;
final double _ironEndTemp = 700.0;
final double _ironHeatCapacity = 0.444;
double heightStart = 0.0;
double heightEnd = 0.0;
double velocityStart = 0.0;
double velocityEnd = 0.0;
double weight = 0.0;
calculateJoule(InputCardWidget value) { double totalEnergy = 0.0;
double boilingWaterAmount = 0.0;
double annealingIronAmount = 0.0;
double calcPotentialEnergy(m, g, h) {
return m * g * h;
} }
calculateBoiledWater() { double calcPotentialEnergyBetweenTwoPointsInJoule(
heightStart, heightEnd, weight) {
return calcPotentialEnergy(weight, weightForce, heightStart) -
calcPotentialEnergy(weight, weightForce, heightEnd);
} }
calculateGlowedIron() { double calcKineticEnergy(m, v) {
return (m * v * v) / 2.0;
} }
}
double calcKineticEnergyBetweenTwoPointsInJoule(
velocityStart, velocityEnd, weight) {
return calcKineticEnergy(weight, velocityEnd) -
calcKineticEnergy(weight, velocityStart);
}
void calcBoilingWaterAmount() {
boilingWaterAmount = (totalEnergy /
(_waterHeatCapacity * (_waterEndTemp - _waterStartTemp)));
}
void calcIronAnnealingAmount() {
annealingIronAmount =
(totalEnergy / (_ironHeatCapacity * (_ironEndTemp - _ironStartTemp)));
}
void calcTotalEnergyInKiloJoule() {
totalEnergy = (calcKineticEnergyBetweenTwoPointsInJoule(velocityStart, velocityEnd, weight) +
calcPotentialEnergyBetweenTwoPointsInJoule(heightStart, heightEnd, weight))
/1000;
}
void calc() {
calcTotalEnergyInKiloJoule();
calcBoilingWaterAmount();
calcIronAnnealingAmount();
notifyListeners();
}
}

View File

@ -1,41 +0,0 @@
import 'package:flutter/material.dart';
class HeightWidget extends StatelessWidget {
const HeightWidget({super.key});
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: <Widget>[
const Text('Height'),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the height of the starting point (in m)',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Invalid input. Please enter the height of the starting point (in m)';
}
return null;
},
),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the height of the ending point (in m)',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Invalid input. Please enter the height of the ending point (in m)';
}
return null;
},
),
],
),
);
}
}

View File

@ -1,26 +0,0 @@
import 'package:cpd_2022_energy/widgets/submit_button_widget.dart';
import 'package:cpd_2022_energy/widgets/velocity_widget.dart';
import 'package:cpd_2022_energy/widgets/weight_widget.dart';
import 'package:cpd_2022_energy/widgets/height_widget.dart';
import 'package:flutter/material.dart';
class InputCardWidget extends StatelessWidget {
const InputCardWidget({super.key});
@override
Widget build(BuildContext context) {
return Card(
child: Column(children: <Widget>[
Form(
child: Column(
children: [
VelocityWidget(),
HeightWidget(),
WeightWidget(),
SubmitButtonWidget(),
],
))
]));
}
}

View File

@ -0,0 +1,113 @@
import 'package:cpd_2022_energy/provider/energy_model.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class InputWidget extends StatelessWidget {
const InputWidget({super.key});
@override
Widget build(BuildContext context) {
var heightStartInputController = TextEditingController();
var heightEndInputController = TextEditingController();
var velocityStartInputController = TextEditingController();
var velocityEndInputController = TextEditingController();
var weightInputController = TextEditingController();
final ButtonStyle style =
ElevatedButton.styleFrom(textStyle: const TextStyle(fontSize: 20));
final formKey = GlobalKey<FormState>();
final energyModel = Provider.of<EnergyModel>(context, listen: false);
void onSubmitButtonClick() {
if (formKey.currentState!.validate() == false) return;
energyModel.heightStart = double.parse(heightStartInputController.text);
energyModel.heightEnd = double.parse(heightEndInputController.text);
energyModel.velocityStart = double.parse(velocityStartInputController.text);
energyModel.velocityEnd = double.parse(velocityEndInputController.text);
energyModel.weight = double.parse(weightInputController.text);
energyModel.calc();
}
bool isNumeric(String s) {
return double.tryParse(s) != null;
}
return Form(
key: formKey,
child: Column(
children: <Widget>[
const Text('Height'),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the height of the starting point (in m)',
),
validator: (String? value) {
if (value == null || value.isEmpty || !isNumeric(value)) {
return 'Invalid input. Please enter the height of the starting point (in m)';
}
return null;
},
controller: heightStartInputController,
),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the height of the ending point (in m)',
),
validator: (String? value) {
if (value == null || value.isEmpty || !isNumeric(value)) {
return 'Invalid input. Please enter the height of the ending point (in m)';
}
return null;
},
controller: heightEndInputController,
),
const Text('Velocity'),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the velocity of the starting point (in s)',
),
validator: (String? value) {
if (value == null || value.isEmpty || !isNumeric(value)) {
return 'Invalid input. Please enter the velocity of the starting point (in s)';
}
return null;
},
controller: velocityStartInputController,
),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the velocity of the ending point (in s)',
),
validator: (String? value) {
if (value == null || value.isEmpty || !isNumeric(value)) {
return 'Invalid input. Please enter the velocity of the ending point (in s)';
}
return null;
},
controller: velocityEndInputController,
),
const Text('Weight'),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the weight in kg',
),
validator: (String? value) {
if (value == null || value.isEmpty || !isNumeric(value)) {
return 'Invalid input. Please enter the weight (in kg)';
}
return null;
},
controller: weightInputController,
),
ElevatedButton(
style: style,
onPressed: onSubmitButtonClick,
child: const Text('Calculate Energy'),
),
],
),
);
}
}

View File

@ -9,10 +9,10 @@ class OutputCardWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<EnergyModel>( return Consumer<EnergyModel>(
builder: (context, model, child) => Card( builder: (context, model, child) => Card(
child: Column(children: const <Widget>[ child: Column(children: <Widget>[
Text('Joule:'), Text("Energy in Kilo Joule: ${model.totalEnergy.toStringAsFixed(2)}"),
Text('Water:'), Text('Water in Liter: ${model.boilingWaterAmount.toStringAsFixed(2)}'),
Text('Iron'), Text('Iron in Kilogram: ${model.annealingIronAmount.toStringAsFixed(2)}'),
]))); ])));
} }
} }

View File

@ -1,26 +0,0 @@
import 'package:flutter/material.dart';
import 'input_card_widget.dart';
class SubmitButtonWidget extends StatelessWidget {
const SubmitButtonWidget({super.key});
@override
Widget build(BuildContext context) {
final ButtonStyle style =
ElevatedButton.styleFrom(textStyle: const TextStyle(fontSize: 20));
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ElevatedButton(
style: style,
onPressed: () {},
child: const Text('Calculate Energy'),
),
],
),
);
}
}

View File

@ -1,36 +0,0 @@
import 'package:flutter/material.dart';
class VelocityWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: <Widget>[
const Text('Velocity'),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the velocity of the starting point (in s)',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Invalid input. Please enter the velocity of the starting point (in s)';
}
return null;
},
),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the velocity of the ending point (in s)',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Invalid input. Please enter the velocity of the ending point (in s)';
}
return null;
},
),
],
),
);
}
}

View File

@ -1,27 +0,0 @@
import 'package:flutter/material.dart';
class WeightWidget extends StatelessWidget {
const WeightWidget({super.key});
@override
Widget build(BuildContext context) {
return Form(
child: Column(
children: <Widget>[
const Text('Weight'),
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter the weight in kg',
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Invalid input. Please enter the weight (in kg)';
}
return null;
},
),
],
),
);
}
}

View File

@ -1,30 +1,55 @@
// This is a basic Flutter widget test. import 'package:cpd_2022_energy/provider/energy_model.dart';
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:cpd_2022_energy/energy_app.dart';
void main() { void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async { EnergyModel model = EnergyModel();
// Build our app and trigger a frame.
await tester.pumpWidget(const EnergyCalculationApp());
// Verify that our counter starts at 0. const double heightStart = 50.0;
expect(find.text('0'), findsOneWidget); const double heightEnd = 10.0;
expect(find.text('1'), findsNothing); const double velocityStart = 0.0;
const double velocityEnd = 40.0;
const double weight = 777.0;
// Tap the '+' icon and trigger a frame. group('Test Energy Model', () {
await tester.tap(find.byIcon(Icons.add)); test('Set Values', () {
await tester.pump(); model.heightStart = heightStart;
model.heightEnd = heightEnd;
model.velocityStart = velocityStart;
model.velocityEnd = velocityEnd;
model.weight = weight;
expect(heightStart, model.heightStart);
expect(heightEnd, model.heightEnd);
expect(velocityStart, model.velocityStart);
expect(velocityEnd, model.velocityEnd);
expect(weight, model.weight);
});
test('Calculate Potential Energy', () {
expect(double.parse(model.calcPotentialEnergy(model.weight, model.weightForce, model.heightStart).toStringAsFixed(2)), 381118.5);
expect(double.parse(model.calcPotentialEnergy(model.weight, model.weightForce, model.heightEnd).toStringAsFixed(2)), 76223.70);
});
test('Calculate Potential Energy between two point in Joule', () {
expect(double.parse(model.calcPotentialEnergyBetweenTwoPointsInJoule(model.heightStart, model.heightEnd, model.weight).toStringAsFixed(2)), 304894.8);
});
test('Calculate Kinetic Energy', () {
expect(double.parse(model.calcKineticEnergy(model.weight, model.velocityStart).toStringAsFixed(2)), 0);
expect(double.parse(model.calcKineticEnergy(model.weight, model.velocityEnd).toStringAsFixed(2)), 621600.0);
});
test('Calculate Kinetic Energy between two points in Joule', () {
expect(double.parse(model.calcKineticEnergyBetweenTwoPointsInJoule(model.velocityStart, model.velocityEnd, model.weight).toStringAsFixed(2)), 621600.0);
});
test('Calculate total energy in Kilo Joule', () {
model.calcTotalEnergyInKiloJoule();
expect(double.parse(model.totalEnergy.toStringAsFixed(2)), 926.49);
});
test('Calculate amount of boiling water', () {
model.calcBoilingWaterAmount();
expect(double.parse(model.boilingWaterAmount.toStringAsFixed(2)), 2.77);
});
test('Calculate amount of annealing iron', () {
model.calcIronAnnealingAmount();
expect(double.parse(model.annealingIronAmount.toStringAsFixed(2)), 3.07);
// Verify that our counter has incremented. });
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
}); });
} }