// 自前ソートモジュールのコンストラクタ 
__MySort = function(){

	// 標準文字列比較関数 ※引数が文字列でない場合は文字列にキャストする。
	var strcmp = function( a , b ){
		var A = "" + a;
		var B = "" + b;

		for( var i = 0 ; A.charAt( i ) == B.charAt( i ) && i < A.length ; i++ );
		var valA = A.charAt( i ).charCodeAt(0);
		var valB = B.charAt( i ).charCodeAt(0);
		if( isNaN(valA) ) valA = 0;
		if( isNaN(valB) ) valB = 0;

		return valA - valB;
	};
	this.strcmp = strcmp;

	// 数値sort関数 昇順
	var myIsNaN = function( a ){
		return isNaN( a ) || a === null || a === undefined;
	};
	this.numAsc = function( a , b ){
		var ret = a - b;
		if( myIsNaN( a ) && myIsNaN( b ) ){
			ret = strcmp( a , b );
		}else if( myIsNaN( a ) ){
			ret = 1;
		}else if( myIsNaN( b ) ){
			ret = -1;
		};
		return ret;
	};
	// 数値sort関数 降順
	this.numDesc = function( a , b ){
		var ret = b - a;
		if( myIsNaN( a ) && myIsNaN( b ) ){
			ret = strcmp( b , a );
		}else if( myIsNaN( a ) ){
			ret = 1;
		}else if( myIsNaN( b ) ){
			ret = -1;
		};
		return ret;
	};
	// 独自ソート用関数を作成し返す。
	this.getStrSort = function( ary , isDesc ){

		// ソート順指定配列
		var aryO = ary.concat();
		// 降順を指定された場合は配列を逆順にする。
//		if( isDesc ){
//			aryO.reverse();
//		};

		//ソート配列内を自身でマッチするか確認
		var aryChaceTarg = [];
		for( var i = 0 ; i < aryO.length ; i ++ ){
			aryChaceTarg.push([]);
			for( var j = 0 ; j < aryO.length ; j ++ ){
				if( aryO[j].length > aryO[i].length ){
					if( aryO[j].substring( 0 , aryO[i].length ) == aryO[i] ){
						aryChaceTarg[i].push( j );
					};
				};
			};
		};

		var isMatch= function( strTarg , str ){
				return ( strTarg.length >= str.length && strTarg.substring(0 , str.length ) == str );
		};

		var getIdx = function( str ){
			var ret = -1;
			for( var i = 0 ; i < aryO.length ; i ++ ){
				if( isMatch( str , aryO[i] ) ){
					ret = i;
					break;
				};
			};

			for( var retChk = -1 ; retChk != ret ; ){
				retChk = ret + 0;
				for( var i = 0 ; i < aryChaceTarg[ ret ].length ; i ++ ){

					if( isMatch( str , aryO[ aryChaceTarg[ ret ][i] ] ) ){
						ret = aryChaceTarg[ ret ][i];
						break;
					};
				};
			};

			return ret;
		};

		var hasTarg = function( str ){
			for( var i = 0 ; i < aryO.length ; i ++ ){
				if( str.indexOf( aryO[i] ) != -1 ){
					return true;
				};
			};
			return false;
		};

		var srtFunc = function( a , b ){
			// とりあえず文字キャストし、安全を担保。
			var A = a + "";
			var B = b + "";

			//各文字を先頭から1文字ずつチェックする。先頭を除去してループを進める点に留意する。
			for( ; true ; ){
				//どこかの時点で、対象となる文字がもう含まれないと分かれば、その時点で通常のstrcmpに切り替える。
				if( ! hasTarg( A ) && ! hasTarg( B ) ){
					return strcmp( A , B );
				};

				//idx判定しないフラグ
				var blIdx = false;
				if( A.length == 0 ){
					if( B.length == 0 ){
						return 0;
					}else{
						blIdx = true;
					};
				}else{
					if( B.length == 0 ){
						blIdx = true;
					};
				};

				if( ! blIdx ){
					var idxA = getIdx( A );
					var idxB = getIdx( B );

					if( idxA != -1 ){
						if( idxA == idxB ){
							A = A.substring(aryO[idxA].length);
							B = B.substring(aryO[idxB].length);
							continue;
						}else if( idxB == -1 ){
							return -1;
						}else{
							return idxA - idxB
						};
						
					}else if( idxB != -1 ){
						return 1;
					};
					// idxA == idxB == -1であるならば、即ち、通常の文字である。
					//一致するなら次の文字へ
					if( A.charAt(0) == B.charAt(0) ){
						//文字長が0なら完全に一致
						A = A.substring(1);
						B = B.substring(1);
						continue;
					};
				};


				//先頭が該当文字に合致しない場合、標準処理、即ちstrcmpに準じて処理する。
				var valA = A.charAt( 0 ).charCodeAt(0);
				var valB = B.charAt( 0 ).charCodeAt(0);

				if( isNaN(valA) ) valA = 0;
				if( isNaN(valB) ) valB = 0;
				//降順指定時は符号を逆にする
				return ( valA - valB );
			};
		};


		return function( a , b ){
			if( isDesc ) return - srtFunc( a , b );
			return srtFunc( a , b );
		};

	};
};
var _MySort =new __MySort();


