Manusortは、二者択一形式の手動によるソートを補助するJavaScriptの決定版です。
説明が長くなるので、先に具体的にどのような場面でこの洗練されたロジックを搭載したManusortが使えるのか、以下に挙げてみました。
- 自分の好きなものの序列化
- タスクの優先度設定
- 順位付けが必要なスポーツやゲームのトーナメント
アイドルマスター ワンフォーオールとは、バンダイナムコエンターテインメント(旧バンダイナムコゲームス)が提供するアイドル育成シミュレーションゲームのことです。
このゲームでは最終的に13人のアイドルをプロデュースすることになりますが、どのアイドルにも甲乙つけがたい個性的な魅力があります。 しかし、彼女たちとコミュニケーションを重ねていく中で、プロデューサーである主人公は、特別に思い入れのあるアイドルを見出すことになるでしょう。 ところが、13人というたくさんのアイドルを比べてその思い入れの強さを自己分析することは容易ではありません。
一般的な計算機の処理において、13人を同時に比較するというのは良い方法とは言えません。 13人の中から2人だけを選んで、それを比較するという手法が最も単純でわかりやすく効率的でしょう。
ここでアイマスに登場する13人のヒロインの中から、4人のアイドルをピックアップします(紹介文はゲーム説明書から引用)。
キュート!?厳しい!?猫かぶりなセレブお嬢様
双海姉妹のカワイイ系!まぶしすぎる美女by亜美
心・体・笑顔!全てが癒し系のお姉さんアイドル
765プロに必要不可欠!事務員兼アイドル
少し残酷な話ですが、この4人に自分の好みの優劣をつけてソートしてみることにしましょう。
先に述べた通り、2人だけを選んでそれを比較するのが、古典的でありながらも単純処理しやすいということでした。
したがって、まずは水瀬伊織と双海亜美を比較してみます。性格やビジュアルなど総合的な判断をして、双海亜美の勝ちという苦渋の判定をしたとしましょう。
結果は次のようになります。
"双海亜美" > "水瀬伊織"
次に双海亜美と三浦あずさを比較します。ここでは包容力と天然属性が大きなポイントとなり、三浦あずさの勝ちという判定をしました。
先の判定と合わせて次のような結果になるので、もはや三浦あずさと水瀬伊織を比較する必要はないということがわかります。
"三浦あずさ" > "双海亜美" > "水瀬伊織"
次は三浦あずさと秋月律子を比較します。
メガネ属性や事務員属性は残念ながらポイントにならなかったので、ここでも三浦あずさの勝ちという判定をしました。
"三浦あずさ" > "秋月律子"
この後は双海亜美と秋月律子を比較します。
もしここで秋月律子の勝ちという判定をすれば、次の結果となりソートは終了します。
"三浦あずさ" > "秋月律子" > "双海亜美" > "水瀬伊織"
そうではなく、双海亜美の勝ちという判定をした場合は、水瀬伊織との比較を最後にすることになります。 比較回数が1回多くなりますが、個人の判断によってそれは変動するので、傾向分析をしない限りはこれ以上の効率化はできません。
ポイントとなるのは、このストーリーで三浦あずさと水瀬伊織を比較しなかったように、これは総当り式の比較ではないということです。 そしてこれを実際に行うManusortは、どんなに比較サンプルが増えても以上のようなアルゴリズムを正確にトレースします。
Manusortは、よく知られた(プログラミング用の)ソートアルゴリズムを一切採用しておりません。ベンチマークスコアや汎用性を犠牲にする代わりに、人間が扱うのに最も都合の良い設計となっています。特長として以下の点が挙げられます。
- マージソートやヒープソートと違い、データの配列を変更しない非破壊的ソートであるため、デバッグやジャンプが簡単
- 機械的に優劣の判定ができない場合などの恣意的判断を考慮したUI実装(「引き分け」、「退場」、「戻る」といった操作が可能)
- ソート後半になればなるほど比較対象の選ばれ方の規則性が乱れてくるため、マージソートやヒープソートに特有の単調さがなく、集中力や判断力の低下が抑止される
- 序列を上から順に決めていくのではなく点数方式で決めていくため、ソートの途中でおよその序列を予想することが可能
初めに、ソート対象の要素群を用意します。
要素群はid
とname
の最低2つのプロパティを持つオブジェクトを格納した配列です。
var elements = [
{
id: 101,
name: '天海春香',
},
{
id: 102,
name: '我那覇響',
},
{
id: 103,
name: '星井美希',
},
...
];
ソートを開始するときは、Manusort()
によってインスタンスを生成してください。
var ms = Manusort(elements);
Manusortの各種APIを利用するには、インスタンスのメソッドであるget(api_name)
を使います。
ms.get(api_name);
stage
は比較する2つの対象を表示します。
返り値はオブジェクトです。
以降、比較対象を対戦者、対戦者0を相手、対戦者1を自分とします。
ms.get('stage');
返り値の例:
{
opponent: {
id: 105,
name: "如月千早",
dropped: 0
},
self: {
id: 101,
name: "天海春香",
dropped: 0
},
change: false
}
- opponent
- 相手に関する情報です。
- self
- 自分に関する情報です。
- change
- これが`true`のとき、GUIとしては相手と自分を表示する位置を一時的に入れ替えた方がユーザー体験の質が向上することを示しています。直前のステージにおける対戦者の1人が続けてステージに配置される場合に、位置が変わらないようにした方が良いということです。
judge
は対戦者を勝利、敗北、引き分け、退場のいずれかに判定します。
このAPIは、次のステージがあればtrue
、なければfalse
を返します。
またこのAPIがtrue
を返したとき、自動的に次のステージへ移ります。
その場合、再びms.get('stage')
を実行することで新たな対戦者の組を取得することができます。
judge
に続けてwin
またはlose
を、さらに対戦者番号を引数として追加します。
番号の引数を指定しなかった場合は1
がデフォルトで与えられます。
ms.get('judge', 'win'); // 自分が勝利
ms.get('judge', 'win', 1); // 上と同じ
ms.get('judge', 'win', 0); // 相手が勝利
ms.get('judge', 'lose'); // 自分が敗北(相手が勝利)
ms.get('judge', 'lose', 1); // 上と同じ
ms.get('judge', 'lose', 0); // 相手が敗北(自分が勝利)
judge
に続けてdraw
を引数として追加します。
ms.get('judge', 'draw');
judge
に続けてdrop
を、さらに番号を引数として追加します。
番号の引数を指定しなかった場合は相手と自分の両者が退場となります。
ms.get('judge', 'drop'); // 両者退場
ms.get('judge', 'drop', 0); // 相手が退場
ms.get('judge', 'drop', 1); // 自分が退場
back
は1つ前のステージに戻ります。戻るステージがない場合はfalse
を返します。
ms.get('back');
round
は終了した試合数を返します。引数にfalse
を与えることで現在が何試合目かを返すように変更できます。
ms.get('round');
ms.get('round', false); // ms.get('round')+1と同じ
result
はトータルの結果を配列で返します。ステージがすべてが終了していなくても途中経過として出力することはできますが、その場合引き分けが同順位にならないことがあります(最終的には同順位になるように収束します)。
ms.get('result');
info
はログに記録されているあらゆる情報を表示します。これは主にデバッグ用途です。
ms.get('info');