ローマ字入力の誤打鍵の自動補正

#１.はじめに
　[ローマ字入力](https://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%83%9E%E5%AD%97%E5%85%A5%E5%8A%9B)とは、読みに対応するローマ字綴りをキーボードなどから入力することをいいます。かな入力とは、キーボードに刻印されたかな文字に基づき、日本語を入力することをいいます。現状、自分の周囲では、ローマ字入力が圧倒的です。

https://weekly.ascii.jp/elem/000/002/631/2631699/

　この記事によると、93.1％が“ローマ字入力”で、“JISかな”は5.1％です。なお、残る1.8％のうち、親指シフト入力は1.2％です。

　この記事では、ローマ字入力についての改善を提案します。

#２. ローマ字入力の課題と解決手段
##２．１．ローマ字入力の課題
　日本語をローマ字綴りする場合、原則は子音⇒母音の順番での２打鍵となります。例外として、あいうえおの母音そのもの、「きゃ」「きゅ」などの拗音、子音の「ん」、長音「ー」があります。
　そして、ローマ字入力する際、高速に打鍵していると、うっかり子音と母音の打鍵順序が逆転する場合があります。例えば、「か」を入力する際に、"ka" ではなく、"ak"と打鍵してしまう場合です。
　打鍵順番の逆転は特に、一方の手で子音キーを、他方の手で母音キーを打鍵するパターンにて発生しやすいようです。

　右手子音+左手母音の組み合わせ
    ya,pa,ha,ja,ka,la,ma,na
    ye,pe,he,je,ke,le,me,le 
　左手子音+右手母音の組み合わせ
    qu,wu,ru,tu,su,du,fu,gu,zu,xu,cu,vu,bu
    qi,wi,ri,ti,si,di,fi,gi,zi,xi,ci,vi,bi
    qo,wo,ro,to,so,do,fo,go,zo,xo,co,vo,bo

このように、「か」の高速打鍵時にローマ字綴りの子音と母音の順序が逆転して「あk」となった場合でも、正しく「か」として入力することを課題とします。

##２．２．課題の解決手段
　このような打鍵順番の逆転に対する解決手段として、同時打鍵を導入することといたしました。
　同時打鍵とは、NICOLA配列規格書に以下のように定義されています。

>　一回の動作で、文字キーと親指キーとの二つを順不同で、ピアノの和音のように、同時性を意図して打鍵すること。

　NICOLA配列規格においては、文字キーと親指キーの打鍵順序は順不同です。同時性を意図して打鍵したものを同時打鍵とし、同時性を意図せずに打鍵したものを順次打鍵とします。
　これを応用して、ローマ字入力においても、子音文字キーと母音文字キーの打鍵順序を順不同とし、同時性を意図して打鍵したものを子音⇒母音の順に出力することとします。これにより、子音と母音の打鍵順序が逆転しても正しい打鍵順序に修正可能です。
　なお、NICOLAの同時打鍵は、親指キーと文字キーという非対称な２つのキーが対象ですが、ローマ字入力における母音キーと子音キーとは、どちらも文字キーであるため、新たに状態遷移表を作成する必要があります。

　なお、同じようなことを考えられ、かつ実装されたのが、Dvorakjの作者blechmusikさんです。

　[ローマ字入力用QWERTY 配列（同時に打鍵する機能付き）を作成した](https://blechmusik.hatenablog.jp/entry/20100627/1277582774)

　こちらは、ローマ字入力の高速化に使えないかと考えられた方です。但し、単に順次打鍵を同時打鍵に置き換えただけでは、高速化は難しいようです。
　[逆あんみつ式ローマ打ち日本語入力](https://tu3.jp/0846)
　[日本語入力の効率化を図る同時打鍵方式手法 - 情報処理学会](https://ipsj.ixsq.nii.ac.jp/ej/?action=repository_uri&item_id=181569&file_id=1&file_no=1)

#３．文字同時打鍵のロジック
　文字同時打鍵の判定は次によります。
　なお、Tthは、同時打鍵時間です。Lは同時打鍵時間の最小割合です。M1,M2,M3は入力された文字キーのコードです。
　M12は、文字キー(M1)と(M2)を同時打鍵したときに出力するキーコードです。
　初期化とは、例えばモディファイアキー（シフトキー・ALTキー・Windowsキー・Ctrlキーなど）の打鍵や、ＩＭＥの英数モードとローマ字モードの遷移です。

##(1) 初期状態
###(1.1)　第１文字キー(M1)押下
- 第１文字キー(M1)が押下された場合、当該文字キー(M1)をセットし、タイムアウト時間を単独打鍵判定時間(Tth*(1-L)/L)にセットして、文字キー押下状態(S2)へ遷移します。

##(2) 文字キー(M1)押下状態
###(2.1)　初期化
- 初期化された場合、セットされている第１文字(M1)を出力し、初期状態(S1)へ遷移します。

###(2.2)　第２文字キー(M2)が押下
- 処理G（組み合わせ判定）・・・第２文字キー(M2)が押下された場合、セットされている第１文字(M1)との組み合わせ出力が有るか否かを判定します。
- (a)	文字(M12)の組み合わせがあれば、組み合わせた文字(M12)をセットし、タイムアウト時間を同時打鍵判定時間(Tth)にセットし、文字キー２押下状態(S3)へ遷移します。
- (b)	文字(M12)の組み合わせがなければ、セットされている文字(M1)を出力し、文字キー(M2)をセットしてタイムアウト時間を単独打鍵判定時間(Tth*(1-L)/L)にセットし、文字キー押下状態(S2)のまま遷移しません。

###(2.3)　第１文字キー(M1)がオフ
- 第１文字キー(M1)がオフされた場合、セットされている第１文字(M1)を出力し、初期状態(S1)へ遷移します。

###(2.4)　タイムアウト
- 単独打鍵判定時間(Tth*(1-L)/L)が経過するとタイムアウトとします。タイムアウトとなった場合、セットされている第１文字(M1)を出力し、初期状態(S1)へ遷移します。

##(3) 文字キー(M2)押下状態

### (3.1)　初期化
- 初期化された場合、セットされている第１文字(M1)と第２文字(M2)を順次出力し、初期状態(S1)へ遷移します。

### (3.2)　第３文字キー(M3)押下
- 処理H（組み合わせ判定と３キー判定）・・・第３文字キー(M3)が押下された場合、セットされている第２文字(M2)との組み合わせ出力が有り、T12≧T23であるか否かを判定します。
  T12は、第１文字(M1)の押下から第２文字(M2)の押下までの時間です。
  T23は、第２文字(M2)の押下から第３文字(M3)の押下までの時間です。

- (a)	文字(M23)の組み合わせがあり、T12≧T23ならば、文字(M12)を出力して、第３文字キー(M3)をセットして、タイムアウト時間を単独打鍵判定時間(Tth*(1-L)/L)にセットすると、文字キー押下状態(S2)へ遷移します。
- (b)	文字(M23)の組み合わせがないか、またはT12＜T23ならば、文字(M1)を出力して、文字キー(M23)をセットして、タイムアウト時間を同時打鍵判定時間(Tth)にセットすると、文字キー２押下状態(S3)のまま遷移しません。

###(3.3)　処理I（重なり厚み判定）
- 第１文字キー(M1)がオフされた場合、第１文字キー(M1)が押下されて第２文字キー(M2)が押下されるまでの時間(T12)と、第２文字キー(M2)が押下されて第１文字キー(M1)がオフされるまでの時間(T2_1)を比較します。
- (a)	T12≧T2_1ならば、文字(M1)を出力して、文字キー(M2)をセットして、タイムアウト時間を単独打鍵判定時間(Tth*(1-L)/L)にセットすると、文字キー押下状態(S2)へ遷移します。
- (b)	T12＜T2_1ならば、タイムアウト時間を単独打鍵判定時間(Tth*(1-L)/L)-T12にセットすると、状態(S4)へ遷移します。

###(3.4)　文字キー(M2)オフ
- 第２文字キー(M2)がオフされた場合、セットされている文字(M12)を出力すると、初期状態(S1)へ遷移します。

###(3.5)　タイムアウト
- 同時打鍵判定時間(Tth)が経過してタイムアウトすると、セットされている文字(M12)を出力し、初期状態(S1)へ遷移します。

##(4) 文字キー(M1)(M2)オン(M1)オフ状態
###(4.1)　初期化
- 初期化された場合、セットされている文字(M1)と(M2)を順次出力し、初期状態(S1)へ遷移します。

###(4.2)　文字キー(M3)オン
- 第３文字キー(M3)が押下された場合、セットされている文字(M12)を出力し、文字キー(M3)をセットして、タイムアウト時間を単独打鍵判定時間(Tth*(1-L)/L)にセットすると、文字キーオン状態(S2)へ遷移します。

###(4.3)　文字キー(M2)オフ
- 第２文字キー(M2)がオフされた場合、セットされている文字(M12)を出力し、初期状態(S1)へ遷移します。

###(4.4)　タイムアウト
- 単独打鍵判定時間が経過してタイムアウトすると、セットされている文字(M1)と(M2)を順次出力し、初期状態(S1)へ遷移します。

|  |S1) 初期状態|S2) M1オン状態|S3) M1M2オン状態|S4) M1M2オンM1オフ状態|
|:-----------------|:-----------------:|:------------------:|:-----------------:|:------------------:|
| 初期化        |…|M1出力、 S1)へ|M12出力、 S1)へ|M1,M2出力、 S1)へ|
|文字キー(M1)オン|M1セット、 S2)へ|…|…|…|
|文字キー(M2)オン|…|処理G（組み合わせ判定）|ー|ー|
|文字キー(M3)オン|…|…|処理H（組み合わせ判定と３キー判定）|M12出力、M3をM1にセット、S2)へ|
|文字キー(M1)オフ|…|M1出力、 S1)へ|処理I (重なり厚み判定)|－|
|文字キー(M2)オフ|…|－|M12出力、 S1)へ|M12出力、 S1)へ|
|タイムアウト    |…|M1出力、 S1)へ|M12出力、 S1)へ|M1,M2出力、 S1)へ|

