NitroType Perfect Nitros with SFB Highlighting (QWERTY, DVORAK, COLEMAK)

Highlights the largest words, single-finger bigrams (SFBs), and custom words/phrases for QWERTY, DVORAK, or COLEMAK layouts. Adds custom color coding for hand-specific characters like 'b' and 'y'.

  1. // ==UserScript==
  2. // @name NitroType Perfect Nitros with SFB Highlighting (QWERTY, DVORAK, COLEMAK)
  3. // @namespace https://gf.qytechs.cn/users/1331131-tensorflow-dvorak
  4. // @version 2.5.1
  5. // @description Highlights the largest words, single-finger bigrams (SFBs), and custom words/phrases for QWERTY, DVORAK, or COLEMAK layouts. Adds custom color coding for hand-specific characters like 'b' and 'y'.
  6. // @author Ray Adams/Nate Dogg, Modified by TensorFlow - Dvorak
  7. // @match https://www.nitrotype.com/race
  8. // @match https://www.nitrotype.com/race/*
  9. // @run-at document-end
  10. // @grant none
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (() => {
  15. // CHANGE THIS to 'QWERTY', 'DVORAK' or 'COLEMAK'
  16. const keyboardLayout = 'QWERTY';
  17.  
  18. const options = {
  19. highlightColor: '#1b1c25',
  20. wordHighlightColor: '#5b048a',
  21. singleFingerBigramColor: '#403dae',
  22. redForRightHand: 'red',
  23. blueForLeftHand: 'blue',
  24. intervalMs: 100
  25. };
  26.  
  27. // Custom wordlist for highlighting (add words or phrases you aim to type differently here)
  28. const customWords = new Set(['number', "you're"]);
  29.  
  30. // SFBs for different keyboard layouts (remove bigrams you don't want to work on)
  31. const SFBs = new Map([
  32. ['QWERTY', ['ed', 'de', 'fr', 'rf', 'gt', 'tg', 'bv', 'vb', 'ju', 'uj', 'ki', 'ik', 'nm', 'mn', 'nu', 'un']],
  33. ['DVORAK', ['pu', 'up', 'ui', 'iu', 'pi', 'ip', 'je', 'ej']],
  34. ['COLEMAK', ['']]
  35. ]);
  36.  
  37. // Define different layouts.
  38. const layoutKeys = {
  39. QWERTY: {
  40. leftHand: 'qwertasdfgzxcvb',
  41. rightHand: 'yuiophjklmn',
  42. targetChars: ['b'] // 'b' is typed by either hand and will be color coded based on which hand should be used. Red = right Blue = Left.
  43. },
  44. DVORAK: {
  45. leftHand: 'aoeuqjkxiyp',
  46. rightHand: 'dhtsnfgcrlbmwvz',
  47. targetChars: ['x']
  48. },
  49. COLEMAK: {
  50. leftHand: 'qwfpbjluyarst',
  51. rightHand: 'neiohjkxvmzcdg',
  52. targetChars: ['b']
  53. }
  54. };
  55.  
  56. const client = () => {
  57. const dashLetters = document.querySelector('.dash-letter');
  58. if (dashLetters) {
  59. clearInterval(intervalId);
  60.  
  61. // Get all words from the race
  62. const wordList = [...document.getElementsByClassName('dash-word')].map(word => word.textContent.replace(/\s/g, ''));
  63.  
  64. // Find the largest words
  65. const maxLength = Math.max(...wordList.map(word => word.length));
  66. const largestWords = wordList.filter(word => word.length === maxLength);
  67.  
  68. // Highlight largest words and bigrams
  69. wordList.forEach((word, index) => {
  70. const wordElement = document.getElementsByClassName('dash-word')[index];
  71.  
  72. // Highlight largest words
  73. if (largestWords.includes(word)) {
  74. wordElement.style.backgroundColor = options.highlightColor;
  75. }
  76.  
  77. // Highlight custom words/phrases
  78. highlightCustomWords(wordElement);
  79.  
  80. // Highlight single-finger bigrams
  81. highlightSingleFingerBigrams(wordElement);
  82.  
  83. // Highlight specific target chars if followed by the same hand's character
  84. highlightTargetCharsWithSameHand(wordElement, keyboardLayout);
  85. });
  86. }
  87. };
  88.  
  89. const highlightCustomWords = (wordElement) => {
  90. const text = wordElement.textContent.toLowerCase();
  91.  
  92. // Loop over each word or phrase in the custom wordlist
  93. customWords.forEach(word => {
  94. const startIndex = text.indexOf(word.toLowerCase());
  95. if (startIndex !== -1) {
  96. for (let i = 0; i < word.length; i++) {
  97. wordElement.querySelector(`.dash-letter:nth-child(${startIndex + i + 1})`).style.color = options.wordHighlightColor;
  98. }
  99. }
  100. });
  101. };
  102.  
  103. const highlightSingleFingerBigrams = (wordElement) => {
  104. const text = wordElement.textContent;
  105.  
  106. // Loop over the text and highlight single-finger bigrams
  107. for (let i = 0; i < text.length - 1; i++) {
  108. const bigram = text[i] + text[i + 1];
  109. if (SFBs.get(keyboardLayout).includes(bigram)) {
  110. wordElement.querySelector(`.dash-letter:nth-child(${i + 1})`).style.color = options.singleFingerBigramColor;
  111. wordElement.querySelector(`.dash-letter:nth-child(${i + 2})`).style.color = options.singleFingerBigramColor;
  112. i++;
  113. }
  114. }
  115. };
  116.  
  117. const highlightTargetCharsWithSameHand = (wordElement, layout) => {
  118. const { leftHand, rightHand, targetChars } = layoutKeys[layout];
  119. const text = wordElement.textContent.toLowerCase();
  120.  
  121. // Check if target characters are followed by the same hand
  122. for (let i = 0; i < text.length - 1; i++) {
  123. const currentChar = text[i];
  124. const nextChar = text[i + 1];
  125.  
  126. if (targetChars.includes(currentChar)) {
  127. if (leftHand.includes(currentChar) && leftHand.includes(nextChar)) {
  128. // Highlight target char to suggest typing with the right hand
  129. wordElement.querySelector(`.dash-letter:nth-child(${i + 1})`).style.color = options.redForRightHand;
  130. } else if (rightHand.includes(currentChar) && rightHand.includes(nextChar)) {
  131. // Highlight target char to suggest typing with the left hand
  132. wordElement.querySelector(`.dash-letter:nth-child(${i + 1})`).style.color = options.blueForLeftHand;
  133. }
  134. }
  135. }
  136. };
  137.  
  138. const intervalId = setInterval(client, options.intervalMs);
  139. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址