DKL9 GitList
Repositories
DKL9 home
site_root
Code
Commits
Branches
Tags
Search
Tree:
993e20c
Branches
Tags
master
site_root
tools
typing_practice.html
Initial commit: track much site content
dkl9
commited
993e20c
at 2025-352 15:27:28
typing_practice.html
Blame
History
Raw
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Typing practice utility</title> <link rel="stylesheet" href="/style.css"> <link rel="icon" type="image/png" href="/favicon.png"> <style> body, select, button { font-size: 2vw; } .hlgood { background-color: lime; } .hlbad { background-color: red; } </style> </head> <body> <noscript>Enable JavaScript, or use a different browser</noscript> <p id="typarea"></p> <p id="results">Setting up...</p> Select corpus: <select id="corpsel"></select> <button id="startbtn">Start</button> If it doesn't work, single-click the text, then type again. <p>Originally developed in 2021. Corpora are from arbitrary Wikipedia articles. Comments and questions are welcome. Email them to <a href="mailto:contact@dkl9.net">contact@dkl9.net</a>. <span style="display: none;">And not <a href="mailto:sucrose@dkl9.net">sucrose@dkl9.net</a>, unless you are a spambot.</span></p> <p><a href="/">dkl9 home</a></p> <script> // progress through the corpus, as a rounded percentage function progress_percent() { return Math.round((typing_progress / corpus.length) * 100) } // accuracy so far, as a rounded percentage function accuracy_percent() { return Math.round((good_count / typing_progress) * 1000) / 10; } // time since first keypress, in semi-rounded seconds function elapsed_secs() { return Math.round((Date.now() - start_time) / 100) / 10; } // average characters per second, partially rounded function char_per_sec() { return Math.round(100 * typing_progress / elapsed_secs()) / 100; } function capital(c) { // hack from stackoverflow to check if c is alphabetic if (c.toUpperCase() != c.toLowerCase()) { return c.toUpperCase(); } if (SCC.includes(c)) { return c; } const sci = SCO.indexOf(c); if (sci > -1) { return SCC[sci]; } alert("capital function failed"); return "_"; } function keydown_handler(ev) { // printable character key if (ev.key.length == 1 && typing_progress <= corpus.length) { // capitalise if shift is down // not handled automatically when keypresses are captured if (shift) { ev.key = capital(ev.key); } const ch_elem = document.getElementById("tch" + typing_progress); const correct_ch = corpus.charAt(typing_progress); if (ev.key == correct_ch) { ch_elem.className = "hlgood"; good_count++; } else { ch_elem.className = "hlbad"; if (!mistakes[correct_ch]) { mistakes[correct_ch] = 1; } else { mistakes[correct_ch]++; } bad_count++; } if (typing_progress == 0) { start_time = Date.now(); } typing_progress++; if (typing_progress >= corpus.length) { results_area.innerText = "Finished in " + elapsed_secs() + " seconds. " + accuracy_percent() + "% accuracy, " + char_per_sec() + " average characters per second." + " Mistakes:"; const mte = Object.entries(mistakes); mte.sort(); for (let i = 0; i < mte.length; i++) { results_area.innerText += " " + mte[i][0] + " (" + mte[i][1] + ")"; } } else { results_area.innerText = progress_percent() + "% complete, " + accuracy_percent() + "% accuracy, " + char_per_sec() + " average CPS"; results_area.innerText = "Keep going ..."; } } if (ev.key == "Shift") { shift = true; } } function keyup_handler(ev) { if (ev.key == "Shift") { shift = false; } } function selchange_handler(ev) { if (!started) { corpus = CORPORA[ev.target.value]; typing_area.innerText = corpus; } } function start_handler(ev) { typing_area.innerHTML = ""; for (let i = 0; i < corpus.length; i++) { // append a single-character span for each character in the corpus // to allow for character-by-character highlighting // this feels disgustingly inefficient // but i haven't experienced any lag from it so whatever const new_ch_elem = document.createElement("span"); new_ch_elem.innerText = corpus.charAt(i); new_ch_elem.id = "tch" + i; typing_area.appendChild(new_ch_elem); } document.onkeydown = keydown_handler; document.onkeyup = keyup_handler; started = true; results_area.innerText = "Setup successful. Begin!"; } // sorted in increasing length const CORPORA = [ // first paragraph from wikipedia article on Of Human Feelings "Of Human Feelings is an album by American jazz saxophonist, composer, and bandleader Ornette Coleman. It was recorded on April 25, 1979, at CBS Studios in New York City with his band Prime Time, which featured guitarists Charlie Ellerbee and Bern Nix, bassist Jamaaladeen Tacuma, and drummers Calvin Weston and Coleman's son Denardo. It followed the saxophonist's failed attempt to record a direct-to-disc session earlier in March of the same year and was the first jazz album to be recorded digitally in the United States.", // paragraph from wikipedia article on automata theory "An automaton runs when it is given some sequence of inputs in discrete (individual) time steps or steps. An automaton processes one input picked from a set of symbols or letters, which is called an input alphabet. The symbols received by the automaton as input at any step are a sequence of symbols called words. An automaton has a set of states. At each moment during a run of the automaton, the automaton is in one of its states. When the automaton receives new input it moves to another state (or transitions) based on a transition function that takes the previous state and current input symbol as parameters. At the same time, another function called the output function produces symbols from the output alphabet, also according to the previous state and current input symbol. The automaton reads the symbols of the input word and transitions between states until the word is read completely, if it is finite in length, at which point the automaton halts. A state at which the automaton halts is called the final state.", // long paragraph from wikipedia article on water "An assessment of water management in agriculture was conducted in 2007 by the International Water Management Institute in Sri Lanka to see if the world had sufficient water to provide food for its growing population.[75] It assessed the current availability of water for agriculture on a global scale and mapped out locations suffering from water scarcity. It found that a fifth of the world's people, more than 1.2 billion, live in areas of physical water scarcity, where there is not enough water to meet all demands. A further 1.6 billion people live in areas experiencing economic water scarcity, where the lack of investment in water or insufficient human capacity make it impossible for authorities to satisfy the demand for water. The report found that it would be possible to produce the food required in the future, but that continuation of today's food production and environmental trends would lead to crises in many parts of the world. To avoid a global water crisis, farmers will have to strive to increase productivity to meet growing demands for food, while industries and cities find ways to use water more efficiently.[76]", // from the wikipedia article on the calkin-wilf tree "The Calkin-Wilf tree resembles the Stern-Brocot tree in that both are binary trees with each positive rational number appearing exactly once. Additionally, the top levels of the two trees appear very similar, and in both trees, the same numbers appear at the same levels. One tree can be obtained from the other by performing a bit-reversal permutation on the numbers at each level of the trees.[5] Alternatively, the number at a given node of the Calkin-Wilf tree can be converted into the number at the same position in the Stern-Brocot tree, and vice versa, by a process involving the reversal of the continued fraction representations of these numbers.[12] However, in other ways, they have different properties: for instance, the Stern-Brocot tree is a binary search tree: the left-to-right traversal order of the tree is the same as the numerical order of the numbers in it. This property is not true of the Calkin-Wilf tree.", // second paragraph from wikipedia article on bodashtart "Bodashtart was a prolific builder, and his name is attested on some 30 eponymous inscriptions found at the Temple of Eshmun and elsewhere in the hinterland of the city of Sidon in Lebanon. The earliest discovered of Bodashtart's inscriptions was excavated in Sidon in 1858 and was donated to the Louvre. This inscription dates back to the first year of Bodashtart's accession to the throne of Sidon and commemorates the building of a temple to the goddess Astarte. The Temple of Eshmun podium inscriptions were discovered between 1900 and 1922 and are classified into two groups. The inscriptions of the first group, known as KAI 15, commemorate building activities in the temple and attribute the work to Bodashtart. The second group of inscriptions, known as KAI 16, were found on podium restoration blocks; they credit Bodashtart and his son Yatonmilk with the construction project and emphasize Yatonmilk's legitimacy as heir. The most recently discovered inscription as of 2020 was found in the 1970s on the bank of the Bostrenos River, not far from the Temple of Eshmun. The inscription credits the King with the building of water canals to supply the temple in the seventh year of his reign.", // long sentence from the wealth of nations, book 1, chapter 1 "Were we to examine, in the same manner, all the different parts of his dress and household furniture, the coarse linen shirt which he wears next his skin, the shoes which cover his feet, the bed which he lies on, and all the different parts which compose it, the kitchen-grate at which he prepares his victuals, the coals which he makes use of for that purpose, dug from the bowels of the earth, and brought to him, perhaps, by a long sea and a long land-carriage, all the other utensils of his kitchen, all the furniture of his table, the knives and forks, the earthen or pewter plates upon which he serves up and divides his victuals, the different hands employed in preparing his bread and his beer, the glass window which lets in the heat and the light, and keeps out the wind and the rain, with all the knowledge and art requisite for preparing that beautiful and happy invention, without which these northern parts of the world could scarce have afforded a very comfortable habitation, together with the tools of all the different workmen employed in producing those different conveniencies; if we examine, I say, all these things, and consider what a variety of labour is employed about each of them, we shall be sensible that, without the assistance and co-operation of many thousands, the very meanest person in a civilized country could not be provided, even according to, what we very falsely imagine, the easy and simple manner in which he is commonly accommodated.", // from wikipedia article on the vessel (web series) "The Vessel is a British comedy web series created and written by Chloe Seddon, Phillip Whiteman and Giovanni Bienne. The series is broadcast on the Internet and premiered on 21 October 2012. Currently 10 episodes have been made and the show can be found distributed across the web on platforms including Blip and YouTube. The Vessel Series follows Kim (Lily Brown) and her two best friends, Rory (Giovanni Bienne) and Mike (Phillip Whiteman), as they start a family. Rory and Mike are a gay couple who have decided they want to have a baby. Rory and Mike want a baby, so they ask their close friend Kim to be the surrogate mother.[1]", // wikipedia article on libertarian party of washington "The party advocates for constitutionally restricted government and significant cuts to government spending and taxation. The party also supports protecting natural rights and expanding civil rights, including sexual and racial equality, LGBT rights, and decriminalization of scheduled drugs and prostitution. In addition, the party also supports school choice, privatizing the ferry system and portions of the state highways, eliminating predatory speed-traps, allowing private investment in water and natural resources, and supporting investment in industrial hemp. The Libertarian Party of Washington operates under a non-aggression pact.", // wikipedia article on "five go down to the sea?" "Five Go Down to the Sea? were an Irish post-punk band from Cork, active from 1978 to 1989. Vocalist and lyricist Finbarr Donnelly, guitarist Ricky Dineen and brothers Philip (bass) and Keith \"Smelly\" O'Connell (drums) formed the band as Nun Attax when they were teenagers. They became known for Donnelly's absurdist, surreal lyrics and stage presence, Dineen's angular guitar and bass parts, and their Captain Beefheart-style rhythm section. The group later included guitarists Mick Finnegan, Giordai Ua Laoghaire, Mick Stack, and cellist Una Ni Chanainn." ]; const SCO = [ "`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "[", "]", "\\", ";", "'", ",", ".", "/", " " ]; const SCC = [ "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "{", "}", "|", ":", "\"", "<", ">", "?", " " ]; // characters of progress through the corpus let typing_progress = 0; // characters typed correctly and incorrectly let good_count = 0; let bad_count = 0; // is shift down? let shift = false; // in unix-epoch milliseconds let start_time; // maps characters to integers // each entry is the number of mistakes made when supposed to type the given letter let mistakes = new Object(); let corpus = "[Select a corpus ...]"; let started = false; const typing_area = document.getElementById("typarea"); const results_area = document.getElementById("results"); const corpus_select = document.getElementById("corpsel"); for (let i = 0; i < CORPORA.length; i++) { const new_opt_element = document.createElement("option"); new_opt_element.value = i; const space_index = CORPORA[i].indexOf(" ", 25); if (space_index == -1) { new_opt_element.innerText = CORPORA[i]; } else { new_opt_element.innerText = CORPORA[i].substring(0, space_index) + "..."; } corpus_select.appendChild(new_opt_element); } corpus_select.onchange = selchange_handler; document.getElementById("startbtn").onclick = start_handler; </script> </body> </html>