Skip to content

Commit 28f81a0

Browse files
committed
Add difficulty indicator
1 parent 14460f4 commit 28f81a0

File tree

1 file changed

+69
-5
lines changed

1 file changed

+69
-5
lines changed

lib/screens/main/textInputBox.dart

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:math';
2+
13
import 'package:flutter/gestures.dart';
24
import 'package:flutter/material.dart';
35
import 'package:typetypego/config/config.dart';
@@ -69,7 +71,7 @@ class TextInputBox extends StatelessWidget {
6971
}
7072

7173
/// The text field displayed in the [TextInputBox].
72-
class TextInputBoxTextField extends StatelessWidget {
74+
class TextInputBoxTextField extends StatefulWidget {
7375
final TextEditingController? controller;
7476
final FocusNode focusNode;
7577
final GlobalKey formKey;
@@ -81,15 +83,75 @@ class TextInputBoxTextField extends StatelessWidget {
8183
required this.formKey,
8284
required this.maxWordLength});
8385

86+
@override
87+
_TextInputBoxTextFieldState createState() => _TextInputBoxTextFieldState();
88+
}
89+
90+
class _TextInputBoxTextFieldState extends State<TextInputBoxTextField> {
91+
String _value = "";
92+
String _difficulty = "VERY EASY";
93+
94+
/// Calculates the difficulty of the [value] and updates [_value] and [_difficulty] accordingly.
95+
void _updateDifficulty(String value) {
96+
setState(() {
97+
final String trimmedValue = value.trim();
98+
_value = trimmedValue;
99+
100+
// Set the difficuly text to "VERY EASY" is the textbox is empty.
101+
if (trimmedValue.isEmpty)
102+
_difficulty = "VERY EASY";
103+
104+
// True if the textbox is not empty.
105+
else {
106+
// Create a list of all the easy characters.
107+
final List<String> easyCharacters =
108+
"abcdefghijklmnopqrstuvwxyz".split("")..addAll([" ", "\n"]);
109+
110+
double difficultyPoints = 0;
111+
112+
// Loop through the text in the textbox.
113+
trimmedValue.split("").forEach((String element) {
114+
// True if the character is not easy.
115+
if (!easyCharacters.contains(element)) {
116+
// Add 0.25 to difficultPoints if the character is a capital letter.
117+
if (easyCharacters.contains(element.toLowerCase()))
118+
difficultyPoints += 0.25;
119+
// Add 0.5 to difficultPoints if the character is a number.
120+
else if (double.tryParse(element) != null)
121+
difficultyPoints += 0.5;
122+
// Add 1 to difficultPoints if the character is a anything else, e.g. !, :, #,...
123+
else
124+
difficultyPoints++;
125+
}
126+
});
127+
128+
// Calculate the difficulty by dividing the points by the square root of the length of text.
129+
final double difficulty = difficultyPoints / sqrt(trimmedValue.length);
130+
131+
// Update the difficuly text according to the calculated difficulty.
132+
if (difficultyPoints < 0.75)
133+
_difficulty = "VERY EASY";
134+
else if (difficulty < 1)
135+
_difficulty = "EASY";
136+
else if (difficulty < 1.25)
137+
_difficulty = "MEDIUM";
138+
else if (difficulty < 1.5)
139+
_difficulty = "HARD";
140+
else
141+
_difficulty = "VERY HARD";
142+
}
143+
});
144+
}
145+
84146
@override
85147
Widget build(BuildContext context) {
86148
return Form(
87-
key: formKey,
149+
key: widget.formKey,
88150
child: SizedBox(
89151
height: 200,
90152
child: TextFormField(
91-
controller: controller,
92-
focusNode: focusNode,
153+
controller: widget.controller,
154+
focusNode: widget.focusNode,
93155
validator: (value) {
94156
final String trimmedValue = value!.trim();
95157
// True if the text field is empty.
@@ -104,11 +166,12 @@ class TextInputBoxTextField extends StatelessWidget {
104166
.reduce((value, element) =>
105167
value.length > element.length ? value : element)
106168
.length >
107-
maxWordLength) {
169+
widget.maxWordLength) {
108170
return 'A word is too long (try making your window bigger)';
109171
}
110172
return null;
111173
},
174+
onChanged: _updateDifficulty,
112175
maxLines: null,
113176
minLines: null,
114177
expands: true,
@@ -123,6 +186,7 @@ class TextInputBoxTextField extends StatelessWidget {
123186
color: Palette.blueGrey.withOpacity(0.5), fontSize: 16),
124187
errorStyle: TextStyle(color: Palette.red, fontSize: 16),
125188
counterStyle: TextStyle(color: Palette.blueGrey, fontSize: 16),
189+
counterText: "Difficulty: $_difficulty - ${_value.length}/1000",
126190
border: OutlineInputBorder(
127191
borderRadius: BorderRadius.circular(Config.borderRadius)),
128192
errorBorder: OutlineInputBorder(

0 commit comments

Comments
 (0)