エレベータと、エレベータに乗りたい人の行動をシミュレートするアプリケーションです。刻々と変わる状況をウェブブラウザ上で確認しながらカスタマイズの改良方法を検討します。
特に規模の大きなビルのエレベータを使っていると、複数基稼働しているのになかなかやってこないと感じることがあります。そんな時はエレベータの稼働アルゴリズムが下手なんじゃないか、と疑ってしまいます。
でも実際にはエレベータの稼働アルゴリズムはかなり難しかったりします。例えば誰かがどこかのフロアで上(または下)に行きたいとボタンを押して知らせた時に、どのエレベータを向かわせるべきなのか? その判断は刻々と変わる状況の中で変更するべきではないのか? エレベータの外や中にいる人が不公平感を感じてストレスがたまったりしないのか? これら全てを考慮したアルゴリズムはかなりややこしそうです。
加えて、そもそもビルは何階建てなのか、エレベータは何基動いているのか、エレベータの定員は、エレベータのスピードは、人の乗り降りのスピードは、・・・ など、アルゴリズムに関わる個別要因も多く存在しています。
何をどこまで考慮するかは自分次第です。「とりあえず全員を目的階まで運ぶ」ことを最低条件にアルゴリズムを考えて実装しましょう。
-
全てのエレベータは初期状態で1階にいる。
-
人は各フロアで2本の待ち行列を作ってエレベータの到着を待つ。
-
目的方向(上 or 下)ごとに1本の待ち行列を作る。
-
目的方向(上 or 下)のボタンを押して待つ。
-
待ち行列へは到達順に並び、途中で順序が入れ替わることはない。
-
「どのタイミングで、どのフロアに、どのフロアへ行こうとしている人がやってくるか」は velev.js ファイルの先頭に waiting_queue 変数で定義しています。必要であればここを編集してください。
-
-
人が待っているフロアに停止(上にも下にも向かっていない)中か、または目的と同じ方向に向かっていて人数に空きのあるエレベータが到達した場合、そのエレベータに乗ることができます。
-
エレベータへは待ち行列の先頭から順に乗る。
-
1回のエレベータで乗り切れなかった場合、乗り切れるぶんだけが乗って、待ち行列を詰めて次のエレベータを待ちます。
-
-
後述するカスタマイズを行うことができます。
-
カスタマイズを行う対象は settings.js と velev.js です。
-
settings.js はエレベータの基数やフロアの数といった環境の設定値です。
-
velev.js にはイベントハンドラが定義されていて、この中に JavaScript による処理が記述されることを想定しています。
-
velev.js に対するカスタマイズが正しくないと、いつまで待ってもエレベータが到着しない人が出てくるかもしれません。気をつけてください。
-
-
-
num: エレベータの基数
- 可動しているエレベータが何台あるか?
-
max_floor: ビルのフロア数
-
ビルの階数
-
なお、このビルには地下は存在していないものとする。
-
また全てのエレベータは全てのフロアに止まることができるものとする。
-
-
-
limit: エレベータ1基の定員
- 1台のエレベータに最大何人が乗車できるか?
-
move_second: エレベータが1フロア移動するのに必要な秒数
- エレベータが1階から2階、2階から3階と、1フロア移動するのに必要な秒数
-
stop_second: エレベータがフロアで乗降時に停止する秒数
-
エレベータが乗客の乗降のためにあるフロアに停止した時に、乗降のために必要な秒数
- なお、全てのエレベータでこの値は同じものとする。
-
大きく2つのカスタマイズをすることができます。1つ目はやってくる人の数や目的、タイミングのカスタマイズ、2つ目はエレベータの挙動(エレベータ待ちのボタンが押された時、どのエレベータを待っている人のフロアに向かわせるかの決定)のカスタマイズです。
前者のカスタマイズは velev.js の先頭部分にある waiting_queue 配列変数の内容で決定することができます。
後者のカスタマイズがこのシミュレータの肝となります。本シミュレータでは3種類のイベントを検知することができ、それらのイベントに合わせてエレベータの動きを指示することができます。
検知することができるイベントや、イベントの中で利用できる関数は後述します。
-
function fireOneSecond( second )
-
シミュレーションスタート後、1秒おきに発生するイベント。
-
引数は秒数。
-
-
function fireCallButtonPush( floor, updown )
-
どこかのフロアでエレベータ呼び出しボタンが押された時に発生するイベント
-
引数 floor はフロア番号(1, 2, .., max_floor )
-
引数 updown は 1 の時「上」ボタンが押された、 -1 の時「下」ボタンが押された。
-
-
function fireElevatorButtonPush( num, floor )
-
どこかのエレベータ内でボタンが押された時に発生するイベント
-
引数 num はエレベータ番号(0, 1, .., num - 1)
-
引数 floor は行先のフロア番号(1, 2, .., max_floor)
-
-
function getElevatorsStatus()
-
全エレベータの稼働状況を得る
-
返り値: 以下のオブジェクトの配列
{ num: エレベータ番号, floor: 現在いるフロア(移動中の場合は最後にいたフロア), updown: -1: 下降中、0: 停止中、1: 上昇中, people: 乗車中の人の配列(※1), move_count: フロアとフロアの間を移動している場合のカウント数(move_second に達したら次の階), stop_count: 乗降中で停止している場合のカウント数(stop_second に達したら移動開始), buttons: エレベータ内のボタン状態の配列(※2), mode: 0: 停止中、1: 移動中、2: 乗降中 } ※1 people は以下のオブジェクトの配列 { src_floor: エレベータに乗る前にいたフロア, dst_floor: エレベータを降りるフロア, waitsec: エレベータに乗るために待ちはじめてからの経過秒, mode: 0: 乗車待ち、1: 乗車中、2: 目的フロア到着 } ※2 buttons は以下のような数値配列で、0 は押されていない、1 は押されている状態を示す。 [ 0, 0, 1, 0, 1 ] ←この例だと 3 階と 5 階のボタンが押されている。
-
-
function goFloor( idx, floor )
-
特定のエレベータを特定階に向かわせる
-
引数 idx はエレベータ番号( 0, 1, .., num - 1 )
-
引数 floor は行き先フロア番号(1, 2, .., max_floor )
-
velev.js の fireOneSecond(), fireCallButtonPush(), fireElevatorButtonPush() イベント内は JavaScript によるカスタマイズが可能です。
一例として、デフォルト状態の fireCallButtonPush() イベント内にコメントで記述されている内容をコメントアウトすると、fireCallButtonPush() 内は以下のようになります:
function fireCallButtonPush( floor, updown ){ //. floor: 階, updown: { -1: 下, 1: 上 }
var elevators_status = getElevatorsStatus();
var idx = -1;
for( var i = 0; i < elevators_status.length && idx == -1; i ++ ){
var s = elevators_status[i];
if( s.mode == 0 ){ //. 停止中のエレベータがあったら使う
idx = i;
goFloor( idx, floor );
}
}
if( idx == -1 ){
//. 停止中のエレベータがなかったら??
}
}
floor 階で、updown ボタンが押された時のイベント処理です。このカスタマイズでは getElevatorsStatus() 関数で各エレベータの状況を参照し、「現在停止中のエレベータが存在しているか?」を探しています。そして停止中のエレベータが見つかったら goFloor() 関数でそのエレベータを floor 階まで向かわせています(到達後はそのエレベータに乗って目的階へ向かいますが、そこはシミュレータが自動的に処理します)。
ただこのカスタマイズは不完全です。このカスタマイズでは「イベントが発生したタイミングで停止中のエレベータがあれば向かわせる」というものですが、「もし停止中のエレベータが存在しなかったら」というケースを想定していません。そこまで対応するのであれば、別のタイミングで再度停止中のエレベータを探すのか、稼働中のエレベータの中から向かわせるエレベータを探すのか、・・・といったカスタマイズが必要になります。
This code is licensed under MIT.
2019 K.Kimura @ Juge.Me all rights reserved.