1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
//! # Gladius - High-Performance Typing Trainer Library
//!
//! Gladius is a comprehensive Rust library for building typing trainer applications.
//! It provides real-time typing analysis, flexible rendering systems, and detailed
//! performance statistics with a focus on accuracy, performance, and ease of use.
//!
//! ## Quick Start
//!
//! ```rust
//! use gladius::TypingSession;
//!
//! // Create a typing session
//! let mut session = TypingSession::new("Hello, world!").unwrap();
//!
//! // Process user input
//! while let Some((char, result)) = session.input(Some('H')) {
//! println!("Typed '{}': {:?}", char, result);
//! break; // Just for demo
//! }
//!
//! // Get progress and statistics
//! println!("Progress: {:.1}%", session.completion_percentage());
//! println!("WPM: {:.1}", session.statistics().measurements.last()
//! .map(|m| m.wpm.raw).unwrap_or(0.0));
//! ```
//!
//! ## Key Features
//!
//! ### ๐ **High Performance**
//! - **Fast character processing** - Amortized O(1) keystroke handling
//! - **O(1) word lookups** - Efficient character-to-word mapping
//! - **Optimized statistics** - Welford's algorithm for numerical stability
//! - **Memory efficient** - Minimal allocations during typing
//!
//! ### ๐ **Comprehensive Statistics**
//! - **Words per minute** (raw, corrected, actual)
//! - **Input per minute** (raw, actual)
//! - **Accuracy percentages** (raw, actual)
//! - **Consistency analysis** with standard deviation
//! - **Detailed error tracking** by character and word
//! - **Real-time measurements** at configurable intervals
//!
//! ### ๐ฏ **Flexible Rendering**
//! - **Character-level rendering** with typing state information
//! - **Line-based rendering** with intelligent word wrapping
//! - **Cursor position tracking** across line boundaries
//! - **Unicode support** for international characters and emojis
//! - **Generic renderer interface** for any UI framework
//!
//! ### โ๏ธ **Configurable Behavior**
//! - **Measurement intervals** for statistics collection
//! - **Line wrapping options** (word boundaries vs. character wrapping)
//! - **Newline handling** (respect or ignore paragraph breaks)
//! - **Performance tuning** for different use cases
//!
//! ## Architecture Overview
//!
//! Gladius is built with a modular architecture where each component has a specific responsibility:
//!
//!
//! ## Core Modules
//!
//! | Module | Purpose | Key Types |
//! |--------|---------|-----------|
//! | [`session`] | Session coordination and main API | [`TypingSession`] |
//! | [`buffer`] | Text storage and word/character management | [`Buffer`](buffer::Buffer) |
//! | [`input_handler`] | Keystroke processing and validation | [`InputHandler`](input_handler::InputHandler) |
//! | [`statistics`] | Performance data collection and analysis | [`Statistics`](statistics::Statistics), [`TempStatistics`](statistics::TempStatistics) |
//! | [`statistics_tracker`] | Real-time statistics coordination | [`StatisticsTracker`](statistics_tracker::StatisticsTracker) |
//! | [`render`] | Text display and line management | [`RenderingContext`](render::RenderingContext), [`LineContext`](render::LineContext) |
//! | [`math`] | Performance calculation algorithms | [`Wpm`](math::Wpm), [`Accuracy`](math::Accuracy), [`Consistency`](math::Consistency) |
//! | [`config`] | Runtime behavior configuration | [`Configuration`](config::Configuration) |
//!
//! ## Usage Examples
//!
//! ### Basic Typing Session
//!
//! ```rust
//! use gladius::TypingSession;
//! use gladius::CharacterResult;
//!
//! let mut session = TypingSession::new("The quick brown fox").unwrap();
//!
//! // Process typing input
//! match session.input(Some('T')) {
//! Some((ch, CharacterResult::Correct)) => println!("Correct: {}", ch),
//! Some((ch, CharacterResult::Wrong)) => println!("Wrong: {}", ch),
//! Some((ch, CharacterResult::Corrected)) => println!("Corrected: {}", ch),
//! Some((ch, CharacterResult::Deleted(state))) => println!("Deleted: {} (was {:?})", ch, state),
//! None => println!("No input processed"),
//! }
//! ```
//!
//! ### Custom Configuration
//!
//! ```rust
//! use gladius::{TypingSession, config::Configuration};
//!
//! let config = Configuration {
//! measurement_interval_seconds: 0.5, // More frequent measurements
//! };
//!
//! let session = TypingSession::new("Hello, world!")
//! .unwrap()
//! .with_configuration(config);
//! ```
//!
//! ### Character-level Rendering
//!
//! ```rust
//! use gladius::TypingSession;
//!
//! let session = TypingSession::new("hello").unwrap();
//!
//! let rendered: Vec<String> = session.render(|ctx| {
//! let cursor = if ctx.has_cursor { " |" } else { "" };
//! let state = match ctx.character.state {
//! gladius::State::Correct => "โ",
//! gladius::State::Wrong => "โ",
//! gladius::State::None => "ยท",
//! _ => "?",
//! };
//! format!("{}{}{}", ctx.character.char, state, cursor)
//! });
//! ```
//!
//! ### Line-based Rendering
//!
//! ```rust
//! use gladius::{TypingSession, render::LineRenderConfig};
//!
//! let session = TypingSession::new("The quick brown fox jumps over the lazy dog").unwrap();
//! let config = LineRenderConfig::new(20).with_word_wrapping(false);
//!
//! let lines: Vec<String> = session.render_lines(|line_ctx| {
//! Some(line_ctx.contents.iter()
//! .map(|ctx| ctx.character.char)
//! .collect())
//! }, config);
//!
//! // Results in word-wrapped lines of ~20 characters each
//! ```
//!
//! ### Complete Session with Statistics
//!
//! ```rust
//! use gladius::{TypingSession, CharacterResult};
//!
//! let mut session = TypingSession::new("rust").unwrap();
//! let text_chars = ['r', 'u', 's', 't'];
//!
//! // Type the complete text
//! for ch in text_chars {
//! session.input(Some(ch));
//! }
//!
//! // Get final statistics
//! if session.is_fully_typed() {
//! let stats = session.finalize();
//! println!("Final WPM: {:.1}", stats.wpm.raw);
//! println!("Accuracy: {:.1}%", stats.accuracy.raw);
//! println!("Total time: {:.2}s", stats.duration.as_secs_f64());
//! println!("Character errors: {:?}", stats.counters.char_errors);
//! }
//! ```
//!
//! ## Performance Characteristics
//!
//! | Operation | Time Complexity | Notes |
//! |-----------|----------------|-------|
//! | Character input | O(1) amortized, O(w) worst case | Usually constant, worst case when recalculating word state |
//! | Character lookup | O(1) | Direct vector indexing |
//! | Word lookup | O(1) | Pre-computed mapping |
//! | Statistics update | O(1) typical, O(m) when measuring | Most updates are constant, measurements scan history |
//! | Rendering | O(n) | Linear in text length |
//! | Line wrapping | O(n) with O(w) lookahead | Linear with word boundary lookahead |
//! | Session creation | O(n) | One-time text parsing |
//!
//! ## Thread Safety
//!
//! Gladius types are not thread-safe by design for maximum performance. Each typing
//! session should be used on a single thread. Multiple sessions can run concurrently
//! on different threads.
//!
//! ## Memory Usage
//!
//! - **Text storage**: O(n) where n is text length
//! - **Statistics history**: O(k) where k is number of measurements
//! - **Input history**: O(m) where m is number of keystrokes
//! - **Word mapping**: O(n) pre-computed character-to-word index
//!
//! Memory usage is optimized for typing trainer use cases with efficient data structures
//! and minimal allocations during active typing.
//!
//! ## Minimum Supported Rust Version (MSRV)
//!
//! Gladius supports Rust 1.88.0 and later.
/// Re-export of the main entry point for convenient access
pub use TypingSession;
// Shared types for readability and type safety
type Timestamp = f64;
type Minutes = f64;
type Float = f64;
/// Represents the current typing state of a character or word
///
/// States have a specific ordering that reflects their priority for word state calculations.
/// Higher priority states override lower priority ones when determining overall word state.
///
/// # State Transitions
///
/// ```text
/// None โ Correct/Wrong โ Deleted โ Corrected (via new input)
/// ```
///
/// # Examples
///
/// ```rust
/// use gladius::State;
///
/// // Priority ordering (Higher states override lower ones)
/// assert!(State::Wrong > State::Corrected);
/// assert!(State::Corrected > State::Correct);
/// assert!(State::Correct > State::None);
/// ```
/// Result of processing a character input during typing
///
/// Indicates what happened when a character was typed or deleted, providing
/// detailed feedback about the typing action for statistics and UI updates.
///
/// # Ordering
///
/// Results are ordered by their impact on typing accuracy, with `Correct` being
/// the best outcome and `Deleted` potentially indicating typing inefficiency.
///
/// # Examples
///
/// ```rust
/// use gladius::{CharacterResult, State};
///
/// // Typing the correct character first time
/// let result = CharacterResult::Correct;
///
/// // Typing wrong, then deleting and typing correctly
/// let wrong = CharacterResult::Wrong;
/// let deleted = CharacterResult::Deleted(State::Wrong);
/// let corrected = CharacterResult::Corrected;
/// ```
/// Represents a word in the text with its boundaries and typing state
///
/// Words are defined as sequences of non-whitespace characters separated by whitespace.
/// Each word tracks its position in the text and its overall typing state based on
/// the states of its constituent characters.
///
/// # Examples
///
/// ```rust
/// use gladius::{Word, State};
///
/// let word = Word {
/// start: 0, // First character index
/// end: 4, // Last character index + 1 (exclusive)
/// state: State::Correct,
/// };
///
/// // Check if a character index is part of this word
/// assert!(word.contains_index(&2)); // Character at index 2 is in the word
/// assert!(!word.contains_index(&5)); // Character at index 5 is not in the word
/// ```
/// Represents a single character in the text with its typing state
///
/// Characters are the fundamental unit of typing analysis. Each character
/// maintains its Unicode value and current state based on user input.
///
/// # Examples
///
/// ```rust
/// use gladius::{Character, State};
///
/// let char = Character {
/// char: 'a',
/// state: State::Correct,
/// };
///
/// // Unicode characters are fully supported
/// let unicode_char = Character {
/// char: '๐',
/// state: State::None,
/// };
/// ```