<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>FACEs</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/" />
    <link rel="self" type="application/atom+xml" href="http://faces.jp/atom.xml" />
   <id>tag:faces.jp,2010://1</id>
    <link rel="service.post" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1" title="FACEs" />
    <updated>2010-03-03T10:41:24Z</updated>
    <subtitle>A NEW POSITION OF WEB CREATION</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type  3.33-ja</generator>
 
<entry>
    <title>FlashPlayer10.1でバグレポート</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2010/03/flashplayer101.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=665" title="FlashPlayer10.1でバグレポート" />
    <id>tag:faces.jp,2010://1.665</id>
    
    <published>2010-03-03T10:39:03Z</published>
    <updated>2010-03-03T10:41:24Z</updated>
    
    <summary>「開発時にはクラッシュレポートみたいなのを表示して、エラーが出た状況を書き込んで...</summary>
    <author>
        <name>maegawa</name>
        <uri>/2006/07/post_2.html</uri>
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        「開発時にはクラッシュレポートみたいなのを表示して、エラーが出た状況を書き込んでもらえれば、ありがたい。そういうライブラリを誰か作ってほしい。」
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;margin-bottom:18px;}
-->
</style>
<div class="ao">
<p>
などと、弊社のババが<a href="http://twitter.com/kampei/status/9667485941">呟き</a>ました。<br>
<br>
ローカルマシンでは正しく動作するのに、別マシンで動かしたら「ActionScriptエラーが発生しました」というポップアップ…。そんなエラーが発生したクライアントの動作環境が分かれば、環境依存するような問題を解決しやすくなります。<br>
<br>
Flash Player 10.1からグローバルなエラー処理が可能となります。<br>つまり、クライアントで発生したエラー内容を記録する仕組みを実現できるようになりました。<br>
<br>
今回は、この仕組みを AS3 + GAE/J（GoogleAppEngin for Java）を利用して簡単に構築してみようと思います。<br>
※開発には、<a href="http://labs.adobe.com/downloads/flashplayer10.html">FlashPlayer10.1 beta 3</a>（2010/03/02現在）をインストールする必要があります。<br>※<a href="http://code.google.com/intl/ja/appengine/">GAE/J</a>を開発する環境も別途必要になります。<br>
<br>
AS3 : UncaughtErrorMonitorクラス
</p>
<pre>
package{

	import flash.display.DisplayObject;
	import flash.events.ErrorEvent;
	import flash.events.UncaughtErrorEvent;
	import flash.external.ExternalInterface;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.net.sendToURL;
	import flash.system.Capabilities;

	/**
	 * エラー補足モニタークラス
	 * 
	 * グローバルエラーを監視し、エラーが発生した場合に内容をポストします
	 * 
	 * @author maegawa@bascule
	 */	
	public class UncaughtErrorMonitor{
		
		/**
		 * コンストラクタ
		 * @param clazz
		 */		
		public function UncaughtErrorMonitor( clazz:PrivateClass ){
			// インスタンスは生成させない
		}
		/**
		 * 初期化する
		 * @param root	:ドキュメントクラス
		 */		 
		public static function init( root:DisplayObject ):void{
			
			if( root && root.loaderInfo ){
				root.loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, function( e:UncaughtErrorEvent ):void{
				
					var errorID	:uint = 0;
					var type	:String = "";
					var message	:String = "";
					var location:String = "";
					
					if( e.error is Error ){	// Errorを捕捉した場合
						var error:Error = e.error as Error;
						errorID = error.errorID;
						type = error.name;
						message = error.message;
						location = error.getStackTrace();
					}else
					if( e.error is ErrorEvent ){	// ErrorEventを捕捉した場合
						var event:ErrorEvent = e.error as ErrorEvent;
						errorID = event.errorID;
						type = event.type; 
						message = event.text;
					}else{
						return;	// Error、ErrorEventを補足した場合は処理を中断
					}
					
					var url:String = "http://GAEアプリID.appspot.com/regist";
					
					var variables:URLVariables = new URLVariables;
						variables.errorID = errorID;		// エラーID
						variables.type = type;			// エラータイプ
						variables.message = message;		// エラーメッセージ
						variables.location = location;		// エラー発生場所
						variables.swf = Capabilities.version;	// SWFのバージョン判定
						variables.userAgent = getUserAgent();	// UserAgent判定
						
					var request:URLRequest = new URLRequest( url );
						request.data = variables;
						request.method = URLRequestMethod.POST;
					
					try{
						sendToURL( request );
					}catch( e:Error ){
					}
				} );
			}
		}
		/**
		 * ユーザーエージェントを取得する
		 * @return 
		 */		
		private static function getUserAgent():String{
			try{
				if( ExternalInterface.available ){
					return ExternalInterface.call( "function(){ return navigator.userAgent; }" );
				}
			}catch( e:Error ){}
			
			return "unknow";
		}
	}
}
class PrivateClass{}
</pre>
<p>
続いて、サーバー側を準備します。<br>
<br>
GAE : UncaughterrorServletクラス
</p>
<pre>
package jp.bascule;

import java.io.IOException;
import java.util.Date;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Transaction;

@SuppressWarnings("serial")
public class RegistUncaughtErrorServlet extends HttpServlet {
	
	public void doGet( HttpServletRequest req, HttpServletResponse res ) throws IOException {
		res.sendError( 400 );
	}
	
	public void doPost( HttpServletRequest req, HttpServletResponse res ) throws IOException {
		
		try {
			String errorID = req.getParameter( "errorID" );// エラーID
			String type = req.getParameter( "type" );// エラータイプ
			String message = req.getParameter( "" );// エラーメッセージ
			String location = req.getParameter( "location" );// エラー発生場所
			String swf = req.getParameter( "swf" );// SWFのバージョン判定
			String userAgent = req.getParameter( "userAgent" );// UserAgent判定
			
			Date date = new Date();
			long time = date.getTime();
			//
			Entity entity = new Entity( "UncaughtError" );
			entity.setProperty( "appkey", appkey );
			entity.setProperty( "error_id", errorID );
			entity.setProperty( "error_type", type );
			entity.setProperty( "error_message", message );
			entity.setProperty( "error_location", location );
			entity.setProperty( "swf_version", swf );
			entity.setProperty( "user_agent", userAgent );
			entity.setProperty( "datetime", time );
			
			
			DatastoreService service = DatastoreServiceFactory.getDatastoreService();
			Transaction transaction = service.beginTransaction();
			try {
				service.put(transaction, entity);
				transaction.commit();
			} finally {
				if (transaction.isActive())
					transaction.rollback();
			}

			res.getWriter().print( "success" );
			
		} catch (Exception e) {
			res.getWriter().print( "error" );
			e.printStackTrace();
		}
	}
}
</pre>
<p>
GAE:web.xml
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"&gt;
	&lt;servlet&gt;
		&lt;servlet-name&gt;RegistUncaughtError&lt;/servlet-name&gt;
		&lt;servlet-class&gt;jp.bascule.RegistUncaughtErrorServlet&lt;/servlet-class&gt;
	&lt;/servlet&gt;
	&lt;servlet-mapping&gt;
		&lt;servlet-name&gt;RegistUncaughtError&lt;/servlet-name&gt;
		&lt;url-pattern&gt;/regist&lt;/url-pattern&gt;
	&lt;/servlet-mapping&gt;
	&lt;welcome-file-list&gt;
		&lt;welcome-file&gt;index.html&lt;/welcome-file&gt;
	&lt;/welcome-file-list&gt;
&lt;/web-app&gt;
</pre>
<p>
この内容をGAEにデプロイすれば完了です。<br>
<br>
AS3:Testクラス
</p>
<pre>
package{

	import flash.display.Sprite;
	import flash.events.ErrorEvent;
	
	/**
	 * Testクラス
	 * 
	 * UncaughtErrorMonitorクラスの動作をチェックします。
	 * 意図的にError、ErrorEventをスローさせます。
	 */	
	public class Test extends Sprite{
		
		public function Test(){
			// モニタリングを開始
			UncaughtErrorMoniter.init( this );
			// Errorの場合
			throw new Error( "エラーが発生！" );
			// ErrorEventの場合
			//throw new ErrorEvent( ErrorEvent.ERROR, false, false, "エラーイベントが発生！" );
		}
	}
}
</pre>
<p>
<br>
こんな感じで呼び出しておけば、クライアント側でエラーが発生した場合に勝手に内容がポストされます。<br>いくつかのプロジェクトで仕組みを使いまわすのであれば、アプリケーション識別子を引数に加えてあげればいいだけです。さらに、画面サイズ、ネットワーク環境など、その他の情報も記録しておけば、よりスムーズに問題を解決できそうです。<br>
<br>
GAEの管理画面にはDatastoreViewerというデータを確認する画面があるので、一覧表示する画面を用意する必要もありません。GAEは無料で使用可能ですが、データ保存容量には限界があります。とくに情報を残す必要がないのであれば、cronを利用して定期的に内容を削除すればよいと思います。
</p>
</div>]]>
    </content>
</entry>
<entry>
    <title> FlashLite1.1：SHA1する</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/10/flashlite11sha1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=664" title=" FlashLite1.1：SHA1する" />
    <id>tag:faces.jp,2009://1.664</id>
    
    <published>2009-10-25T14:14:12Z</published>
    <updated>2009-10-25T14:51:15Z</updated>
    
    <summary>手元のケータイでしか確認してませんが実機でも動きます。...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        手元のケータイでしか確認してませんが実機でも動きます。
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;margin-bottom:18px;}
-->
</style><div class="ao"><p>

前回の <a href="http://faces.jp/2009/10/flash_lite_md5.html">md5</a> では FlashLite の Infinity に屈したわけですが、今回は対策を練ってから。<br/>
<br/>
int の上位ビットに数値がかかると、桁があふれて Infinity になるため、<br/>
内部で int を 1/16 したまま扱ってしまうような設計にしました。<br/>
ソース内で xint と記述しているのがそうですが、<br/>
int の符号を再現するために Windows の「電卓」がかなり役に立ちましたw<br/>
<br/>
<img alt="sha1.swf" src="http://qrcode.jp/qr?q=http%3a%2f%2ffaces.jp%2f2009%2f10%2f25%2fsha1.swf" width="148" height="148" /></a><br/>
<a href="http://faces.jp/2009/10/25/sha1.swf">http://faces.jp/2009/10/25/sha1.swf</a><br/>
<a href="http://faces.jp/2009/10/25/1025_sha1.zip">ソースをダウンロード</a><br/>
<br/>
符号再現のあたりでビット演算のために2の乗数での剰除を繰り返してますが、<br/>
負の数に対しての "%" 演算結果が、DeviceCentral(FL1.1,FL2.1) と実機で違ってる。<br/>
実機の結果は Flash4(PC) で走らせた結果と同じになるんだけど、これはCS3だからかも？<br/>
<br/>
また、md5 では50KBを超えた swf も、call のおかげで今回は10KB以下に抑えられましたが<br/>
最後に残念なお知らせというか、期待通りのオチがあります。<br/>
<br/>
OAuth のようなことをしたくてこれを作ったのですが、<br/>
どんな短い String でも実機上での hash に10秒以上かかります。<br/>
ケータイはキー押下すぐのタイミングでしかリクエストを送れないので、<br/>
これじゃ全然間に合いません。<br/>
<br/>
一番処理を食っているのは int のエミュレーションですが<br/>
FL2 であれば十分実用に足るものが作れるに違いないと我々は信じてやみません。<br/>
</p>
</div>]]>
    </content>
