@haoling haoling / yoromorsify.html
Created at Sun Jan 12 17:38:44 GMT 2020
ヨロチャンのモールスを変換するっす
yoromorsify.html
Raw
  1. <html>
  2.  
  3. <head>
  4. <title>すすーっすっすーっっすっーっすすーっすっすっーっっすすーすっっすっーっすすっすーすっすすっーすすすっすーっすすすーっーっすっすっーっすっっーっすっすっーすすすっすーすっすすっーっすすっーすすすっすー</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  6. <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  7. </head>
  8.  
  9. <body>
  10. <div>
  11. 原文<br />
  12. <div style="font-size: x-small;">
  13. 全角カタカナで入力してください<br />
  14. ひらがなからカタカナへの変換などは行いません。<br />
  15. 半角カナはサポートしていません。<br />
  16. </div>
  17. <textarea id="text" rows="10" cols="40">アンナチャン…</textarea><br />
  18. </div>
  19. <div>
  20. <button id="btn_encode">↓エンコード</button>&nbsp;&nbsp;<button id="btn_decode">↑デコード</button><br />
  21. </div>
  22. <div>
  23. ヨロモールス&nbsp;<button id="play" style="font-size: xx-small;">再生</button><br />
  24. <textarea id="yoro" rows="10" cols="40">ススッススーッスッスッーッスッーッッスッーッススーッスッスッー…</textarea><br />
  25. </div>
  26. <script>
  27. /**
  28. * @var Map<String, String> table カタカナとモールス信号の対照表。すっじゃなくて10で書いてるのは、単純に視認性が良かったから。
  29. */
  30. var table = {
  31. 'ア': '11011',
  32. 'カ': '0100',
  33. 'サ': '10101',
  34. 'タ': '10',
  35. 'ナ': '010',
  36. 'ハ': '1000',
  37. 'マ': '1001',
  38. 'ヤ': '011',
  39. 'ラ': '000',
  40. 'ワ': '101',
  41. 'イ': '01',
  42. 'キ': '10100',
  43. 'シ': '11010',
  44. 'チ': '0010',
  45. 'ニ': '1010',
  46. 'ヒ': '11001',
  47. 'ミ': '00101',
  48. 'リ': '110',
  49. 'ヰ': '01001',
  50. 'ウ': '001',
  51. 'ク': '0001',
  52. 'ス': '11101',
  53. 'ツ': '0110',
  54. 'ヌ': '0000',
  55. 'フ': '1100',
  56. 'ム': '1',
  57. 'ユ': '10011',
  58. 'ル': '10110',
  59. 'ン': '01010',
  60. 'オ': '01000',
  61. 'ケ': '1011',
  62. 'セ': '01110',
  63. 'テ': '01011',
  64. 'ネ': '1101',
  65. 'ヘ': '0',
  66. 'メ': '10001',
  67. 'レ': '111',
  68. 'ヱ': '01100',
  69. '、': '010101',
  70. 'エ': '10111',
  71. 'コ': '1111',
  72. 'ソ': '1110',
  73. 'ト': '00100',
  74. 'ノ': '0011',
  75. 'ホ': '100',
  76. 'モ': '10010',
  77. 'ヨ': '11',
  78. 'ロ': '0101',
  79. 'ヲ': '0111',
  80. '。': '010100',
  81. '0': '11111',
  82. '1': '01111',
  83. '2': '00111',
  84. '3': '00011',
  85. '4': '00001',
  86. '5': '00000',
  87. '6': '10000',
  88. '7': '11000',
  89. '8': '11100',
  90. '9': '11110',
  91. '゛': '00',
  92. 'ー': '01101',
  93. '゜': '00110',
  94. };
  95.  
  96. /**
  97. * @var Map<String, String> revTable 逆検索用のテーブルを作ってキャッシュしたもの
  98. */
  99. var revTable = {};
  100. $.each(table, function (k, v) { revTable[v] = k; });
  101.  
  102. $('#btn_encode').on('click', function () {
  103. // テキストを正規化する
  104. // 濁点と半濁点を分離。小音を普通の大きさにする。
  105. var text = $('#text').val();
  106. text = text.replace(/ガ/g, 'カ゛').replace(/ギ/g, 'キ゛').replace(/グ/g, 'ク゛').replace(/ゲ/g, 'ケ゛').replace(/ゴ/g, 'コ゛');
  107. text = text.replace(/ザ/g, 'サ゛').replace(/ジ/g, 'シ゛').replace(/ズ/g, 'ス゛').replace(/ゼ/g, 'セ゛').replace(/ゾ/g, 'ソ゛');
  108. text = text.replace(/ダ/g, 'タ゛').replace(/ヂ/g, 'チ゛').replace(/ヅ/g, 'ツ゛').replace(/デ/g, 'テ゛').replace(/ド/g, 'ト゛');
  109. text = text.replace(/バ/g, 'ハ゛').replace(/ビ/g, 'ヒ゛').replace(/ブ/g, 'フ゛').replace(/ベ/g, 'ヘ゛').replace(/ボ/g, 'ホ゛');
  110. text = text.replace(/バ/g, 'ハ゛').replace(/ビ/g, 'ヒ゛').replace(/ブ/g, 'フ゛').replace(/ベ/g, 'ヘ゛').replace(/ボ/g, 'ホ゛');
  111. text = text.replace(/ァ/g, 'ア').replace(/ィ/g, 'イ').replace(/ゥ/g, 'ウ').replace(/ェ/g, 'エ').replace(/ォ/g, 'オ');
  112. text = text.replace(/ッ/g, 'ツ').replace(/ャ/g, 'ヤ').replace(/ュ/g, 'ユ').replace(/ョ/g, 'ヨ').replace(/ヮ/g, 'ワ');
  113.  
  114. // 1文字ずつ分離して処理する
  115. var yoro = '';
  116. $.each(text.split(''), function (pos, c) {
  117. var m = table[c];
  118. if (m == undefined) {
  119. // モールスに無い文字はそのまま書く
  120. m = c;
  121. } else {
  122. // 1101 => すすっすー
  123. m = m.replace(/1/g, 'す').replace(/0/g, 'っ');
  124. m += 'ー';
  125. }
  126. yoro += m;
  127. });
  128. $('#yoro').val(yoro);
  129. });
  130.  
  131. $('#btn_decode').on('click', function () {
  132. var yoromors = $('#yoro').val();
  133. // ヨロモールス側は、カタカナ、ひらがな、半角カナを受け入れる
  134. // すすっすーっっすっー => 1101,0010
  135. var mors = yoromors.replace(/[すスス]/g, '1').replace(/[っッッ]/g, '0').replace(/[ー─-ー]/g, ',');
  136. var text = '';
  137.  
  138. // 1グループごとに処理する
  139. $.each(mors.split(','), function (pos, mor) {
  140. // モールスパターンとの完全一致検索
  141. var c = revTable[mor];
  142.  
  143. // 一致するものが無い場合は、モールスパターンをそのまま出す。
  144. if (c == undefined) c = mor;
  145.  
  146. text += c;
  147. });
  148. $('#text').val(text);
  149. });
  150.  
  151.  
  152. /**
  153. * モールス信号再生
  154. * @see https://qiita.com/kurehajime/items/27c98de56fd06f93d0b8
  155. */
  156. var audio = new Audio();
  157. audio.src = 'http://xiidec.appspot.com/etc/pi.wav';
  158. $('#play').on('click', function () {
  159. // ヨロモールスを文字単位に分解
  160. var yoromors = $('#yoro').val().split('');
  161.  
  162. // オーディオリセット
  163. audio.currentTime = 0;
  164.  
  165. /**
  166. * @var Integer remain 次のオーディオ割り込みまでの残り周期
  167. */
  168. var remain = 0;
  169.  
  170. /**
  171. * @var String mors モールスのグループを覚えておく変数。再生中の原文の逐次出力に使う。
  172. */
  173. var mors = '';
  174.  
  175. // 50ミリ秒ごとに割り込み処理
  176. var timer = setInterval(function () {
  177. if (remain > 0) {
  178. // まだ割り込まない
  179. remain--;
  180. if (remain == 0) {
  181. audio.pause();
  182. audio.currentTime = 0;
  183. }
  184. return;
  185. }
  186.  
  187. // オーディオを停止してリセット
  188. audio.pause();
  189. audio.currentTime = 0;
  190.  
  191. if (yoromors.length <= 0) {
  192. // 終わり
  193. clearInterval(timer);
  194. return;
  195. }
  196.  
  197. var onoff = yoromors.shift();
  198. $('#yoro').val($('#yoro').val() + onoff);
  199. if (onoff.match(/[すスス]/)) {
  200. // 長音を再生する
  201. audio.play();
  202. remain = 4;
  203. mors += '1';
  204. } else if (onoff.match(/[っッッ]/)) {
  205. // 単音を再生する
  206. audio.play();
  207. remain = 2;
  208. mors += '0';
  209. } else if (onoff.match(/[ー─-ー]/)) {
  210. // 区切りなので、再生せず無音を作る
  211. remain = 3;
  212.  
  213. // 1グループ分のモールスをデコードして、原文テキストに追記
  214. $('#text').val($('#text').val() + revTable[mors]);
  215. mors = '';
  216. } else {
  217. // モールスとして解読できなかった文字はそのまま原文テキストに転記
  218. $('#text').val($('#text').val() + onoff);
  219. }
  220. }, 50);
  221. $('#text').val('');
  222. $('#yoro').val('');
  223. });
  224. </script>
  225. </body>
  226.  
  227. </html>