2009年2月8日日曜日

[Air]はてなの注目エントリをながら見するツールを作った

いつも家でご飯食べるとき、両手を使わないでウェブが見れるツールが欲しいと思っていたので、Airで作ってみました。

以下のリンクからダウンロードして、インストールすれば動くはずですが、初Airなので自信無し。
nagarami.air

はてなブックマークの注目エントリ(コンピュータと科学)のRSSを取得して、載っているURLにアクセスして行きます。
画面は上下2画面あって、コンピュータの注目エントリが上画面、科学が下画面に表示されます。
スクロールは3秒間隔で一画面分ずつ動いて行きます。
実行時はこんなかんじ。


以下長いですがソースです。

Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:nagara="*" layout="absolute" applicationComplete="onInit()">
    <mx:Script>
     <![CDATA[
        import HtmlViewer;
        private function onInit():void {
            var htmlViewer1:HtmlViewer = new HtmlViewer();
            var htmlViewer2:HtmlViewer = 
            new HtmlViewer("http://b.hatena.ne.jp/entrylist/knowledge?sort=hot&threshold=&mode=rss");
            loader1.source = htmlViewer1 
            loader2.source = htmlViewer2 
        }   
     ]]>    
    </mx:Script>
    <mx:VBox>
        <mx:SWFLoader id="loader1" width="100%" height="100%"/>
        <mx:HRule width="100%"/>
        <mx:SWFLoader id="loader2" width="100%" height="100%"/>
    </mx:VBox>
</mx:WindowedApplication>


HtmlViewer.as
package
{
    import flash.html.HTMLLoader;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.events.Event;
    import flash.utils.Timer;
    import flash.events.TimerEvent;

    public class HtmlViewer extends HTMLLoader
    {
        private var urls:Array;
        private var scrollTimer:Timer;
        private var loader:URLLoader;
        private var windowHeight:int = 360;
        public function HtmlViewer(seedUrl:String="http://b.hatena.ne.jp/entrylist/it?sort=hot&threshold=&mode=rss")
        {
            this.width = 1000;
            this.height = windowHeight;

            loader = new URLLoader();
            var req:URLRequest = new URLRequest(seedUrl);
            loader.addEventListener(Event.COMPLETE, onRssLoadComplete);
            loader.load(req);
        }

        private function onRssLoadComplete(event:Event):void
        {
            var RSS:Namespace   = new Namespace("",     "http://purl.org/rss/1.0/");
            var RDF:Namespace   = new Namespace("rdf",  "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
            var xml:XML = new XML(event.target.data);
            urls = new Array();
            for each(var url:XML in xml.RSS::item){
                urls.push(url.@RDF::about);
            }

            loadNew();
        }

        private function loadNew():void
        {
            var url:String = urls.pop();
            if (url != null)
            {
                this.addEventListener(Event.COMPLETE, scrollHtml);
                var urlReq:URLRequest = new URLRequest(url);
                this.load(urlReq);
            }
        }

        private function scrollHtml(event:Event):void
        {
            var maxScrollCount:int = (this.contentHeight - windowHeight) / windowHeight;
            scrollTimer = new Timer(3000, maxScrollCount+2);
            scrollTimer.addEventListener(TimerEvent.TIMER, onTick);
            scrollTimer.addEventListener(TimerEvent.TIMER_COMPLETE,showNext);
            scrollTimer.start();
        }

        private function showNext(event:TimerEvent):void
        {
            loadNew();
        }

        private function onTick(event:TimerEvent):void
        {
            this.scrollV += windowHeight;
        }
    }
}

2009年1月14日水曜日

Flashで分散処理(のアイデアだけ)

Pythonのmultiprocessingで遊んでた流れから、こんどはFlashで分散処理をしてみたくなりました。
DBにオセロの末端から5手前ぐらいの局面を鬼のように登録して行って、Flashでそのタスクを取得、計算して、結果をDBに登録。さらに結果をバッチかなにかで集計して局面の評価値を決めて行くという感じです。

Flashを表示した人のCPUパワーを勝手に借りて行う分散処理。画期的じゃないですか。
まあでも実際やったら勝手にCPU借りるのはおこられそうなので、なにかユーザの興味を引くコンテンツを表示しつつ、裏では計算させてもらいますと、そんな感じでやれば角も立たないんじゃないかなと考えてます。

ただいま実装中。

2009年1月7日水曜日

[Python]multiprocessingを使ったオセロ

Pythonのmultiprocessingを使ってオセロの分散並列処理をやってみました。
サーバのキューに登録されるタスクをクライアントが黙々と計算して結果を返します。

構成はこんな感じです。

  • server.py タスク配布用と結果受け取り用のキューを持っているサーバ。

  • Othello.py オセロの探索を行うクラス。

  • game.py Othelloのサブクラス。オセロの探索対象の局面をサーバのキューに登録するクラス。

  • client.py Othelloのサブクラス。キューに入ったタスクを探索して、評価値を返すクラス。

  • game_launcher.py ユーザからの入力を受け取ってgameに初期条件等を与える。


使い方は

  • サーバでserver.pyを立ち上げる

  • クライアントでclient.pyを立ち上げる

  • クライアントorサーバでgame_launcher.pyを立ち上げる

あとはプロンプトが出てくるので、自分の色を選んで、手を入力して行くと、タスクがクライアントに配布されて探索されます。
クライアントはいくつでも接続できますが、タスク自体が現局面での合法手分しか作られないので、7〜8クライアントぐらいで速度が頭打ちになると思います。

ちょこっと解説。
server.py

task_queue = Queue.Queue()
result_queue = Queue.Queue()
class QueueManager(BaseManager): pass

QueueManager.register('get_task_queue',callable=lambda:task_queue)
QueueManager.register('get_result_queue',callable=lambda:result_queue)
m = QueueManager(address=('',8001),authkey='abc')
s = m.get_server()
s.serve_forever()

タスク配布用と結果受け取り用のキューを作成して、サーバをたてます。
remoteからはサーバに接続した後get_task_queue,get_result_queueでキューを取得できます。

game.py(一部抜粋)

class Game(Othello):

    def __init__(self,color):
        Othello.__init__(self,color)

        QueueManager.register('get_task_queue')
        QueueManager.register('get_result_queue')
        m = QueueManager(address=('example.com',8001),authkey='abc')
        m.connect()
        self.task_queue = m.get_task_queue()
        self.result_queue = m.get_result_queue()

こちらはサーバに接続して、キューを取得しています。
分散並列処理のきもはここだけです。なんて簡単!
あとはタスクをキューに入れて、client側で取って探索するだけ。
client側の接続処理もこの処理と同じです。

2009年1月6日火曜日

[python]multiprocessingで分散並列処理

pythonのmultiprocessingを使って、以前作ったオセロを分散並列処理するように改造してます。
さあ一通りできたしブログにのせるかあ。と思って、ソースを見直していたら、いろいろバグ発見。
直してるうちに、壮大なリファクタリングになってしまって納まりがつかなくなってしまいました。
もうちょっとリファクタリングとバグ修正したら公開する予定。

2009年1月5日月曜日

技術系の話はこちらで

こーたです。

最近ブログを書いていて、将棋系の話と技術系の話を両方読んでる人は居ないんじゃないかと思ったので、
ブログを二つに分けました。
将棋系の話はこーた日記の方で、技術系の話はこちらで書いて行こうと思います。