import 'package:filcnaplo_kreta_api/models/grade.dart'; import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_input.dart'; import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner.dart'; import 'package:filcnaplo_premium/ui/mobile/goal_planner/route_option.dart'; import 'package:flutter/material.dart'; enum PlanResult { available, // There are possible solutions unreachable, // The solutions are too hard don't even try unsolvable, // There are no solutions reached, // Goal already reached } class GoalPlannerTest extends StatefulWidget { const GoalPlannerTest({Key? key}) : super(key: key); @override State createState() => _GoalPlannerTestState(); } class _GoalPlannerTestState extends State { double goalValue = 4.0; List grades = []; Plan? recommended; Plan? fastest; Plan? selectedRoute; List otherPlans = []; PlanResult getResult() { final currentAvg = GoalPlannerHelper.averageEvals(grades); recommended = null; fastest = null; otherPlans = []; if (currentAvg >= goalValue) return PlanResult.reached; final planner = GoalPlanner(goalValue, grades); final plans = planner.solve(); plans.sort((a, b) => (a.avg - (2 * goalValue + 5) / 3).abs().compareTo(b.avg - (2 * goalValue + 5) / 3)); try { final singleSolution = plans.every((e) => e.sigma == 0); recommended = plans.where((e) => singleSolution ? true : e.sigma > 0).first; plans.removeWhere((e) => e == recommended); } catch (_) {} plans.sort((a, b) => a.plan.length.compareTo(b.plan.length)); try { fastest = plans.removeAt(0); } catch (_) {} if ((recommended?.plan.length ?? 0) - (fastest?.plan.length ?? 0) >= 3) { recommended = fastest; } if (recommended == null) { recommended = null; fastest = null; otherPlans = []; selectedRoute = null; return PlanResult.unsolvable; } if (recommended!.plan.length > 10) { recommended = null; fastest = null; otherPlans = []; selectedRoute = null; return PlanResult.unreachable; } otherPlans = List.from(plans); return PlanResult.available; } @override Widget build(BuildContext context) { final currentAvg = GoalPlannerHelper.averageEvals(grades); final result = getResult(); return Scaffold( body: SafeArea( child: ListView( padding: const EdgeInsets.all(20.0), children: [ const Align( alignment: Alignment.topLeft, child: BackButton(), ), const SizedBox(height: 12.0), const Text( "Set a goal", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20.0, ), ), const SizedBox(height: 4.0), Text( goalValue.toString(), style: TextStyle( fontWeight: FontWeight.w900, fontSize: 42.0, color: gradeColor(goalValue.round()), ), ), const SizedBox(height: 24.0), const Text( "Pick a route", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20.0, ), ), const SizedBox(height: 12.0), if (recommended != null) RouteOption( plan: recommended!, mark: RouteMark.recommended, selected: selectedRoute == recommended!, onSelected: () => setState(() { selectedRoute = recommended; }), ), if (fastest != null && fastest != recommended) RouteOption( plan: fastest!, mark: RouteMark.fastest, selected: selectedRoute == fastest!, onSelected: () => setState(() { selectedRoute = fastest; }), ), ...otherPlans.map((e) => RouteOption( plan: e, selected: selectedRoute == e, onSelected: () => setState(() { selectedRoute = e; }), )), if (result != PlanResult.available) Text(result.name), ], ), ), bottomSheet: MediaQuery.removePadding( context: context, removeBottom: false, removeTop: true, child: Container( color: Theme.of(context).scaffoldBackgroundColor, child: Container( padding: const EdgeInsets.only(top: 24.0), decoration: BoxDecoration( color: const Color.fromARGB(255, 215, 255, 242), borderRadius: const BorderRadius.vertical(top: Radius.circular(24.0)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(.1), blurRadius: 8.0, ) ]), child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ GoalInput( value: goalValue, currentAverage: currentAvg, onChanged: (v) => setState(() { selectedRoute = null; goalValue = v; }), ), const SizedBox(height: 24.0), SizedBox( width: double.infinity, child: RawMaterialButton( onPressed: () {}, fillColor: const Color(0xff01342D), shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 8.0), child: const Text( "Track it!", style: TextStyle( color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.w600, ), ), ), ) ], ), ), ), ), ), ), ); } }