finished
parent
3a3b7841a6
commit
13d3a48d06
|
@ -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>
|
|
@ -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:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -36,7 +36,7 @@ class EnergyCalculation extends StatelessWidget {
|
|||
create: (context) => EnergyModel(),
|
||||
child: Column(
|
||||
children: const [
|
||||
InputCardWidget(),
|
||||
InputWidget(),
|
||||
OutputCardWidget(),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,18 +1,64 @@
|
|||
import 'package:cpd_2022_energy/widgets/input_card_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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(),
|
||||
],
|
||||
))
|
||||
]));
|
||||
}
|
||||
}
|
|
@ -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'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -9,10 +9,10 @@ class OutputCardWidget extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return Consumer<EnergyModel>(
|
||||
builder: (context, model, child) => Card(
|
||||
child: Column(children: const <Widget>[
|
||||
Text('Joule:'),
|
||||
Text('Water:'),
|
||||
Text('Iron'),
|
||||
child: Column(children: <Widget>[
|
||||
Text("Energy in Kilo Joule: ${model.totalEnergy.toStringAsFixed(2)}"),
|
||||
Text('Water in Liter: ${model.boilingWaterAmount.toStringAsFixed(2)}'),
|
||||
Text('Iron in Kilogram: ${model.annealingIronAmount.toStringAsFixed(2)}'),
|
||||
])));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,30 +1,55 @@
|
|||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// 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:cpd_2022_energy/provider/energy_model.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:cpd_2022_energy/energy_app.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const EnergyCalculationApp());
|
||||
EnergyModel model = EnergyModel();
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
const double heightStart = 50.0;
|
||||
const double heightEnd = 10.0;
|
||||
const double velocityStart = 0.0;
|
||||
const double velocityEnd = 40.0;
|
||||
const double weight = 777.0;
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
group('Test Energy Model', () {
|
||||
test('Set Values', () {
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue