Yea, the super wide screen is super annoying. Is there some reason for the big width? A little stealth at work would be nice, hard to hide something that huge.
Slightly related question: are there any standard workloads and tools out there for experimenting with elevator programming?
My apartment building has a utility elevator and two normal elevators. Each floor has two sets of call buttons. These have been programmed in different ways over the years, and I've always been curious if there was a good way to quantify the changes.
This is incredible. I've been successfully nerd-sniped away from work. Also nice touch w/ the time-scale factors being Fibonacci numbers :) Great work.
I got to Challenge #5 by just having the elevators go to every floor like in the first example. It'd be nice to have an earlier challenge with only a single elevator force you to have a more complex controller. With 4 elevators going at a time, it's harder for me to "debug" and figure out how to use the API.
I cheated with #6. My elevators wait on the ground floor until they fill up, then they deliver the patrons to their floors. Everyone not on the ground floor... is stuck forever.
Arguably https://www.bloc.io/ruby-warrior (warning: sound autoplays) - although there's something direct and storyless about the elevator one that I prefer.
http://www.pythonchallenge.com/ - Gamified way to learn Python, but is a puzzle in addition to being a game. Is not exclusive to Python, but many things are intended to be solved with things that are idiomatic in Python.
www.checkio.org - Looks more like a game, but the programming environment feels more "in-your-face" than elevator saga to me.
I was horrendously worried this would be a parody of the incident with Rebecca Watson. I'm glad this is much more tasteful - looks really, really fun actually.
Wow. I want so many more of these kind of things for my kids. It's so close to using code to solve real problems. How about an assembly line version where many parts have to come together in the correct order? Or an air traffic control one? Subway scheduling? Pizza delivery? More please!
It isn't quite programming, but your assembly line comment reminded me of http://pleasingfungus.com/Manufactoria/ which is a game about making state automata.
Yeah! Something I think about occasionally is traffic-light optimization problems, optimizing for throughput, wait-time, safety etc. I think it could work well in a packaging similar to Elevator Saga.
Non-programmer here playing. It gamifies coding for sure. Intended purpose unknown.
If the makers read this, firstly this is brilliant. Second my feature request would be to have some record of history to watch how I improve (or not) each simulation.
Nitpick. Accidentally programming an infinite loop kills the page. Refreshing restores the offending code and immediately does it again. Had to clear cookies to get going again?
Slightly related - SimTower was originally created as an elevator simulator - if you right click on an elevator engine room in the game you get a wealth of programming options
Need help on this. I tried registering a handler for the up_button_pressed and down_button_pressed events, but the handler doesn't seem to be passed any arguments.
I don't think you need an argument. Within the callback function you still hold a reference to floor, and you know the up button has been pressed. There doesn't seem to be any more information. Note that there is also down_button_pressed
I believe some people really need think in term of comparations and, for those, adding a "==" symbol make sense, even if the resultant code doesn't make any sense at all!!
Many languages are expressions (as opposed to statements) including C-like languages. I've always thought that 'return' itself was redundant. If a compound statement was defined to return the value of the final (executed) statement, then functional methods would get much simpler. And remove the need for the '?' operator for instance.
I'm missing your point I guess. All those are equivalent?
In C an assignment has the value of the RHS, so that doesn't change anything in these examples.
Responding to GP; I think it's a tiny bit clearer with `== true`, but I don't feel particularly strongly about it. I wrote this code without caring too much about style and cleanliness.
However, I don't agree that the shortest code is always the cleanest. In JS for example, I've found that wrapping every conditional body in braces even if it's a single statement helps avoid bugs and clear out ambiguity.
LoDash actually, not Underscore. Mostly because it's included by the game already. The code should run as-is. That said, it does occasionally get stuck. I think I have a bug with the direction indicators.
In more than a few buildings I've worked in, these 'destination controlled' elevators shine the moment after a fire-drill and a couple of hundred people attempt to get back upstairs. It must be quicker, how else to justify what I'd imagine to be a far higher cost of operation.
init: function(elevators, floors) {
var elevator = elevators[0]; // Let's use the first elevator
elevator.on("idle", function() {
// The elevator is idle, so let's go to all the floors (or did we forget one?)
var nextFloor;
do nextFloor = Math.round(Math.random() * 2); while (nextFloor == this.currentFloor);
elevator.goToFloor(this.currentFloor = nextFloor);
});
},
update: function(dt, elevators, floors) {
// We normally don't need to do anything here
},
vendor: 'Sirius Cybernetics Corporation'
}
Okay, didn't read or look (currentFloor is already defined) and this won't work in this context.
Here is another approach that brought me through till challenge #7:
{
init: function(elevators, floors) // hook up events
{
// these are the global wish lists that idle elevators choose from (key are floor numbers, values are number of people):
var wishListUp = {}, wishListDown = {};
for (var i = 0, l = elevators.length; i < l; i++)
{
var elevator = elevators[i];
// API: goToFloor(n) [enqueues], stop() [clears queue], currentFloor(),
// goingUpIndicator([set]), goingDownIndicator([set]), loadFactor() [0..1],
// destinationQueue[], checkDestinationQueue() [after manual update]
elevator.on("idle", function() // elevator destination queue finished
{
processWishList();
});
elevator.on("floor_button_pressed", function(floorNum) // passenger indicates where to go
{
if (this.destinationQueue.filter(function (d) { return d == floorNum; }).length == 0) // if not already enqueued
this.goToFloor(floorNum); // enqueue
// note: passengers coming first need to be delivered first (or at least at all)
// however, the elevator will check by passing, whether one destination
// can be approached before the others since it comes on the way.
});
elevator.on("passing_floor", function(floorNum, direction/*"up"/"down"*/) // if not in destination queue
{
updateIndicators(this); // indicate next destination from here
// we stop here if the queue contains this destination,
// or if a passenger on the global wish list want to go in our direction.
// we can only hope that people check where the elevator is going.
if (this.destinationQueue.filter(function(d) { return d == floorNum; }).length > 0)
{
this.destinationQueue = this.destinationQueue.filter(function(d) { return d != floorNum; }); // remove from later
this.destinationQueue.unshift(floorNum); // add as immediate next destination
this.checkDestinationQueue(); // announce modification
}
else if (this.loadFactor() < 1.0) // if there is some space left
{
switch (getDirection(this))
{
case 1: // going up
if (wishListUp[floorNum]) // are people waiting to go up from here?
{
//if ((1.0 - this.loadFactor()) * 10.0 - wishListUp[floorNum] > 0) // assume capacity for 10 people with regular weight
// delete wishListUp[floorNum]; // mark as visited
this.destinationQueue.unshift(floorNum); // add as immediate next destination
this.checkDestinationQueue(); // announce modification
}
break;
case -1: // going down
if (wishListDown[floorNum]) // are people waiting to go down from here?
{
...
107 comments
[ 2.5 ms ] story [ 184 ms ] threadhttps://news.ycombinator.com/item?id=8928433
My apartment building has a utility elevator and two normal elevators. Each floor has two sets of call buttons. These have been programmed in different ways over the years, and I've always been curious if there was a good way to quantify the changes.
https://www.youtube.com/watch?v=B3rKBw5ZNL4
Strange, that strategy doesn't allow me to get past challenge 2 (just going to every floor one after the other).
The first 5 are easy to "brute force" but six is making me think a bit more.
www.checkio.org - Looks more like a game, but the programming environment feels more "in-your-face" than elevator saga to me.
Long story short: a simple, rules-based algorithm defeated my best efforts at having multiple elevators working together to coordinate their action.
[1]: https://clarkmoody.com/Moody_AgentBasedElevatorControl.pdf
There is a problem with your code: .init@http://play.elevatorsaga.com/app.js line 66 > eval:12:9 createWorldController/controller.start@http://play.elevatorsaga.com/world.js:185:13 app.startChallenge@http://play.elevatorsaga.com/app.js:175:9 @http://play.elevatorsaga.com/app.js:216:13 riot.observable/el.trigger@http://play.elevatorsaga.com/libs/riot.js:45:1 pop@http://play.elevatorsaga.com/libs/riot.js:89:31
Clearing cookies/localstorage should fix that for you, at least until the devs figure out a fix :)
{ init: function(elevators, floors) { console.log(window.world); }, update: function(dt, elevators, floors) { _.each(window.world.users, function(user) { if(user.done) { user.removeMe = true; user.trigger("removed"); user.off("*"); }else{ user.done = true; user.trigger("exited_elevator", 0); } }) } }
If the makers read this, firstly this is brilliant. Second my feature request would be to have some record of history to watch how I improve (or not) each simulation.
Just drop in a while (1) {} to reproduce.
Is this correct?
https://gist.github.com/kballenegger/e275a99d50de2ee07f97
Also, I can never understand why people write ..
.. or things like extra parens on conditionals, or weird styles like: I strongly believe people write as they talk, and talk as they think; which not clearly translates linearly when what you write is code ;)e.g.
orfor instance:
what r should be set to? true or false?I don't see the point of adding such complexity.. it's waaay more clear to be explicit
or, if you intended the other way I guess that's why you need to be strictly correct, or highly opinionated, to design a language.However, I don't agree that the shortest code is always the cleanest. In JS for example, I've found that wrapping every conditional body in braces even if it's a single statement helps avoid bugs and clear out ambiguity.
Also, this code:
is not equivalent to because foo() could return something that isn't boolean. The correct short version would be: It's far less obvious what is going on here. That said, I'd probably go with:side note: why are you using underscore? I wanted to try your code, but doesn't work out-of-the-box.
{ currentFloor: 0,
Here is another approach that brought me through till challenge #7: