RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

エレベータープログラミングしてみた

こんにちは、fuj_takです。

エレベーターがなかなか来なくてもやもやすることありませんか?
かく言う私もエレベーター待ちになると、いつ来るんだろうと悩まされます。

自分にエレベーターの制御をやらせれば、もっといい感じにできる
皆さんも一度は考えた事があるのではないでしょうか!

そんなあなたにこちらをご紹介します。

Elevator Saga Elevator Saga - the elevator programming game f:id:fuj_tak:20190221134651j:plain

GitHubにも公開されています。 GitHub - magwo/elevatorsaga: The elevator programming game!

※私の環境だとIEでうまく画面表示できなかったので、Chromeなどのブラウザでお試しください

プログラミング内容

ブラウザ上でJavaScriptのコードを記述し、エレベーターの操作を行います。
エレベーターに乗った乗客の行先ボタンに応じた制御、
各階での上下ボタンが押された場合のエレベータの制御、
などを行い、時間内に多数の乗客を輸送できるかどうかにチャレンジするという内容。

ブラウザさえあれば誰でもお手軽に試せるので、チーム内ワークショップとかでも使えると思います。
2015年頃に公開されているようなので、一度は触ってみたことがある方もいそうですね。
APIも公開されています。

Elevator Saga - help and API documentation

やってみた

エレベーターの数や各階の数が異なる設定で全18ステージあります。

https://play.elevatorsaga.com/#challenge=1
https://play.elevatorsaga.com/#challenge=2
 ~
https://play.elevatorsaga.com/#challenge=18

頑張ってみたのですが、5ステージを超える事ができませんでした。。。。 f:id:fuj_tak:20190221131311g:plain

色々と無駄な動きが多いですね。
エレベーターの制御プログラムを作っている方々、えらそうなことを言ってすみませんでした m(_ _)m

我こそはという方は是非チャレンジしてみてください!!

参考に

APIを頼りに作ったコードです。
いけてない点があるのは承知していますが、笑って許してください。

{
    init: function(elevators, floors) {
        var waitFloor = [];

        var queuePush = function(floorNum){
            if (waitFloor.indexOf(floorNum) < 0) {
                waitFloor.push(floorNum);
                waitFloor.sort(function(a,b){
                    if( a < b ) return -1;
                    if( a > b ) return 1;
                    return 0;
                });
            }
        }

        // 動作対象のエレベーター取得
        var getTargetElevetor = function(updown, floorNum){
            var target = null;
            elevators.forEach(function(e) {
                // エレベータ内の混在率を考慮
                if(e.loadFactor() < 1) {
                    if (updown == "up") {
                        if (e.destinationDirection == "up") {
                            if (e.currentFloor < floorNum) {
                                target = e;
                            }
                        } else {
                            target = e;
                        }
                    } else if (updown == "down") {
                        if (e.destinationDirection == "down") {
                            if (e.currentFloor > floorNum) {
                                target = e;
                            }
                        } else {
                            target = e;
                        }
                    } 
                }
            });

            return target;
        };

        // エレベーターの上昇/下降に合わせて停止階を決める
        var setStopFloor = function(e, floorNum){
            // 上昇中は上階のみ止まる
            if (e.destinationDirection == "up") {
                if (e.currentFloor < floorNum) {
                    e.goToFloor(floorNum);
                }

                // 下降中は上階のみ止まる
            } else if (e.destinationDirection == "down") {
                if (e.currentFloor > floorNum) {
                    e.goToFloor(floorNum);
                }

                // 停止中は指定階に向かう
            } else {
                e.goToFloor(floorNum);
            }

        };

        elevators.forEach(function(e) {
            // 待機中
            e.on("idle", function() {
                // 1階で待機
                e.goToFloor(0);
            });
            // 行先ボタンプッシュ
            e.on("floor_button_pressed", function(floorNum) {

                // 上昇中
                if(e.goingUpIndicator()) {
                    if(e.currentFloor() < floorNum) {
                        e.goToFloor(floorNum);
                    }
                    // 下降中
                } else if(e.goingDownIndicator()) {
                    if(e.currentFloor() > floorNum) {
                        e.goToFloor(floorNum);
                    }
                } else {
                    e.goToFloor(floorNum);
                }
                // 行先を制御
                setStopFloor(e, floorNum);
            })
            // 移動中
            e.on("passing_floor", function(floorNum) {

            });
            // 到着
            e.on("stopped_at_floor", function(floorNum) {
                // エレベーター待ちをクリアする
                waitFloor = waitFloor.slice(waitFloor.indexOf(floorNum), 1);
            });
        });

        // 各階で上下ボタンがプッシュされた
        floors.forEach(function(f) {
            f.on("up_button_pressed", function() {

                queuePush(f.floorNum());
                var e = getTargetElevetor("up", f.floorNum());
                if(e != null) {
                    // 行先を制御
                    e.goToFloor(f.floorNum());
                }

            });
            f.on("down_button_pressed", function() {

                queuePush(f.floorNum());
                var e = getTargetElevetor("down", f.floorNum());
                if(e != null) {
                    // 行先を制御
                    e.goToFloor(f.floorNum());
                }
            });
        });
    },

        update: function(dt, elevators, floors) {
            // We normally don't need to do anything here
        }
}
Copyright © RAKUS Co., Ltd. All rights reserved.