In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: VoiceChat (Japanese support)

日本語対応
Get Adobe Flash player
by ikekou 16 Aug 2011
/**
 * Copyright ikekou ( http://wonderfl.net/user/ikekou )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/w08s
 */

// forked from paq's VoiceChat
package 
{
    import com.bit101.components.ComboBox;
    import com.bit101.components.PushButton;
    import com.bit101.components.Window;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.media.Sound;
    import flash.net.URLRequest;
    import flash.net.URLRequestHeader;
    import flash.net.URLRequestMethod;
    import flash.net.URLVariables;
    import flash.system.IME;
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.ui.Keyboard;
    import net.user1.reactor.IClient;
    import net.user1.reactor.Reactor;
    import net.user1.reactor.ReactorEvent;
    import net.user1.reactor.Room;
    import net.user1.reactor.RoomEvent;
    
    /**
     * Union と Google TTS を使ったチャット
     * 日本語は使えない
     * 
     * @author paq89
     */
    /**
     * 日本語を無理矢理しゃべらせる
     * "Google Text To Speech" speak Japanese. (http://wonderfl.net/c/faUk)
     * と組み合わせてみた
     * 
     * @author ikekou
     */
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")]
    public class Main extends Sprite 
    {
        private var _reactor:Reactor;
        private var _room:Room;
        private var _sound:Sound;
        private var _header:URLRequestHeader;
        private var _request:URLRequest;
        private var _inputText:TextField;
        private var _outputText:TextField;
        private var _variable:URLVariables;
        //private var _languages:Array = ["en", "de", "fr", "es", "it"];
        private var _languages:Array = ["ja", "en", "de", "af", "sq", "hy",
                                        "ca", "hr", "cs", "da", "nl",
                                        "fi", "fr", "el", "ht", "hi",
                                        "hu", "is", "id", "it", "la",
                                        "lv", "mk", "no", "pl", "pt",
                                        "ro", "ru", "sr", "sk", "es",
                                        "sw", "sv", "tr", "vi", "cy"]
        private var _comboBox:ComboBox;
        private var _window:Window;
        private var _selectedLanguage:String;
        private var _sendButton:PushButton;
        private var isChanged:Boolean = false;
        
        // Constructor
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
            graphics.beginFill(0xFFFFFF);
            graphics.drawRect(0, 0, 465, 465);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            // init google tts
            //_request = new URLRequest("http://paq-web.appspot.com/proxy");
            _request.method=URLRequestMethod.POST;
            _variable = new URLVariables();
            _request.data = _variable;
            
            // init union reactor
            _reactor = new Reactor();
            _reactor.addEventListener(ReactorEvent.READY, _onReady);
            _reactor.connect("tryunion.com", 80);
            
            // build ui
            //_inputText = new InputText(this, 0, 465 - 20, "");
            _inputText = new TextField();
            addChild(_inputText);
            _inputText.x = 0;
            _inputText.y = 465 - 20;
            _inputText.width = 465 - 100;
            _inputText.height = 19;
            _inputText.border = true;
            _inputText.borderColor = 0x999999;
            _inputText.multiline = false;
            _inputText.type = TextFieldType.INPUT;
            _inputText.addEventListener(KeyboardEvent.KEY_UP, _onKeyUp);
            
            //_outputText = new Text(this, 0, 0);
            _outputText = new TextField();
            addChild(_outputText);
            _outputText.width = 465 -1;
            _outputText.height = 465 - 20;
            _outputText.border = true;
            _outputText.borderColor = 0x999999;
            
            _sendButton = new PushButton(this, 465 - 100, 465 - 20, "SEND", _onSend);
            
            //_comboBox = new ComboBox(this, 465 - 40, 0, "", _languages);
            //_comboBox.width = 40;
            //_comboBox.selectedIndex = 0;

            _selectedLanguage = _languages[0];
            _window = new Window(this, 465 - 100, 0, "Languages");
            _window.width = 100;
            _window.height = 18 * 20;
            _window.minimized = true;
            _window.shadow = false;
            _window.draggable = false;
            _window.hasMinimizeButton = true;
            _window.title = "Languages (" + _selectedLanguage + ")";
            
            var len:int = _languages.length;
            var x:int = 0;
            var y:int = 0;
            for (var i:int = 0; i < len; i++ )
            {
                var button:PushButton = new PushButton(_window.content, x * 50, y * 20, _languages[i], _onClick);
                button.width = 50;
                y++;
                if (y > 16) {
                    x++;
                    y = 0;
                }
                
                //default language japanese
                if (i == 0)
                {
                    button.dispatchEvent(new Event(MouseEvent.CLICK));
                }
            }
            
            stage.focus = _inputText;
        }
        
        private function _onKeyUp(e:KeyboardEvent):void 
        {
            if (e.keyCode == Keyboard.ENTER) {
                _onSend(e);
            }
        }
        
        private function speak(text:String):void
        {
            if (text.slice(0,2) != "ja")
            {
                _sound = new Sound();
                _sound.addEventListener(Event.COMPLETE, _onComplete);
                _variable.url = "http://translate.google.com/translate_tts?tl=" + text.slice(0,2) + "&q=" + encodeURI(text.slice(2));
                // _request.url = "http://translate.google.com/translate_tts?tl=" + text.slice(0,2) + "&q=" + encodeURI(text.slice(2));
                // _request.url = "http://paq-web.appspot.com/proxy?url=" +  encodeURIComponent("http://translate.google.com/translate_tts?tl=" + text.slice(0, 2) + "&q=" + text.slice(2));
                _sound.load(_request);
            }
            else
            {
                var p:Parser = new Parser();
                p.addEventListener(Event.COMPLETE, _onParseComplete4Ja);
                p.parse(text.slice(2));
                
                stage.focus = _inputText;
            }
        }
        
        private function displayMessage(text:String):void
        {
            _outputText.text = text + "\n" + _outputText.text;
        }
        
        private function _onReady(e:ReactorEvent):void 
        {
            _reactor.self().setAttribute("USERNAME", this.root.loaderInfo.parameters["viewer.displayName"]);
            
            _room = _reactor.getRoomManager().createRoom("wonderfl_paq_voice_chat");
            _room.addEventListener(RoomEvent.ADD_OCCUPANT, _onAddOccupant)
            _room.addEventListener(RoomEvent.REMOVE_OCCUPANT, _onRemoveOccupant);
            _room.addMessageListener("CHAT_MESSAGE", _onChatMessage);
            _room.join();
        }
        
        private function _onAddOccupant(e:RoomEvent):void 
        {
            displayMessage(e.getClient().getAttribute("USERNAME") + " joined the chat.");
        }
        
        private function _onRemoveOccupant(e:RoomEvent):void 
        {
            displayMessage(e.getClient().getAttribute("USERNAME") + " left the chat.");
        }
        
        private function _onChatMessage(client:IClient, message:String):void 
        {
            speak(message);
            displayMessage(client.getAttribute("USERNAME") + ": " + message.slice(2));
        }
        
        private function _onComplete(e:Event):void 
        {
            _sound.play();
        }
        
        private function _onSend(e:Event):void
        {
            if (_inputText.text == "") return;
            if (_inputText.text.length > 100)
            {
                displayMessage("!!error!!");
                return;
            }
            _room.sendMessage("CHAT_MESSAGE", true, null, _selectedLanguage + _inputText.text);
            //_room.sendMessage("CHAT_MESSAGE", true, null, _languages[_comboBox.selectedIndex] + _inputText.text);
            _inputText.text = "";
        }
        
        private function _onClick(e:Event):void
        {
            _selectedLanguage = e.target.label;
            _window.minimized = true;
            _window.title = "Languages (" + _selectedLanguage + ")";
            
            if (_selectedLanguage != "ja")
            {
                _inputText.removeEventListener(KeyboardEvent.KEY_DOWN, _onKeyUp4Ja);
                _inputText.removeEventListener(Event.CHANGE, _onChange4Ja);
                
                _inputText.addEventListener(KeyboardEvent.KEY_UP, _onKeyUp);
                
                IME.enabled = false;
                _inputText.restrict = "0-9A-Za-z,. !?"; //ここらへん適当
            }
            else
            {
                _inputText.removeEventListener(KeyboardEvent.KEY_UP, _onKeyUp);
                
                _inputText.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyUp4Ja);
                _inputText.addEventListener(Event.CHANGE, _onChange4Ja);
                
                IME.enabled = true;
                _inputText.restrict = "0-9A-Za-z,.、-熙0-9A-z  !?!?"; //ここらへん適当
            }
        }
        
        private function _onChange4Ja(e:Event):void 
        {
            isChanged = true;
        }
        
        private function _onKeyUp4Ja(e:KeyboardEvent):void 
        {
            if (e.keyCode == Keyboard.ENTER && isChanged) 
            {
                isChanged = false;
                
                _onSend(null);
            }
        }
        
        private function _onParseComplete4Ja(e:Event):void 
        {
            var c:ParsedXMLConverter = new ParsedXMLConverter();
            var result:String = c.convert(Parser(e.target).data);
            
            var s:Speaker = new Speaker();
            s.speak(result);
        }
    }
    
}

    internal class Config 
    {
        
        public static const URL_PROXY:String = "http://api.ikekou.jp/proxy.php";
        
    }

    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.media.Sound;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.net.URLVariables;
    
    internal class Parser extends EventDispatcher
    {
        public var data:XML;
        
        public function parse(target:String, useProxy:Boolean = false ):void
        {
            if (!target) return;
            
            var req:URLRequest = new URLRequest(Config.URL_PROXY);
            var vars:URLVariables = new URLVariables();
            req.data = vars;
            vars.url = "http://jlp.yahooapis.jp/MAService/V1/parse?appid=0GIwpCyxg67plKeaS4vB4tJQVU8hQ9RTaAC4AlZibwtGU0tYbRB7SbLkFvgEs2Db&sentence=" + encodeURI(target);
            
            var ul:URLLoader = new URLLoader();
            ul.addEventListener(Event.COMPLETE, _onComplete);
            ul.load(req);
        }
        
        private function _onComplete(e:Event):void 
        {
            data = new XML(XMLUtil.deleteNameSpace(URLLoader(e.target).data));
            dispatchEvent(new Event(Event.COMPLETE));
        }
        
    }
    
    internal class XMLUtil 
    {
        /**
         * 
         * clockmakerさんのを拝借
         * 
         * 名前空間を削除します
         * @param    オリジナルストリング(XML形式)
         * @return    namespace宣言を取り去ったXML
         */
        public static function deleteNameSpace(xmlText:String):XML
        {
            // remove the namespaces from the string representation of the XML
            xmlText = xmlText.replace(new RegExp("xmlns[^\"]*\"[^\"]*\"", "gi"), "");
            xmlText = xmlText.replace(new RegExp("xsi[^\"]*\"[^\"]*\"", "gi"), "");

            // set the string rep. of the XML back to real XML
            return new XML(xmlText);
        }
        
    }
    
    internal class ParsedXMLConverter 
    {
        
        public function convert(parsedXml:XML):String
        {
            var converter:Converter = new Converter();
            var words:XMLList = parsedXml..word;
            var result:String = "";
            
            //var n:int = words.length();
            //for (var i:int = 0; i < n; i++) 
            //{
                //result += converter.convert(words[i].reading, words[i].pos) + " ";
            //}
            
            //助詞以外は全部くっつけちゃったほうがいいかも
            var buf:String = "";
            var n:int = words.length();
            for (var i:int = 0; i < n; i++) 
            {
                if (words[i].pos == "助詞")
                {
                    result += converter.convert(buf) + " ";
                    buf = "";
                    
                    result += converter.convert(words[i].reading, words[i].pos) + " ";
                }
                else
                {
                    buf += words[i].reading;
                }
                
            }
            
            result += converter.convert(buf) + " ";
            
            return result;
        }
    }
    
    internal class Converter 
    {
        public static const COLLECTION_BASIC:Array = [
            ["あ", "a"],
            ["い", "i"],
            ["う", "u"],
            ["え", "e"],
            ["お", "o"],
            ["ぁ", "a"],
            ["ぃ", "i"],
            ["ぅ", "u"],
            ["ぇ", "e"],
            ["ぉ", "o"],
            ["か", "ka"],
            ["き", "ki"],
            ["く", "ku"],
            ["け", "ke"],
            ["こ", "ko"],
            ["きゃ", "kya"],
            ["きゅ", "kyu"],
            ["きょ", "kyo"],
            ["さ", "sa"],
            ["し", "shi"],
            ["す", "su"],
            ["せ", "se"],
            ["そ", "so"],
            ["しゃ", "sha"],
            ["しゅ", "shu"],
            ["しょ", "sho"],
            ["た", "ta"],
            ["ち", "chi"],
            ["つ", "tsu"],
            ["て", "te"],
            ["と", "to"],
            ["ちゃ", "cha"],
            ["ちゅ", "chu"],
            ["ちょ", "cho"],
            ["な", "na"],
            ["に", "ni"],
            ["ぬ", "nu"],
            ["ね", "ne"],
            ["の", "no"],
            ["にゃ", "nya"],
            ["にゅ", "nyu"],
            ["にょ", "nyo"],
            ["は", "ha"],
            ["ひ", "hi"],
            ["ふ", "fu"],
            ["へ", "he"],
            ["ほ", "ho"],
            ["ひゃ", "hya"],
            ["ひゅ", "hyu"],
            ["ひょ", "hyo"],
            ["ま", "ma"],
            ["み", "mi"],
            ["む", "mu"],
            ["め", "me"],
            ["も", "mo"],
            ["みゃ", "mya"],
            ["みゅ", "myu"],
            ["みょ", "myo"],
            ["や", "ya"],
            ["ゆ", "yu"],
            ["よ", "yo"],
            ["ら", "ra"],
            ["り", "ri"],
            ["る", "ri"],
            ["れ", "re"],
            ["ろ", "ro"],
            ["りゃ", "rya"],
            ["りゅ", "ryu"],
            ["りょ", "ryo"],
            ["わ", "wa"],
            ["を", "o"],
            ["ん", "nn"],
            ["が", "ga"],
            ["ぎ", "gi"],
            ["ぐ", "gu"],
            ["げ", "ge"],
            ["ご", "go"],
            ["ぎゃ", "gya"],
            ["ぎゅ", "gyu"],
            ["ぎょ", "gyo"],
            ["ざ", "za"],
            ["じ", "zi"],
            ["ず", "zu"],
            ["ぜ", "ze"],
            ["ぞ", "zo"],
            ["じゃ", "zya"],
            ["じゅ", "zyu"],
            ["じょ", "zyo"],
            ["だ", "da"],
            ["じ", "ji"],
            ["ず", "zu"],
            ["で", "de"],
            ["ど", "do"],
            ["じゃ", "zya"],
            ["じゅ", "zyu"],
            ["じょ", "zyo"],
            ["ば", "ba"],
            ["び", "bi"],
            ["ぶ", "bu"],
            ["べ", "be"],
            ["ぼ", "bo"],
            ["びゃ", "bya"],
            ["びゅ", "byu"],
            ["びょ", "byo"],
            ["ぱ", "pa"],
            ["ぴ", "pi"],
            ["ぷ", "pu"],
            ["ぺ", "pe"],
            ["ぽ", "po"],
            ["ぴゃ", "pya"],
            ["ぴゅ", "pyu"],
            ["ぴょ", "pyo"],
            ["、", "."],
            ["。", "."]
        ];
        public static const COLLECTION_PARTICLE:Array = [
            ["あ", "a"],
            ["い", "i"],
            ["う", "u"],
            ["え", "e"],
            ["お", "o"],
            ["か", "ka"],
            ["き", "ki"],
            ["く", "ku"],
            ["け", "ke"],
            ["こ", "ko"],
            ["きゃ", "kya"],
            ["きゅ", "kyu"],
            ["きょ", "kyo"],
            ["さ", "sa"],
            ["し", "shi"],
            ["す", "su"],
            ["せ", "se"],
            ["そ", "so"],
            ["しゃ", "sha"],
            ["しゅ", "shu"],
            ["しょ", "sho"],
            ["た", "ta"],
            ["ち", "chi"],
            ["つ", "tsu"],
            ["て", "te"],
            ["と", "to"],
            ["ちゃ", "cha"],
            ["ちゅ", "chu"],
            ["ちょ", "cho"],
            ["な", "na"],
            ["に", "ni"],
            ["ぬ", "nu"],
            ["ね", "ne"],
            ["の", "no"],
            ["にゃ", "nya"],
            ["にゅ", "nyu"],
            ["にょ", "nyo"],
            ["は", "wa"],
            ["ひ", "hi"],
            ["ふ", "fu"],
            ["へ", "he"],
            ["ほ", "ho"],
            ["ひゃ", "hya"],
            ["ひゅ", "hyu"],
            ["ひょ", "hyo"],
            ["ま", "ma"],
            ["み", "mi"],
            ["む", "mu"],
            ["め", "me"],
            ["も", "mo"],
            ["みゃ", "mya"],
            ["みゅ", "myu"],
            ["みょ", "myo"],
            ["や", "ya"],
            ["ゆ", "yu"],
            ["よ", "yo"],
            ["ら", "ra"],
            ["り", "ri"],
            ["る", "ri"],
            ["れ", "re"],
            ["ろ", "ro"],
            ["りゃ", "rya"],
            ["りゅ", "ryu"],
            ["りょ", "ryo"],
            ["わ", "wa"],
            ["を", "o"],
            ["ん", "nn"],
            ["が", "ga"],
            ["ぎ", "gi"],
            ["ぐ", "gu"],
            ["げ", "ge"],
            ["ご", "go"],
            ["ぎゃ", "gya"],
            ["ぎゅ", "gyu"],
            ["ぎょ", "gyo"],
            ["ざ", "za"],
            ["じ", "zi"],
            ["ず", "zu"],
            ["ぜ", "ze"],
            ["ぞ", "zo"],
            ["じゃ", "ja"],
            ["じゅ", "ju"],
            ["じょ", "jo"],
            ["だ", "da"],
            ["じ", "ji"],
            ["ず", "zu"],
            ["で", "de"],
            ["ど", "do"],
            ["じゃ", "ja"],
            ["じゅ", "ju"],
            ["じょ", "jo"],
            ["ば", "ba"],
            ["び", "bi"],
            ["ぶ", "bu"],
            ["べ", "be"],
            ["ぼ", "bo"],
            ["びゃ", "bya"],
            ["びゅ", "byu"],
            ["びょ", "byo"],
            ["ぱ", "pa"],
            ["ぴ", "pi"],
            ["ぷ", "pu"],
            ["ぺ", "pe"],
            ["ぽ", "po"],
            ["ぴゃ", "pya"],
            ["ぴゅ", "pyu"],
            ["ぴょ", "pyo"]
        ];
        
        public function convert(target:String, pos:String="noun"):String
        {
            if ( !target) return "";
            
            var collection:Array = COLLECTION_BASIC;
            if (pos == POS.PARTICLE) collection = COLLECTION_PARTICLE;
            
            var result:String = _convert(target, collection);
            
            return result;
        }
        
        private function _convert(target:String, collection:Array):String
        {
            target = StringUtil.toHiragana(target);
            
            var result:String = "";
            var isPrevSmallTsu:Boolean = false;
                
            var n:int = target.length;
            for (var i:int = 0; i < n; i++) 
            {
                result = __convert(
                                    result,
                                    target.charAt(i),
                                    target.charAt(i - 1),
                                    target.charAt(i + 1),
                                    collection
                                    );
            }
            
            return result;
        }
        
        private function __convert(result:String, current:String, prev:String, next:String, collection:Array):String
        {
            var tmp:String = current;
            
            if (/[A-Za-z\.]/.test(current))
            {
                if (!/[a-zA-Z\.]/.test(prev))
                {
                    result += " ";
                }
                
                result += tmp;
                return result;
            }
            
            if (/[ゃゅょ]/.test(next))
            {
                tmp += next;
            }
            
            if (/[ゃゅょ]/.test(current) && result != "")
            {
                return result;
            }
            
            if (current == "っ")
            {
                return result;
            }
            
            if (result != "" &&
                /ー/.test(current)
                )
            {
                result = result + result.substr(result.length - 1, 1);
                return result;
            }
            
            var converted:String = "";
            
            var m:int = collection.length;
            for (var j:int = 0; j < m; j++) 
            {
                if (collection[j][0] == tmp)
                {
                    converted = collection[j][1];
                }
            }
            
            if (prev == "っ")
            {
                var fl:String = converted.charAt(0);
                if (fl.indexOf("aiueo") == -1)
                {
                    converted = fl + converted;
                }
            }
            
            if (converted) 
            {
                if (result) result += " ";
                result += converted;
            }
            
            return result;
        }
        
    }
    

    internal class Speaker 
    {
        
        public function speak(target:String):void
        {
            if (!target) return;
            
            var req:URLRequest = new URLRequest(Config.URL_PROXY);
            var vars:URLVariables = new URLVariables();
            req.data = vars;
            vars.url = "http://translate.google.com/translate_tts?tl=es&q=" + encodeURI(target);
            
            var snd:Sound = new Sound();
            snd.addEventListener(Event.COMPLETE, _onComplete);
            snd.load(req);
        }
        
        private function _onComplete(e:Event):void 
        {
            Sound(e.target).play();
        }
        
    }
    
    internal class POS 
    {
        
        public static const PARTICLE:String = "助詞";
        
    }
    
    internal class StringUtil 
    {
        
        public static function toHiragana(target:String):String
        {
            var result:String = "";
            
            var n:int = target.length;
            for (var i:int = 0; i < n; i++) 
            {
                var char:String = target.charAt(i);
                if (/[ァ-ヴ]/.test(char))
                {
                    result += String.fromCharCode(char.charCodeAt() + (12354 - 12450));
                }
                else
                {
                    result += char;
                }
            }
            
            return result;
        }
        
    }