Rubyで仮面ライダークウガのグロンギ語翻訳ロジックを書いてみた-part1-

# Rubyで仮面ライダークウガのグロンギ語翻訳ロジック

## はじめに
仮面ライダークウガを知っていますか？
2000年に初回放映された、平成仮面ライダーの記念すべき第1作目です。
主演はオダギリジョー。

物語は、日本の遺跡に封印されていたグロンギ族が現代に蘇り、
人類を対象に行われる殺戮ゲームを止めるために、仮面ライダークウガが戦うというものです。

その作品中に仮面ライダークウガの敵役の、グロンギ族が扱う「グロンギ語」というものがあります。

## グロンギ語って？
作品中でグロンギ族が使う言語です。

グロンギ族は、私たち現代人とは違う種族です。
種族が違うことから作中で彼らが使用する言語も変えて、彼らに不気味さを持たせていました。
グロンギ語の台詞の中には序盤のうちに、作中の謎の核心についても触れられており、これらを隠すためにも効果的だったようです。

グロンギ語は日本語を換字式暗号によって置き換えたもので表現されているので、
ルールさえわかれば、翻訳ロジックは簡単です。

## 翻訳ルール
1. 対応表に沿う
googleさんで、グロンギ語で検索してください。
か行は、バ行。た行は、ダ行などに変換していきます。
例）
こんにちは　=>　ボンビヂザ

2. 特定の単語は変換を行わない
グロンギ語には、特定の意味を持つ単語があります。
クウガ　→　仮面ライダークウガのこと。
リント　→　グロンギ族が殺戮ゲームの対象にする種族。要するに我々のこと。
ゲゲル　→　グロンギ族が行う、殺戮ゲームのこと。クリアすると上位ランクへ昇格する。
グロンギの名前　→　劇中に出てくるグロンギの名前(ダグバ、バルバなど他にも多数)
などなど。
これらの単語は、変換を行いません。
例）
それは、「クウガ」のベルト　→　ゴゼバ、「クウガ」ボゼブド

3. 「ー」及び「っ」の扱い
ーがある場合は、前の文字を重ねる。
っがある場合は、後の文字を重ねる。
例）
ゲーム　→　ゲゲル
電撃キック　→　ゼンゲビビブブ

4. その他(今回採用しなかったもの)
他にも、ルールがいくつかあります。
要件に入れてしまうと膨大になってしまうので、とりあえず保留です。
・強調したい単語は、文末へ持っていく。
・助詞で使う「の」は変化する。
・漢字への対応
・9進数の使用

## コード
※2015年　12月30日時点のソース

```lang:gurongi.rb

require 'yaml'
require 'active_support/core_ext/object/blank.rb'

class Gurongi
  GURONGI_MAP = YAML.load_file("mapping_table.yml")
  FILTER_WORDS = YAML.load_file("filter_words.yml")

  ########################
  # 例外単語位置特定メソッド
  # 日本語の文字列の中に例外の単語(クウガ、ゲゲルなど)があった場合、
  # 該当する文字列の開始位置と終了位置の配列を持つハッシュを返却する。
  def search_exception_points jp
    start_points = []
    end_points = []
    FILTER_WORDS.each do |e|
      if (origin = jp.index(e))
        start_points.push origin
        end_points.push (origin + (e.length - 1))
      end
    end
    ext_potision = {
      :s => start_points.sort ,
      :e => end_points.sort
    }
  end

  ########################
  # 翻訳メソッド
  # 日本語の文字列を受け取り、グロンギ語で翻訳した文字列を返却する
  def translate_gurongi ext_p, jp
    gurongi_array = []
    ext_i = 0
    jp.split("").each_with_index do |c, i|
      gurongi_array.push(translate_chars(c, jp, ext_p[:s][ext_i] , ext_p[:e][ext_i], i))
      if ext_p[:e][ext_i + 1].present?
        ext_i = ext_i + 1 if ext_p[:e][ext_i] < i
      end
    end
    gurongi_array
  end

  ########################
  # 文字変換メソッド
  # 渡された文字によって、翻訳ルールに沿って変換後の文字を返却する
  def translate_chars c, jp, sp, ep, i
    return GURONGI_MAP[jp[i - 1]] if 'ー' === c
    return GURONGI_MAP[jp[i + 1]] if 'っ' === c || 'ッ' === c
    if sp.present? && ep.present?
      sp <= i && i <= ep ? c : c = GURONGI_MAP[c]
    else
      GURONGI_MAP[c]
    end
  end
end

if (str_jp = ARGV[0]).blank?
  puts '引数を入力してください。Usage => [ruby gurongi.rb ほげほげ]'
  exit
end
gurongi = Gurongi.new
ext_poiints = gurongi.search_exception_points(str_jp)
result_array = gurongi.translate_gurongi(ext_poiints, str_jp).join
puts result_array

```

- 日本語の五十音とグロンギ語の対応するyml

```lang:mapping_table.yml
あ: ガ
い: ギ
う: グ
え: ゲ
お: ゴ
か: バ
き: ビ
  ・
　・
　・
（これが続く）
```


- 翻訳しない例外単語を記述するyml

```lang:filter_words.yml
- クウガ
- リント
- ゲリザギバスゲゲル
- ザギバスゲゲル
- ゲゲル
- ン・ダグバ・ゼバ
- ダグバ
- ラ・バルバ・デ
　・
　・
　・
（これが続く）
```
## 感想
フレームワークとか使わずに、とりあえずロジックを勢いで書いてみました。
案外、ルールを絞ったのですが複雑になるものですね。

特にルール2の例外単語を識別し、開始位置と終了位置を取得するロジックが、すごい苦労しました。
(例外単語を見つけるために、例外単語を繰り返しているのが、気に入らないので、後々改修したい)
ソースも特別、綺麗ではないのですが、引き続き手を入れていきます。

現在、iOSの勉強もしているので、
iOSアプリ作成して、そのうちグロンギ翻訳アプリ作成したいです。
このロジックをAPIとして利用するか、
swiftでロジックを書きなおすかは、その時の気分次第。
次は、９進数に挑戦しようかなと思います。