</entry>
<entry>
    <title>FlashLite1.1：SLGの戦略AIを作る</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/10/flashlite11slgai.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=663" title="FlashLite1.1：SLGの戦略AIを作る" />
    <id>tag:faces.jp,2009://1.663</id>
    
    <published>2009-10-17T08:13:30Z</published>
    <updated>2009-10-17T09:27:40Z</updated>
    
    <summary>距離移動コストと敵の強さから費用対効果を計算してそれぞれ行動します。...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        距離移動コストと敵の強さから費用対効果を計算してそれぞれ行動します。
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;margin-bottom:18px;}
-->
</style><div class="ao"><p>
<img alt="slg.gif" src="http://faces.jp/2009/10/17/slg.gif" width="240" height="320" />　
<img src="http://qrcode.jp/qr?q=http%3a%2f%2ffaces.jp%2f2009%2f10%2f17%2fslg.swf" width="148"/><br />
実装してませんが、複数ユニットで攻撃するようなチームプレイ戦略とかを<br />
算出できるようになれば面白くなりそう。<br />
<a href="http://faces.jp/2009/10/17/1017_slg.zip">zipファイル</a><br />
※ちなみに as/init.as の<br />
//playerAsCpu = "xooo";<br />
のコメントをはずすと青軍を操作できます。
</p>
<pre>

//thinkTarget.as
//攻撃のROI計算

targetBin = "";
_maxYummy = 0;

for(i = 1; i &lt;= playerCount; i++ ) {
	if (i != player) {
		_units	= eval("units" add i);
		while (length(_units) &gt; 0) {
			_unitId		= i * 1000 + ord(subString(_units, 1,	1)) - 0x80;
			x			= getProperty("map/unit" add _unitId, _x);
			y			= getProperty("map/unit" add _unitId, _y);
			_unitHp		= ord(subString(_units, 3,	1)) - 0x80;
			
			_index		= 1 + x + y * mapWidth;
			_minCost	= -1;
			
			if (y &gt; 0) {
				_cost		= ord(subString(costMap, _index - mapWidth, 1)) - 0x80;
				if ((_cost &gt;= 0) and ((_cost &lt; _minCost) or (_minCost &lt; 0))) {
					_minCost	= _cost;
					s			= mbChr(0x80 + x) add mbChr(0x80 + y - 1);
					_direction	= 1;
				}	
			}
			if (x &lt; mapWidth-1) {
				_cost		= ord(subString(costMap, _index + 1, 1)) - 0x80;
				if ((_cost &gt;= 0) and ((_cost &lt; _minCost) or (_minCost &lt; 0))) {
					_minCost	= _cost;
					s			= mbChr(0x80 + x + 1) add mbChr(0x80 + y);
					_direction	= 2;
				}
			}
			if (y &lt; mapHeight-1) {
				_cost		= ord(subString(costMap, _index + mapWidth, 1)) - 0x80;
				if ((_cost &gt;= 0) and ((_cost &lt; _minCost) or (_minCost &lt; 0))) {
					_minCost	= _cost;
					s			= mbChr(0x80 + x) add mbChr(0x80 + y + 1);
					_direction	= 3;
				}
			}
			if (x &gt; 0) {
				_cost		= ord(subString(costMap, _index - 1, 1)) - 0x80;
				if ((_cost &gt;= 0) and ((_cost &lt; _minCost) or (_minCost &lt; 0))) {
					_minCost	= _cost;
					s			= mbChr(0x80 + x - 1) add mbChr(0x80 + y);
					_direction	= 4;
				}
			}
			
			if (_minCost &gt;= 0) {
				_yummy = (unitHp/_unitHp)/(_minCost/unitMove+1)
				if (_yummy &gt; _maxYummy) {
					_maxYummy	= _yummy;
					targetBin	= mbChr(0x80 + i) add subString(_units, 1, 3) add s add mbChr(0x80 + _direction);
				}
			}else {
				//攻撃不可
			}
			_units	= subString(_units, 4);
		}
	}
}
</pre>
<pre>

//thinkCost.as
//コスト計算（マップ移動）

//-1 未調査 -1 囲まれて移動不可エリアか未調査エリア
//-2 距離が大きすぎ 
//-3 超えられないもの
//-4 敵	

_timer = getTimer() + 1000 / 12;

while((length(_stack) &gt; 0) and (_timer &gt; getTimer())) {
	x			= ord(subString(_stack, 1, 1)) - 0x80;
	y			= ord(subString(_stack, 2, 1)) - 0x80;
	_cost		= ord(subString(_stack, 3, 1)) - 0x80;
	_direction	= ord(subString(_stack, 4, 1)) - 0x80;
	_stack		= subString(_stack, 5);
		
	_index		= 1 + x + y * mapWidth;
	i			= ord(subString(costMap, _index, 1)) - 0x80;
	//速度優先最適化
	//if (i &gt; -2) {
		_cost		+= ord(subString(moveCostsByChip, ord(subString(fieldMap, _index, 1)) - 0x80, 1)) - 0x80;
		if ((_cost &lt; i) or (i == -1)) {
			if (_cost &gt; unitMove * 2) {
				costMap	= subString(costMap, 1, _index - 1 ) add mbChr(0x80 - 2)			add subString(costMap, _index + 1);
			}else {
				costMap	= subString(costMap, 1, _index - 1 ) add mbChr(0x80 + _cost)		add subString(costMap, _index + 1);
				moveMap = subString(moveMap, 1, _index - 1 ) add mbChr(0x80 + _direction)	add subString(moveMap, _index + 1);
				switch(false) {
					case(_direction == 3):
						if (y &gt; 0) {
							if (ord(subString(costMap, _index - mapWidth, 1)) - 0x80 &gt; -2) {
								_stack = _stack add mbChr(0x80 + x)		add mbChr(0x80 + y - 1)	add mbChr(0x80 + _cost) add mbChr(0x80 + 1);
							}
						}
					case(_direction == 4):
						if (x &lt; mapWidth - 1) {
							if (ord(subString(costMap, _index + 1, 1)) - 0x80 &gt; -2) {
								_stack = _stack add mbChr(0x80 + x + 1)	add mbChr(0x80 + y)		add mbChr(0x80 + _cost) add mbChr(0x80 + 2);
							}
						}
					case(_direction == 1):
						if (y &lt; mapHeight - 1) {
							if (ord(subString(costMap, _index + mapWidth, 1)) - 0x80 &gt; -2) {
								_stack = _stack add mbChr(0x80 + x)		add mbChr(0x80 + y + 1)	add mbChr(0x80 + _cost) add mbChr(0x80 + 3);
							}
						}
					case(_direction == 2):
						if (x &gt; 0) {
							if (ord(subString(costMap, _index - 1, 1)) - 0x80 &gt; -2) {
								_stack = _stack add mbChr(0x80 + x - 1)	add mbChr(0x80 + y)		add mbChr(0x80 + _cost) add mbChr(0x80 + 4);
							}
						}
				}
			}			

		}	
		
	//}
}
</pre>
</div>]]>
    </content>
</entry>
<entry>
    <title>Flash Lite で MD5 を作ってみた。</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/10/flash_lite_md5.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=662" title="Flash Lite で MD5 を作ってみた。" />
    <id>tag:faces.jp,2009://1.662</id>
    
    <published>2009-10-15T07:40:25Z</published>
    <updated>2009-10-16T05:22:40Z</updated>
    
    <summary>残念ながら FlashLite2.0 機種上の FlashLite1.1 でしか...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        残念ながら FlashLite2.0 機種上の FlashLite1.1 でしか動きません。

        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;margin-bottom:18px;}
-->
</style><div class="ao"><p>ケータイ SWF からリクエストする際の内容を証明できるようにしたかったんですが、<br />メモリは食わないものの、スクリプトだけで<font color="red"> SWF が <b>50KB</b> 超えます。</font><br />
逆にFL2.x以降ならシフトローテート、関数、配列、論理演算を使って短く記述できるので、<br />
SHA1とかも可能と思う。FlashLite2.0以降であれば、 OpenSocial なリクエストもできそう。<br />
Fla はここに <a href="http://faces.jp/files/ao/20091015_md5/fl1md5.zip">http://faces.jp/files/ao/20091015_md5/fl1md5.zip</a></p>
<p>com.adobe.crypto.MD5 を参考にしたんですが、中身は AND XOR など論理演算が中心で<br />
アセンブラで組みこめそうな内容でした</p>
<pre>

//md5Init.as

len = length(str);
s = str add mbChr(0x80)

blocks		= ''
blocksMask	= ''

for(i = 0; i &lt;= len; i += 4 ) {
	for (j = 4; j&gt;0; j-- ) {
		c = subString(s, i + j, 1)
		if (c eq '') {
			blocks		= blocks add '.'
			blocksMask	= blocksMask add '0'
		}else {
			blocks		= blocks add c
			blocksMask	= blocksMask add '1'
		}
	}
}

i = (int((len * 8 + 0x40) / 0x0200) * 0x10 + 0x0e) * 4

while(length(blocks) &lt; i) {
	blocks		= blocks add '.';
	blocksMask	= blocksMask add '0'	
}

for(i = 0x01000000; i &gt;=1; i /= 0x0100 ) {
	byte = int((len*8) / i) % 0x0100;
	if (byte == 0) {
		blocks		= blocks add '.';
		blocksMask	= blocksMask add '0'
	}else {
		blocks		= blocks add mbChr(byte);
		blocksMask	= blocksMask add '1'
	}
}

a = 1732584193;
b = -271733879;
c = -1732584194;
d = 271733878;

s = 4294967296;//0x100000000
n = 0x80000000;

p = 0;
</pre>
<pre>

//md5Encode.as


for (j = 0; j &lt; 16; j++ ) {
	name		= 'x' add subString('0123456789ABCDEF',j+1,1)
	eval(name)	= 0;
	for (k = 0x01000000; k &gt;= 1; k /= 0x0100 ) {
		if (subString(blocksMask, p+1, 1) &gt; 0) {
			eval(name) += ord(subString(blocks, p+1, 1)) * k
		}
		p++
	}
}

aa = a;
bb = b;
cc = c;
dd = d;	

