9393</template >
9494
9595<script setup lang="ts">
96- import { WritableComputedRef } from ' vue' ;
96+ import { ref , computed } from ' vue' ;
9797import {
9898 useHomeStore ,
9999 KEYOPTIONS ,
@@ -126,6 +126,8 @@ import { calculateRawWPM, calculateWPM, focusInput } from '@/utils/input';
126126import type { Database } from ' ~/types/database.types' ;
127127import formatLocaleTime from ' ~/utils/format-locale-time' ;
128128import { IntervalCounter , BaseCounter } from ' ~/src/counters' ;
129+ import { isKeySpace , isQuickRestartShortcut } from ' ~/src/helpers' ;
130+ import { WordLog , CharacterLog , IntervalLog } from ' ~/src/log' ;
129131
130132definePageMeta ({
131133 middleware: ' auth' ,
@@ -242,7 +244,7 @@ const currentSelectionData = computed(() => {
242244 }
243245});
244246
245- // manage carot
247+ // manage caret
246248const CARETLEFT = ref (0 );
247249const CARETTOP = ref (0 );
248250
@@ -300,46 +302,6 @@ const currentMetadata: globalThis.ComputedRef<InputMetadata> = computed(() => {
300302 };
301303});
302304
303- // writable computed ref is used for write only, get is gotten from currentmetadata.
304- const currentCharacterStatus: WritableComputedRef <CharLogStatus > = computed ({
305- get : (): CharLogStatus => {
306- return allData .value [currentWordNum .value ]?.characters [
307- currentCharNum .value
308- ].status ;
309- },
310- set : (newValue : CharLogStatus ): void => {
311- allData .value [currentWordNum .value ].characters [
312- currentCharNum .value
313- ].status = newValue ;
314- },
315- });
316-
317- // writable computed ref is used for write only, get is gotten from currentmetadata.
318- const currentCharacterEndTime: WritableComputedRef <string > = computed ({
319- get : (): string => {
320- return allData .value [currentWordNum .value ]?.characters [
321- currentCharNum .value
322- ].end_time ;
323- },
324- set : (newValue : string ): void => {
325- allData .value [currentWordNum .value ].characters [
326- currentCharNum .value
327- ].end_time = newValue ;
328- },
329- });
330- const currentCharacterStartTime: WritableComputedRef <string > = computed ({
331- get : (): string => {
332- return allData .value [currentWordNum .value ]?.characters [
333- currentCharNum .value
334- ].start_time ;
335- },
336- set : (newValue : string ): void => {
337- allData .value [currentWordNum .value ].characters [
338- currentCharNum .value
339- ].start_time = newValue ;
340- },
341- });
342-
343305//
344306async function fetchWords() {
345307 loading .value = true ;
@@ -417,21 +379,9 @@ function handleKeydown(e: KeyboardEvent) {
417379 }
418380}
419381
420- function isQuickRestartShortcut(e : KeyboardEvent ) {
421- const key = e .key ;
422- if (key === ' Tab' ) return true ;
423- return false ;
424- }
425-
426- function isSpace(e : KeyboardEvent ) {
427- const key = e .key ;
428- if (key === ' ' ) return true ;
429- return false ;
430- }
431-
432382function handleSpace() {
433383 const metadata = currentMetadata .value ;
434- metadata .currentWordMetadata .status = getWordStatus ()
384+ metadata .currentWordMetadata .status = getWordStatus ();
435385 insertWord (metadata .currentWord );
436386 pushWordLogs ();
437387 currentWordNum .value += 2 ;
@@ -445,9 +395,10 @@ function handleQuickRestart() {
445395}
446396
447397function isFinalWord(index : number ) {
448- if (selectedMode .value === ' word' && index === selectedWords .value - 1 )
449- return true ;
450- return false ;
398+ return (
399+ selectedMode .value === ' word' &&
400+ index === selectedWords .value - 1
401+ );
451402}
452403
453404function handleInput(e : KeyboardEvent ) {
@@ -461,7 +412,7 @@ function handleInput(e: KeyboardEvent) {
461412 }
462413 if (currentWordType !== ' separator' ) {
463414 totalCharactersCount .increment ();
464- if (isSpace (e )) {
415+ if (isKeySpace (e )) {
465416 if (! isFinalWord (index )) handleSpace ();
466417 return ;
467418 }
@@ -475,25 +426,29 @@ function handleInput(e: KeyboardEvent) {
475426}
476427
477428function handleCorrectInput() {
478- deleteExtras ();
479429 intervalCharacterCount .increment ();
480430 const { currentWordMetadata } = currentMetadata .value ;
481431 if (currentWordMetadata && currentWordMetadata .type !== ' separator' ) {
482432 totalCorrectsCount .increment ();
483433 }
484-
485434 const metadata = currentMetadata .value ;
486- const currentCharMetadata = currentMetadata .value .currentCharMetadata ;
435+ let currentCharMetadata = currentMetadata .value .currentCharMetadata ;
487436 const time = Date .now ();
488437 const duration = getCharDuration (time );
489- const index = metadata .currentCharLocation ;
438+ let index = metadata .currentCharLocation ;
490439 const wordIndex = metadata .currentWordMetadata .index ;
440+ if (currentWordMetadata .type === ' separator' ){
441+ currentCharMetadata = allData .value [currentWordNum .value ]?.characters [
442+ metadata .currentCorrectCharLocation
443+ ];
444+ index = metadata .currentCorrectCharLocation
445+ }
491446
492447 updateCurrentCharacterObject ();
493448 if (isEndSession ()) {
494449 handleEndSession (time );
495450 return ;
496- } else if (isEndWord ()) {
451+ } else if (isEndWord () || currentWordMetadata . type === ' separator ' ) {
497452 handleEndWord ();
498453 } else {
499454 incrementChar ();
@@ -515,12 +470,6 @@ function handleCorrectInput() {
515470 }
516471}
517472
518- watch ([CARETTOP ], () => {
519- if (CARETTOP .value > oldTop && oldTop !== 0 ) {
520- handleNewLine ();
521- }
522- oldTop = CARETTOP .value ;
523- });
524473function getCharDuration(time : number ) {
525474 return (time - finalKeydown ) / 1000 ;
526475}
@@ -640,37 +589,28 @@ function resetPrevCharMetadata() {
640589 const currentWordIndex = currentWordMetadata .index ;
641590 let prevCharIndex: number ;
642591 let prevCharMetadata: CharacterMetadata ;
643- if (correctCharIndex .value === 0
644- ) {
592+ if (correctCharIndex .value === 0 ) {
645593 let prevWordMetadata: WordMetadata ;
646- let newWordIndex: number
647- if (currentWordMetadata .type === ' separator' ){
648- newWordIndex = currentWordNum .value - 1
649- prevWordMetadata =
650- allData .value [newWordIndex ];
651- }else {
652- newWordIndex = currentWordNum .value - 2
653- prevWordMetadata =
654- allData .value [newWordIndex ];
594+ let newWordIndex: number ;
595+ if (currentWordMetadata .type === ' separator' ) {
596+ newWordIndex = currentWordNum .value - 1 ;
597+ prevWordMetadata = allData .value [newWordIndex ];
598+ } else {
599+ newWordIndex = currentWordNum .value - 2 ;
600+ prevWordMetadata = allData .value [newWordIndex ];
655601 }
656- for (
657- let i = 0 ;
658- i < prevWordMetadata .characters ?.length ;
659- i ++
660- ) {
602+ for (let i = 0 ; i < prevWordMetadata .characters ?.length ; i ++ ) {
661603 if (
662- allData .value [newWordIndex ]
663- .characters [ i ]. status === ' pending'
604+ allData .value [newWordIndex ]. characters [ i ]
605+ .status === ' pending'
664606 ) {
665607 break ;
666608 } else {
667609 prevCharIndex = i ;
668610 }
669611 }
670612 prevCharMetadata =
671- allData .value [newWordIndex ].characters [
672- prevCharIndex
673- ];
613+ allData .value [newWordIndex ].characters [prevCharIndex ];
674614 if (prevCharMetadata .status === ' extra' ) {
675615 currentMetadata .value .currentWordMetadata .characters .splice (
676616 prevCharIndex ,
@@ -851,7 +791,7 @@ function setShowResults() {
851791
852792function handleEndWord() {
853793 const metadata = currentMetadata .value ;
854- metadata .currentWordMetadata .status = getWordStatus ()
794+ metadata .currentWordMetadata .status = getWordStatus ();
855795 if (metadata .currentWordMetadata .type === ' word' ) {
856796 insertWord (metadata .currentWord );
857797 pushWordLogs ();
@@ -864,18 +804,22 @@ function pushWordLogs() {
864804 // internal
865805 const wordLength = currentMetadata .value .currentWordLength ;
866806 // to push
867- const index = getWordIndex ();
868- const word = currentMetadata .value .currentWord ;
869- const type = getWordType ();
870- const startTime = getWordStartTime ();
871- const endTime = getWordEndTime ();
872807 const duration = getWordDuration ();
873- const status = getWordStatus ();
874808 const wpm = getWordWpm ();
875- let session_id: number ; // fill at the end
809+
810+ const newWordLog = new WordLog ({
811+ index: getWordIndex (),
812+ word: currentMetadata .value .currentWord ,
813+ type: getWordType (),
814+ start_time: getWordStartTime (),
815+ end_time: getWordEndTime (),
816+ duration ,
817+ status: getWordStatus (),
818+ wpm ,
819+ });
876820
877821 if (wpm && duration ) {
878- insertWordLogs ( );
822+ wordLogs . push ( newWordLog . getData () );
879823 }
880824
881825 function getWordIndex() {
@@ -911,33 +855,19 @@ function pushWordLogs() {
911855 (wordLength / 5 / (duration / 60 )).toFixed (2 )
912856 );
913857 }
914- function insertWordLogs(): void {
915- const updatedWordObject = {
916- index ,
917- word ,
918- start_time: startTime ,
919- end_time: endTime ,
920- duration ,
921- status ,
922- type ,
923- wpm ,
924- session_id ,
925- };
926- wordLogs .push (updatedWordObject );
927- }
928858}
929859
930860function getWordStatus(): WordLogStatus {
931- const wordLength = currentMetadata .value .currentWordLength
932- for (let i = 0 ; i < wordLength ; i ++ ) {
933- if (
934- currentMetadata .value .currentWordMetadata
935- .characters [i ].status !== ' correct'
936- )
937- return ' error' ;
938- }
939- return ' correct' ;
861+ const wordLength = currentMetadata .value .currentWordLength ;
862+ for (let i = 0 ; i < wordLength ; i ++ ) {
863+ if (
864+ currentMetadata .value .currentWordMetadata .characters [i ]
865+ .status !== ' correct'
866+ )
867+ return ' error' ;
940868 }
869+ return ' correct' ;
870+ }
941871
942872function insertWord(word : string ) {
943873 collectedWords .push (word );
@@ -1159,21 +1089,6 @@ async function insertLogsToDatabase() {
11591089 }
11601090}
11611091
1162- // watcher to get fresh data when any mode/settings changed
1163- watch (
1164- [
1165- selectedDifficulty ,
1166- selectedDuration ,
1167- selectedKey ,
1168- selectedMode ,
1169- selectedDataset ,
1170- selectedWords ,
1171- ],
1172- () => {
1173- fetchFreshWords ();
1174- }
1175- );
1176-
11771092// function resetlivetimer live wpm
11781093function resetLiveInterval() {
11791094 liveTimer .value = 0 ;
@@ -1307,6 +1222,21 @@ function pushIntervalLogs(
13071222 intervalLogs .push (updatedIntervalLogObject );
13081223}
13091224
1225+ // watcher to get fresh data when any mode/settings changed
1226+ watch (
1227+ [
1228+ selectedDifficulty ,
1229+ selectedDuration ,
1230+ selectedKey ,
1231+ selectedMode ,
1232+ selectedDataset ,
1233+ selectedWords ,
1234+ ],
1235+ () => {
1236+ fetchFreshWords ();
1237+ }
1238+ );
1239+
13101240// watch if input out of focus
13111241watch (currentActive , () => {
13121242 if (currentActive .value .id !== ' MasterInput' ) {
@@ -1336,6 +1266,13 @@ onMounted(() => {
13361266 }
13371267});
13381268
1269+ watch ([CARETTOP ], () => {
1270+ if (CARETTOP .value > oldTop && oldTop !== 0 ) {
1271+ handleNewLine ();
1272+ }
1273+ oldTop = CARETTOP .value ;
1274+ });
1275+
13391276// get profile data from auth
13401277watchEffect (async () => {
13411278 if (user .value ) {
0 commit comments