[YouTube-Chat] Words Typing

Added word typing game in chat area.

当前为 2022-11-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name [YouTube-Chat] Words Typing
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1beta
  5. // @description Added word typing game in chat area.
  6. // @author You
  7. // @include https://www.youtube.com/live_chat*
  8. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  9. // @require https://greasyfork.org/scripts/455302-youtube-auto-add-text-in-chatbox/code/%5BYouTube%5D%20Auto%20add%20Text%20in%20ChatBox.js?version=1120375
  10. // @grant none
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. let words
  15. let chatTextBox
  16. let wordArea
  17. let setWords = ['test','sample','word','arc', 'air', 'arm', 'ace', 'act', 'ash', 'asp','arc', 'air', 'arm', 'ace', 'act', 'ash', 'asp']
  18. let inputEvent
  19. let separator = " "
  20. let searchTime = new Date().getTime()
  21. let roundTypeCounter = 0
  22. let typeCounter = 0
  23.  
  24. /**
  25. *@Description 単語集をロードする。
  26. */
  27. fetch(`https://dl.dropboxusercontent.com/s/tw2j3ifk8mv2ten/jpWordsSample.txt?dl=0`).then(function(response) {
  28.  
  29. return response.text()
  30.  
  31. }).then(function(text) {
  32.  
  33. //textを取得した
  34. words = text.split("\r\n")
  35.  
  36. htmlSetUp()
  37. });
  38.  
  39.  
  40.  
  41.  
  42.  
  43. function htmlSetUp(){
  44.  
  45. const shortcutKeys = `
  46. Esc: Word skip
  47. Tab: Switch Text Box
  48. `
  49.  
  50. document.getElementById("top").insertAdjacentHTML("afterend",`
  51. <div id="minimum-dictionary">
  52. <div id="word-table">#<span id="wordarea">${setWords.join(separator)}</span></div>
  53. <div id="word-tools">
  54. <input id="word-search-box" maxlength="6" autocomplete="off" value="????" placeholder="[?] Search">
  55. <span><span id="word-match">0</span> word</span>
  56. <span id="shortcut-keys" title="${shortcutKeys}">⌨</span>
  57. <span><span id="typing-count">0</span> types</span>
  58. <span><span id="typing-speed">0.0</span> k/s</span>
  59. </div>
  60. </div>
  61. <style>
  62. #minimum-dictionary{
  63. margin-left: 48px;
  64. white-space: nowrap;
  65. }
  66. #word-search-box{
  67. background: rgb(0 0 0 / 10%);
  68. border: #000000 thin;
  69. border-top: none;
  70. outline: solid thin #ffffffa6;
  71. color: rgb(255 255 255 / 87%);
  72. width: 8rem;
  73. }
  74. #minimum-dictionary > div {
  75. margin-bottom: 1rem;
  76. }
  77. #word-tools > *{
  78. margin-right: 0.9rem;
  79. }
  80. #shortcut-keys:hover{
  81. text-decoration: underline;
  82. cursor: help;
  83. }
  84.  
  85. </style>`)
  86.  
  87.  
  88. chatTextBox = document.querySelector("#input > #input")
  89. wordArea = document.getElementById("wordarea")
  90. inputEvent = new typingCheck()
  91.  
  92. chatTextBox.addEventListener("input", inputEvent.typeCheck.bind(inputEvent))
  93. chatTextBox.addEventListener("keydown", inputEvent.enterSubmitWord.bind(inputEvent))
  94. document.getElementById("word-search-box").addEventListener("keydown",wordSearch)
  95. setInterval(updateTypingSpeed,1000)
  96. }
  97.  
  98.  
  99.  
  100. class typingCheck {
  101.  
  102. constructor() {
  103. this.typelog = "";
  104. }
  105.  
  106.  
  107. /**
  108. *@Description inputイベントで入力ワードを比較する。
  109. */
  110. typeCheck(event){
  111.  
  112. const c = new RegExp(`^${chatTextBox.textContent.slice(1)}`,"i")
  113. const match = setWords[0] ? setWords[0].match(c) : ""
  114. const matchLength = (match ? match[0].length : 0)
  115.  
  116. if(event.data && /insertCompositionText|insertText/.test(event.inputType) && this.typelog.length < event.target.textContent.length){
  117. document.getElementById("typing-count").textContent = ++typeCounter;
  118. updateTypingSpeed()
  119. }
  120.  
  121. this.typelog = event.target.textContent || "";
  122.  
  123. if(match){
  124. wordArea.textContent = setWords[0].slice(matchLength) + separator + setWords.slice(1).join(separator)
  125. }else if(!chatTextBox.textContent){
  126. wordArea.textContent = setWords.join(separator)
  127. }
  128.  
  129. }
  130.  
  131.  
  132.  
  133. /**
  134. *@Description チャットテキストボックスのkeydownイベント。
  135.  
  136. *@note
  137. *Enterで送信時、入力したワードを評価。
  138. *Escでワードスキップ
  139. *Tabでテキストボックスフォーカス切り替え
  140. */
  141. enterSubmitWord(event){
  142.  
  143. if(event.key == "Enter"){
  144.  
  145. if(setWords[0] == chatTextBox.textContent.slice(1)){
  146. setWords = setWords.slice(1)
  147. }
  148.  
  149. if(chatTextBox.textContent != "#" && chatTextBox.textContent){
  150. document.getElementById("typing-count").textContent = ++typeCounter;
  151. updateTypingSpeed()
  152. }
  153.  
  154. wordArea.textContent = setWords.join(separator)
  155.  
  156. }else if(event.key == "Escape"){
  157.  
  158. setWords = setWords.slice(1)
  159. wordArea.textContent = setWords.join(separator)
  160.  
  161. }else if(event.key == "Tab"){
  162.  
  163. document.getElementById("word-search-box").focus()
  164. event.preventDefault()
  165.  
  166. }
  167. }
  168.  
  169. }
  170.  
  171.  
  172.  
  173.  
  174. /**
  175. *@Description ?でワードを検索する。
  176. */
  177. function wordSearch(event){
  178.  
  179. //検索ボックスにフォーカスしている状態でEnterを押した
  180. if(event.key == "Enter"){
  181. //Enterを押した検索ボックスの要素
  182. const searchBox = event.target
  183. //文字列で正規表現を作成
  184. const RegText = `^${searchBox.value.replace(/[?]/g, "\\D").replace(/[?]/g, "\\d")}$`
  185. //文字列を正規表現に変換
  186. const Reg = new RegExp(RegText ,"i")
  187.  
  188. //正規表現にマッチする単語のみを絞り込む
  189. setWords = words.filter(word => Reg.test(word)).slice(0,500);
  190.  
  191. //日本語検索時は全角スペースで区切る。英単語は半角スペースで区切る。
  192. separator = (/?/.test(searchBox.value) ? " " : " ")
  193.  
  194. //結果を出力
  195. wordArea.textContent = setWords.join(separator)
  196. //結果件数を表示
  197. document.getElementById("word-match").textContent = setWords.length
  198. //検索ボックスを初期化
  199. searchBox.value = ""
  200. //打鍵速度計測用時間・測定用打鍵数を設定
  201. searchTime = new Date().getTime()
  202. roundTypeCounter = new Number(typeCounter)
  203. document.getElementById("typing-speed").textContent = (0).toFixed(1)
  204.  
  205. }else if(event.key == "Tab"){
  206.  
  207. chatTextBox.focus()
  208.  
  209. event.preventDefault()
  210.  
  211. }
  212.  
  213. }
  214.  
  215.  
  216.  
  217.  
  218. /**
  219. *@Description 打鍵速度を更新する
  220. */
  221. function updateTypingSpeed(){
  222.  
  223. document.getElementById("typing-speed").textContent = ((typeCounter - roundTypeCounter) / ((new Date().getTime()-searchTime)/1000)).toFixed(1)
  224.  
  225. }