diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/lib/energy_app.dart b/lib/energy_app.dart index a4e04d1..25310c9 100644 --- a/lib/energy_app.dart +++ b/lib/energy_app.dart @@ -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(), ], ), diff --git a/lib/provider/energy_model.dart b/lib/provider/energy_model.dart index 516630f..fb79b30 100644 --- a/lib/provider/energy_model.dart +++ b/lib/provider/energy_model.dart @@ -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; } -} \ No newline at end of file + + 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(); + } +} diff --git a/lib/widgets/height_widget.dart b/lib/widgets/height_widget.dart deleted file mode 100644 index 1481fcd..0000000 --- a/lib/widgets/height_widget.dart +++ /dev/null @@ -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: [ - 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; - }, - ), - ], - ), - ); - } -} diff --git a/lib/widgets/input_card_widget.dart b/lib/widgets/input_card_widget.dart deleted file mode 100644 index 9e1792c..0000000 --- a/lib/widgets/input_card_widget.dart +++ /dev/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: [ - Form( - child: Column( - children: [ - VelocityWidget(), - HeightWidget(), - WeightWidget(), - SubmitButtonWidget(), - ], - )) - ])); - } -} diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart new file mode 100644 index 0000000..86fdf26 --- /dev/null +++ b/lib/widgets/input_widget.dart @@ -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(); + + final energyModel = Provider.of(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: [ + 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'), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/output_card_widget.dart b/lib/widgets/output_card_widget.dart index cac2b5b..626acd2 100644 --- a/lib/widgets/output_card_widget.dart +++ b/lib/widgets/output_card_widget.dart @@ -9,10 +9,10 @@ class OutputCardWidget extends StatelessWidget { Widget build(BuildContext context) { return Consumer( builder: (context, model, child) => Card( - child: Column(children: const [ - Text('Joule:'), - Text('Water:'), - Text('Iron'), + child: Column(children: [ + 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)}'), ]))); } } diff --git a/lib/widgets/submit_button_widget.dart b/lib/widgets/submit_button_widget.dart deleted file mode 100644 index 3e91245..0000000 --- a/lib/widgets/submit_button_widget.dart +++ /dev/null @@ -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: [ - ElevatedButton( - style: style, - onPressed: () {}, - child: const Text('Calculate Energy'), - ), - ], - ), - ); - } -} diff --git a/lib/widgets/velocity_widget.dart b/lib/widgets/velocity_widget.dart deleted file mode 100644 index 22a92df..0000000 --- a/lib/widgets/velocity_widget.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; - -class VelocityWidget extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Form( - child: Column( - children: [ - 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; - }, - ), - ], - ), - ); - } -} diff --git a/lib/widgets/weight_widget.dart b/lib/widgets/weight_widget.dart deleted file mode 100644 index 1372928..0000000 --- a/lib/widgets/weight_widget.dart +++ /dev/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: [ - 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; - }, - ), - ], - ), - ); - } -} diff --git a/test/widget_test.dart b/test/widget_test.dart index 5190f51..cbe5c42 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -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); + }); }); + }