v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(c/i)%2))||((!(int(b/i)%2))&&(int(d/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x0-680876936;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x2000000)*0x80)+int(((v&lt;0)?v+s :v)/0x2000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(b/i)%2))||((!(int(a/i)%2))&&(int(c/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x1-389564586;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x100000)*0x1000)+int(((v&lt;0)?v+s :v)/0x100000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(a/i)%2))||((!(int(d/i)%2))&&(int(b/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x2+606105819;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x8000)*0x20000)+int(((v&lt;0)?v+s :v)/0x8000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(d/i)%2))||((!(int(c/i)%2))&&(int(a/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x3-1044525330;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x400)*0x400000)+int(((v&lt;0)?v+s :v)/0x400)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(c/i)%2))||((!(int(b/i)%2))&&(int(d/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x4-176418897;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x2000000)*0x80)+int(((v&lt;0)?v+s :v)/0x2000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(b/i)%2))||((!(int(a/i)%2))&&(int(c/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x5+1200080426;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x100000)*0x1000)+int(((v&lt;0)?v+s :v)/0x100000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(a/i)%2))||((!(int(d/i)%2))&&(int(b/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x6-1473231341;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x8000)*0x20000)+int(((v&lt;0)?v+s :v)/0x8000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(d/i)%2))||((!(int(c/i)%2))&&(int(a/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x7-45705983;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x400)*0x400000)+int(((v&lt;0)?v+s :v)/0x400)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(c/i)%2))||((!(int(b/i)%2))&&(int(d/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x8+1770035416;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x2000000)*0x80)+int(((v&lt;0)?v+s :v)/0x2000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(b/i)%2))||((!(int(a/i)%2))&&(int(c/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x9-1958414417;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x100000)*0x1000)+int(((v&lt;0)?v+s :v)/0x100000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(a/i)%2))||((!(int(d/i)%2))&&(int(b/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xA-42063;		if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x8000)*0x20000)+int(((v&lt;0)?v+s :v)/0x8000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(d/i)%2))||((!(int(c/i)%2))&&(int(a/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+xB-1990404162;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x400)*0x400000)+int(((v&lt;0)?v+s :v)/0x400)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(c/i)%2))||((!(int(b/i)%2))&&(int(d/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+xC+1804603682;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x2000000)*0x80)+int(((v&lt;0)?v+s :v)/0x2000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(b/i)%2))||((!(int(a/i)%2))&&(int(c/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+xD-40341101;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x100000)*0x1000)+int(((v&lt;0)?v+s :v)/0x100000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(a/i)%2))||((!(int(d/i)%2))&&(int(b/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xE-1502002290;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x8000)*0x20000)+int(((v&lt;0)?v+s :v)/0x8000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(d/i)%2))||((!(int(c/i)%2))&&(int(a/i)%2)))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+xF+1236535329;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x400)*0x400000)+int(((v&lt;0)?v+s :v)/0x400)+c;	if(b&gt;n)b-=s;

v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(d/i)%2))||((int(c/i)%2)&&(!(int(d/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x1-165796510;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x8000000)*0x20)+int(((v&lt;0)?v+s :v)/0x8000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(c/i)%2))||((int(b/i)%2)&&(!(int(c/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x6-1069501632;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x800000)*0x200)+int(((v&lt;0)?v+s :v)/0x800000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(b/i)%2))||((int(a/i)%2)&&(!(int(b/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xB+643717713;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x40000)*0x4000)+int(((v&lt;0)?v+s :v)/0x40000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(a/i)%2))||((int(d/i)%2)&&(!(int(a/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x0-373897302;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x1000)*0x100000)+int(((v&lt;0)?v+s :v)/0x1000)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(d/i)%2))||((int(c/i)%2)&&(!(int(d/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x5-701558691;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x8000000)*0x20)+int(((v&lt;0)?v+s :v)/0x8000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(c/i)%2))||((int(b/i)%2)&&(!(int(c/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+xA+38016083;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x800000)*0x200)+int(((v&lt;0)?v+s :v)/0x800000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(b/i)%2))||((int(a/i)%2)&&(!(int(b/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xF-660478335;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x40000)*0x4000)+int(((v&lt;0)?v+s :v)/0x40000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(a/i)%2))||((int(d/i)%2)&&(!(int(a/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x4-405537848;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x1000)*0x100000)+int(((v&lt;0)?v+s :v)/0x1000)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(d/i)%2))||((int(c/i)%2)&&(!(int(d/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x9+568446438;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x8000000)*0x20)+int(((v&lt;0)?v+s :v)/0x8000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(c/i)%2))||((int(b/i)%2)&&(!(int(c/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+xE-1019803690;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x800000)*0x200)+int(((v&lt;0)?v+s :v)/0x800000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(b/i)%2))||((int(a/i)%2)&&(!(int(b/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x3-187363961;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x40000)*0x4000)+int(((v&lt;0)?v+s :v)/0x40000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(a/i)%2))||((int(d/i)%2)&&(!(int(a/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x8+1163531501;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x1000)*0x100000)+int(((v&lt;0)?v+s :v)/0x1000)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)&&(int(d/i)%2))||((int(c/i)%2)&&(!(int(d/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+xD-1444681467;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x8000000)*0x20)+int(((v&lt;0)?v+s :v)/0x8000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)&&(int(c/i)%2))||((int(b/i)%2)&&(!(int(c/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x2-51403784;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x800000)*0x200)+int(((v&lt;0)?v+s :v)/0x800000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)&&(int(b/i)%2))||((int(a/i)%2)&&(!(int(b/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x7+1735328473;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x40000)*0x4000)+int(((v&lt;0)?v+s :v)/0x40000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)&&(int(a/i)%2))||((int(d/i)%2)&&(!(int(a/i)%2))))*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+xC-1926607734;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x1000)*0x100000)+int(((v&lt;0)?v+s :v)/0x1000)+c;	if(b&gt;n)b-=s;

v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(b/i)%2)+(int(c/i)%2))%2)+(int(d/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x5-378558;		if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x10000000)*0x10)+int(((v&lt;0)?v+s :v)/0x10000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(a/i)%2)+(int(b/i)%2))%2)+(int(c/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x8-2022574463;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x200000)*0x800)+int(((v&lt;0)?v+s :v)/0x200000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(d/i)%2)+(int(a/i)%2))%2)+(int(b/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xB+1839030562;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x10000)*0x10000)+int(((v&lt;0)?v+s :v)/0x10000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(c/i)%2)+(int(d/i)%2))%2)+(int(a/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+xE-35309556;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x200)*0x800000)+int(((v&lt;0)?v+s :v)/0x200)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(b/i)%2)+(int(c/i)%2))%2)+(int(d/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x1-1530992060;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x10000000)*0x10)+int(((v&lt;0)?v+s :v)/0x10000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(a/i)%2)+(int(b/i)%2))%2)+(int(c/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x4+1272893353;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x200000)*0x800)+int(((v&lt;0)?v+s :v)/0x200000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(d/i)%2)+(int(a/i)%2))%2)+(int(b/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x7-155497632;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x10000)*0x10000)+int(((v&lt;0)?v+s :v)/0x10000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(c/i)%2)+(int(d/i)%2))%2)+(int(a/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+xA-1094730640;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x200)*0x800000)+int(((v&lt;0)?v+s :v)/0x200)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(b/i)%2)+(int(c/i)%2))%2)+(int(d/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+xD+681279174;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x10000000)*0x10)+int(((v&lt;0)?v+s :v)/0x10000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(a/i)%2)+(int(b/i)%2))%2)+(int(c/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x0-358537222;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x200000)*0x800)+int(((v&lt;0)?v+s :v)/0x200000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(d/i)%2)+(int(a/i)%2))%2)+(int(b/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x3-722521979;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x10000)*0x10000)+int(((v&lt;0)?v+s :v)/0x10000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(c/i)%2)+(int(d/i)%2))%2)+(int(a/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x6+76029189;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x200)*0x800000)+int(((v&lt;0)?v+s :v)/0x200)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(b/i)%2)+(int(c/i)%2))%2)+(int(d/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x9-640364487;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x10000000)*0x10)+int(((v&lt;0)?v+s :v)/0x10000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(a/i)%2)+(int(b/i)%2))%2)+(int(c/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+xC-421815835;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x200000)*0x800)+int(((v&lt;0)?v+s :v)/0x200000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(d/i)%2)+(int(a/i)%2))%2)+(int(b/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xF+530742520;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x10000)*0x10000)+int(((v&lt;0)?v+s :v)/0x10000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((((int(c/i)%2)+(int(d/i)%2))%2)+(int(a/i)%2))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x2-995338651;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x200)*0x800000)+int(((v&lt;0)?v+s :v)/0x200)+c;	if(b&gt;n)b-=s;

