Let's study English!!
Google TTSを利用した学習用タイピングゲームです。
/**
* Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jQMb
*/
//ブラウザによっては、発音が聞こえないみたいです。
package {
import flash.net.SharedObject;
import flash.text.TextFormat;
import flash.text.TextField;
import flash.events.Event;
import flash.display.Sprite;
import com.bit101.components.*;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.utils.escapeMultiByte;
[SWF(backgroundColor="0x001133")]
public class FlashTest extends Sprite {
private var page1:Sprite = new Sprite();
private var list:List;
private var page2:Sprite = new Sprite();
private var typing:Typing;
private var manager:TypeManager;
private var monitor:TypeMonitor;
private var page3:Sprite = new Sprite();
private var menu:Array = [];
private var titles:Array = [ "Katakana", "FF", "Baceball" ];
private var score:TextField = new TextField();
private var time:TextField = new TextField();
private var score2:TextField = new TextField();
private var highScores:Object = {};
private var selected:String = ""
private var wordsList:Object = {
study:[
{ word:"スケーリングの誤解。同じ材質の大きい橋と小さい橋では大きい方が壊れやすい。", kana:"scaling fallicy" },
{ word:"逆向きに考えろ。困った時の思考法。", kana:"Work backwards." },
{ word:"帰納的に考えろ。例示をたくさんすることで問題がわかりやすくなる事がある。", kana:"Think inductively." },
{ word:"偽薬。薬効のないラムネでも、思い込みで効くことがある。" , kana:"placebo" },
{ word:"北京の蝶のはばたきがニューヨークで嵐をおこす。天気予報などの未来の予測が難しい原因。", kana:"butterfly effect" },
{ word:"車輪の再発明。付加価値のないものにコストをかけてしまうことを表す慣用句。" , kana:"reinventing the wheel" },
{ word:"割れ窓理論。割れた窓を放置するとますます治安が悪くなる。" , kana:"broken windows theory" },
{ word:"見えざる手。需要と供給のバランスは自然に調節される。" , kana:"invisible hand" },
{ word:"サンクコスト。もう回収できない費用。サンクコストに縛られて行動するべきではない。" , kana:"sunk cost" },
{ word:"囚人のジレンマ。各個人が自分の利益を最大化しようと行動すると、損をする事例。", kana:"prisoners' dilemma" },
{ word:"オッカムの剃刀。ある事象を説明するために、必要以上に仮定を増やすべきではない。", kana:"Occam's razor" },
{ word:"人間原理。宇宙が人間にとって都合がいいのは、そうでないと人間が観測できないから。", kana:"anthropic principle" },
{ word:"", kana:"" },
{ word:"", kana:"" },
{ word:"", kana:"" },
{ word:"", kana:"" },
{ word:"", kana:"" },
{ word:"", kana:"" }
], Katakana : [
{ word : "才能。才能のある人々、タレント。" , kana : "talent" },
{ word : "容器、包むもの。コンテナ。" , kana : "container" },
{ word : "混乱させる、困らせる。難問、パズル。", kana : "puzzle" },
{ word : "舌。言葉、言語能力。舌の肉、タン。" , kana : "tongue" },
{ word : "消化する。整理する、要約する。" , kana : "disest" },
{ word : "展示する、陳列する。表示。誇示。展示。コンピューターのディスプレイ" , kana : "display" },
{ word : "感覚。感じ、気持ち。意味。常識。勘。" , kana : "sense" },
{ word : "だます、あざむく。たくらみ、策略。意外に難しい。癖。いたずら。手品。", kana : "trick" },
{ word : "計画する。計画する、予想する。投げ出す、投影する。表現する。計画、事業。" , kana : "project" },
{ word : "鉄。アイロンをかける。アイロン。" , kana : "iron" },
{ word : "主催者、主人。主催者を務める。亭主。" , kana : "host" },
{ word : "ジグザグ。" , kana : "zigzag" },
{ word : "商業上の。営利用の、営業用の。広告用の。" , kana : "commercial" },
{ word : "魅力。引きつける力。引力。呼び物。" , kana : "attraction" },
{ word : "割合。大きさ、広さ。釣り合わせる、比例させる。" , kana : "propotion" },
{ word : "強調する。緊張させる。圧力、圧迫。強調、力説。緊張、ストレス。" , kana : "stress" },
{ word : "載せる、積み込む。重くする。課する。負荷。積み荷。読み込み、ロード。" , kana : "load" },
{ word : "反応。反響。反作用。反射。" , kana : "reaction" },
{ word : "傾斜させる、勾配をつける。坂、斜面、スロープ。傾斜。微分係数。" , kana : "slope" },
{ word : "一様な。お揃いの。規則正しい。制服、ユニフォーム。軍人" , kana : "uniform" },
{ word : "道理にかなった。分別ある。あまり値段が高くない。" , kana : "reasonable" },
{ word : "便利、好都合。便利なもの。" , kana : "convenience" },
{ word : "押すこと、圧迫。圧力、気圧、血圧。苦悩。圧力をかける。" , kana : "pressure" },
{ word : "1組、1対。カップル。結びつける。つなぐ。二,三。" , kana : "couple" },
{ word : "複雑な、錯綜した。多くのものが複合した。複合体。コンプレックス。" , kana : "complex" },
{ word : "唯一の。唯一の人。匹敵するもののない。" , kana : "unique" },
{ word : "ユーモア、面白さ。人の気質。気分。液。" , kana : "humor" },
{ word : "移動しやすい、固定されていない。気分が変わりやすい。機動力がある。" , kana : "mobile" },
{ word : "賢い、効果的な。生意気な。おしゃれな。きびきびした。" , kana : "smart" },
{ word : "世間知らずの、単純な。考えが甘い。経験不足の。うぶな。" , kana : "naive" },
{ word : "豪邸、大邸宅、館。" , kana : "mansion" },
{ word : "人気のある。普及している。大衆の。大衆向けの。" , kana : "popular" },
{ word : "似合う。好みに合う。好都合な。ふさわしい。訴訟。求婚。スーツ、服。一式" , kana : "suit" },
{ word : "整理する。並べる。手配する。準備する" , kana : "arrange" },
{ word : "鼓舞する。呼び起こす。吹き込む、吸い込む、息をする。" , kana : "inspire" },
{ word : "足跡、跡。見取り図。さかのぼる。たどる。透写する、なぞる。" , kana : "trace" },
{ word : "柱、円柱。円柱状のもの。行列。新聞などの縦長の欄。コラム。" , kana : "column" },
{ word : "支配する。" , kana : "control" },
{ word : "選択肢。選択、選択権。標準装備以外のもの。" , kana : "option" },
{ word : "忠告する。助言する。" , kana : "advise" },
{ word : "自慢。自尊心、誇り。うぬぼれ。自慢する。誇る。" , kana : "pride" },
{ word : "水路。水道管。側溝。経路。方針。水路を作る。水路で運ぶ。" , kana : "channel" },
{ word : "具体的な、明確な。実際の、現実の。固める。具体化する。コンクリート。" , kana : "concrete" }
],FF : [
{ word : "排水口。流し出す。排水する。" , kana : "drain" },
{ word : "追い払う。一掃する。" , kana : "dispel" },
{ word : "酸。すっぱい。" , kana : "acid" },
{ word : "水薬" , kana : "potion" },
{ word : "震える、おののく、揺れる。震え、地震。" , kana : "quake" },
{ word : "隕石、流星。" , kana : "meteor" },
{ word : "急ぐこと、迅速。あわてること、性急、軽率。" , kana : "haste" },
{ word : "気息音(ハヒフヘホのHの音などのこと)。気息音を発音する。吸い込む。" , kana : "aspirate" },
{ word : "困惑させる。混乱させる。混同する。間違える。" , kana : "confuse" },
{ word : "消える。見えなくなる。絶滅する。隠す。" , kana : "vanish" },
{ word : "ヒキガエル" , kana : "toad" },
{ word : "もや、霧。" , kana : "mist" },
{ word : "瞬きする。点滅する。瞬き、ちらつき。" , kana : "blink" },
{ word : "上にあげる。上昇させる。元気づける。蘇らせる。" , kana : "raise" },
{ word : "抵抗する。" , kana : "resist" },
{ word : "再生する。改心させる。再生した。改心した。" , kana : "regenerate" },
{ word : "重力。重大さ。" , kana : "gravity" },
{ word : "世話、介護。注意、関心。世話。気づかう。" , kana : "care" },
{ word : "神聖な。高徳な。" , kana : "holy" },
{ word : "能力、才能、実力、力量。" , kana : "ability" },
{ word : "暗殺者。" , kana : "assassin" },
{ word : "泥棒、こそどろ。" , kana : "thief" },
{ word : "たまねぎ。" , kana : "onion" },
{ word : "結晶。水晶。" , kana : "crystal" },
{ word : "鉄。" , kana : "iron" },
{ word : "不可視の、見ることができない。目につかないほど小さい。" , kana : "invisible" },
{ word : "毒。" , kana : "poison" },
{ word : "毒牙、牙。とがったもの。" , kana : "fang" },
{ word : "親愛なる。かわいい。いとしい人。高価な。" , kana : "dear" },
{ word : "猛吹雪。" , kana : "blizzard" },
{ word : "洪水、大水" , kana : "flood" },
{ word : "毒牙、牙。とがったもの。" , kana : "fang" },
{ word : "保護する。守る。保険をかける。" , kana : "protect" },
{ word : "兵器、武器。攻撃手段。" , kana : "weapon" },
{ word : "最後の、究極の。根本的な。最終段階。最高の" , kana : "ultimate" },
{ word : "能力。腕前、力量。法的資格。" , kana : "ability" },
{ word : "要素の、単一の、元素の。基本的な。地水火風の霊。" , kana : "elemental" },
{ word : "大気。空気。気圧。雰囲気。" , kana : "atmosphere" },
{ word : "ノアの方舟。避難所。箱。" , kana : "ark" },
{ word : "非常に硬いもの。非常に堅い。不動の、断固な。" , kana : "adamant" },
{ word : "空中浮揚する。空中浮揚させる。" , kana : "levitate" },
{ word : "図書館。資料室。蔵書。知識の宝庫、情報源。" , kana : "library" },
{ word : "信じること。信頼。自信。義務、責任。宗教、信仰。" , kana : "faith" },
{ word : "お守り、魔よけ。" , kana : "amulet" },
{ word : "ほうき星。" , kana : "comet" },
{ word : "つぶれる。崩壊させる。折りたためる。倒壊。挫折。" , kana : "collapse" },
{ word : "たつまき、雷雨、大旋風。" , kana : "tornado" },
{ word : "次元。大きさ、寸法。" , kana : "dimension" },
{ word : "反射する。反響する。像を映す、反映する。" , kana : "reflect" },
{ word : "逃げる。もれる。逃亡、現実逃避" , kana : "escape" },
{ word : "狂暴な" , kana : "berserk" }
],
Baceball : [
{ word : "変える。改心させる。改宗する。転向する。両替する。" , kana : "convert" },
{ word : "公正な、正当な。適切な。かなり良い。まっすぐに。" , kana : "fair" },
{ word : "間違い。思い違い。過失。過ち。誤差。" , kana : "error" },
{ word : "土台。底。基礎。出発点。基地。" , kana : "base" },
{ word : "空を飛ぶ。舞い上がる。ハエ、飛ぶ昆虫。" , kana : "fly" },
{ word : "土手。塚。古墳。" , kana : "mound" },
{ word : "こっそり盗む。盗みをする。そっと行く。お買い得品" , kana : "steal" },
{ word : "打つ、叩く。衝突する。胸を打つ、感心させる。向う。根づく。" , kana : "strike" },
{ word : "食器のフォーク。フォーク状のもの。音叉。熊手。分岐する。" , kana : "fork" },
{ word : "沈むもの、沈む人。井戸掘り人。重り。" , kana : "sinker" },
{ word : "滑るもの、滑る人。" , kana : "slider" },
{ word : "悪臭のある。腐った。汚い。ひどく不快な。不正な。" , kana : "foul" },
{ word : "救う。守る。むだづかいしないようにする。手間を省く。" , kana : "save" },
{ word : "指の関節。げんこつ。" , kana : "knuckle" },
{ word : "頭突き。突く、押す。" , kana : "bunt" },
{ word : "ひとそろい、一組。電池、バッテリー。殴打。砲台。" , kana : "battery" },
{ word : "程よい時間での、時を得た。好都合な時に。" , kana : "timely" },
{ word : "急に止まる。立ち往生する。妨害する。じゃま物。" , kana : "balk" },
{ word : "平均値。平均する。平均の" , kana : "average" },
{ word : "強く打つ人。強打者。" , kana : "slugger" }
]
};
public var so: SharedObject = SharedObject.getLocal("savedata");
function FlashTest() {
if(so){ highScores = so.data; }
var lbl:Label= new Label( page1, 1,1, "Let's study English!!" )
lbl.scaleX = lbl.scaleY = 2;
//page1
for each( var str:String in titles ){
var data:Object = { title:str, words:wordsList[str], highScore:highScores[str] };
menu.push( data )
}
list = new List( page1,5, 40 );
list.listItemClass = Item;
list.items = menu;
list.listItemHeight = 55;
list.setSize( 455, 420 );
list.addEventListener(Event.SELECT, onMenuSelect);
addChild( page1 );
//page2
typing = new Typing( stage );
TypeStyle.setStyle( TypeStyle.DARK )
//keyboard
var keyboard:TypeKeyboard = new TypeKeyboard( typing );
page2.addChild( keyboard );
keyboard.scaleX = keyboard.scaleY = 0.7;
keyboard.x = 20;
keyboard.y = 270;
//panel
var panel1:TypePanel = new TypePanel( typing, 464, 30, 0, 0, 1 );
panel1.y = 180;
page2.addChild( panel1 );
var panel2:TypePanel = new TypePanel( typing, 464, 16, 0, 1, 0 );
panel2.y = 220;
page2.addChild( panel2 );
//monitor
monitor = new TypeMonitor( typing, 445, 100, 0.25, 0.45, 0.30 );
monitor.x = 10;
monitor.y = 10;
page2.addChild( monitor );
manager = new TypeManager( typing, wordsList["FFantasy"] );
manager.timeLimit = 60;
score.defaultTextFormat = new TextFormat( null,28,0xFF2200,true );
score.y = 435;
score.width = 465;
time.defaultTextFormat = new TextFormat( null,58,0xFF1100,true, null, null, null, null, "right", null, null, null, null)
time.y = 405;
time.width = 465;
page2.addChild( score );
page2.addChild( time );
page2.visible = false;
addChild( page2 );
score2.defaultTextFormat = new TextFormat( null,58,0xFFFFFF,true, null, null, null, null, "center", null, null, null, null)
score2.y = 140;
score2.width = 465;
page3.addChild( score2 );
new PushButton( page3, 115, 260, "tweet", tweet );
new PushButton( page3, 250, 260, "back", back );
page3.visible = false;
addChild( page3 );
addEventListener( "exitFrame", onFrame );
typing.addEventListener( "stop", onStop );
typing.addEventListener( "missed", onMiss );
speak( "Let's study English!!" );
}
private function onMenuSelect( e:Event ):void{
if( list.selectedItem ){
selected = list.selectedItem.title;
var words:Array = list.selectedItem.word;
manager.setWordList( wordsList[selected] );
page1.visible = false;
page2.visible = true;
typing.addEventListener( "wordAdded", onAdded );
typing.init();
typing.start();
}
}
private function onAdded( e:TypeEvent ):void{
speak( e.word.kana )
}
private function onStop( e:TypeEvent ):void{
typing.removeEventListener( "wordAdded", onAdded );
page2.alpha = 0.1;
page3.visible = true;
score2.text = "SCORE: " + monitor.typeCount;
if( highScores[selected] == null || highScores[selected] < monitor.typeCount ){
highScores[selected] = monitor.typeCount;
}
}
private function onFrame( e:Event ):void{
score.text = "SCORE: " + monitor.typeCount;
if( manager.timeCount < 60 ){ time.text = "" + (60 - manager.timeCount).toFixed(3); }
else{ time.text = "Finish" }
}
private function onMiss( e:Event ):void{ manager.timeCount++; }
private function tweet( e:Event ):void{
var str:String = "SCORE:" + monitor.typeCount + " " + "http://wonderfl.net/c/jQMb/" + " " + "#wonderfl ";
navigateToURL(new URLRequest("http://twitter.com/home?status=" + escapeMultiByte(str)), "_blank");
}
private function back( e:Event ):void{
page1.visible = true;
page2.alpha = 1;
menu = [];
for each( var str:String in titles ){
var data:Object = { title:str, words:wordsList[str], highScore:highScores[str] };
menu.push( data )
}
list.listItemClass = Item;
list.items = menu;
list.listItemHeight = 55;
list.setSize( 455, 420 );
page2.visible = false;
page3.visible = false;
}
}
}
import flash.events.Event;
import flash.display.DisplayObjectContainer;
import flash.media.Sound;
import flash.net.URLRequest;
import com.bit101.components.*;
function speak( _text:String ):void {
var req:URLRequest = new URLRequest(
"http://www.google.com/gwt/n?u=http%3A%2F%2Ftranslate.google.com%2Ftranslate_tts%3Ftl%3Den%26q%3D" + encodeURI(_text)
);
var snd:Sound = new Sound(req)
snd.play();
}
class Item extends ListItem{
private var _highScore:Label;
function Item(parent: DisplayObjectContainer = null, xpos: Number = 0, ypos: Number = 0, data: Object = null) {
super(parent, xpos, ypos, data);
_highScore = new Label( this, 5 ,12 );
}
override public function draw():void{
dispatchEvent(new Event(Component.DRAW));
graphics.clear();
graphics.beginFill(_selected ? _selectedColor : (_mouseOver ? _rolloverColor : _defaultColor));
graphics.drawRect(0, 0, _width, _height);
if( data == null ){ return; }
_label.text = "" + _data.title + " (" + _data.words.length + " words)"
if( _data.highScore ){ _highScore.text = "high score: " + _data.highScore }
else{ _highScore.text = "high score: -" }
}
}
import flash.utils.Timer;
import flash.display.Shape;
import flash.text.TextFormat;
import flash.text.TextField;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.utils.getTimer;
import flash.display.Stage;
class TypeData {
/** 半角文字のリスト */
static public const HANKAKU:String = "1234567890-^\\qwertyuiop@[asdfghjkl;:]zxcvbnm,./!\"#$%&'()=~|QWERTYUIOP`{ASDFGHJKL+*}ZXCVBNM<>?_ ";
/** HANKAKUに対応する全角文字のリスト */
static public const ZENKAKU:String = "1234567890ー^¥qwertyuiop@[asdfghjkl;:]zxcvbnm,./!”#$%&’()=~|QWERTYUIOP‘{ASDFGHJKL+*}ZXCVBNM<>?_ ";
/** かなからローマ字への変換表*/
static public const ROMANS:Object = {
"あ":["a"], "う":["u", "wu", "whu"], "い":["i", "yi"], "え":["e"], "お":["o"],
"か":["ka", "ca"], "き":["ki"], "く":["ku", "cu"], "け":["ke"], "こ":["ko", "co"],
"さ":["sa"], "し":["si", "shi", "ci"], "す":["su"], "せ":["se", "ce"], "そ":["so"],
"た":["ta"], "ち":["ti", "chi"], "つ":["tu", "tsu"], "て":["te"], "と":["to"],
"な":["na"], "に":["ni"], "ぬ":["nu"], "ね":["ne"], "の":["no"],
"は":["ha"], "ひ":["hi"], "ふ":["fu", "hu"], "へ":["he"], "ほ":["ho"],
"ま":["ma"], "み":["mi"], "む":["mu"], "め":["me"],"も":["mo"],
"や":["ya"], "ゆ":["yu"], "よ":["yo"],
"ら":["ra"], "り":["ri"], "る":["ru"], "れ":["re"],"ろ":["ro"],
"わ":["wa"], "を":["wo"], "ん":["nn"],
"が":["ga"], "ぎ":["gi"], "ぐ":["gu"], "げ":["ge"],"ご":["go"],
"ざ":["za"], "じ":["ji", "zi"], "ず":["zu"], "ぜ":["ze"], "ぞ":["zo"],
"だ":["da"], "ぢ":["di"], "づ":["du"], "で":["de"], "ど":["do"],
"ば":["ba"], "び":["bi"], "ぶ":["bu"], "べ":["be"], "ぼ":["bo"],
"ぱ":["pa"], "ぴ":["pi"], "ぷ":["pu"], "ぺ":["pe"], "ぽ":["po"],
"しゃ":["sya", "sha"], "しゅ":["syu", "shu"], "しょ":["syo", "sho"], "しぃ":["syi"], "しぇ":["sye", "she"],
"きぃ":["kyi"], "きゃ":["kya"], "きゅ":["kyu"], "きぇ":["kye"], "きょ":["kyo"],
"にゃ":["nya"], "にぃ":["nyi"], "にゅ":["nyu"], "にぇ":["nye"], "にょ":["nyo"],
"ちゃ":["tya", "cha", "cya"], "ちぃ":["tyi", "cyi"], "ちゅ":["tyu", "chu", "cyu"], "ちぇ":["tye", "che", "cye"], "ちょ":["tyo", "cho", "cyo"],
"とぁ":["twa"], "とぃ":["twi"], "とぅ":["twu"], "とぇ":["twe"], "とぉ":["two"],
"てゃ":["tha"], "てぃ":["thi"], "てゅ":["thu"], "てぇ":["the"], "てょ":["tho"],
"ひゃ":["hya"], "ひぃ":["hyi"], "ひょ":["hyo"], "ひぇ":["hye"], "ひゅ":["hyu"],
"りゃ":["rya"], "りぃ":["ryi"], "りゅ":["ryu"], "りぇ":["rye"], "りょ":["ryo"],
"うぁ":["wa", "wha"], "うぃ":["wi", "whi"], "うぇ":["we", "whe"], "うぉ":["wo", "who"],
"ヴぁ":["va"], "ヴぃ":["vi"], "ヴ":["vu"], "ヴぇ":["ve"], "ヴぉ":["vo"], "ヴゃ":["vya"], "ヴゅ":["vyu"], "ヴょ":["vyo"],
"くぁ":["qa", "kwa", "qwa"], "くぃ":["qi", "qwi", "qyi"], "くぅ":["qwu", "qwu"], "くぇ":["qe", "qwe", "qye"], "くぉ":["qo", "qwo"], "くゃ":["qya"], "くゅ":["qyu"], "くょ":["qyo"],
"すぁ":["swa"], "すぃ":["swi"], "すぅ":["swu"], "すぇ":["swe"], "すぉ":["swo"],
"ふぁ":["fa", "fwa"], "ふぃ":["fi", "fwi", "fyi"], "ふぅ":["fwu"], "ふぇ":["fe", "fwe", "fye"], "ふぉ":["fo", "fwo", "fwo"], "ふゃ":["fya"], "ふゅ":["fyu"], "ふょ":["fyo"],
"ぎゃ":["gya"], "ぎぃ":["gyi"], "ぎゅ":["gyu"], "ぎぇ":["gye"], "ぎょ":["gyo"],
"じゃ":["ja", "zya", "jya"], "じぃ":["zyi", "jyi"], "じゅ":["ju", "zyu", "jyu"], "じぇ":["je", "zye", "jye"], "じょ":["jo", "zyo", "jyo"],
"ぐぁ":["gwa"], "ぐぃ":["gwi"], "ぐぅ":["gwu"], "ぐぇ":["gwe"], "ぐぉ":["gwo"],
"ぢゃ":["dya"], "ぢぃ":["dyi"], "ぢゅ":["dyu"], "ぢぇ":["dye"], "ぢょ":["dyo"],
"どぁ":["dwa"], "どぃ":["dwi"], "どぅ":["dwu"], "どぇ":["dwe"], "どぉ":["dwo"],
"でゃ":["dha"], "でぃ":["dhi"], "でゅ":["dhu"], "でぇ":["dhe"], "でょ":["dho"],
"びゃ":["bya"], "びぃ":["byi"], "びゅ":["byu"], "びぇ":["bye"], "びょ":["byo"],
"ぴゃ":["pya"], "ぴぃ":["pyi"], "ぴょ":["pyo"], "ぴぇ":["pye"], "ぴゅ":["pyu"],
"つぁ":["tsa"], "つぃ":["tsi"], "つぇ":["tse"], "つぉ":["tso"],
"いぇ":["ye"],
"ぁ":["la", "xa"], "ぃ":["li", "xi", "lyi", "xyi"], "ぅ":["lu", "xu"], "ぇ":["le","xe","lye","xye"], "ぉ":["lo","xo"],
"ゃ":["lya","xya"],"ゅ":["lyu","xyi"],"ょ":["lyo","xyu"],"ゎ":["lwa","xwa"],
"っ":["ltu","ltsu"],"ヶ":["lke","xke"],"ヵ":["lka","xka"],
"「":["["], "」":["]"], "。":["."], "、":[","]
}
/** ローマ字からかなへの変換表 */
static public const KANA:Object = {
qwa:"くぁ", qa:"くぁ", bye:"びぇ", kwa:"くぁ", sho:"しょ", syu:"しゅ", byo:"びょ", byu:"びゅ", syi:"しぃ", pya:"ぴゃ",
sye:"しぇ", qi:"くぃ", shu:"しゅ", ti:"ち", qwi:"くぃ", qe:"くぇ", qyi:"くぃ", pyo:"ぴょ", cu:"く", tu:"つ", qwu:"くぅ",
kya:"きゃ", pyi:"ぴぃ", qo:"くぉ", chi:"ち", pyu:"ぴゅ", kyi:"きぃ", she:"しぇ", qye:"くぇ", tsa:"つぁ", pye:"ぴぇ",
qwe:"くぇ", qya:"くゃ", kyu:"きゅ", tsu:"つ", tsi:"つぃ", kye:"きぇ", te:"て", nu:"ぬ", qyu:"くゅ", to:"と", qwo:"くぉ",
ne:"ね", tse:"つぇ", kyo:"きょ", "]":"」", no:"の", tso:"つぉ", "[":"「", qyo:"くょ", xa:"ぁ", na:"な", ha:"は", ye:"いぇ",
swa:"すぁ", li:"ぃ", nya:"にゃ", swo:"すぉ", la:"ぁ", swi:"すぃ", lyi:"ぃ", nyi:"にぃ", xyi:"ゅ", swe:"すぇ", ku:"く",
swu:"すぅ", ke:"け", nyu:"にゅ", fa:"ふぁ", myi:"みぃ", nyo:"にょ", xu:"ぅ", nye:"にぇ", ni:"に", lu:"ぅ", mya:"みゃ",
e:"え", hi:"ひ", fyi:"ふぃ", fwa:"ふぁ", i:"い", fwi:"ふぃ", myo:"みょ", fu:"ふ", le:"ぇ", fi:"ふぃ", xi:"ぃ", hu:"ふ",
xe:"ぇ", mye:"みぇ", o:"お", lye:"ぇ", ho:"ほ", he:"へ", u:"う", myu:"みゅ", sa:"さ", cha:"ちゃ", fwu:"ふぅ", cya:"ちゃ",
xye:"ぇ", co:"こ", fe:"ふぇ", ma:"ま", tyi:"ちぃ", fwe:"ふぇ", tya:"ちゃ", cyi:"ちぃ", fye:"ふぇ", mi:"み", xya:"ゃ",
lo:"ぉ", tyu:"ちゅ", lya:"ゃ", xo:"ぉ", lyu:"ゅ", fwo:"ふぉ", cyu:"ちゅ", mo:"も", fo:"ふぉ", lyo:"ょ", chu:"ちゅ",
mu:"む", xyu:"ょ", ya:"や", che:"ちぇ", fyu:"ふゅ", me:"め", fya:"ふゃ", cye:"ちぇ", tye:"ちぇ", shi:"し", a:"あ",
xwa:"ゎ", fyo:"ふょ", ri:"り", lwa:"ゎ", yu:"ゆ", cho:"ちょ", gya:"ぎゃ", ru:"る", tyo:"ちょ", yo:"よ", ci:"し",
ltu:"っ", twi:"とぃ", cyo:"ちょ", ra:"ら", lka:"ヵ", gyu:"ぎゅ", gyi:"ぎぃ", xka:"ヵ", lke:"ヶ", ltsu:"っ", ja:"じゃ",
xke:"ヶ", ko:"こ", re:"れ", twa:"とぁ", zya:"じゃ", gyo:"ぎょ", gye:"ぎぇ", jya:"じゃ", twu:"とぅ", jyi:"じぃ", su:"す",
zyi:"じぃ", twe:"とぇ", ro:"ろ", ju:"じゅ", si:"し", two:"とぉ", wa:"うぁ", jyu:"じゅ", zyu:"じゅ", tha:"てゃ", wo:"うぉ",
je:"じぇ", thu:"てゅ", thi:"てぃ", nn:"ん", jye:"じぇ", tho:"てょ", gi:"ぎ", ga:"が", jo:"じょ", zyo:"じょ", zye:"じぇ",
jyo:"じょ", hyi:"ひぃ", ge:"げ", the:"てぇ", gwa:"ぐぁ", hyo:"ひょ", hya:"ひゃ", zi:"じ", gu:"ぐ", hye:"ひぇ", za:"ざ",
go:"ご", gwu:"ぐぅ", hyu:"ひゅ", ji:"じ", gwe:"ぐぇ", ce:"せ", rya:"りゃ", gwo:"ぐぉ", zu:"ず", gwi:"ぐぃ", ryi:"りぃ",
dya:"ぢゃ", ze:"ぜ", se:"せ", dyi:"ぢぃ", zo:"ぞ", ".":"。", so:"そ", dyu:"ぢゅ", da:"だ", rye:"りぇ", ",":"、", dye:"ぢぇ",
di:"ぢ", ryo:"りょ", ryu:"りゅ", dyo:"ぢょ", du:"づ", wha:"うぁ", ta:"た", whi:"うぃ", de:"で", wi:"うぃ", dwa:"どぁ",
"do":"ど", whe:"うぇ", dwi:"どぃ", ba:"ば", who:"うぉ", ki:"き", dwu:"どぅ", we:"うぇ", va:"ヴぁ", dwe:"どぇ", bu:"ぶ",
bi:"び", vi:"ヴぃ", dwo:"どぉ", be:"べ", ka:"か", ca:"か", dha:"でゃ", bo:"ぼ", vu:"ヴ", dhi:"でぃ", pa:"ぱ", ve:"ヴぇ",
dhu:"でゅ", pi:"ぴ", vo:"ヴぉ", dhe:"でぇ", pu:"ぷ", vya:"ヴゃ", dho:"でょ", pe:"ぺ", wu:"う", yi:"い", bya:"びゃ",
po:"ぽ",vyo:"ヴょ",vyu:"ヴゅ",byi:"びぃ",sya:"しゃ",whu:"う",sha:"しゃ",syo:"しょ"
}
/** nのうしろに来てもnが「ん」にならない文字 */
static public const NN:String = "euioany";
/** 二つ続くと「っ」になる文字 */
static public const LTU:String = "qwrtypsdfghjklzxcvbm";
static public const CODE48:String = "0123456789";
static public const CODE65:String = "abcdefghijklmnopqrstuvwxyz";
static public const CODE186:String = ":;,-./@";
static public const CODE219:String = "[¥]^";
static public const CODE226:String = "\\";
static public const QWERTY_KEY:Array = [ "1234567890-^¥", "qwertyuiop@[", "asdfghjkl;:]", "zxcvbnm,./\\" ];
static public const QWERTY_SHIFT:Array = [ "!\"#$%&'() =~|", "QWERTYUIOP`{", "ASDFGHJKL+*}", "ZXCVBNM<>?_" ];
static public const DVORAK_KEY:Array = [ "1234567890[]¥", ":,.pyfgcrl/@", "aoeuidhtns-^", ";qjkxbmwvz\\" ];
static public const DVORAK_SHIFT:Array = [ "!\"#$%&'() {}|", "*<>PYFGCRL?`", "AOEUIDHTNS=~", "+QJKXBMWVZ_" ]
static public const BOARD_INDENT:Array = [ 1, 1.5, 1.8, 2.3, 5 ]
}
class TypeUtil
{
// romanのかなに変換可能な部分をかなに変換して返します
static public function kana( roman:String, option:TypeOption = null ):String {
if( roman == "" ){ return "" }
var kana:String;
for( var i:uint = 3; i > 0; i-- ){
var subroman:String = roman.substr( 0, i );
if( option ){ kana = option.kana( subroman ); }
if( !kana ){ kana = TypeData.KANA[subroman]; }
if( !kana && i == 1 ){
var next:String = roman.substr( i, 1 );
var hankaku:int = TypeData.HANKAKU.indexOf( subroman );
if( subroman == next && TypeData.LTU.indexOf(subroman) != -1 ){ kana = "っ" }
else if( subroman == "n" && TypeData.NN.indexOf(next) == -1 ){ kana = "ん" }
else if( hankaku != -1 ){ kana = TypeData.ZENKAKU.substr( hankaku,1 ) }
}
if( kana ){ return kana + TypeUtil.kana( roman.substr(i), option ) }
}
return "";
}
//kanaに対してromanが入力されているときに、次にタイプできるキーの候補を返します。
static public function next( kana:String, roman:String = "", option:TypeOption = null ):Array{
var next:Array = [];
if( kana == "" ){ return [] }
for( var i:uint = 2; i > 0; i-- ){
var roman2:String = roman;
var subkana:String = kana.substr( 0, i );
var nextKana:String = kana.substr( i );
var subromans:Array = [];
if ( option ) { ArrayUtil.blend( subromans, option.romans( subkana ) ); }
if ( i == 1 ) {
var zenkaku:int = TypeData.ZENKAKU.indexOf( subkana );
var hankaku:int = TypeData.HANKAKU.indexOf( subkana );
if( subkana == "っ" ){ ArrayUtil.blend( subromans, _preLtu( nextKana, option ) ) }
else if ( subkana == "ん" ) { ArrayUtil.blend( subromans, _preN( nextKana, option )) }
else if ( zenkaku != -1 ) { subromans.push( TypeData.HANKAKU.substr( zenkaku,1 ) ); }
else if ( hankaku != -1 ) { subromans.push( TypeData.HANKAKU.substr( hankaku,1 ) ); }
}
ArrayUtil.blend( subromans, TypeData.ROMANS[subkana] );
var l:uint = subromans.length;
var flag:Boolean = false;
while( l > 0 ){
if( roman2.length == 0 ){ ArrayUtil.blend( next, _firsts(subromans) ); break; }
var first:String = roman2.substr(0, 1);
for( var j:uint = 0; j < l; j++ ){
if( subromans[j].substr( 0, 1 ) == first ){
subromans[j] = subromans[j].substr( 1 );
if ( subromans[j] == "" ) {
ArrayUtil.blend( next, TypeUtil.next( nextKana, roman2.substr(1), option ) );
subromans.splice(j,1); l--; j--;
}
}else{
subromans.splice(j,1); l--; j--;
}
}
roman2 = roman2.substr(1);
}
}
return next;
}
//かなを渡すとそのかなの手前に来ることで「っ」になりうるローマ字を返します。
static private function _preLtu( kana:String, option:TypeOption ):Array{
var next:Array = next( kana, "", option );
var pre:Array = [];
var l:uint = next.length;
const LTU:String = TypeData.LTU;
for( var i:uint = 0; i<l; i++ ){
var n:String = next[i];
if( LTU.indexOf(n) != -1 ){ pre.push(n); }
}
return pre;
}
//かなを渡すとそのかなの手前にn来ることで「ん」になる場合[n]を返します。
static private function _preN( kana:String, option:TypeOption ):Array{
var next:Array = next( kana, "", option );
var l:uint = next.length;
const NN:String = TypeData.NN;
for( var i:uint = 0; i<l; i++ ){
var n:String = next[i];
if( NN.indexOf(n) == -1 ){ return ["n"]; }
}
return [];
}
//arrの一文字目の配列を作ります。
static private function _firsts( arr:Array ):Array {
var l:uint = arr.length;
var firsts:Array = [];
for( var i:uint; i<l; i++ ){
firsts.push( arr[i].substr(0,1) );
}
return firsts;
}
/**
* 入力されているときのかなに対するもっとも簡単なローマ字のふりかたを返します。
* @param kana
* @param roman
* @param option
* @return
*/
static public function simplestRoman( kana:String, roman:String = "", option:TypeOption = null ):String {
if ( roman == "" ) { return _simplestRoman( kana, option); }
for ( var i:uint = 2; i > 0; i-- ) {
var roman2:String = roman;
var subkana:String = kana.substr( 0, i );
var nextKana:String = kana.substr( i );
var subromans:Array = [];
if ( option ) { ArrayUtil.blend( subromans, option.romans( subkana ) ); }
if ( i == 1 ) {
var zenkaku:int = TypeData.ZENKAKU.indexOf( subkana );
var hankaku:int = TypeData.HANKAKU.indexOf( subkana );
if( subkana == "っ" ){ ArrayUtil.blend( subromans, _preLtu( nextKana, option ) ) }
else if ( subkana == "ん" ) { ArrayUtil.blend( subromans, _preN( nextKana, option )) }
else if ( zenkaku != -1 ) { subromans.push( TypeData.HANKAKU.substr( zenkaku,1 ) ); }
else if ( hankaku != -1 ) { subromans.push( TypeData.HANKAKU.substr( hankaku,1 ) ); }
}
ArrayUtil.blend( subromans, TypeData.ROMANS[subkana] );
var l:uint = subromans.length;
for( var j:uint = 0; j < l; j++ ){
var subroman:String = subromans[j];
var rl:uint = subroman.length;
var c:uint = 0;
while ( true ) {
var one:String = roman2.substr( c, 1 );
if( subroman.indexOf( one, c ) == c ){ ;
if ( rl == c + 1 ) {
var next:String = simplestRoman( nextKana, roman2.substr(rl), option );
if ( next != null ) { return subroman + next }
break
}
}else { break; }
c++;
}
}
}
return null;
}
//かなに対するもっとも簡単なローマ字のふりかたを返します。
static private function _simplestRoman( kana:String, option:TypeOption = null ):String {
if ( kana == "" ) { return "" }
var roman:String;
for ( var i:uint = 2; i > 0; i-- ) {
var subkana:String = kana.substr( 0, i );
var nextKana:String = kana.substr( i );
if ( option ) { roman = option.romans( subkana )[0]; }
if ( !roman && i == 1 ) {
var zenkaku:int = TypeData.ZENKAKU.indexOf( subkana );
var hankaku:int = TypeData.HANKAKU.indexOf( subkana );
if( subkana == "っ" ){ roman = _preLtu( nextKana, option )[0] }
else if ( subkana == "ん" ) { roman = _preN( nextKana, option )[0] }
else if ( zenkaku != -1 ) { roman = TypeData.HANKAKU.substr( zenkaku,1 ); }
else if ( hankaku != -1 ) { roman = TypeData.HANKAKU.substr( hankaku,1 ); }
}
if ( !roman ) {
var romans:Array = TypeData.ROMANS[subkana];
if( romans ){ roman = romans[0] }
}
if ( roman ) {
var next:String = _simplestRoman( nextKana, option );
if ( next != null ) { return roman + next }
}
}
return null;
}
}
class ArrayUtil{
/**
* arr2のうち、arr1にまだ含まれないもののみを配列の前方に追加します。
* @param arr1
* @param arr2
* @return
*/
static public function blend( arr1:Array, arr2:Array ):Array {
if ( !arr2 ) { return arr1; }
var l:uint = arr2.length;
for ( var i:uint = 0; i < l; i++ ) {
var e:* = arr2[i];
if ( arr1.indexOf( e ) == -1 ) { arr1.push( e ); }
}
return arr1;
}
}
class TypeConfig{
static public var option:TypeOption;
static public var dovrak:Boolean = false;
static public var space:Boolean = true;
}
class TypeStyle{
/** クリーム系の配色です。 */
static public const CREAM:Object = { fill:0xEEDDCC, activeFill:0xDDAA77, activeFill2:0xDDBB99, disableFill:0x776655, line:0x554433 }
/** 暗いの配色です。 */
static public const DARK:Object = { fill:0x111116, activeFill:0xDD4411, activeFill2:0x1144DD, disableFill:0xCCCCCC, line:0xDDDDEE }
static public const DEFAULT:Object = CREAM;
/** アクセサリーの通常時のfillColorです。 */
static public var fill:uint = DEFAULT.fill;
/** アクセサリーがフォーカスを得た時などに使われるfillColorです。 */
static public var activeFill:uint = DEFAULT.activeFill;
/** fillとactiveFillの中間にあたるfillColorです。 */
static public var activeFill2:uint = DEFAULT.activeFill2;
/** アクセサリーがの時などに使われるfillColorです。 */
static public var disableFill:uint = DEFAULT.disableFill;
/** 枠線に使われる色です。 */
static public var line:uint = DEFAULT.line;
static public var defaultTextFormat:TextFormat = new TextFormat( "メイリオ", 70, 0xFFFFFF, true, null, null, null, null, "center", null, null, null, null)
static public var nextFormat:TextFormat = new TextFormat( null, null, 0x666666 );
static public var typedFormat:TextFormat = new TextFormat( null, null, 0xFFFFFF );
static public var typingFormat:TextFormat = new TextFormat( null, null, 0x001133 );
static public function setStyle( style:Object ):void {
TypeStyle.fill = style.fill;
TypeStyle.activeFill = style.activeFill;
TypeStyle.activeFill2 = style.activeFill2;
TypeStyle.disableFill = style.disableFill;
TypeStyle.line = style.line;
}
}
//===========================================================================================================
dynamic class TypeWord{
public var word:String;
public var kana:String = "";
public var chosen:Boolean;
public var isTarget:Boolean;
public var typable:Boolean;
public var roman:String;
public var defaultRoman:String;
public var next:Array;
function TypeWord( obj:Object ):void {
for ( var str:String in obj ) {
this[str] = obj[str]
}
if( TypeConfig.space ){ kana += " " }
this.defaultRoman = TypeUtil.simplestRoman( kana, "", TypeConfig.option );
}
}
class TypeOption{
/** [[かな,roman],...] */
public var options:Array = [];
static public const IROHA:Array = [["ゑ","we"],["ゐ","wi"]];
static public const CHA:Array = [["ちゃ", "cha"], ["ち", "chi"], ["ちゅ", "tyu"], ["ちぇ", "che"], ["ちょ", "cho"]];
function TypeOption( ...arrays ) {
options = options.concat.apply( null, arrays );
}
public function romans( kana:String ):Array {
var l:uint = options.length;
var romans:Array = [];
for ( var i:uint = 0; i < l; i++ ) {
var option:Array = options[i]
if ( option[0] == kana ) { romans.push( option[1] ); }
}
return romans;
}
public function kana( roman:String ):String {
var l:uint = options.length;
for ( var i:uint = 0; i < l; i++ ) {
var option:Array = options[i]
if ( option[1] == kana ) { return option[0]; }
}
return null;
}
}
class TypeEvent extends Event{
public var lastTyped:String;
public var word:TypeWord;
static public const WORD_REMOVED:String = "wordRemoved";
static public const WORD_ADDED:String = "wordAdded";
static public const MISSED:String = "missed";
static public const INITED:String = "inited";
static public const TYPED:String = "typed";
static public const START:String = "start";
static public const STOP:String = "stop";
function TypeEvent( type:String ) { super( type ); }
}
//===========================================================================================
class Typing extends EventDispatcher {
public var stage:Stage;
public var target:Vector.<TypeWord>;
public var active:Vector.<TypeWord>;
private var _running:Boolean;
public function get running():Boolean{ return _running; }
private var _typed:String;
public function get typed():String{ return _typed; }
private var _next:Array;
public function get next():Array{ return _next; }
function Typing( stage:Stage ){
this.stage = stage;
init();
}
/** 初期化を行います */
public function init():void {
_next = [];
_typed = "";
_running = false;
target = new Vector.<TypeWord>();
active = new Vector.<TypeWord>();
dispatchEvent( new TypeEvent( TypeEvent.INITED ) );
}
/** targetに新たな単語を登録します。 */
public function addTarget( word:TypeWord ):void{
target.push( word );
word.next = TypeUtil.next( word.kana, typed, TypeConfig.option );
word.typable = ( word.next.length != 0 );
if( word.typable ){ active.push( word ); }
word.roman = TypeUtil.simplestRoman( word.kana, typed, TypeConfig.option );
ArrayUtil.blend( _next, word.next );
var e:TypeEvent = new TypeEvent( TypeEvent.WORD_ADDED );
e.word = word;
dispatchEvent( e );
}
/** キーボードの監視をスタートさせます。 */
public function start():void {
if ( !_running ) {
_running = true;
stage.addEventListener( "keyDown", onKeyDown );
dispatchEvent( new TypeEvent( TypeEvent.START ) );
}
}
/** キーボードの監視を停止させます。 */
public function stop():void {
if ( _running ) {
_running = false;
stage.removeEventListener( "keyDown", onKeyDown );
dispatchEvent( new TypeEvent( TypeEvent.STOP ) );
}
}
/** キーをタイプしたときに呼び出されるイベントハンドラです。この関数を呼び出すことでキーをタイプしたときと同じ挙動をさせることが可能になります。 */
public function onKeyDown( evt:KeyboardEvent ):void{
var s:String = String.fromCharCode( evt.charCode );
var nx:int = next.indexOf( s );
var e:TypeEvent;
if ( nx == -1 ) {
e = new TypeEvent( TypeEvent.MISSED );
e.lastTyped = s;
dispatchEvent( e );
}else {
_typed += s;
var flag:Boolean = false;
var l:uint = active.length;
var c:uint = 0;
_next = [];
for( var i:uint = 0; i < l; i++ ) {
var word:TypeWord = active[i];
if( word.typable ){
word.next = TypeUtil.next( word.kana, typed, TypeConfig.option );
word.typable = word.next == null || ( word.next.length != 0 );
ArrayUtil.blend( _next, word.next );
if ( word.roman == typed ) {
target.splice( target.indexOf(word), 1 );
active.splice( i, 1 );
flag = true;
i--; l--;
}
if ( word.typable ) { word.roman = TypeUtil.simplestRoman( word.kana, typed, TypeConfig.option ); }
else{ word.roman = word.defaultRoman; }
}else {
active.splice( i, 1 );
i--; l--;
}
}
e = new TypeEvent( TypeEvent.TYPED );
e.lastTyped = s;
dispatchEvent( e );
if ( flag ) {
wordsInit();
e = new TypeEvent( TypeEvent.WORD_REMOVED );
e.lastTyped = s;
e.word = word;
dispatchEvent( e );
}
}
}
private function wordsInit():void {
var l:uint = target.length;
active = new Vector.<TypeWord>();
_typed = "";
_next = [];
for ( var i:uint = 0; i < l; i++ ) {
var word:TypeWord = target[i];
active.push( word );
word.next = TypeUtil.next( word.kana, typed, TypeConfig.option );
ArrayUtil.blend( _next, word.next );
word.typable = ( word.next.length != 0 );
word.roman = word.defaultRoman;
}
}
}
class TypeManager extends EventDispatcher{
public var typing:Typing;
public var wordList:Vector.<TypeWord>;
public var next:Vector.<TypeWord>;
public var nextMax:int = 10;
public var timeLimit:Number = -1;
public var timeCount:Number = 0;
private var _useTimeLimit:Boolean = false;
public var addLimit:int = -1;
public var addCount:int = 0;
public var removeLimit:int = -1;
public var removeCount:int = 0;
public var cycleLimit:int = -1;
public var cycleCount:int;
public var typeCount:int = 0;
public var zeroPost:Boolean = true;
public var timePost:Number = -1;
public var shuffle:Boolean = false;
private var _currentTime:Number = 0;
private var _lastAdd:Number = 0;
function TypeManager( typing:Typing, wordList:Array = null ):void{
this.typing = typing;
if( wordList ){ setWordList( wordList ) }
typing.addEventListener( TypeEvent.INITED, init );
typing.addEventListener( "start", onStart );
}
public function setWordList( wordList:Array ): void{
this.wordList = new Vector.<TypeWord>();
for each( var w:Object in wordList ) { this.wordList.push(new TypeWord(w)); }
init( null );
}
public function add():void{
if( !wordList || wordList.length==0 ){ return; }
if ( addLimit != addCount ) {
addCount++;
setNext();
next.reverse();
typing.addTarget( next.pop() );
next.reverse();
setNext();
}
}
public function setNext():void {
var wordList:Vector.<TypeWord> = this.wordList;
var l:int = wordList.length;
if(! wordList || l == 0 ){ return; }
var next:Vector.<TypeWord> = this.next;
var c:int = 0;
while ( next.length < nextMax ) {
var w:TypeWord = wordList[ (Math.random() * l) >>> 0 ];
if ( c > 10 || next.indexOf(w) == -1 ) { next.push( w ); c = 0; }
c++;
}
}
public function onStart( e:Event ):void{
typing.stage.addEventListener( "enterFrame", onFrame );
typing.addEventListener( "wordAdded", onWordAdded );
typing.addEventListener( "wordRemoved", onWordRemoved );
_currentTime = getTimer() / 1000;
}
public function init( e:Event ):void{
timeCount = 0;
addCount = 0;
removeCount = 0;
cycleCount = 0;
_useTimeLimit = ( timeLimit != -1 );
next = new Vector.<TypeWord>();
setNext();
add();
}
private function onFrame( e:Event ):void{
var time:Number = getTimer() * 0.001;
timeCount += time - _currentTime;
_currentTime = time;
if( _useTimeLimit && timeCount >= timeLimit){ complete() }
if( 0 < timePost && timePost < time - _lastAdd ){ add() }
}
private function onWordAdded( e:Event ):void{
_lastAdd = getTimer() * 0.001;
}
private function onWordRemoved( e:Event ):void{
if( removeLimit == removeCount++ ){ complete(); }
if( typing.target.length == 0 ){
if( addLimit == addCount ){ complete(); }
else if( zeroPost ){ add(); }
}
}
public function complete():void{
this.removeEventListener( "enterFrame", onFrame );
typing.removeEventListener( "wordAdded", onWordAdded );
typing.removeEventListener( "wordRemoved",onWordRemoved)
typing.stop();
this.dispatchEvent( new Event( Event.COMPLETE ) );
}
}
class TypeKeyboard extends Sprite{
private var _typing:Typing;
public function get typing():Typing{ return _typing }
public var keys:Array = TypeData.QWERTY_KEY;
public var shiftKeys:Array = TypeData.QWERTY_SHIFT;
private var _dvorak:Boolean = false;
/**
* Dvorak配列を用いるかどうかのBooleanです。
*/
public function get dvorak():Boolean{ return _dvorak; }
public function set dvorak( b:Boolean ):void{
if( _dvorak != b ){
_dvorak = b;
if( b ){
keys = TypeData.DVORAK_KEY;
shiftKeys = TypeData.DVORAK_SHIFT;
}else{
keys = TypeData.QWERTY_KEY;
shiftKeys = TypeData.QWERTY_SHIFT;
}
init();
}
}
static public var indent:Array = TypeData.BOARD_INDENT;
static private const keySize:Number = 40;
public var typeKeys:Vector.<TypeKey> = new Vector.<TypeKey>;
public var shiftKey1:TypeKey;
public var shiftKey2:TypeKey;
private var _shifted:Boolean = false;
public function get shifted():Boolean{ return _shifted; }
function TypeKeyboard( typing:Typing = null ) {
this._typing = typing;
init();
}
//typingの現状を読み込んで次に打つべきキーのヒントを出力します。
private function read( e:TypeEvent ):void {
var next:Array = _typing.next;
var l:int = next.length;
if( _shifted ){ unshift() }
for each( var key1:TypeKey in typeKeys ){ key1.up(); }
for ( var i:int = 0; i < l; i++ ) {
var str:String = next[i];
for each( var key:TypeKey in typeKeys ){
if( key.key == str ){
if ( i == 0) { key.down(); }
else if( key.state == "up" && shifted == false ){ key.over(); }
}else if ( key.shiftKey == str ) {
if ( i == 0) { key.down(); shiftKey1.down(); shiftKey2.down(); shift() }
else if( key.state == "up" && shifted ){ key.over(); }
}
}
}
}
private function init():void{
if ( typing ) {
typing.addEventListener( TypeEvent.TYPED, read );
typing.addEventListener( TypeEvent.WORD_ADDED, read );
typing.addEventListener( TypeEvent.WORD_REMOVED, read );
if ( typing.running ) { read( null ) }
else{ typing.addEventListener( TypeEvent.START, read ); }
}
while( this.numChildren > 0 ){ this.removeChildAt(0); }
var h:int = keys.length;
var s:Number = keySize;
for( var i:int = 0; i < h; i++ ){
var w:int = keys[i].length
for( var j:int = 0; j < w; j++ ){
var str:String = keys[i].substr(j,1)
var code:int = 48 + TypeData.CODE48.indexOf( str );
if( code == 47 ){ code = 65 + TypeData.CODE65.indexOf( str ) }
if( code == 64 ){ code = 186 + TypeData.CODE186.indexOf( str ) }
if( code == 185 ){ code = 219 + TypeData.CODE219.indexOf( str ) }
if( code == 218 ){ code = 226 + TypeData.CODE226.indexOf( str ) }
var mark:Boolean = i == 2 &&( j == 3 || j == 6 )
var key:TypeKey= new TypeKey( s-1, s-1, str, shiftKeys[i].substr(j,1), code, mark );
key.x = ( j + indent[i] ) * s;
key.y = i * s;
addChild( key );
typeKeys.push( key );
}
}
for( i = 0; i < 3; i++ ){
key = new TypeKey( s*indent[i]-1, s-1, "", null, [229,9,22][i] );
key.y = i * s;
addChild( key );
}
var w0:Number = keys[0].length + indent[0];
var w1:Number = keys[1].length + indent[1];
var w2:Number = keys[2].length + indent[2];
var w3:Number = keys[3].length + indent[3];
//back space
key = new TypeKey( s-1, s-1, "BS", "BS", 8 );
key.x = w0 * s;
addChild( key );
typeKeys.push( key );
//shift
key = new TypeKey( indent[3]*s- 1, s-1, "Shift", "Shift", 16 );
key.y = 3 * s;
addChild( key );
typeKeys.push( key );
shiftKey1 = key;
key = new TypeKey( (w0-w3+1)*s -1, s-1, "Shift", "Shift", 16 );
key.x = w3 * s;
key.y = 3 * s;
addChild( key );
typeKeys.push( key );
shiftKey2 = key;
//enter
key = new TypeEnterKey( (w0-w1+1)*s -1, (w0-w2+1)*s -1, s-1, 2*s-1 );
key.x = w1 * s;
key.y = 1 * s;
addChild( key );
typeKeys.push( key );
//space
key = new TypeKey( 4*s -1, s-1, " ", " ", 32 );
key.x = indent[4] * s;
key.y = 4 * s;
addChild( key );
typeKeys.push( key );
}
public function shift():void {
_shifted = true;
for each( var key:TypeKey in typeKeys ){ key.shift() }
}
public function unshift():void {
_shifted = false;
for each( var key:TypeKey in typeKeys ){ key.unshift() }
}
}
class TypeKey extends Sprite{
public var upFill:uint = TypeStyle.fill;
public var downFill:uint = TypeStyle.activeFill;
public var overFill:uint = TypeStyle.activeFill2;
public var disableFill:uint = TypeStyle.disableFill;
public var fillColor:uint = upFill;
public var lineColor:uint = TypeStyle.line;
public var state:String = "up";
public var textField:TextField = new TextField();
protected var w:Number;
protected var h:Number;
public var key:String;
public var shiftKey:String;
public var code:int;
public var shifted:Boolean;
public var mark:Boolean;
function TypeKey( width:Number, height:Number, key:String, shiftKey:String, code:Number, mark:Boolean = false ){
w = width; h = height; this.key = key; this.shiftKey = shiftKey; this.code = code; this.mark = mark
var format:TextFormat = new TextFormat( "_monospace", h/2.33, lineColor, true );
textField.defaultTextFormat = format;
textField.x = 6;
textField.y = 1;
textField.selectable = false;
draw();
addChild( textField );
drawText();
}
public function draw():void{
var g:Graphics = this.graphics;
g.clear();
g.beginFill( fillColor, 1 );
g.lineStyle( 2, lineColor );
g.drawRoundRect( 0,0, w, h, 8 );
g.endFill();
if( mark ){
var cw:Number = w/2;
g.lineStyle( 1, lineColor, 0.8 );
g.moveTo( cw + 4, h - 13 );
g.lineTo( cw - 4, h - 13 );
}
g.lineStyle( 1, 0xFFFFFF, 0.5 );
g.moveTo( 5, 1 );
g.lineTo( 5, h-10 );
g.lineTo( w-5 , h-10 );
g.lineTo( w-5 , 1 );
}
public function drawText():void {
if( shifted ){ textField.text = shiftKey; }
else { textField.text = key; }
}
public function down():void{
fillColor = downFill;
state = "down";
draw();
}
public function over():void{
fillColor = overFill;
state = "over";
draw();
}
public function up():void{
fillColor = upFill;
state = "up";
draw();
}
public function disable():void{
fillColor = disableFill;
state = "disable";
draw();
}
public function shift():void{
shifted = true;
drawText();
}
public function unshift():void{
shifted = false;
drawText();
}
}
class TypeEnterKey extends TypeKey{
private var w2:Number;
private var h2:Number;
function TypeEnterKey ( width:Number, width2:Number, height:Number, height2:Number ){
w2 = width2; h2 = height2;
super( width, height, "Enter", "Enter", 13 )
addChild( textField );
drawText();
}
override public function draw():void{
var g:Graphics = this.graphics;
g.clear();
g.beginFill( fillColor, 1 );
g.lineStyle( 2, lineColor );
var l:Function = g.lineTo;
var c:Function = g.curveTo;
var r:Number = 8;
var x0:Number = 0, x1:Number = w - w2, x2:Number = w;
var y0:Number = 0, y1:Number = h, y2:Number = h2;
g.moveTo( x0, y0 + r );
l( x0, y1 - r ); c( x0, y1, x0 + r, y1 );
l( x1 , y1 );
l( x1, y2 - r ); c( x1, y2, x1 + r, y2 );
l( x2 - r, y2 ); c( x2, y2, x2, y2 - r );
l( x2, y0 + r ); c( x2, y0, x2 - r, y0 );
l( x0 + r, y0 ); c( x0, y0, x0, y0 + r );
g.endFill();
g.lineStyle( 1, 0xFFFFFF, 0.5 );
x0 = 4, x1 = w - w2 + 4, x2 = w - 4;
y0 = 1, y1 = h - 10, y2 = h2 - 10;
g.moveTo( x0, y0 );
l( x0, y1 ); l( x1, y1 ); l( x1, y2 ); l( x2, y2 ); l( x2, y0 );
}
}
class TypePanel extends Sprite{
public var typing:Typing;
public var kanaField:TextField = new TextField();
public var wordField:TextField = new TextField();
public var romanField:TextField = new TextField();
private var w:Number, h:Number;
private var nextFormat:TextFormat = TypeStyle.nextFormat;
private var typedFormat:TextFormat = TypeStyle.typedFormat;
private var typingFormat:TextFormat = TypeStyle.typingFormat;
function TypePanel( typing:Typing, width:Number, height:Number, kanaWeight:Number = 0.2, wordWeight:Number = 0.5, romanWeight:Number = 0.3 ){
this.typing = typing;
w = width; h = height;
var y:Number = 0;
var th:Number;
var format:TextFormat;
var weights:Array = [ kanaWeight, wordWeight, romanWeight ];
var fields:Array = [ kanaField, wordField, romanField ];
for( var i:int = 0; i < 3; i++ ){
var weight:Number = weights[i];
var field:TextField = fields[i];
if( weight > 0 ){
th = h * weight;
format = TypeStyle.defaultTextFormat;
field.scaleX = field.scaleY = th * 0.01;
field.width = w / field.scaleX;
field.height = th / field.scaleY;
field.y = y;
field.selectable = false;
field.defaultTextFormat = format;
addChild( field );
y += th;
}
}
update( null );
typing.addEventListener( "wordAdded", update );
typing.addEventListener( "wordRemoved", update );
typing.addEventListener( "typed", update );
}
private function update( e:Event ):void {
if( typing.active.length == 1 ){
var word:TypeWord = typing.active[0];
var wordNum:Number = 0;
kanaField.text = word.kana;
wordField.text = word.word;
romanField.text = word.roman;
romanField.setTextFormat( typingFormat, -1, -1 );
var tl:int = typing.typed.length;
if ( tl > -1 ) {
if( tl > 0 && tl < word.roman.length ){ romanField.setTextFormat( typedFormat, -1, tl); }
if( tl + 1 < word.roman.length){ romanField.setTextFormat( nextFormat, tl, tl + 1 ); }
}
}
}
}
class TypeMonitor extends Sprite{
public var typing:Typing;
public var maxText:TextField = new TextField();
public var minText:TextField = new TextField();
public var text:TextField = new TextField();
private var w:Number, h:Number;
private var graph:Shape = new Shape;
private var gw:Number, gh:Number;
public var time:int;
public var typeCount:int;
public var speed:Number;
public var miss:Number;
private var currentTime:int;
private var typeHistory: Vector.<int>;
private var missHistory: Vector.<int>;
private var timer:Timer = new Timer( 100 );
private var type3Graph:Vector.<Number>;
private var miss3Graph:Vector.<Number>;
private var graphMax:Number = 0.05;
private var graphLen:int = 0;
function TypeMonitor( typing:Typing, width:Number, height:Number, kanaWeight:Number = 0.2, wordWeight:Number = 0.5, romanWeight:Number = 0.3 ){
this.typing = typing;
w = width; h = height;
var g:Graphics = this.graphics;
g.beginFill( 0x222222, 1 );
g.lineStyle( 1, 0x444444, 1 );
g.drawRect( 0,0, w, h );
g.endFill();
var m:Number = 8;
gh = h - 2 * m - 10; gw = w - 2 * m - 60;
this.addChild( graph );
graph.x = 60 + m; graph.y = m;
g.beginFill( 0, 1 );
g.lineStyle( 1, 0x444444, 1 );
g.drawRect( graph.x, graph.y, gw, gh );
text = new TextField();
text.width = w - m;
text.y = gh + m;
text.defaultTextFormat = new TextFormat( null, 10, 0xAAAAAA, null, null, null, null, null, "right" )
addChild( text );
maxText = new TextField();
maxText.width = 60;
maxText.x = m;
maxText.defaultTextFormat = new TextFormat( null, 10, 0xAAAAAA, null, null, null, null, null, "right" )
addChild( maxText );
minText = new TextField();
minText.width = 60;
minText.x = m;
minText.y = gh;
minText.defaultTextFormat = new TextFormat( null, 10, 0xAAAAAA, null, null, null, null, null, "right" )
minText.text = "0key/s";
addChild( minText );
timer.addEventListener( "timer", update );
typing.addEventListener( "inited", onInited );
typing.addEventListener( "start", onStart );
typing.addEventListener( "stop", onStop );
typing.addEventListener( "typed", onTyped );
typing.addEventListener( "missed", onMissed );
onInited(null);
}
private function onInited( e:Event ):void{
time = 0;
typeCount = 0;
miss = 0;
speed = 0;
typeHistory = new Vector.<int>();
missHistory = new Vector.<int>();
type3Graph = new Vector.<Number>();
miss3Graph = new Vector.<Number>();
graphMax = 0.01;
graphLen = 0;
draw();
}
private function onStart( e:Event ):void{
currentTime = getTimer();
timer.start();
}
private function onStop( e:Event ):void{
timer.stop();
}
private function onTyped( e:Event ):void{
time += getTimer() - currentTime;
currentTime = getTimer();
typeHistory.push( time );
typeCount++;
}
private function onMissed( e:Event ):void{
time += getTimer() - currentTime;
currentTime = getTimer();
missHistory.push( time );
}
private function update( e:Event ):void{
time += getTimer() - currentTime;
currentTime = getTimer();
var t:Number = time / 1000;
text.text = " Time:"+ t.toFixed(1)+"sec" + " Miss:" + miss.toFixed(2) + "key/s"+ " CurrentSpeed:" + speed.toFixed(2) + "key/s" +" AverageSpeed:" + (typeCount/t).toFixed(2) + "key/s";
maxText.text = "" + ( graphMax * 10 ).toFixed(2) + "key/s";
while( t > ( graphLen + 3 ) / 10 ){
tgPush();
mgPush();
graphLen += 3;
}
draw();
}
private function tgPush():void{
var t:int = currentTime;
var start:int = (graphLen - 30) * 100;
var end:int = graphLen * 100;
var c:int = 0;
for( var i:int = typeHistory.length - 1; i >= 0; i--){
t = typeHistory[i]
if( end > t ){
if( t > start ){ c++ }
else{ typeHistory.splice( 0, i+1 ); i = -1; }
}
}
var s:Number;
if( graphLen > 30 ){
s = c / 30;
if( graphMax < s ){ graphMax = s; }
type3Graph.push( s );
speed = s*10;
if( type3Graph.length > gw ){
type3Graph.reverse();
type3Graph.pop();
type3Graph.reverse();
}
}
}
private function mgPush():void{
var t:int = currentTime;
var start:int = (graphLen - 30) * 100;
var end:int = graphLen * 100;
var c:int = 0;
for( var i:int = missHistory.length - 1; i >= 0; i--){
t = missHistory[i]
if( end > t ){
if( t > start ){ c++; }
else{ missHistory.splice( 0, i+1 ); i = -1; }
}
}
var s:Number;
if( graphLen > 30 ){
s = c / 30;
if( graphMax < s ){ graphMax = s; }
miss3Graph.push( s );
miss = s*10;
if( miss3Graph.length > gw ){
miss3Graph.reverse();
miss3Graph.pop();
miss3Graph.reverse();
}
}
}
private function draw():void{
var g:Graphics = graph.graphics;
g.clear();
g.lineStyle( 1, 0xAAAAAA, 0.8 );
var l:int; var i:int;
l = miss3Graph.length;
g.lineStyle( 0.5, 0xFF0000, 0.8 );
for( i = 0; i < l; i++ ){
if( i == 0 ){ g.moveTo( l-i, gh * ( graphMax - miss3Graph[i] ) / graphMax ) }
else{ g.lineTo( l-i, gh * ( graphMax - miss3Graph[i] ) / graphMax ) }
}
l = type3Graph.length;
g.lineStyle( 0.5, 0xFF00, 0.8 );
for( i = 0; i < l; i++ ){
if( i == 0 ){ g.moveTo( l-i, gh * ( graphMax - type3Graph[i] ) / graphMax ) }
else{ g.lineTo( l-i, gh * ( graphMax - type3Graph[i] ) / graphMax ) }
}
}
}