/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/otR3
*/
// Google IME APIをつかったmigemoっぽいの
// 通信が間に合わないときは"><"がかえる
// あんまりGPLにしたくないです
package {
import flash.display.Sprite;
import flash.text.TextField;
import jp.progression.commands.net.*;
import flash.net.*;
import flash.display.Bitmap;
import flash.utils.*;
import flash.events.*;
import com.bit101.components.*;
import com.adobe.serialization.json.JSON;
public class Test extends Sprite {
private var _tf : TextField;
private var _it : InputText;
public function Test() {
_tf = new TextField();
_tf.width = 465;
_tf.height = 465;
_tf.y = 40;
addChild(_tf);
WonderflMigemo._tf = _tf;
_it = new InputText(this, 100, 20, "", function(e:Event) : void{
WonderflMigemo.complement(_it.text, function(reg : String) : void{
tr(_it.text + "\t" + reg);
});
});
}
private function tr(...o : Array) : void
{
_tf.appendText(o + "\n");
}
}
}
import com.adobe.serialization.json.JSON;
import flash.events.Event;
import flash.net.*;
import flash.utils.*;
import flash.text.*;
class WonderflMigemo {
public static var _tf : TextField;
public static var _blocking : Boolean = false;
/**
* 正規表現を作成
*/
public static function complement(query : String, callback : Function) : void
{
if(_blocking){
callback("><");
return;
}
var ret : Vector.<String> = new Vector.<String>();
ret.push(query);
if (query.length == 0){
callback(concatVec(ret));
return;
}
// 英字の半角をexpand
ret.push(expandAlphabet(query));
query = convertHiraganaToKatakana(query);
var expandedRomans : Vector.<String> = expandConsonant(query.replace(/([sktpgdzc]){2,}/g, "xtu$1"));
var reqmap : Object = {};
for each(var eroman : String in expandedRomans) {
var kata : String = convertRomanToKatakana(eroman);
ret.push(kata);
var hira : String = convertKatakanaToHiragana(kata);
ret.push(hira);
reqmap[hira] = hira;
}
var reqs : Array = [];
for(var key : String in reqmap){
reqs.push(key);
}
if(reqs.length != 1){
ret.sort(compstr); // ソート
ret = uniq(ret); // 同一表現を除去
callback(concatVec(ret));
}else{
_blocking = true;
var proxyUrl : String = "http://uwiproxy.appspot.com/simpleproxy?url=";
var url : String = "http://www.google.com/transliterate?langpair=ja-Hira|ja%26text=";
var x : String = reqs[0];
var nurl : String = proxyUrl + url + escapeMultiByte(x);
var ul : URLLoader = new URLLoader();
ul.dataFormat = URLLoaderDataFormat.BINARY;
ul.load(new URLRequest(nurl));
ul.addEventListener(Event.COMPLETE, function(e : Event) : void
{
ul.removeEventListener(Event.COMPLETE, arguments.callee);
var ba : ByteArray = ul.data as ByteArray;
var str : String = ba.readMultiByte(ba.length, "MS932");
str = str.replace(/,\s*\]/gs, "]"); // JSON規約違反を直す
var json : Object = JSON.decode(str);
if(json.length == 1){
for each(var ss : String in json[0][1]){
ret.push(ss);
}
ret.sort(compstr); // ソート
ret = uniq(ret); // 同一表現を除去
_blocking = false;
callback(concatVec(ret));
}else{
var reg : String = "";
for each(var seg : Object in json){
if(seg[1].length > 0){
var vec : Vector.<String> = new Vector.<String>();
for each(var st : String in seg[1]){
vec.push(st);
}
reg += "(" + concatVec(vec) + ")";
}
}
_blocking = false;
callback(concatVec(ret) + "|(" + reg + ")");
}
});
}
}
/**
* 正規表現のメタ文字をエスケープして|でつなぐ
* @param vec
* @return
*/
public static function concatVec(vec : Vector.<String>) : String
{
var s2 : String = "";
var s1 : String = "";
for each(var str : String in vec) {
var s : String = escapeRegex(str);
if(s.length == 1){
s1 += s;
}else{
s2 += s + "|";
}
}
if(s1.length == 0 && s2.length == 0)return "";
if(s1.length == 0)return s2.substring(0, s2.length - 1);
if(s1.length == 1)return s2 + s1;
return s2 + "[" + s1 + "]";
}
public static function escapeRegex(str : String) : String
{
return str.replace(/([\*\+\.\?\{\}\(\)\[\]\^\$\-\|\/\\])/g, "\\$1");
}
/**
* 隣接する共通文字列を除去
* @param vec
* @return
*/
private static function uniq(vec : Vector.<String>) : Vector.<String>
{
var ret : Vector.<String> = new Vector.<String>();
var prev : String = null;
for each(var str : String in vec) {
if (str.length == 0 || prev == str) continue;
ret.push(str);
prev = str;
}
return ret;
}
/**
* 簡単な文字列比較関数
* @param a
* @param b
* @return
*/
private static function compstr(a : String, b : String) : int
{
return a < b ? -1 : 1;
}
/**
* 半角英数を全角英数に変換
* @param src
* @return
*/
private static function expandAlphabet(src : String) : String
{
var vec : Array = new Array();
for (var i : int = 0; i < src.length; i++) {
var c : int = src.charCodeAt(i);
if (c >= 0x0021 && c <= 0x007e) {
c += (0xff01 - 0x0021);
}
vec.push(c);
}
return String.fromCharCode.apply(String, vec);
}
/**
* 全角ひらがなを全角カタカナに変換
* @param kana
* @return
*/
private static function convertHiraganaToKatakana(kana : String) : String
{
kana = kana.replace(/う゛/g, "ヴ");
var vec : Array = [];
for (var i : int = 0; i < kana.length; i++) {
var c : int = kana.charCodeAt(i);
if (c >= 0x3041 && c <= 0x3093) {
c += (0x30a1 - 0x3041);
}
vec.push(c);
}
return String.fromCharCode.apply(String, vec);
}
/**
* 全角カタカナを全角ひらがなに変換
* @param kana
* @return
*/
private static function convertKatakanaToHiragana(kana : String) : String
{
kana = kana.replace(/ヴ/g, "う゛");
var vec : Array = [];
for (var i : int = 0; i < kana.length; i++) {
var c : int = kana.charCodeAt(i);
if (c >= 0x30a1 && c <= 0x30f3) {
c += (0x3041 - 0x30a1);
}
vec.push(c);
}
return String.fromCharCode.apply(String, vec);
}
/**
* ローマ字を全角カタカナに変換
* @param roman
* @return
*/
private static function convertRomanToKatakana(roman : String) : String
{
var ret : String = "";
var p : int = 0;
while(true) {
for (var q : int = p + 1; q <= roman.length; q++) {
var str : String = roman.substring(p, q);
var kata : String = ROMA2KATA[str];
if (kata != null) {
ret += kata;
p = q;
break;
}else if(str.charAt(0) == "n" && str.length == 2){
ret += "ン";
q--;
p = q;
break;
}
}
if (q > roman.length)break;
}
return ret;
}
/**
* ローマ字を補完
* @param roman
* @return
*/
private static function expandConsonant(roman : String) : Vector.<String>
{
var ret : Vector.<String> = new Vector.<String>();
if (roman.length == 0) return ret;
var lastc : int = roman.charCodeAt(roman.length - 1);
switch(lastc){
case 0x63: // 'c'
ret.push(roman + "hi");
break;
case 0x78: // 'x'
ret.push(roman + "tu");
ret.push(roman + "ya");
ret.push(roman + "yu");
ret.push(roman + "yo");
break;
case 0x79: // 'y'
ret.push(roman + "a");
ret.push(roman + "u");
ret.push(roman + "o");
break;
case 0x6e: // 'n'
ret.push(roman + "n");
case 0x62: // 'b'
case 0x64: // 'd'
case 0x66: // 'f'
case 0x67: // 'g'
case 0x68: // 'h'
case 0x6a: // 'j'
case 0x6b: // 'k'
case 0x6d: // 'm'
case 0x70: // 'p'
case 0x72: // 'r'
case 0x73: // 's'
case 0x74: // 't'
case 0x77: // 'w'
case 0x7a: // 'z'
ret.push(roman + "a");
ret.push(roman + "i");
ret.push(roman + "u");
ret.push(roman + "e");
ret.push(roman + "o");
if (roman.slice(-2) != "sh" && lastc != 0x6e) {
var c : String = String.fromCharCode(lastc);
var base : String = roman.slice(0, -1) + "xtu" + c;
ret.push(base + "a");
ret.push(base + "i");
ret.push(base + "u");
ret.push(base + "e");
ret.push(base + "o");
}
break;
default:
ret.push(roman);
break;
}
return ret;
}
// ローマ字→全角カタカナ変換テーブル
private static const ROMA2KATA : Object = {
"a" : "ア",
"i" : "イ",
"u" : "ウ",
"e" : "エ",
"o" : "オ",
"ka" : "カ",
"ki" : "キ",
"ku" : "ク",
"ke" : "ケ",
"ko" : "コ",
"sa" : "サ",
"si" : "シ",
"su" : "ス",
"se" : "セ",
"so" : "ソ",
"ta" : "タ",
"ti" : "チ",
"tu" : "ツ",
"te" : "テ",
"to" : "ト",
"na" : "ナ",
"ni" : "ニ",
"nu" : "ヌ",
"ne" : "ネ",
"no" : "ノ",
"ha" : "ハ",
"hi" : "ヒ",
"hu" : "フ",
"he" : "ヘ",
"ho" : "ホ",
"ma" : "マ",
"mi" : "ミ",
"mu" : "ム",
"me" : "メ",
"mo" : "モ",
"ya" : "ヤ",
"yi" : "イ",
"yu" : "ユ",
"ye" : "イェ",
"yo" : "ヨ",
"ra" : "ラ",
"ri" : "リ",
"ru" : "ル",
"re" : "レ",
"ro" : "ロ",
"wa" : "ワ",
"wi" : "ヰ",
"wu" : "ウ",
"we" : "ヱ",
"wo" : "ヲ",
"ga" : "ガ",
"gi" : "ギ",
"gu" : "グ",
"ge" : "ゲ",
"go" : "ゴ",
"za" : "ザ",
"zi" : "ジ",
"zu" : "ズ",
"ze" : "ゼ",
"zo" : "ゾ",
"da" : "ダ",
"di" : "ヂ",
"du" : "ヅ",
"de" : "デ",
"do" : "ド",
"ba" : "バ",
"bi" : "ビ",
"bu" : "ブ",
"be" : "ベ",
"bo" : "ボ",
"pa" : "パ",
"pi" : "ピ",
"pu" : "プ",
"pe" : "ペ",
"po" : "ポ",
"la" : "ァ",
"li" : "ィ",
"lu" : "ゥ",
"le" : "ェ",
"lo" : "ォ",
"lya" : "ャ",
"lyi" : "ィ",
"lyu" : "ュ",
"lye" : "ェ",
"lyo" : "ョ",
"xa" : "ァ",
"xi" : "ィ",
"xu" : "ゥ",
"xe" : "ェ",
"xo" : "ォ",
"xya" : "ャ",
"xyi" : "ィ",
"xyu" : "ュ",
"xye" : "ェ",
"xyo" : "ョ",
"kya" : "キャ",
"kyi" : "キィ",
"kyu" : "キュ",
"kye" : "キェ",
"kyo" : "キョ",
"gwa" : "グァ",
"gwi" : "グィ",
"gwu" : "グゥ",
"gwe" : "グェ",
"gwo" : "グォ",
"gya" : "ギャ",
"gyi" : "ギィ",
"gyu" : "ギュ",
"gye" : "ギェ",
"gyo" : "ギョ",
"sha" : "シャ",
"shi" : "シ",
"shu" : "シュ",
"she" : "シェ",
"sho" : "ショ",
"swa" : "スァ",
"swi" : "スィ",
"swu" : "スゥ",
"swe" : "スェ",
"swo" : "スォ",
"sya" : "シャ",
"syi" : "シィ",
"syu" : "シュ",
"sye" : "シェ",
"syo" : "ショ",
"tha" : "テャ",
"thi" : "ティ",
"thu" : "テュ",
"the" : "テェ",
"tho" : "テョ",
"tsa" : "ツァ",
"tsi" : "ツィ",
"tsu" : "ツ",
"tse" : "ツェ",
"tso" : "ツォ",
"twa" : "トァ",
"twi" : "トィ",
"twu" : "トゥ",
"twe" : "トェ",
"two" : "トォ",
"tya" : "チャ",
"tyi" : "チィ",
"tyu" : "チュ",
"tye" : "チェ",
"tyo" : "チョ",
"nya" : "ニャ",
"nyi" : "ニィ",
"nyu" : "ニュ",
"nye" : "ニェ",
"nyo" : "ニョ",
"hya" : "ヒャ",
"hyi" : "ヒィ",
"hyu" : "ヒュ",
"hye" : "ヒェ",
"hyo" : "ヒョ",
"bya" : "ビャ",
"byi" : "ビィ",
"byu" : "ビュ",
"bye" : "ビェ",
"byo" : "ビョ",
"pya" : "ピャ",
"pyi" : "ピィ",
"pyu" : "ピュ",
"pye" : "ピェ",
"pyo" : "ピョ",
"mya" : "ミャ",
"myi" : "ミィ",
"myu" : "ミュ",
"mye" : "ミェ",
"myo" : "ミョ",
"rya" : "リャ",
"ryi" : "リィ",
"ryu" : "リュ",
"rye" : "リェ",
"ryo" : "リョ",
"ca" : "カ",
"ci" : "シ",
"cu" : "ク",
"ce" : "セ",
"co" : "コ",
"cha" : "チャ",
"chi" : "チ",
"chu" : "チュ",
"che" : "チェ",
"cho" : "チョ",
"fa" : "ファ",
"fi" : "フィ",
"fu" : "フ",
"fe" : "フェ",
"fo" : "フォ",
"fwa" : "ファ",
"fwi" : "フィ",
"fwu" : "フゥ",
"fwe" : "フェ",
"fwo" : "フォ",
"fya" : "フャ",
"fyi" : "フィ",
"fyu" : "フュ",
"fye" : "フェ",
"fyo" : "フョ",
"ja" : "ジャ",
"ji" : "ジ",
"ju" : "ジュ",
"je" : "ジェ",
"jo" : "ジョ",
"jya" : "ジャ",
"jyi" : "ジィ",
"jyu" : "ジュ",
"jye" : "ジェ",
"jyo" : "ジョ",
"qa" : "クァ",
"qi" : "クィ",
"qu" : "ク",
"qe" : "クェ",
"qo" : "クォ",
"qwa" : "クァ",
"qwi" : "クィ",
"qwu" : "クゥ",
"qwe" : "クェ",
"qwo" : "クォ",
"qya" : "クャ",
"qyi" : "クィ",
"qyu" : "クュ",
"qye" : "クェ",
"qyo" : "クョ",
"va" : "ヴァ",
"vi" : "ヴィ",
"vu" : "ヴ",
"ve" : "ヴェ",
"vo" : "ヴォ",
"vya" : "ヴャ",
"vyi" : "ヴィ",
"vyu" : "ヴュ",
"vye" : "ヴェ",
"vyo" : "ヴョ",
"nn" : "ン",
"n'" : "ン",
"xn" : "ン",
"ltu" : "ッ",
"xtu" : "ッ",
"lwa" : "ヮ",
"xwa" : "ヮ",
"lka" : "ヵ",
"xka" : "ヵ",
"lke" : "ヶ",
"xke" : "ヶ",
"kwa" : "クァ",
"-" : "ー",
"~" : "~",
"," : "、",
"." : "。",
"[" : "「",
"]" : "」",
"mba" : "ンバ",
"mbi" : "ンビ",
"mbu" : "ンブ",
"mbe" : "ンベ",
"mbo" : "ンボ",
"mpa" : "ンパ",
"mpi" : "ンピ",
"mpu" : "ンプ",
"mpe" : "ンペ",
"mpo" : "ンポ",
"mma" : "ンマ",
"mmi" : "ンミ",
"mmu" : "ンム",
"mme" : "ンメ",
"mmo" : "ンモ",
"tcha" : "ッチャ",
"tchi" : "ッチ",
"tchu" : "ッチュ",
"tche" : "ッチェ",
"tcho" : "ッチョ"
};
}