-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtextHandler.js
More file actions
157 lines (145 loc) · 9.36 KB
/
textHandler.js
File metadata and controls
157 lines (145 loc) · 9.36 KB
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
export const state = {
currentText: '',
currentWordIndex: 0
};
const paragraphsWithSymbols = {
easy: [
`In 2045 city used #AI tech Hovercars moved at 80mph with *Quantum#X1* code Coders typed at 100wpm using *API#10* with 95% hit rate Neon signs showed *Sale@30%* for *VR#A* at $299 Drones named #XJ-1000 sent items in 10min via *GPS#V1* Hackers tried *Proxy#10* but 90% failed Cafes had 100Mbps Wi-Fi with !click! keys Factories made 100000 chips at 0.01mm precision Coders sent 20 *GitHub#A* updates daily TypeRiser v1 promised 120wpm Markets sold *Crypto#A* items with 128-bit keys Nightlife had *RGB#00FFFF* lights at 100BPM Schools taught *Python1* to 1000 kids 70% learned by age 10 Motto 'Code@2045' sparked 100 startups`
],
medium: [
`In 2045 cyber city thrived with #AI tech Hovercars sped at 100mph coded with *Quantum#X9* algorithms Coders typed at 120wpm integrating *API#23* with 99% accuracy Neon signs flashed *Sale@50%* for *VR#Z* headsets at $499.99 Drones marked #XJ-3927 delivered in 5min tracked by *GPS#V8* Hackers used *Proxy#42* for 0-day exploits but 95% blocked Cafes offered 500Mbps Wi-Fi with !click-clack! keyboards Factories ran 24/7 producing 500000 chips with 0.001mm precision Coders pushed 50 *GitHub#X* commits daily TypeRiser v4.0 promised 200wpm Markets sold *Crypto#Z* gadgets secured by 256-bit keys Nightlife pulsed with *RGB#FF00FF* lights at 120BPM Schools taught *Python3* to 5000 kids 80% mastered by age 12 Motto 'Innovate@2045' inspired 1000 startups`
],
hard: [
`In 2045 cyber metropolis thrived with #QuantumAI tech Hovercars zoomed at 150mph coded with *Quantum#X99* algorithms Coders typed at 180wpm integrating *API#X99* with 99.9% accuracy Neon billboards flashed *MegaSale@75%* for *VR#Z99* headsets at $999.99 Drones tagged #XJ-9999 delivered in 3min tracked by *GPS#V99* Hackers deployed *Proxy#X99* for zero-day exploits but 99% blocked Cafes offered 1Gbps Wi-Fi with !click-clack-buzz! keyboards Factories operated 24/7 producing 1000000 chips with 0.0001mm precision Coders pushed 100 *GitHub#X99* commits daily TypeRiser v9.9 promised 300wpm Markets traded *Crypto#Z99* gadgets secured by 512-bit keys Nightlife pulsed with *RGB#FF00FF* at 150BPM Schools taught *Python9* to 10000 kids 90% mastered by age 11 Motto 'Revolution@2045' inspired 5000 startups`
]
};
const paragraphsWithoutSymbols = {
easy: [
`A village in hills grew crops Families worked fields sharing short tales daily Crops colored land green and gold Kids played in fields while elders told stories Markets hummed with traders from near towns Smell of bread and blooms filled air At night families sang by fire their homes cozy Seasons shaped lives spring growth summer work fall harvest winter calm Village was hub of bonds and effort its legacy lasting for ages`
],
medium: [
`A village nestled in hills thrived on farming Families worked fields sharing harvest stories daily Crops painted land green and gold Children laughed in meadows while elders shared tales Markets buzzed with traders from distant towns Scent of bread and flowers filled air At night families sang by firelight their homes warm Seasons shaped their lives spring growth summer labor autumn harvests winter rest Village was haven of community and perseverance its legacy enduring through generations`
],
hard: [
`A settlement flourished amidst rolling valleys cultivating extensive agriculture Households collaborated tirelessly exchanging intricate narratives regularly Vegetation adorned terrain in vibrant emerald and amber Youth reveled in expansive grasslands whilst patriarchs recounted elaborate chronicles Bazaars thrived with merchants from remote regions Fragrance of freshly baked loaves and blossoms permeated atmosphere Nocturnal gatherings illuminated by hearths fostered warmth Cycles of seasons dictated existence vernal sprouting summery exertion autumnal reaping wintry repose Community embodied resilience and solidarity its heritage perpetuating across epochs`
]
};
const defaultText = 'The quick brown fox jumps over the lazy dog';
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM fully loaded for textHandler.js');
elements.typingArea = document.getElementById('typing-area');
elements.textTypeSelect = document.getElementById('symbol-mode');
elements.difficultySelect = document.getElementById('difficulty');
elements.challengeText = document.getElementById('challenge-text');
console.log('Elements initialized:', {
typingArea: !!elements.typingArea,
textTypeSelect: !!elements.textTypeSelect,
difficultySelect: !!elements.difficultySelect,
challengeText: !!elements.challengeText
});
if (elements.typingArea && elements.textTypeSelect && elements.difficultySelect) {
setRandomParagraph();
setDailyChallenge();
} else {
console.error('Required elements not found, using default text');
if (elements.typingArea) {
elements.typingArea.textContent = defaultText;
}
}
});
const elements = {
typingArea: null,
textTypeSelect: null,
difficultySelect: null,
challengeText: null
};
function shuffleWords(text) {
const words = text.split(/\s+/).filter(word => word);
for (let i = words.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[words[i], words[j]] = [words[j], words[i]];
}
return words.join(' ');
}
export function setRandomParagraph() {
console.log('setRandomParagraph called');
if (!elements.typingArea || !elements.textTypeSelect || !elements.difficultySelect) {
console.error('Required elements not found:', {
typingArea: !!elements.typingArea,
textTypeSelect: !!elements.textTypeSelect,
difficultySelect: !!elements.difficultySelect
});
state.currentText = defaultText;
state.currentWordIndex = 0;
updateTextDisplay();
return;
}
const textType = elements.textTypeSelect.value || 'no-symbols';
const difficulty = elements.difficultySelect.value || 'easy';
console.log('Text type:', textType, 'Difficulty:', difficulty);
const paragraphs = textType === 'with-symbols' ? paragraphsWithSymbols[difficulty] : paragraphsWithoutSymbols[difficulty];
if (!paragraphs || paragraphs.length === 0) {
console.error('No paragraphs available for', textType, difficulty, 'using default text');
state.currentText = defaultText;
} else {
const selectedParagraph = paragraphs[Math.floor(Math.random() * paragraphs.length)] || defaultText;
state.currentText = shuffleWords(selectedParagraph); // Shuffle words
}
state.currentWordIndex = 0;
console.log('Selected text (shuffled):', state.currentText);
updateTextDisplay();
}
export function updateTextDisplay(typedWords = [], currentWordIndex = 0) {
console.log('updateTextDisplay called, currentWordIndex:', currentWordIndex);
if (!elements.typingArea) {
console.error('Typing area element not found');
return;
}
if (!state.currentText) {
console.error('Current text is empty, setting default');
state.currentText = defaultText;
}
const words = state.currentText.split(/\s+/).filter(word => word);
console.log('Words to display:', words);
const fragment = document.createDocumentFragment();
// Estimate words per line (assuming avg word length ~5 chars, 80 chars per line)
const maxWordsPerLine = Math.floor(80 / 6); // Approx 13 words per line
const maxWordsToShow = maxWordsPerLine * 3; // Show up to 3 lines (~39 words)
// Center display around current word
const startIndex = Math.max(0, currentWordIndex - Math.floor(maxWordsToShow / 2));
const endIndex = Math.min(words.length, startIndex + maxWordsToShow);
for (let index = startIndex; index < endIndex; index++) {
const span = document.createElement('span');
span.textContent = words[index] + (index < words.length - 1 ? ' ' : '');
if (index < currentWordIndex) {
span.className = typedWords[index] === words[index] ? 'correct' : 'incorrect';
} else if (index === currentWordIndex) {
span.className = 'current-word';
} else {
span.className = 'untyped';
}
fragment.appendChild(span);
}
elements.typingArea.innerHTML = '';
elements.typingArea.appendChild(fragment);
// Ensure typing area stays focused at current word without scrolling
if (elements.typingArea) {
elements.typingArea.scrollTop = 0; // Prevent scrolling
}
console.log('Text display updated, current word index:', currentWordIndex, 'words shown:', startIndex, 'to', endIndex);
}
export function setDailyChallenge() {
console.log('setDailyChallenge called');
if (!elements.challengeText) {
console.error('Challenge text element not found');
return;
}
const challenges = [
'Type 30 words in under 1 minute',
'Achieve 90% accuracy',
'Type 40 words in under 1 minute',
'Complete 3 tests today'
];
elements.challengeText.textContent = challenges[new Date().getDate() % challenges.length];
console.log('Challenge set:', elements.challengeText.textContent);
}