- 零遅延モードにおいては、文字キーの押下と共に先行出力され、以下にて確定したキーと先行出力とを比較します。確定したキーと先行出力とが相違していれば、バックスペースキーを出力したのち、確定したキーを出力します。

#４．配列ファイル

　以下に、ローマ字入力用QWERTY配列のパターンファイルを示します。母音と子音の組み合わせを同時打鍵として定義しています。この配列ファイルに基づき、紅皿が同時打鍵として認識した場合には、正しいローマ字綴りの文字を出力するようにしています。

```ini:ローマ字入力用QWERTY配列.bnz
;ローマ字入力用QWERTY配列
; 規定時間中に「母音キー + 子音キー」を入力すると
; 「子音キー + 母音キー」に変換する
; たとえば、ak と素早く入力したときには、 ka を出力する
; https://tu3.jp/0846

[配列]
名称=ローマ字入力用QWERTY配列
バージョン=
URL=http://d.hatena.ne.jp/blechmusik2/20100627/1277582774

[ローマ字シフト無し]
１,２,３,４,５,６,７,８,９,０,－,＾,￥,後
ｑ,ｗ,ｅ,ｒ,ｔ,ｙ,ｕ,ｉ,ｏ,ｐ,＠,［
ａ,ｓ,ｄ,ｆ,ｇ,ｈ,ｊ,ｋ,ｌ,；,：,］
ｚ,ｘ,ｃ,ｖ,ｂ,ｎ,ｍ,，,．,／,￥

<a>
無,無,無,無,無,無,無,無,無,無,無,無,無
くぁ,わ,無,ら,た,や,無,無,無,ぱ,無,無
無,さ,だ,ふぁ,が,は,じゃ,か,ぁ,無,無,無
ざ,ぁ,か,ゔぁ,ば,な,ま,無,無,無,無

<i>
無,無,無,無,無,無,無,無,無,無,無,無,無
くぃ,うぃ,無,り,ち,無,無,無,無,ぴ,無,無
無,し,ぢ,ふぃ,ぎ,ひ,じ,き,ぃ,無,無,無
じ,ぃ,し,ゔぃ,び,に,み,無,無,無,無

<u>
無,無,無,無,無,無,無,無,無,無,無,無,無
く,う,無,る,つ,ゆ,無,無,無,ぷ,無,無
無,す,づ,ふ,ぐ,ふ,じゅ,く,ぅ,無,無,無
ず,ぅ,く,ゔ,ぶ,ぬ,む,無,無,無,無

<e>
無,無,無,無,無,無,無,無,無,無,無,無,無
くぇ,うぇ,無,れ,て,いぇ,無,無,無,ぺ,無,無
無,せ,で,ふぇ,げ,へ,じぇ,け,ぇ,無,無,無
ぜ,ぇ,せ,ゔぇ,べ,ね,め,無,無,無,無

<o>
無,無,無,無,無,無,無,無,無,無,無,無,無
くぉ,を,無,ろ,と,よ,無,無,無,ぽ,無,無
無,そ,ど,ふぉ,ご,ほ,じょ,こ,ぉ,無,無,無
ぞ,ぉ,こ,ゔぉ,ぼ,の,も,無,無,無,無

[ローマ字小指シフト]
！,”,＃,＄,％,＆,’,（,）,'',＝,～,｜
Ｑ,Ｗ,Ｅ,Ｒ,Ｔ,Ｙ,Ｕ,Ｉ,Ｏ,Ｐ,‘,｛
Ａ,Ｓ,Ｄ,Ｆ,Ｇ,Ｈ,Ｊ,Ｋ,Ｌ,＋,＊,｝
Ｚ,Ｘ,Ｃ,Ｖ,Ｂ,Ｎ,Ｍ,＜,＞,？,＿

```


#５．結論
##５．１．ダウンロード先と使用方法
　上記の仕様を組み込んだものが、紅皿 ver.0.1.4.6 です。OSDNからダウンロード可能です。

https://osdn.net/projects/benizara/releases/

　紅皿を起動すると、紅皿設定ダイアログを表示させたのち、配列ファイルとして "ローマ字入力用QWERTY配列.bnz" を選択してください。これにより、ローマ字同時打鍵が動作します。

##５．２．今後の課題
-　同時打鍵を導入したため、キー入力が画面出力されるのが一瞬遅れます。これに対処するために零遅延モードがあるのですが、文字同時打鍵ではなかなか文字が確定しないため、画面がちらついて見えにくくなります。文字同時打鍵であっても、適切に画面表示可能な方法を考える必要があります。