@@ -32,6 +32,10 @@ impl ToipeResults {
32
32
33
33
/// Percentage of letters that were typed correctly.
34
34
pub fn accuracy ( & self ) -> f64 {
35
+ if self . total_chars_typed == 0 {
36
+ return 0.0 ;
37
+ }
38
+
35
39
( self . total_chars_typed as isize - self . total_char_errors as isize ) as f64
36
40
/ self . total_chars_typed as f64
37
41
}
@@ -51,3 +55,150 @@ impl ToipeResults {
51
55
/ ( self . duration ( ) . as_secs_f64 ( ) / 60.0 )
52
56
}
53
57
}
58
+
59
+ #[ cfg( test) ]
60
+ mod tests {
61
+ use super :: * ;
62
+ use approx:: assert_ulps_eq;
63
+
64
+ #[ test]
65
+ fn sanity ( ) {
66
+ let started_at = Instant :: now ( ) ;
67
+ let ended_at = started_at + Duration :: new ( 10 , 0 ) ;
68
+ let results = ToipeResults {
69
+ total_words : 0 ,
70
+ total_chars_typed : 100 ,
71
+ total_chars_in_text : 120 ,
72
+ total_char_errors : 10 ,
73
+ final_chars_typed_correctly : 80 ,
74
+ final_uncorrected_errors : 2 ,
75
+ started_at,
76
+ ended_at,
77
+ } ;
78
+
79
+ assert_eq ! ( results. duration( ) , Duration :: new( 10 , 0 ) ) ;
80
+
81
+ assert_ulps_eq ! ( results. accuracy( ) , 0.9 , max_ulps = 1 ) ;
82
+ assert_ulps_eq ! ( results. wpm( ) , 84.0 , max_ulps = 1 ) ;
83
+ }
84
+
85
+ #[ test]
86
+ fn accuracy ( ) {
87
+ fn get_toipe_results ( total_chars_typed : usize , total_char_errors : usize ) -> ToipeResults {
88
+ ToipeResults {
89
+ total_words : 0 ,
90
+ total_chars_typed,
91
+ total_chars_in_text : 0 ,
92
+ total_char_errors,
93
+ final_chars_typed_correctly : 0 ,
94
+ final_uncorrected_errors : 0 ,
95
+ started_at : Instant :: now ( ) ,
96
+ ended_at : Instant :: now ( ) ,
97
+ }
98
+ }
99
+
100
+ let max_ulps = 1 ;
101
+
102
+ // no errors
103
+ assert_ulps_eq ! (
104
+ get_toipe_results( 100 , 0 ) . accuracy( ) ,
105
+ 1.0 ,
106
+ max_ulps = max_ulps
107
+ ) ;
108
+ // nothing typed
109
+ assert_ulps_eq ! ( get_toipe_results( 0 , 0 ) . accuracy( ) , 0.0 , max_ulps = max_ulps) ;
110
+ // all wrong
111
+ assert_ulps_eq ! (
112
+ get_toipe_results( 100 , 100 ) . accuracy( ) ,
113
+ 0.0 ,
114
+ max_ulps = max_ulps
115
+ ) ;
116
+ // half correct
117
+ assert_ulps_eq ! (
118
+ get_toipe_results( 100 , 50 ) . accuracy( ) ,
119
+ 0.5 ,
120
+ max_ulps = max_ulps
121
+ ) ;
122
+ // more errors than correct
123
+ assert_ulps_eq ! (
124
+ get_toipe_results( 100 , 150 ) . accuracy( ) ,
125
+ -0.5 ,
126
+ max_ulps = max_ulps
127
+ ) ;
128
+ }
129
+
130
+ #[ test]
131
+ fn wpm ( ) {
132
+ fn get_toipe_results (
133
+ final_chars_typed_correctly : usize ,
134
+ final_uncorrected_errors : usize ,
135
+ duration : f64 ,
136
+ ) -> ToipeResults {
137
+ let started_at = Instant :: now ( ) ;
138
+ let seconds = duration. round ( ) ;
139
+ let nanoseconds = ( duration - seconds) * 1_000_000_000.0 ;
140
+ let ended_at = started_at + Duration :: new ( seconds as u64 , nanoseconds as u32 ) ;
141
+ ToipeResults {
142
+ total_words : 0 ,
143
+ total_chars_typed : 0 ,
144
+ total_chars_in_text : 0 ,
145
+ total_char_errors : 0 ,
146
+ final_chars_typed_correctly,
147
+ final_uncorrected_errors,
148
+ started_at,
149
+ ended_at,
150
+ }
151
+ }
152
+
153
+ let max_ulps = 1 ;
154
+ assert_ulps_eq ! (
155
+ get_toipe_results( 100 , 5 , 30.0 ) . wpm( ) ,
156
+ 30.0 ,
157
+ max_ulps = max_ulps
158
+ ) ;
159
+ assert_ulps_eq ! (
160
+ get_toipe_results( 1000 , 50 , 30.0 ) . wpm( ) ,
161
+ 300.0 ,
162
+ max_ulps = max_ulps
163
+ ) ;
164
+ assert_ulps_eq ! (
165
+ get_toipe_results( 200 , 0 , 30.0 ) . wpm( ) ,
166
+ 80.0 ,
167
+ max_ulps = max_ulps
168
+ ) ;
169
+ assert_ulps_eq ! (
170
+ get_toipe_results( 200 , 30 , 30.0 ) . wpm( ) ,
171
+ 20.0 ,
172
+ max_ulps = max_ulps
173
+ ) ;
174
+ // too many errors - cancels out
175
+ assert_ulps_eq ! (
176
+ get_toipe_results( 200 , 40 , 30.0 ) . wpm( ) ,
177
+ 0.0 ,
178
+ max_ulps = max_ulps
179
+ ) ;
180
+ // no negative wpms
181
+ assert_ulps_eq ! (
182
+ get_toipe_results( 200 , 50 , 30.0 ) . wpm( ) ,
183
+ 0.0 ,
184
+ max_ulps = max_ulps
185
+ ) ;
186
+ assert_ulps_eq ! (
187
+ get_toipe_results( 1 , 0 , 1.0 ) . wpm( ) ,
188
+ 12.0 ,
189
+ max_ulps = max_ulps
190
+ ) ;
191
+ // skdlhaslkd won't give you any score!
192
+ assert_ulps_eq ! (
193
+ get_toipe_results( 0 , 10 , 1.0 ) . wpm( ) ,
194
+ 0.0 ,
195
+ max_ulps = max_ulps
196
+ ) ;
197
+ assert_ulps_eq ! (
198
+ get_toipe_results( 0 , 0 , 0.01 ) . wpm( ) ,
199
+ 0.0 ,
200
+ max_ulps = max_ulps
201
+ ) ;
202
+ // we don't consider the case of duration = 0 because that seems impossible
203
+ }
204
+ }
0 commit comments