1
1
pub mod typing {
2
- use rand_word;
3
2
use ratatui:: {
4
3
style:: { Color , Style } ,
5
4
text:: Span ,
6
5
} ;
7
- use std:: time:: SystemTime ;
6
+ use std:: { collections :: HashSet , time:: SystemTime } ;
8
7
9
8
#[ derive( Debug ) ]
10
9
pub struct TypingGame {
@@ -13,51 +12,69 @@ pub mod typing {
13
12
pub start_time : Option < SystemTime > ,
14
13
pub end_time : Option < SystemTime > ,
15
14
pub word_count : usize ,
15
+ pub mistakes : u32 ,
16
+ pub mistake_indices : HashSet < usize > ,
16
17
}
17
18
18
19
impl TypingGame {
19
20
pub fn new ( words : usize ) -> Self {
20
21
let mut goal = rand_word:: new ( words) ;
22
+ let cap = goal. len ( ) ;
23
+
21
24
while goal. contains ( "º" ) {
22
25
goal = rand_word:: new ( words) ;
23
26
}
27
+
24
28
TypingGame {
25
29
goal,
26
30
current : "" . to_string ( ) ,
27
31
start_time : None ,
28
32
end_time : None ,
29
33
word_count : words,
34
+ mistakes : 0 ,
35
+ mistake_indices : HashSet :: with_capacity ( cap) ,
30
36
}
31
37
}
32
38
33
39
pub fn reset ( & mut self ) {
34
40
self . current = "" . to_string ( ) ;
35
41
self . start_time = None ;
42
+
43
+ self . mistake_indices . clear ( ) ;
44
+ self . mistakes = 0 ;
36
45
}
37
46
38
47
pub fn new_goal ( & mut self ) {
39
48
self . goal = TypingGame :: new ( self . word_count ) . goal ;
40
49
}
41
50
42
- pub fn accuracy ( & self ) -> f64 {
51
+ pub fn accuracy ( & mut self ) -> f32 {
43
52
let mut correct_count = 0 ;
44
53
let goal_chars = self . goal . chars ( ) . collect :: < Vec < char > > ( ) ;
45
54
46
55
for ( i, ch) in self . current . char_indices ( ) {
47
56
if goal_chars[ i] == ch {
48
57
correct_count += 1 ;
58
+ } else if !self . mistake_indices . contains ( & i) {
59
+ self . mistakes += 1 ;
60
+ self . mistake_indices . insert ( i) ;
49
61
}
50
62
}
51
- correct_count as f64 * 100f64 / self . current . len ( ) as f64
63
+
64
+ let correct = u32:: checked_sub ( correct_count, self . mistakes ) . unwrap_or ( 0 ) ;
65
+
66
+ // average correctly typed characters + correct but PREVIOUSLY incorrect characters
67
+ // then change it into a percentage
68
+ ( ( correct + correct_count) as f32 / 2f32 * 100f32 ) as f32 / self . current . len ( ) as f32
52
69
}
53
70
54
- pub fn wpm ( & self ) -> f64 {
55
- self . current . split_whitespace ( ) . count ( ) as f64
71
+ pub fn wpm ( & self ) -> f32 {
72
+ self . current . split_whitespace ( ) . count ( ) as f32
56
73
/ ( SystemTime :: now ( )
57
74
. duration_since ( self . start_time . unwrap ( ) )
58
75
. unwrap ( )
59
- . as_secs_f64 ( )
60
- / 60f64 )
76
+ . as_secs_f32 ( )
77
+ / 60f32 )
61
78
}
62
79
63
80
pub fn curr_spans ( & self ) -> Vec < Span > {
0 commit comments