v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)+((int(b/i)%2)||(!(int(d/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x0-198630844;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x4000000)*0x40)+int(((v&lt;0)?v+s :v)/0x4000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)+((int(a/i)%2)||(!(int(c/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x7+1126891415;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x400000)*0x400)+int(((v&lt;0)?v+s :v)/0x400000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)+((int(d/i)%2)||(!(int(b/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xE-1416354905;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x20000)*0x8000)+int(((v&lt;0)?v+s :v)/0x20000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)+((int(c/i)%2)||(!(int(a/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x5-57434055;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x800)*0x200000)+int(((v&lt;0)?v+s :v)/0x800)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)+((int(b/i)%2)||(!(int(d/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+xC+1700485571;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x4000000)*0x40)+int(((v&lt;0)?v+s :v)/0x4000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)+((int(a/i)%2)||(!(int(c/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+x3-1894986606;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x400000)*0x400)+int(((v&lt;0)?v+s :v)/0x400000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)+((int(d/i)%2)||(!(int(b/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+xA-1051523;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x20000)*0x8000)+int(((v&lt;0)?v+s :v)/0x20000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)+((int(c/i)%2)||(!(int(a/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x1-2054922799;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x800)*0x200000)+int(((v&lt;0)?v+s :v)/0x800)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)+((int(b/i)%2)||(!(int(d/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x8+1873313359;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x4000000)*0x40)+int(((v&lt;0)?v+s :v)/0x4000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)+((int(a/i)%2)||(!(int(c/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+xF-30611744;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x400000)*0x400)+int(((v&lt;0)?v+s :v)/0x400000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)+((int(d/i)%2)||(!(int(b/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x6-1560198380;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x20000)*0x8000)+int(((v&lt;0)?v+s :v)/0x20000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)+((int(c/i)%2)||(!(int(a/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+xD+1309151649;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x800)*0x200000)+int(((v&lt;0)?v+s :v)/0x800)+c;	if(b&gt;n)b-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(c/i)%2)+((int(b/i)%2)||(!(int(d/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=a+x4-145523070;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	a=((v%0x4000000)*0x40)+int(((v&lt;0)?v+s :v)/0x4000000)+b;	if(a&gt;n)a-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(b/i)%2)+((int(a/i)%2)||(!(int(c/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=d+xB-1120210379;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	d=((v%0x400000)*0x400)+int(((v&lt;0)?v+s :v)/0x400000)+a;	if(d&gt;n)d-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(a/i)%2)+((int(d/i)%2)||(!(int(b/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=c+x2+718787259;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	c=((v%0x20000)*0x8000)+int(((v&lt;0)?v+s :v)/0x20000)+d;	if(c&gt;n)c-=s;
v=0;for(i=1;i&lt;s;i*=2){v+=(((int(d/i)%2)+((int(c/i)%2)||(!(int(a/i)%2))))%2)*i;}if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	v+=b+x9-343485551;	if(v&lt;0){v+=s;}else if(v&gt;n){v-=s};	b=((v%0x800)*0x200000)+int(((v&lt;0)?v+s :v)/0x800)+c;	if(b&gt;n)b-=s;

a += aa;if(a&lt;0){a+=s;}else if(a&gt;n){a-=s};
b += bb;if(b&lt;0){b+=s;}else if(b&gt;n){b-=s};
c += cc;if(c&lt;0){c+=s;}else if(c&gt;n){c-=s};
d += dd;if(d&lt;0){d+=s;}else if(d&gt;n){d-=s};</pre>
<pre>

//md5Hex.as

if(p&lt;length(blocks)){
	gotoAndPlay(_currentframe-1)
}else{
	hex = ''
	for(i = 1; i &lt;s ; i *= 0x100 ) {
		hex = hex add subString('0123456789abcdef',(int(a/(i*0x10))%0x10)+1,1)
		hex = hex add subString('0123456789abcdef',(int(a/i)%0x10)+1,1)
	}
	for(i = 1; i &lt;s ; i *= 0x100 ) {
		hex = hex add subString('0123456789abcdef',(int(b/(i*0x10))%0x10)+1,1)
		hex = hex add subString('0123456789abcdef',(int(b/i)%0x10)+1,1)
	}
	for(i = 1; i &lt;s ; i *= 0x100 ) {
		hex = hex add subString('0123456789abcdef',(int(c/(i*0x10))%0x10)+1,1)
		hex = hex add subString('0123456789abcdef',(int(c/i)%0x10)+1,1)
	}
	for(i = 1; i &lt;s ; i *= 0x100 ) {
		hex = hex add subString('0123456789abcdef',(int(d/(i*0x10))%0x10)+1,1)
		hex = hex add subString('0123456789abcdef',(int(d/i)%0x10)+1,1)
	}
}

</pre>
</div>]]>
    </content>
</entry>
<entry>
    <title>PHP：Mixiアプリモバイルの RESTful API を RESTful に使う</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/10/phpmixi_apirequest.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=661" title="PHP：Mixiアプリモバイルの RESTful API を RESTful に使う" />
    <id>tag:faces.jp,2009://1.661</id>
    
    <published>2009-10-11T12:33:07Z</published>
    <updated>2009-10-11T18:02:03Z</updated>
    
    <summary>クラスを作ってみた。...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        クラスを作ってみた。
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;margin-bottom:18px;}
-->
</style><div class="ao"><p>
Auth を気にすることなくサクサク書けます。
</p>
<pre>

require_once('MixiAppMobileApi.php');

// APIのURLなどの詳細は以下を参照。
// http://developer.mixi.co.jp/appli/appli_mobile/lets_enjoy_making_mixiappmobile/for_partners

$personApi		= 'http://****************************************';
$persistenceApi	= 'http://****************************************';


$mixi = new MixiAppMobileApi;

// owner(viewer) データ取得
print_r($mixi->get($personApi));

// appData 追加
$mixi->post(
	$persistenceApi,
	array(
		'score'	=> 530000,
		'time'	=> time(),
	)
);

// appData から score を削除
$mixi->delete($persistenceApi.'?fields=score');

// appData 取得
$myAppData = $mixi->get($persistenceApi);
print_r($myAppData);

</pre>
<p>3つのメソッドにURLをそえるだけ。なんて RESTful なんでしょう。<br />
<br />
さておき、複数のアプリとか複数の環境で開発したりしていて、<br />
Consumer を逐一書き換えるのが手間な場合は、以下のクラスメソッドを使えばOKです。</p>
<pre>
MixiAppMobileApi::initWithConsumer(
	'********************',//key
	'****************************************'//secret
);

$mixi = new MixiAppMobileApi;
print_r($mixi->get($personApi));
</pre>
<p>
以下ソース MixiAppMobileApi.php<br />
※ OAuth のライブラリが必要です。
</p>
<pre>
&lt;?

require_once('OAuth.php');

class MixiAppMobileApi{
	
	static	$consumer;	
	static	$consumerKey	= '';//設定して下さい
	static	$consumerSecret	= '';//設定して下さい
	static	$appId		= '';
	static	$ownerId	= '';
	
	var 	$rawData;
	
		public static function initWithConsumer($key,$secret){
		self::$consumerKey		= $key;
		self::$consumerSecret	= $secret;
		self::init();
	}
	
	static function init(){
	
		if(isset($_GET['opensocial_app_id'])){
			self::$appId	= $_GET['opensocial_app_id'];
		}
		
		if(isset($_GET['opensocial_owner_id'])){
			self::$ownerId	= $_GET['opensocial_owner_id'];
		}
		
		self::$consumer	= new OAuthConsumer(
			self::$consumerKey,
			self::$consumerSecret,
			null
		);
		
	}
	
	function MixiAppMobileApi(){
		if(!isset(self::$consumer)){self::init();}
	}
	
	public function get($url)		{ return( $this-&gt;request($url) );		}
	public function post($url,$data)	{ return( $this-&gt;request($url,$data) );		}
	public function delete($url)		{ return( $this-&gt;request($url,null,'DELETE') );	}
	
	function request($url,$data=null,$method=null){
		
		switch(true){
			case(isset($data)):
				$options	= array('method' =&gt; 'POST', 'content' =&gt; json_encode($data));
				break;

			case(empty($method)):
				$options	= array('method' =&gt; 'GET');
				break;

			default:
				$options	= array('method' =&gt; $method);

		}
		
		list($baseFeed,$queryString)	= explode('?', $url, 2);
		
		$parameters		= $this-&gt;parameters($queryString);
		$options['header']	= $this-&gt;header(
			OAuthRequest::from_consumer_and_token(
				self::$consumer,
				null,
				$options['method'],
				$baseFeed,
				$parameters
			)
		);
		
		$this-&gt;rawData	= file_get_contents(
			$baseFeed . '?' . http_build_query($parameters,'','&'),
			null,
			stream_context_create(array('http' =&gt; $options))
		);

		return(json_decode($this-&gt;rawData));
		
	}
	
	function parameters($queryString=null){
		$parameters	= array(
			'xoauth_requestor_id' =&gt; self::$ownerId,
		);
		if(isset($queryString)){
			parse_str($queryString,$q);
			$parameters += $q;
		}
		return($parameters);
	}
		
	function header($request){
		$request-&gt;sign_request(
			new OAuthSignatureMethod_HMAC_SHA1(),
			self::$consumer,
			null
		);
		$rows = array(
			'Content-Type: application/json',
			$request-&gt;to_header(),
			'',
		);
		return(implode("\r\n",$rows));
	}
	
	function id($string){
		list($null,$id) = explode(':',$string);
		return($id);
	}
}
</pre>
</div>]]>
    </content>
</entry>
<entry>
    <title>flashでmp3をzipで固めたのを読みこんで再生</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/10/flashmp3zip.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=660" title="flashでmp3をzipで固めたのを読みこんで再生" />
    <id>tag:faces.jp,2009://1.660</id>
    
    <published>2009-10-04T20:51:43Z</published>
    <updated>2009-10-04T21:43:22Z</updated>
    
    <summary>SE系の、小さなMP3ファイルをたくさん読みこむ時は、zipにまとめたほうがスマ...</summary>
    <author>
        <name>kamp</name>
        <uri>/2006/08/kampprofile.html</uri>
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        SE系の、小さなMP3ファイルをたくさん読みこむ時は、zipにまとめたほうがスマートかな、と思い、やってみました。
        <![CDATA[<div id="zip_mp3_div"></div>
<script type="text/javascript">
new SWFObject("/files/kampei/zip_mp3/zip_mp3.swf", "boid", 400, 600, 9, "#000000").write("zip_mp3_div");
</script>
<br>
zipを動的に読み込み、zip内のmp3ファイルをリストアップし、Soundクラスとして扱えるようにします。

リストをクリックすると、音が出ます。

<br>

Flash内でのzip解凍は、<a href="http://codeazur.com.br/lab/fzip/" target="_blank">FZip</a>というライブラリを使ってます。

このライブラリは、普通のzipファイルは読み込めず、Alder32っていうchecksumを足す必要があるようです。僕もよく分かってないのですが、FZipのサイトにPythonのスクリプトが落ちてるので、無心にそれを実行するとよいです。
<br>

音源は、SLNさんの公開している、<a href="http://blog.slndesignstudio.com/archives/2008/10/general_audio_service_01.html" target="_blank">General Audio Service</a>でダウンロードできる<a href="http://yasuhirotsuchiya.com/archives/sln_gas_01_mp3.zip">mp3をzipで固めたもの</a>を、読み込んでます。
<br>

また、zipから取り出したmp3をいったんByteArrayに取り込んで、Soundクラスとして生成し直すまでのプロセスは、<a href="http://www.flexiblefactory.co.uk/flexible/?p=46" target="_blank">MP3FileReferenceLoaderLib</a>を使わせてもらいました。これはバイナリを何かゴニョゴニョしていていて、神すぎて全く分からないのですが、FilreReferenceからmp3を読み込むようになってたのを、zip経由で読み込むようにしたり、メモリを使いすぎないようにしたりしていたら、いろいろ変わってしまったので、畏れ多くも、com.kampei以下に入れときました。
(そういう自由なライセンスだと読めたんだけど、どうだろう...)<br>


やってみたのはいいのですが、思った以上にメモリを食い、実用性を疑っています。
普通にMP3を読み込んだ方がメモリ負荷は軽いのかな？？？
<br>

<a href="/files/kampei/zip_mp3/zip_mp3_src.zip">ソース</a>です。Pythonのスクリプトとかも、モロモロ入ってます。もはやライブラリの組み合わせでしかないけど...


]]>
    </content>
</entry>
<entry>
    <title>FLASH Lite 1.1 で再起処理 / 追記：FPSをキープ</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/08/flash_lite_11_fps.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=659" title="FLASH Lite 1.1 で再起処理 / 追記：FPSをキープ" />
    <id>tag:faces.jp,2009://1.659</id>
    
    <published>2009-08-31T12:06:15Z</published>
    <updated>2009-09-01T02:36:47Z</updated>
    
    <summary>一定フレームに収まらない量の処理をさせると、すぐSWFが落ちることがあるようです...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        一定フレームに収まらない量の処理をさせると、すぐSWFが落ちることがあるようです。
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"><p>
ゲームで使うCPU思考ルーチン(AI)、迷路自動生成などのスタック処理は、Device Central で問題なくても<br />
実機上で一定フレーム以上かかると落ちる、というより落とされてしまうようです。<br />

重いループを書くときは注意。</p>
<pre>
_timer = getTimer() + 1000 / 12;//ms
while((length(_stack) > 0) and (_timer > getTimer())) {
	//スタック処理
}
</pre>
<p>次のフレームに</p>
<pre>
if(length(_stack) > 0){
	gotoAndPlay(_currentframe-1)
}
</pre>
</div>]]>
    </content>
</entry>
<entry>
    <title>FLASH Lite 1.1 で再帰処理</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/08/flash_lite_11.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=658" title="FLASH Lite 1.1 で再帰処理" />
    <id>tag:faces.jp,2009://1.658</id>
    
    <published>2009-08-14T22:07:00Z</published>
    <updated>2009-08-15T18:42:29Z</updated>
    
    <summary>関数が使えないので無理です。...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        関数が使えないので無理です。
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"><p>
が、スタック処理を書けば擬似的に実現できます。<br />
スタックには Array が必要ですが、FLASH Lite 1.1 には Array がありません。<br />
普通は eval を使って擬似的に実装しますが、メモリを食うので再帰処理には不向き。<br />
そこで String をスタックメモリに見立てて while します。<br />
<br />
<a href="http://gumina.sakura.ne.jp/CREATION/OLD/MAKING/SESS03.htm">この再帰処理</a>を Flash Lite 1.1 で書くとこんな感じ。</p>
<pre>
//mapを作る
mapSize	= 11;
mapData	= "";
moveData	= "";
moveRecData	= "";

for(i = 0; i &lt; mapSize; i++ ) {
	for (j = 0; j &lt; mapSize; j++ ) {
		mapData		= mapData add (1+random(3));
		moveData	= moveData add "1";
		moveRecData	= moveRecData add "0";
	}
}

unitX = 5
unitY = 5
unitMove = 4

//擬似再帰処理 --------------------------------

//PUSH
stack = ""
stack = stack add mbChr(unitX + 1) add mbChr(unitY - 1 + 1) add mbChr(unitMove + 1) add mbChr(1 + 1);//up
stack = stack add mbChr(unitX + 1 + 1) add mbChr(unitY + 1) add mbChr(unitMove + 1) add mbChr(2 + 1);//right
stack = stack add mbChr(unitX + 1) add mbChr(unitY + 1 + 1) add mbChr(unitMove + 1) add mbChr(3 + 1);//down
stack = stack add mbChr(unitX - 1 + 1) add mbChr(unitY + 1) add mbChr(unitMove + 1) add mbChr(4 + 1);//left

while(length(stack) &gt; 3) {

	//SHIFT
	ax	= mbOrd(subString(stack, 1, 1)) - 1;
	ay	= mbOrd(subString(stack, 2, 1)) - 1;
	mv	= mbOrd(subString(stack, 3, 1)) - 1;
	di	= mbOrd(subString(stack, 4, 1)) - 1;
	stack	= subString(stack, 5);//この取り出し方だとスタックではなく正確にはキューというらしい。
	
	index = 1 + ax + ay * mapSize;
	if (subString(moveRecData, index,1) == 0) {
		switch(subString(mapData, index,1)) {
			case(1):	moveCost = 1;	break;
			case(2):	moveCost = 2;	break;
			case(3):	moveCost = 10;	break;
			default:	moveCost = 0;
		}
		if (mv - moveCost &gt;= 0) {
			moveData = subString(moveData, 1, index-1 ) add "0" add subString(moveData,	index + 1);
			moveRecData = subString(moveRecData, 1, index-1 ) add "1" add subString(moveRecData,	index + 1);
			mv = mv - moveCost;
			//PUSH
			switch(false) {
				case(di == 3):stack = stack add mbChr(ax + 1) add mbChr(ay - 1 + 1) add mbChr(mv + 1) add mbChr(1 + 1);
				case(di == 4):stack = stack add mbChr(ax + 1 + 1) add mbChr(ay + 1) add mbChr(mv + 1) add mbChr(2 + 1);
				case(di == 1):stack = stack add mbChr(ax + 1) add mbChr(ay + 1 + 1) add mbChr(mv + 1) add mbChr(3 + 1);
				case(di == 2):stack = stack add mbChr(ax - 1 + 1) add mbChr(ay + 1) add mbChr(mv + 1) add mbChr(4 + 1);
			}
		}
	}
}

//実行結果 --------------------------------

trace("map ----------");
for(i = 0; i &lt; mapSize; i++ ) {
	s = "";
	for (j = 0; j &lt; mapSize; j++ ) {
		s = s add subString(mapData, 1 + j + i*mapSize,1) add " ";
	}
	t = "0000" add i;
	trace ( subString(t,length(t)-3) add " &gt; " add s);
}
trace("move ----------");
for(i = 0; i &lt; mapSize; i++ ) {
	s = "";
	for (j = 0; j &lt; mapSize; j++ ) {
		s = s add subString(moveData, 1 + j + i*mapSize,1) add " ";
	}
	t = "0000" add i;
	trace ( subString(t,length(t)-3) add " &gt; " add s);
}
trace("moveRec ----------");
for(i = 0; i &lt; mapSize; i++ ) {
	s = "";
	for (j = 0; j &lt; mapSize; j++ ) {
		s = s add subString(moveRecData, 1 + j + i*mapSize,1) add " ";
	}
	t = "0000" add i;
	trace ( subString(t,length(t)-3) add " &gt; " add s);
}
</pre>
<p>※8/16追記<br />
表題の再帰処理とは関係ないアルゴリズムの部分なんだけど、<br />
上のソースでは検索する順序によって結果が違ってくるので<br />
条件分岐はこう書いた方が冗長でもベターではなかろうかと思われる。</p>
<pre>moveCostsByChip	= mbChr(1 + 1) add mbChr(2 + 1) add mbChr(10 + 1);

mapSize	= 11;
mapData	= "";
moveData	= "";
moveRecData	= "";

for(i = 0; i &lt; mapSize; i++ ) {
	for (j = 0; j &lt; mapSize; j++ ) {
		mapData		= mapData add (1+random(3));
		moveData	= moveData add "1";
		moveRecData	= moveRecData add "0";
	}
}

unitX		= 5;
unitY		= 5;
unitMove	= 4;

index		= 1 + unitX + unitY * mapSize;
moveCost	= mbOrd(subString(moveCostsByChip, subString(mapData, index, 1), 1)) - 1;
stack		= mbChr(unitX + 1) add mbChr(unitY + 1) add mbChr(unitMove + moveCost + 1) add mbChr(0 + 1);

while(length(stack) &gt; 3) {
	ax	= mbOrd(subString(stack, 1, 1)) - 1;
	ay	= mbOrd(subString(stack, 2, 1)) - 1;
	mv	= mbOrd(subString(stack, 3, 1)) - 1;
	di	= mbOrd(subString(stack, 4, 1)) - 1;
	stack	= subString(stack, 5);
	
	index	= 1 + ax + ay * mapSize;
	mv	-= mbOrd(subString(moveCostsByChip, subString(mapData, index,1), 1)) - 1;
	
	if (mv &gt;= 0) {
		moveData	= subString(moveData, 1, index - 1 ) add "0" add subString(moveData, index + 1);
		if (mv &gt; subString(moveRecData, index, 1)) {
			moveRecData	= subString(moveRecData, 1, index - 1 ) add mv add subString(moveRecData, index + 1);
			switch(false) {
				case(di == 3):stack = stack add mbChr(ax + 1) add mbChr(ay - 1 + 1) add mbChr(mv + 1) add mbChr(1 + 1);
				case(di == 4):stack = stack add mbChr(ax + 1 + 1) add mbChr(ay + 1) add mbChr(mv + 1) add mbChr(2 + 1);
				case(di == 1):stack = stack add mbChr(ax + 1) add mbChr(ay + 1 + 1) add mbChr(mv + 1) add mbChr(3 + 1);
				case(di == 2):stack = stack add mbChr(ax - 1 + 1) add mbChr(ay + 1) add mbChr(mv + 1) add mbChr(4 + 1);
			}
		}
	}
}</pre>
</div>]]>
    </content>
</entry>
<entry>
    <title>FLASH Lite 1.1：chr とか ord とか</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/08/flash_lite_11chr_ord.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=657" title="FLASH Lite 1.1：chr とか ord とか" />
    <id>tag:faces.jp,2009://1.657</id>
    
    <published>2009-08-11T11:57:33Z</published>
    <updated>2009-08-11T13:47:29Z</updated>
    
    <summary></summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{margin:0;padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"><pre>
trace("A : " add ord(chr(200)));

str = chr(200);
trace("B : " add ord(str));

i = 200;
str = chr(i);
trace("C : " add ord(str));

i = 0;
str = chr(200+i);
trace("D : " add ord(str));

str = chr(200+0);
trace("E : " add ord(str));
</pre>
<p>
↓結果<br />
A : 200<br />
B : 69<br />
C : 200<br />
D : 200<br />
E : 69<br />
<br />
な、なんだって？？？
</p>
<p>・・・</p>
<pre>
trace("A : " add mbord(mbchr(200)));

str = mbchr(200);
trace("B : " add mbord(str));</pre>
<p>↓結果<br />
A : 200<br />
B : 200<br />回避は可能みたい。</p>
</div>]]>
    </content>
</entry>
<entry>
    <title>FLASH Lite1.1：擬似配列とメモリコスト</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/08/flash_lite11.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=656" title="FLASH Lite1.1：擬似配列とメモリコスト" />
    <id>tag:faces.jp,2009://1.656</id>
    
    <published>2009-08-10T15:32:27Z</published>
    <updated>2009-08-11T12:17:50Z</updated>
    
    <summary>400個のMCを並べるものを書いていたんですが、 MCの中に変数一個追加しただけ...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        400個のMCを並べるものを書いていたんですが、
MCの中に変数一個追加しただけで100KB近く増えるので調査した。


        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{width:250px;margin:0;padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao">
<table>
<tr><td><pre>
for(i=0;i&lt;<b>100</b>;i++){
	eval("myArray" add i) = 100;
}
</pre></td><td>
190KB
</td></tr>
<tr><td><pre>
for(i=0;i&lt;<b>1000</b>;i++){
	eval("myArray" add i) = 100;
}
</pre></td><td>
421KB
</td></tr>
<tr><td><pre>
for(i=0;i&lt;<b>10000</b>;i++){
	eval("myArray" add i) = 100;
}
</pre></td><td>
2811KB
</td></tr>
<tr><td><pre>
for(i=0;i&lt;<b>100000</b>;i++){
	eval("myArray" add i) = 100;
}
</pre></td><td>
メモリエラー
</td></tr>

</table>
<p>↓<br />
trace((2811-421)/(10000-1000))<br />
//0.265555555555556<br />
trace((2811-190)/(10000-100))<br />
//0.264747474747475<br />
trace((421-190)/(1000-100))<br />
//0.256666666666667<br />
1変数あたりのコストは、257Byte ～ 266Byte<br />
intのつもりでもデータ部分に 256Byte 変数名テーブル内に数Byteの割り当てな感じ。<br />
先に書いた400個のMCだと、256Byte*400 = 100KB で推定できる。
</p>
<p>ちなみに</p>

<table>
<tr><td><pre>
for(i=0;i&lt;10000;i++){
	eval("<b>m</b>" add i) = 100;
}
</pre></td><td>
2059KB
</td></tr>
<tr><td><pre>
for(i=0;i&lt;10000;i++){
	eval("<b>myA</b>" add i) = 100;
}
</pre></td><td>
2651KB
</td></tr>
<tr><td><pre>
for(i=0;i&lt;10000;i++){
	eval("<b>myAr</b>" add i) = 100;
}
</pre></td><td>
2811KB
</td></tr>
<tr><td><pre>
for(i=0;i&lt;10000;i++){
	eval("<b>myArray</b>" add i) = 100;
}
</pre></td><td>
2811KB
</td></tr>
<tr><td><pre>
for(i=0;i&lt;10000;i++){
	eval("<b>myArrayArray</b>" add i) = 100;
}
</pre></td><td>
3068KB
</td></tr>
</table>
<p>きれいに比例じゃないっぽいけど、変数名はメモリ上で管理されているので<br />
eval使って配列するときなんかは変数名は長すぎないほうがいい</p>

<table>
<tr><td><pre>
for(i=0;i&lt;<b>10000</b>;i++){
	eval("myArray" add i) = 100;
}
</pre></td><td>
2811KB
</td></tr>
<tr><td><pre>
//Stringもいっしょ
for(i=0;i&lt;<b>10000</b>;i++){
	eval("myArray" add i) = <b>"100"</b>;
}
</pre></td><td>
2811KB
</td></tr>
<tr><td><pre>
//キャストできるわけではない
for(i=0;i&lt;<b>10000</b>;i++){
	eval("myArray" add i) = <b>int(100)</b>;
}
</pre></td><td>
2811KB
</td></tr>
</table>
<p>とりあえず確認。型をあいまいに解釈してるのでメモリは変わらない。</p>

<p>で、常識的に考えるとそんなにでっかいデータを入れることもないので、<br />
↓とかの方のがいいと思われる。</p>
<table>
<tr><td><pre>
myArray = ""
for(i=0;i&lt;<b>100</b>;i++){
	myArray = myArray add chr(100);
}
trace(ord(substring(myArray,100,1)));
</pre></td><td>
170KB
</td></tr>
<tr><td><pre>
myArray = ""
for(i=0;i&lt;<b>1000</b>;i++){
	myArray = myArray add chr(100);
}
trace(ord(substring(myArray,1000,1)));
</pre></td><td>
171KB
</td></tr>
<tr><td><pre>
myArray = ""
for(i=0;i&lt;<b>10000</b>;i++){
	myArray = myArray add chr(100);
}
trace(ord(substring(myArray,10000,1)));
</pre></td><td>
180KB
</td></tr>
<tr><td><pre>
myArray = ""
for(i=0;i&lt;<b>50000</b>;i++){
	myArray = myArray add chr(100);
}
trace(ord(substring(myArray,50000,1)));
</pre></td><td>
219KB
</td></tr>
<tr><td><pre>
myArray = ""
for(i=0;i&lt;<b>100000</b>;i++){
	myArray = myArray add chr(100);
}
trace(ord(substring(myArray,100000,1)));
</pre></td><td>
メモリエラー
</td></tr>
</table>
<p>
きれいに1バイトづつ増えてますね。<br />
これで湯水のようにメモリが使えるようになります。<br />
ただ、<a href="http://faces.jp/2009/08/flash_lite_11chr_ord.html">chr → ord で戻すと上位1ビットがうまく扱えないらしく、<br />
1～128までの整数しか入らない。</a>工夫すればなんとかなりそうだけど。<br />
※2文字づつ格納で16384、3文字づつ格納で2097152まで。
</p>
<table>
<tr><td><pre>
myArray = ""
for(i=0;i&lt;10000;i++){
	myArray = myArray add chr(100);
}
trace(ord(substring(myArray,10000,1)));
</pre></td><td>
180KB
</td></tr>
<tr><td><pre>
myArray = ""
for(i=0;i&lt;10000;i++){
	myArray = myArray add chr(100);
}
trace(ord(substring(myArray,10000,1)));
<b>myArray = ""</b>
</pre></td><td>
169KB
</td></tr></table>
<p>メモリ開放もすぐできるしね</p>









</div>]]>
    </content>
</entry>
<entry>
    <title>Objective-C as Flash : Sprite</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/05/objectivec_as_flash_movieclip.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=655" title="Objective-C as Flash : Sprite" />
    <id>tag:faces.jp,2009://1.655</id>
    
    <published>2009-05-25T13:50:30Z</published>
    <updated>2009-08-11T06:11:32Z</updated>
    
    <summary>CALayer だとボタンやテキストフィールドが乗らないので UIView で ...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        CALayer だとボタンやテキストフィールドが乗らないので UIView で Sprite を作りました。
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"><p>速度的には<a href="http://faces.jp/2009/05/objectivec_calayer_movieclip.html">CALayerだけの方</a>が速い気がしますが（ OpenGL の方が速いらしいです。）<br />
UIパーツを使うならこっちの方が便利です。<br />
※8/11追記：<font color="#87C300">NSObjectを継承させていますがUIResponderが入らないのでTouchイベントが来ないことになります。<br />
ドラッグとかピンチを書きたい場合はUIResponderに挿げ替えるか、UIViewの子を継承させてパラメータをやりくりさせるようなものを作る方がいいかも。</font><br />
<br />
import するとこんな風に書けます</p>
<pre>

//ボタン作成君
Sprite* buttonMc(NSString *img, NSString *touch_img){
	UIButton	*b	= [UIButton buttonWithType:UIButtonTypeCustom];
	UIImage		*up	= [UIImage imageNamed:img];
	UIImage		*down	= [UIImage imageNamed:touch_img];
	[b setBackgroundImage:up	forState:UIControlStateNormal];
	[b setBackgroundImage:down	forState:UIControlStateHighlighted];
	b.layer.frame = CGRectMake(0,0,up.size.width,up.size.height);
	return [[Sprite alloc] by:b];
}

//アプリケーション起動後
- (void)applicationDidFinishLaunching:(UIApplication *)application {    
	Sprite *stage	= [[Sprite alloc] by:window];
	Sprite *bg	= [[Sprite alloc] by:@"bg.png"];
	[stage addChild:bg];
	
	Sprite *spr	= [[Sprite alloc] initWithFrame:stage.frame];
	Sprite *button	= buttonMc(@"button.png",@"button_press.png");
	[spr addChild:button];
	
	spr.x = 50;
	spr.y = 50;
	spr.alpha = 0.5f;
	spr.scale = 0.5f;
	spr.rotation = 90.0f;
	
	[stage addChild:spr];
	[window makeKeyAndVisible];
}</pre>
<p>※ よく使うプロパティも何個か追加しました。<br />
<br />Sprite.h</p>
<pre>//
//  Sprite.h
//  Sprite
//
//  Created by ao on 09/05/25.
//  Copyright 2009 bascule. All rights reserved.
//

#import &lt;Foundation/Foundation.h&gt;
#import &lt;UIKit/UIKit.h&gt;
#import &lt;QuartzCore/QuartzCore.h&gt;

@interface Sprite : NSObject {
	float		width;
	float		height;
	float		x;
	float		y;
	
	float		alpha;
	Sprite		*parent;
	float		rotation;
	float		scale;
	BOOL		visible;
	BOOL		enabled;
	
	
	CGAffineTransform transform;
	
	UIView		*view;
	CALayer		*layer;
	//NSString	*text;
	CGRect		frame;
	CGPoint		position;
	CGPoint		offset;
}

- by:(id)anObject;
- init;
- initWithFrame:(CGRect)aFrame;
- initWithView:(UIView*)aView;
- initWithImage:(UIImage*)anImage;
- initWithImageNamed:(NSString*)anImageName;

- (void)setFrame:(CGRect)aFrame;
- (CGRect)frame;

- (void)setWidth:(float)aWidth;
- (float)width;

- (void)setHeight:(float)aHeight;
- (float)height;

- (void)setPosition:(CGPoint)aPoint;
- (CGPoint)position;

- (void)setX:(float)aX;
- (float)x;

- (void)setY:(float)aY;
- (float)y;

@property float alpha;
@property (nonatomic, retain) Sprite *parent;

@property CGAffineTransform transform;
- (void)setTransform:(CGAffineTransform)aTransform;
- (CGAffineTransform)transform;
CGAffineTransform matrix(float aScale,float aRotation);

- (void)setRotation:(float)aRotation;
- (float)rotation;
- (void)setScale:(float)aScale;
- (float)scale;
- (void)setVisible:(BOOL)aVisible;
- (BOOL)visible;
- (BOOL)enabled;
- (void)setEnabled:(BOOL)anEnabled;

@property (nonatomic, retain) UIView *view;
- (CALayer*)layer;

- (void)addChild:(Sprite*)mc;

@end
</pre>
<p><br />Sprite.m</p>
<pre>//
//  Sprite.m
//  Sprite
//
//  Created by ao on 09/05/25.
//  Copyright 2009 bascule. All rights reserved.
//

#import "Sprite.h"

@implementation Sprite
@synthesize view;
@synthesize parent;

- initWithView:(UIView*)aView{
	[super init];
	view		= aView;
	self.frame	= view.layer.frame;
	alpha		= 1;
	rotation	= 0;
	scale		= 1;
	visible		= true;
	return self;
}

- initWithFrame:(CGRect)aFrame{
	[self initWithView:[[[UIView alloc] initWithFrame:aFrame] autorelease]];
	return self;
}

- init{
	[self initWithFrame: CGRectMake(0,0,0,0)];
	return self;
}

- initWithImage:(UIImage*)anImage{
	[self initWithFrame: CGRectMake(0,0,anImage.size.width,anImage.size.height)];
	view.layer.contents	= (id)anImage.CGImage;
	return self;
}

- initWithImageNamed:(NSString*)anImageName{
	id image = [[UIImage imageNamed:anImageName] autorelease];
	return [self initWithImage:image];
}

- by:(id)anObject{
	if([anObject isKindOfClass:[UIView class]]){
		[self initWithView:anObject];
	}else if([anObject isKindOfClass:[UIImage class]]){
		[self initWithImage:anObject];
	}else if([anObject isKindOfClass:[NSString class]]){
		[self initWithImageNamed:anObject];
	//}else if([anObject isKindOfClass:[CGRect class]]){
		//[self initWithFrame:aObject];
	}else{
		[self init];
	}
	return self;
}

- (CALayer*)layer{return view.layer;}

- (void)setFrame:(CGRect)aFrame{
	self.layer.frame	= aFrame;
	width			= self.frame.size.width;
	height			= self.frame.size.height;
	offset			= CGPointMake(width/2,height/2);
	self.position		= self.frame.origin;
}
- (CGRect)frame{return self.layer.frame;}

- (void)setPosition:(CGPoint)aPoint{
	x = aPoint.x;
	y = aPoint.y;
	//view.center.x
	self.layer.position	= CGPointMake(x + offset.x , y + offset.y );
}
- (CGPoint)position{
	x = self.layer.position.x - offset.x;
	y = self.layer.position.y - offset.y;
	return CGPointMake(x,y);
}

- (void)setWidth:(float)aWidth{	self.frame = CGRectMake(x,y,aWidth,height);}
- (void)setHeight:(float)aHeight{	self.frame = CGRectMake(x,y,width,aHeight);}
- (void)setX:(float)aX{		self.position = CGPointMake(aX,y);}
- (void)setY:(float)aY{		self.position = CGPointMake(x,aY);}
- (float)width{			return self.frame.size.width;}
- (float)height{			return self.frame.size.height;}
- (float)x{				return self.position.x;}
- (float)y{				return self.position.y;}

- (void)setAlpha:(float)anAlpha{view.alpha = anAlpha;}
- (float)alpha{return view.alpha;}

- (void)setTransform:(CGAffineTransform)aTransform{
	view.transform = aTransform;
}
- (CGAffineTransform)transform{ return view.transform;}

CGAffineTransform matrix(float aScale,float aRotation){
	return CGAffineTransformConcat(CGAffineTransformMakeScale(aScale,aScale),CGAffineTransformMakeRotation(M_PI*aRotation/180.0f));
}

- (void)setRotation:(float)aRotation{
	rotation = aRotation;
	self.transform = matrix(scale,rotation);
}
- (float)rotation{return rotation;}

- (void)setScale:(float)aScale{
	scale = aScale;
	self.transform = matrix(scale,rotation);
}
- (float)scale{return scale;}

- (void)setVisible:(BOOL)aVisible{	view.hidden = (aVisible == false);}
- (BOOL)visible{return view.hidden == false;}

- (void)setEnabled:(BOOL)anEnabled{
	if([view isKindOfClass:[UIControl class]]){
		[(UIControl*)view setEnabled:anEnabled];
	}
}
- (BOOL)enabled{
	if([view isKindOfClass:[UIControl class]]){
		enabled = [(UIControl*)view isEnabled];
	}else{
		enabled = false;
	}
	return enabled;
}

- (void)addChild:(Sprite*)aSprite{
	aSprite.parent = self;
	[view addSubview:aSprite.view];
}

@end
</pre></div>]]>
    </content>
</entry>
<entry>
    <title>Objective-C as Flash : URLLoader</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/05/objectivec_urlloader.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=654" title="Objective-C as Flash : URLLoader" />
    <id>tag:faces.jp,2009://1.654</id>
    
    <published>2009-05-16T17:01:28Z</published>
    <updated>2009-05-25T06:18:24Z</updated>
    
    <summary>FLASH の URLLoader が使いたかったので暫定実装。 ...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        FLASH の URLLoader が使いたかったので暫定実装。

        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"><p>

URLLoader.delegate ・・・Dispatch先のクラス<br />
URLLoader.open ・・・開始時メソッドを指定（SEL）<br />
<font color="blue">URLLoader.ioError ・・・エラーメソッドを指定（SEL）※5/25追記</font><br />
URLLoader.progress ・・・now loading メソッドを指定（SEL）<br />
URLLoader.complete ・・・完了時メソッドを指定（SEL）<br />
<br />
[URLLoader load:string_url] ・・・ロード<br />
<font color="blue">[URLLoader close] ・・・ロードをキャンセル※5/25追記</font><br />
<br />
complete後に以下のプロパティが読めます。<br />
URLLoader.data ・・・生データ（NSData）<br />
URLLoader.text ・・・ふつうにテキストを読んでくる（UTF-8）<br />
URLLoader.variables ・・・loadVariablesみたいにパース（NSDictionary）<br />
※↑携帯コンテンツのアプリ移植に便利なようにSJISで読む仕様<br />
URLLoader.image ・・・画像で渡す（UIImage：ASでいうbitmapData）<br />
URLLoader.tsv ・・・独自仕様の Tab Separated Values（NSDictionary：連想配列）<br />
<br />
import するとこんな風に書けます。<br/>
iPhone ではネットが切れることが日常なのでエラー処理があると便利です。</p>
<pre>
- (void)onComplete:(URLLoader*)aLoader{
	NSLog(@"%@",aLoader.text);
}
<font color="blue">- (void)onError:(URLLoader*)aLoader{
	NSLog(@"%@",[aLoader.error localizedDescription]);//5/25追記
}</font>
- (void)applicationDidFinishLaunching:(UIApplication *)application {    
	URLLoader *l	= [[URLLoader alloc] initWithDelegate:self];
	l.complete	= @selector(onComplete:);
	<font color="blue">l.ioError	= @selector(onError:);//5/25追記</font>
	[l load:@"http://faces.jp/"];
	[window makeKeyAndVisible];
}
</pre>
<p><br />URLLoader.h</p>
<pre>//
//  URLLoader.h
//  fooLoader
//
//  Created by ao on 09/05/25.
//  Copyright 2009 Bascule. All rights reserved.
//

#import &lt;Foundation/Foundation.h&gt;

@interface URLLoader : NSObject {
	int		bytesLoaded;
	int		bytesTotal;
	NSMutableData	*data;
	NSString	*dataFormat;
	
	SEL		complete;
	//SEL		httpStatus;
	SEL		ioError;
	SEL		open;
	SEL		progress;
	//SEL		securityError;
	
	NSError		*error;
	NSString	*text;
	NSDictionary	*variables;
	NSDictionary	*tsv;
	UIImage		*image;
	
	NSURLConnection	*urlConection;
	id		delegate;
}

@property (assign) id	delegate;

@property int					bytesLoaded;
@property int					bytesTotal;
@property (nonatomic, retain) NSMutableData	*data;
@property (nonatomic, retain) NSString		*dataFormat;

- initWithDelegate:(id)aDelegate;
- (void)close;
- (void)load:(NSString *)aUrl;

@property SEL					complete;
@property SEL					ioError;
@property SEL					open;
@property SEL					progress;

@property (nonatomic, retain) NSError		*error;

- (NSString*)text;
- (NSDictionary*)variables;
- (NSDictionary*)tsv;
- (UIImage*)image;

@end</pre>
<p><br />URLLoader.m</p>
<pre>//
//  URLLoader.m
//  fooLoader
//
//  Created by ao on 09/05/25.
//  Copyright 2009 Bascule. All rights reserved.
//

#import "URLLoader.h"

@implementation URLLoader

//パブリックプロパティ
@synthesize bytesLoaded;
@synthesize bytesTotal;
@synthesize data;
@synthesize dataFormat;

//イベントメソッド
@synthesize complete;
@synthesize open;
@synthesize progress;
@synthesize ioError;

@synthesize delegate;
@synthesize error;

NSArray* explode(NSString *$delimiter, NSString *$string){
	return [$string componentsSeparatedByString:$delimiter];
}

int count(NSArray *$array){
	return [$array count];
}

NSMutableDictionary* parse_str(NSString *$str){
	id $item	= [[NSMutableDictionary alloc] init];
	id $queries	= explode(@"&",$str);
	for(id $q in $queries){
		id $array = explode(@"=",$q);
		if(count($array)==1){
			$array = [NSArray arrayWithObjects:[$array objectAtIndex:0], @"", nil];
		}
		if(count($array)&gt;=2){
			[$item setValue:[$array objectAtIndex:1] forKey:[$array objectAtIndex:0] ];
		}
	}
	return $item;
}

- initWithDelegate:(id)aDelegate{
	[self init];
	self.delegate = aDelegate;
	return self;
}

- (NSString*)text{
	text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
	return text;
}

- (NSDictionary*)variables{
	id s = [[NSString alloc] initWithData:data encoding:NSShiftJISStringEncoding];
	variables = parse_str(s);
	return variables;
}

- (UIImage*)image{
	return [UIImage imageWithData:data];
}

- (NSDictionary*)tsv{
	id rows		= explode(@"\n",self.text);
	id keys		= explode(@"\t",[rows objectAtIndex:0]);
	id items	= [[NSMutableDictionary alloc] init];
	for(int i=1;i&lt;count(rows);i++){
		id cells	= explode(@"\t",[rows objectAtIndex:i]);
		id item		= [[NSMutableDictionary alloc] init];
		[item setValue:[[NSNumber alloc] initWithInteger:i] forKey:@"id"];
		for(int j=0;j&lt;count(cells);j++){
			if(![[cells objectAtIndex:j] isEqualToString:@""]){
				[item setObject:[cells objectAtIndex:j] forKey:[keys objectAtIndex:j]];
			}
		}
		[items setValue:item forKey:[[NSNumber alloc] initWithInteger:i]];
	}
	return items;
}

- (void)dispatch:(SEL)aSelector{
	if( [delegate respondsToSelector:aSelector] ) {
		[delegate performSelector:aSelector withObject:self];
	}
}

- (void)load:(NSString *)aUrl{
	NSURLRequest*	request	= [NSURLRequest requestWithURL:[NSURL URLWithString:aUrl]];
	urlConection			= [[NSURLConnection alloc] initWithRequest:request delegate:self];
	bytesLoaded	= 0;
}

- (void)close{
	[urlConection cancel];//未テスト。動かなかったらごめん
}

- (void)connection:(NSURLConnection *)aConnection didFailWithError:(NSError *)anError{
	error = anError;
	[self dispatch:ioError];
	//ダイアログは不要ならカットして
	UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Error" message:[[anError localizedDescription] capitalizedString] delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK",nil] autorelease];
	[alert show];
}

//- (void)connection:(NSURLConnection *)aConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)aChallenge{}

- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)aData{
	[data appendData:aData];
	bytesLoaded	= data.length;
	[self dispatch:progress];
}

- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)aResponse{
	bytesTotal	= [aResponse expectedContentLength];
	dataFormat	= [aResponse MIMEType];
	data		= [[NSMutableData alloc] init];
	[self dispatch:open];
}

//- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{}
//- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse{}

- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection{
	[self dispatch:complete];
}

@end</pre></div>]]>
    </content>
</entry>
<entry>
    <title>ビットマップを切り替え表示する際の負荷の検討</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/05/bitmapaddchildbitmapbitmapdata.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=653" title="ビットマップを切り替え表示する際の負荷の検討" />
    <id>tag:faces.jp,2009://1.653</id>
    
    <published>2009-05-07T04:02:08Z</published>
    <updated>2009-05-07T04:24:36Z</updated>
    
    <summary>既にどこかで検証されてる気がものすごくしますが、 ビットマップをどんどん切り替え...</summary>
    <author>
        <name>kamp</name>
        <uri>/2006/08/kampprofile.html</uri>
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        <![CDATA[既にどこかで検証されてる気がものすごくしますが、<br />
ビットマップをどんどん切り替えるような処理をするときに、どうするのが一番負荷が低いか、<br />
3つの方法を比べてみました。<br />
]]>
        <![CDATA[<em><style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"></em><p>
<ul>
<li>BitmapをaddChild、そしてremoveChild</li>
<li>Bitmap.bitmapDataを入れ替える</li>
<li>Graphics.beginBitmapFilldで塗る</li>
</ul>
結果、Bitmap.bitmapDataを入れ替える、が圧倒的に早そうです。</p>
<pre>
package {
	import flash.display.Bitmap;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.utils.getTimer;

	public class BitmapLoadTest extends Sprite
	{
		
		[Embed(source='../image.jpg')] private static const SampleImage:Class;
		private var img:Bitmap = new SampleImage();

		public function pen_BitmapLoadTest()
		{
			test_addChild(); // 24 
			test_swapBmpd(); // 6
			test_fillBmpd(); // 20
		}
		
		private var testTimes:int = 10000;
		
		private function test_addChild():void
		{
			var sTime:int = getTimer();
			
			for(var i:int=0; i&lt;testTimes; i++)
			{
				addChildAt(img, 0);
				removeChild(img);
			}
			
			trace(getTimer() - sTime);
		}
		
		private function test_swapBmpd():void
		{
			var bmpCon:Bitmap = new Bitmap();
			addChild(bmpCon);
			
			var sTime:int = getTimer();
			
			for(var i:int=0; i&lt;testTimes; i++)
			{
				bmpCon.bitmapData = img.bitmapData
			}
			
			trace(getTimer() - sTime);
			
			removeChild(bmpCon);
		}
		
		private function test_fillBmpd():void
		{
			var g:Graphics = graphics;
			var w:int = img.width;
			var h:int = img.height;
			
			var sTime:int = getTimer();
			
			for(var i:int=0; i&lt;testTimes; i++)
			{
				g.clear();
				g.beginBitmapFill(img.bitmapData);
				g.drawRect(0, 0, w, h);
				g.endFill();
			}
			
			trace(getTimer() - sTime);
		}
	}
}

</pre></div>]]>
    </content>
</entry>
<entry>
    <title>Objective-C : CALayer を MovieClip に</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/05/objectivec_calayer_movieclip.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=652" title="Objective-C : CALayer を MovieClip に" />
    <id>tag:faces.jp,2009://1.652</id>
    
    <published>2009-05-01T08:33:19Z</published>
    <updated>2009-11-18T08:53:55Z</updated>
    
    <summary>慣れない CALayer を MovieClip っぽく使えるように適当にラッピ...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        慣れない CALayer を MovieClip っぽく使えるように適当にラッピングしてみた。
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"><p>
import するとこんな風に書けて、だいぶ気が楽になります。</p>
<pre>
- (void)viewDidLoad {
	MovieClip *stage	= [[MovieClip alloc] initWithView:self.view];
	MovieClip *mc		= [[MovieClip alloc] init];
	MovieClip *img		= [[MovieClip alloc] initWithImage:@"test.png"];
	
	[mc addChild: img];
	[stage addChild: mc];

	mc.x = (320 - img.width)/2;
	mc.y = (460 - img.height)/2;
	mc.alpha = 0.5f;
	mc.visible = true;
}
</pre>
<p>CALayer 自体は mc.layer で参照して、<br />
mc.layer.position = CGPointMake(0,0);<br />
とか直接触れます。</p>


<p><br />MovieClip.h</p>
<pre>
//
//  MovieClip.h
//
//  Created by bascule on 09/04/30.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import &lt;Foundation/NSObject.h&gt;
#import &lt;UIKit/UIKit.h&gt;
#import &lt;QuartzCore/QuartzCore.h&gt;

@interface MovieClip : NSObject {
	float		x;
	float		y;
	float		width;
	float		height;
	float		alpha;
	
	float		offset_x;
	float		offset_y;
	
	BOOL		visible;
	
	UIView		*view;
	CALayer		*layer;
	NSString	*text;
	CGPoint		*position;
}

- (MovieClip*)initWithView:(UIView*)view;

- (void)setX:(float)_x;
- (float)x;

- (void)setY:(float)_y;
- (float)y;

- (void)setPosition:(CGPoint)_point;
- (CGPoint)position;

- (void)setWidth:(float)_width;
- (float)width;

- (void)setHeight:(float)_height;
- (float)height;

- (void)setAlpha:(float)_alpha;
- (float)alpha;

- (void)setVisible:(BOOL)_visible;
- (BOOL)visible;

- (void)setLayer:(CALayer*)_layer;
- (CALayer*)layer;

- (void)setView:(UIView*)_view;
- (UIView*)view;

- (void)addChild:(MovieClip*)mc;

@end
</pre>
<p><br />MovieClip.m</p>
<pre>
//
//  MovieClip.m
//
//  Created by bascule on 09/04/30.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "MovieClip.h"

@interface MovieClip (MovieClipPrivate)
- (void)set_pos;
- (void)set_rect;
@end

@implementation MovieClip

- (void)setPosition:(CGPoint)_point{
	x = _point.x;
	y = _point.y;
	layer.position	= CGPointMake(x + offset_x , y + offset_y );
}
- (CGPoint)position{
	//ここ間違えてる
	return layer.position;
}


- (MovieClip*)init
{
	layer		= [CALayer layer];
	width		= 0;
	height		= 0;
	x			= 0;
	y			= 0;
	offset_x	= 0;
	offset_y	= 0;
	visible		= true;
	alpha		= 1;
	
	[self set_pos];
	return self;
}


- (MovieClip*)initWithView:(UIView*)_view
{
	//UIImage	*img			= [UIImage imageNamed:img_str];
	view	= _view;
	layer	= view.layer;
	width	= layer.frame.size.width;
	height	= layer.frame.size.height;
	x		= self.x;
	y		= self.y;
	visible	= true;
	alpha	= 1;
	
	[self set_pos];
	[self set_rect];
	
	return self;
}

- (MovieClip*)initWithImage:(NSString*)img_str
{
	UIImage	*img	= [UIImage imageNamed:img_str];
	
	layer	= [CALayer layer];
	width	= img.size.width;
	height	= img.size.height;
	x		= 0;
	y		= 0;
	visible	= true;
	alpha	= 1;
	
	[self set_pos];
	[self set_rect];
	
	layer.contents	= (id)img.CGImage;
	//view			= img;
	
	return self;
}

- (void)set_rect{
	layer.frame		= CGRectMake(x,y,width,height);
	offset_x		= width/2;
	offset_y		= height/2;
}

- (void)set_pos{
	[CATransaction begin];
	[CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration];
	layer.position	= CGPointMake(x + offset_x , y + offset_y );
	[CATransaction commit];
}
- (void)set_alpha{
	[CATransaction begin];
	[CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration];
	
	if(visible){
		layer.opacity = alpha;
	}else{
		layer.opacity = 0;
	}
	
	[CATransaction commit];
}

- (void)setView:(UIView*)_view{
	view=_view;
	[self initWithView:view];
}

- (UIView*)view{
	return view;
}

- (void)setLayer:(CALayer*)_layer{
	layer=_layer;
}

- (CALayer*)layer{
	return layer;
}

- (void)setX:(float)_x{
	x = _x;
	[self set_pos];
}

- (float)x{
	x = layer.position.x - offset_x;
	return x;
}
- (void)setY:(float)_y{
	y = _y;
	[self set_pos];
}

- (float)y{
	y = layer.position.y - offset_y;
	return y;
}

- (void)setWidth:(float)_width{
	width = _width;
	[self set_rect];
}

- (float)width{
	return layer.frame.size.width;
}

- (void)setHeight:(float)_height{
	height = _height;
	[self set_rect];
}

- (float)height{
	return layer.frame.size.height;
}

- (void)setAlpha:(float)_alpha{
	alpha = _alpha;
	[self set_alpha];
}

- (float)alpha{
	float f;
	if(visible){
		f = layer.opacity;
	}else{
		f = alpha;
	}
	return f;
}

- (void)setVisible:(BOOL)_visible{
	visible = _visible;
	[self set_alpha];
}
- (BOOL)visible{
	return visible;
}

- (void)addChild:(MovieClip*)mc{
	[layer addSublayer:mc.layer];
}

@end

</pre></div>]]>
    </content>
</entry>
<entry>
    <title>swfmill の Windows ローカルテスト環境を</title>
    <link rel="alternate" type="text/html" href="http://faces.jp/2009/03/swfmill_windows.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://faces2.bascule.co.jp/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=651" title="swfmill の Windows ローカルテスト環境を" />
    <id>tag:faces.jp,2009://1.651</id>
    
    <published>2009-03-21T11:07:33Z</published>
    <updated>2009-03-21T11:23:02Z</updated>
    
    <summary>最近 MacBookPro を買ってやっぱり Windows として使ってます。...</summary>
    <author>
        <name>ao</name>
        
    </author>
            <category term="article" />
    
    <content type="html" xml:lang="ja" xml:base="http://faces.jp/">
        <![CDATA[最近 MacBookPro を買ってやっぱり Windows として使ってます。しかし、EMOBILE (細くない方のPCカードタイプ)がささらず外出時はサーバー確認できないのが困ります。ここはローカル環境を整備するしかないと思い、<a href="http://www.apachefriends.org/jp/xampp-windows.html">XAMPP</a> と <a href="http://swfmill.org/">windows 用の swfmill</a> を入れてみたのですが、うまく swf をはいてくれない・・・]]>
        <![CDATA[<style type=text/css>
<!--
div.ao p{line-height:24px;margin-bottom:18px;}
div.ao pre{padding:9px;font-size:12px;background:#FFFFDD;border:1px solid #87C300;}
-->
</style><div class="ao"><p>

swf をバイナリエディタで開いたところでやっとわかりました。入力されたSWFの"0A"が"0D0A"として出力されてます。パイプ処理をかましたからだと思いますが、Windowsの改行を変換すれば解決。

・・・ こんなんしなくてもMacなら普通に環境を作れると思いますが。
</p>
<pre>
&lt;?

header('Content-type: application/x-shockwave-flash');
echo xml2swf(swf2xml('test.swf'));

function xml2swf($xml){
	$is_xampp = in_array('xampp',explode('/',$_SERVER["DOCUMENT_ROOT"]))&gt;0;
	
	$descriptorspec = array(
		0 =&gt; array("pipe", "r"),
		1 =&gt; array("pipe", "w"),
		2 =&gt; array("file", "error.log", "a"),
	);
	if($is_xampp){
		$cmd = '/xampp/htdocs/www/bin/swfmill xml2swf stdin stdout';
	}else{
		$cmd = '/usr/local/bin/swfmill xml2swf stdin stdout';
	}
	$process = proc_open($cmd, $descriptorspec, $pipes);
	if (is_resource($process)) {
		fwrite($pipes[0], $xml);
		fclose($pipes[0]);
		$swf = stream_get_contents($pipes[1]);
		fclose($pipes[1]);
		proc_close($process);
		<b>if($is_xampp) $swf = str_replace("\r\n","\n",$swf);</b>
	}else{
		$swf = null;
	}
	return($swf);
}

function swf2xml($swf){
	$is_xampp = in_array('xampp',explode('/',$_SERVER["DOCUMENT_ROOT"]))&gt;0;
	
	if($is_xampp){
		$process = popen('/xampp/htdocs/www/bin/swfmill swf2xml '.$swf,'r');
		if (is_resource($process)) {
			$xml = stream_get_contents($process);
			pclose($process);
		}else{
			$xml = null;
		}
	}else{
		$descriptorspec = array(
			0 =&gt; array("pipe", "r"),
			1 =&gt; array("pipe", "w"),
			2 =&gt; array("file", "error.log", "a"),
		);
		$process = proc_open('/usr/local/bin/swfmill swf2xml stdin stdout', $descriptorspec, $pipes);
		if (is_resource($process)) {
			fwrite($pipes[0], file_get_contents($swf));
			fclose($pipes[0]);
			$xml = stream_get_contents($pipes[1]);
			fclose($pipes[1]);
			proc_close($process);
		}else{
			$xml = null;
		}
	}
	return($xml);
}

</pre>
</div>]]>
    </content>
</entry>

</feed> 

