## GameLevel constructor

Creates an instance of GameLevel

@param {object} options Configuration object
@param {ServerChannel} channel The ServerChannel instance
438369
function GameLevel(options, channel) {

    /**
     * ### GameLevel.channel
     *
     * Reference to the Channel
     */
    this.channel = channel;

    /**
     * ### GameLevel.registry
     *
     * The registry of all connected clients
     *
     * @see ChannelRegistry
     */
    this.registry = this.channel.registry;

    /**
     * ### GameLevel.options
     *
     * Configuration options
     */
    this.options = options;

    /**
     * ### GameLevel.name
     *
     * The name of the level
     */
    this.name = options.name;

    /**
     * ### GameLevel.sysLogger
     *
     * The logger for the channel
     */
    this.sysLogger = this.channel.sysLogger;

    /**
     * ### GameLevel.waitingRoom
     *
     * The waiting room for the channel.
     *
     * @see GameLevel.createWaitingRoom
     */
    this.waitingRoom = null;

    /**
     * ### GameLevel.requirementsRoom
     *
     * The requirements room for the channel.
     *
     * @see GameLevel.createRequirementsRoom
     */
    this.requirementsRoom = null;

    /**
     * ### GameLevel.gameRooms
     *
     * Associative container for all the game rooms in the channel.
     *
     * @see GameLevel.createGameRoom
     */
    this.gameRooms = {};

    // Creates waiting and requriements room.
    if (options.requirements && options.requirements.enabled) {
        this.createRequirementsRoom(options.requirements);
    }
    if (options.waitroom) {
        this.createWaitingRoom(options.waitroom);
    }

    // Sets the entry room, if either requirements or waiting is created.
    if (this.requirementsRoom) this.setEntryRoom(this.requirementsRoom);
    else if (this.waitingRoom) this.setEntryRoom(this.waitingRoom);
}
812706
function(id, gameGroup, options) {
  options = options || {};
  this.id = id;
  this.gameGroup = gameGroup;
  this.players = {};
  this.numPlayers = 0;
  this.sendQueue = [];
  this.options = options;
  this.setGameId();
  debug("create game " + this.gameId);
}
1085175
function (channels) {
            var that = this,
                panels = [];

            // Multiple channels may come as comma-delimited
            if (typeof channels === 'string') {
                channels = channels.split(',');
            }

            $.each(channels, function (index, channel_name_key) {
                // We may have a channel key so split it off
                var spli = channel_name_key.trim().split(' '),
                    channel_name = spli[0],
                    channel_key = spli[1] || '';

                // Trim any whitespace off the name
                channel_name = channel_name.trim();

                // Add channel_prefix in front of the first channel if missing
                if (that.get('channel_prefix').indexOf(channel_name[0]) === -1) {
                    // Could be many prefixes but '#' is highly likely the required one
                    channel_name = '#' + channel_name;
                }

                // Check if we have the panel already. If not, create it
                channel = that.panels.getByName(channel_name);
                if (!channel) {
                    channel = new _kiwi.model.Channel({name: channel_name, network: that, key: channel_key||undefined});
                    that.panels.add(channel);
                }

                panels.push(channel);

                that.gateway.join(channel_name, channel_key);
            });


            return panels;
        }
986705
function ServerNode(opts) {

    opts = opts || {};

    /**
     * ### ServerNode.defaultConfDir
     *
     * The directory of execution of the server
     */
    this.rootDir = path.resolve(__dirname, '..');


    // Creates the http or https server (must be after rootDir is set).
    this.createServer(opts);

    /**
     * ### ServerNode.http
     *
     * The server
     */
    this.http = exp;

    /**
     * ### ServerNode.port
     *
     * Default port for server
     */
    this.port = 8080;

    /**
     * ### ServerNode.version
     *
     * The software version of the server as a string
     */
    this.version = require(path.resolve(this.rootDir, 'package.json')).version;

    /**
     * ### ServerNode.nodeGameVersion
     *
     * The official release version of nodeGame
     *
     * This includes all other modules, and it is passed by the launcher.
     *
     * Default: ServerNode.version
     */
    this.nodeGameVersion = opts.nodeGameVersion || this.version;

    /**
     * ### ServerNode.modulesVersion
     *
     * Versions of all nodegame submodules
     *
     * This includes all other modules, and it is passed by the launcher.
     *
     * Default: ServerNode.version
     */
    this.modulesVersion =
        require(path.join(this.rootDir, 'bin', 'info.js')).modulesVersion;

    /**
     * ### ServerNode.defaultConfDir
     *
     * The directory from which the default configuration files are located
     *
     * @see ServerNode.rootDir
     */
    this.defaultConfDir = path.join(this.rootDir, 'conf');

    /**
     * ### ServerNode.channels
     *
     * Object containing references to all the existing channels
     *
     * @see ServerChannel
     */
    this.channels = {};

    /**
     * ### ServerNode.defaultChannel
     *
     * The name of the default channel (will be served from '/')
     *
     * @see ServerChannel
     */
    this.defaultChannel = null;

    /**
     * ### ServerNode._defaultChannel
     *
     * The name of the default channel as specified by options
     *
     * Needs to be distinguished at load time.
     */
    this._defaultChannel = opts.defaultChannel || null;

    /**
     * ### ServerNode.rooms
     *
     * Object containing references to all existing game rooms in all channels
     *
     * @see GameRoom
     */
    this.rooms = {};

    /**
     * ### ServerNode.info
     *
     * Object containing global information about games and channels
     *
     * Games actually include also aliases.
     *
     * @see ServerNode.loadGames
     */
    this.info = {
        channels: {},
        games: {},
        aliases: {}
    };

    /**
     * ### ServerNode.defaults
     *
     * Defaults settings for the server and the channels
     *
     * Will be populated by the configure function.
     */
    this.defaults = {};

    /**
     * ### ServerNode.gamesDirs
     *
     * Array of directories that will be sequentially scanned for games
     */
    this.gamesDirs = [];

    /**
     * ### ServerNode.scannedGamesDirs
     *
     * Keeps tracks of games directories already scanned and of the outcome
     */
    this.scannedGamesDirs = {};

    /**
     * ### ServerNode.logger
     *
     * Default logger before any configuration is loaded.
     *
     * Does not print anything.
     */
    this.logger = winston;
    if (opts.logLevel) {
        if (opts.logLevel !== 'error' &&
            opts.logLevel !== 'warn' &&
            opts.logLevel !== 'info' &&
            opts.logLevel !== 'verbose' &&
            opts.logLevel !== 'debug' &&
            opts.logLevel !== 'silly') {

            throw new Error('ServerNode constructor: invalid logLevel: ' +
                            opts.logLevel);
        }
    }
    this.logger.level = opts.logLevel || 'warn';

    /**
     * ### ServerNode.debug
     *
     * If TRUE, errors will be thrown, otherwise caught and logged.
     */
    this.debug = false;

    /**
     * ### ServerNode.asyncQueue
     *
     * Object containing callbacks to be executed if no operation is in progress
     */
    this.asyncQueue = J.getQueue();

    /**
     * ### ServerNode.sio
     *
     * The Socket.IO app of the server.
     *
     * The app is shared with all the channels.
     */
    this.sio = socket_io.listen(http);

    // see http://nodejs.org/docs/latest/
    //            api/events.html#events_emitter_setmaxlisteners_n
    this.sio.sockets.setMaxListeners(0);

    /**
     * ### ServerNode.gameLoader
     *
     * Object responsible to load the games from the file system.
     */
    this.gameLoader = new GameLoader(this);

    /**
     * ### ServerNode.page
     *
     * Loading, caching of static resources and templates from file system.
     */
    this.resourceManager = new ResourceManager(this);

    /**
     * ### ServerNode.logDir
     *
     * Log directory
     */
    this.logDir = path.join(this.rootDir, 'log');

    /**
     * ### ServerNode.lastError
     *
     * Last error caught by error manager
     */
    this.lastError = null;

    /**
     * ### ServerNode.acm
     *
     * Access control from channels on servernode
     *
     * Important! Currently, acm is not enforced, all channels have access
     * to ServerNode and can modify it. Do not rely on this in production!
     *
     * @experimental
     */
    this.acm = {
        read: {},
        modify: {}
    };

    // Loading configurations.
    this.init(opts || {});
}
763590
function GameRoom(config) {
    var that, node;

    Room.call(this, 'Game', config);
    if (!this.logicPath) this.logicPath  = './rooms/game.room';

    if (config.treatmentName && 'string' !== typeof config.treatmentName) {
        throw new TypeError('GameRoom: config.treatmentName must be ' +
                            'undefined or string. Found: ' +
                            config.treatmentName);
    }

    if (config.runtimeConf && 'object' !== typeof config.runtimeConf) {
        throw new TypeError('GameRoom: config.runtimeConf must be object. ' +
                            'Found: ' + config.runtimeConf);
    }

    /**
     * ### GameRoom.treatmentName
     *
     * The name of the treatment played, or 'standard' if not defined
     */
    this.treatmentName = config.treatmentName || 'standard';

    if (!this.game.settings[this.treatmentName]) {
        throw new Error('GameRoom: game ' + this.gameName + ' treatment ' +
                        'not found: ' + this.treatmentName);
    }

    /**
     * ### GameRoom.gameLevel
     *
     * Game paths for the room
     */
    this.gameLevel = config.gameLevel;

    if (this.gameLevel && !this.game.levels[this.gameLevel]) {
        throw new Error('GameRoom: game ' + this.gameName + ' game level ' +
                        'not found: ' + this.gameLevel);
    }

    /**
     * ### GameRoom.gamePaths
     *
     * Game paths for the room
     */
    this.clientTypes = this.gameLevel ?
        this.game.levels[this.gameLevel].clientTypes :
        this.game.clientTypes;

    /**
     * ### GameRoom.gameTreatment
     *
     * Actual settings for current game based on treatment and runtime conf
     *
     * @see GameRoom.runtimeConf
     * @see GameRoom.setupGame
     */
    this.gameTreatment = this.game.settings[this.treatmentName];
    if (this.runtimeConf) J.mixin(this.gameTreatment, this.runtimeConf);

    /**
     * ### GameRoom.dataDir
     *
     * Path to the data directory
     *
     * @see ServerChannel.getGameDir
     */
    if (config.ownDataDir || this.channel.roomOwnDataDir) {
        this.dataDir = path.resolve(this.channel.getGameDir(),
                                    'data', this.name);


        // TODO: warning if it already exists.
        fs.ensureDir(this.dataDir);
    }
    else {
        this.dataDir = path.resolve(this.channel.getGameDir(), 'data');
    }
    this.dataDir += '/';

    // Configure disconnect/reconnect policy.

    that = this;
    node = this.node;

    /**
     * ## GameRoom.wrongNumOfPlayers
     *
     * Default listener for `onWronPlayerNum` on logics
     *
     * This listener is added as default stager property `onWrongPlayerNum`
     * to all `logic` client types by method `GameRoom.getClientType`,
     * if no other is already defined.
     *
     * The listener is invoked when there is a "wrong" number of players.
     * The number of players is "wrong" if it has been defined any
     * min|max|exactPlayers property in current game step.
     *
     * Default behavior:
     *
     * 1 - Immediately pauses all connected players. A message is displayed
     *     with information.
     * 2 - A timer is started for the value specified in settings.WAIT_TIME,
     *     or 30 seconds otherwise.
     * 3 - If timer expires, game is resumed and, if a custom callback is
     *     is defined, it is executed.
     *
     * The listener is then invoked with `node.game` context.
     *
     * @param {string} type The type of "wrong" number: 'min', 'max', 'exact'
     * @param {function} customCb Optional. A callback to be executed in
     *     in case the timer expires.
     * @param {object} player Optional. The player object that triggered
     *     the listener by either connecting or disconnecting (if available)
     *
     * @see GameRoom.correctNumOfPlayersAgain
     * @see GameRoom.getClientType
     */
    this.wrongNumOfPlayers = function(type, customCb, player) {
        var node;
        var waitTime, msgToClients;
        node = this.node;

        // If the default value (30) is changed the documentation
        // on the wiki needs to be updated too (Disconnections page).
        waitTime = 'number' === typeof this.settings.WAIT_TIME ?
            this.settings.WAIT_TIME : 30;

        if (type === 'min') {

            msgToClients = this.settings.WAIT_TIME_TEXT ||
                'One or more players disconnected. We are waiting ' +
                '<span id="ng_pause_timer">' + waitTime +
                '</span> seconds to see if they reconnect.';

            node.warn('warning: not enough players!!');
        }
        else if (type === 'max') {
            msgToClients = this.settings.WAIT_TIME_TEXT ||
                'Too many players connected. We are waiting ' +
                '<span id="ng_pause_timer">' + waitTime + '</span> ' +
                'seconds to see if the right number of players is restored.';

            node.warn('warning: too many players!!');
        }
        else {
            msgToClients = this.settings.WAIT_TIME_TEXT ||
                'Wrong number of connected players detected. We are waiting' +
                '<span id="ng_pause_timer">' + waitTime + '</span> ' +
                'seconds to see if the right number of players is restored.';

            node.warn('warning: wrong number of players!!');
        }

        if (!node.game.isPaused()) {
            // Pause connected players.
            node.remoteCommand('pause', 'ROOM', msgToClients);
            node.game.pause();
        }

        that.countdown = setTimeout(function() {
            node.warn('Disconnection Countdown fired: ' + node.nodename);
            node.remoteCommand('resume', 'ROOM');
            node.game.resume();
            if (customCb) customCb.call(node.game, player);
            setTimeout(function() {
                if (node.game.shouldStep()) node.game.step();
            }, 100);

        }, waitTime * 1000);
    };

    /**
     * ## GameRoom.correctNumOfPlayersAgain
     *
     * Listener invoked at any time the correct number of players is recovered
     *
     * The number of players is "wrong" if it has been defined any
     * min|max|exactPlayers property in current game step.
     *
     * Default behavior:
     *
     * 1 - Immediately resumes all connected players that have been
     *     paused by callback `wrongNumOfPlayers`
     * 2 - The timer defined by `wrongNumOfPlayers` is cleared
     * 3 - If any custom callback was defined, it gets executed
     *
     * This listener is added as default stager property `onCorrectPlayerNum`
     * to all `logic` client types by method `GameRoom.getClientType`,
     * if no othe is already defined.
     *
     * The listener is then invoked with `node.game` context.
     *
     * @param {string} type The type of "wrong" number: 'min', 'max', 'exact'
     * @param {function} customCb Optional. A callback to be executed in
     *     in case the timer expires.
     * @param {object} player Optional. The player object that triggered
     *     the listener by either connecting or disconnecting (if available)
     *
     * @see GameRoom.wrongNumOfPlayers
     * @see GameRoom.getClientType
     */
    this.correctNumOfPlayersAgain = function(type, customCb, player) {
        var node;
        node = this.node;
        if (type === 'min') {
            node.warn('warning: enough players again!!');
        }
        else if (type === 'max') {
            node.warn('warning: number of players below maximum again!!');
        }
        else {
            node.warn('warning: correct number of players again!!');
        }

        // Delete countdown to terminate the game.
        clearTimeout(that.countdown);
        that.countdown = null;

        // Player can reconnect during the countdown or after.
        // If after, then the game won't be paused.
        if (node.game.isPaused()) {
            node.game.resume();
            // Resume other players.
            setTimeout(function() {
                node.game.pl.each(function(p) {
                    if (player.id !== p.id) {
                        node.remoteCommand('resume', p.id);
                    }
                });
            }, 100);
        }

        if (customCb) customCb.call(node.game, player);
    };

    // Logs connections.
    node.on.pconnect(function(p) {
        that.logClientEvent(p, 'connect');
    });

    // Some players are already there, and do not fire pconnect.
    node.once('INIT', function(p) {
        // Avoid the whole loop.
        if (!that.logClients) return;
        node.game.pl.each(function(p) {
            that.logClientEvent(p, 'connect');
        });

    });

    // Logs disconnection.
    node.on.pdisconnect(function(p) {
        console.log('Disconnection: ' + p.id + ' (server stage: ' +
                    node.player.stage + ')');
        that.logClientEvent(p, 'disconnect');

    });

    // Player reconnecting.
    // This function is called first, and it invokes any
    // min/max/exact handler accordingly.
    node.on.preconnect(function(p) {
        var code, discoStage, discoStageLevel, curStage, reconCb, res;
        var compareSteps, reconOptions;
        var milliseconds, resetTime;

        that.logClientEvent(p, 'reconnect');

        node.warn('Oh...somebody reconnected!', p);
        code = that.channel.registry.getClient(p.id);

        discoStage = code.disconnectedStage;
        curStage = node.game.getCurrentGameStage();
        compareSteps = GameStage.compare(discoStage, curStage);

        // Check if only within stage reconnections are allowed.
        if (that.sameStepReconnectionOnly && compareSteps) {
            node.err('GameRoom: player reconnected from another step. ' +
                     'Not allowed. Player: ' + p.id);
            disposeClient(node, p);
            return;
        }

        // Setup client.
        that.setupClient(p.id);

        if (code.lang.name !== 'English') {
            // If lang is different from Eng, remote setup it.
            // TRUE: sets also the URI prefix.
            node.remoteSetup('lang', p.id, [code.lang, true]);
        }

        // Start the game on the reconnecting client.
        // Need to give step: false, we just init it.
        node.remoteCommand('start', p.id, { step: false });

        // Create the reconnection options object.
        reconOptions = { plot: {} };

        // Mark the state as DONE, if this is the case.
        // Important!
        // IF the client was DONE, and waiting for other players,
        // and the STEP command is sent right before its disconnection,
        // THEN the willBeDone option is applied to the next step, which
        // is the wrong thing to do. So we add willBeDone only on same
        // stage, or if the client is ahead.
        discoStageLevel = code.disconnectedStageLevel;
        if (compareSteps <= 0 && discoStageLevel === DONE) {
            reconOptions.willBeDone = true;
            // Temporarily remove the done callback.
            reconOptions.plot.done = null;
            reconOptions.plot.autoSet = null;
        }

        // Sets the timer on reconnecting client if milliseconds is found.
        milliseconds = node.game.timer.milliseconds;
        if ('number' === typeof milliseconds) {
            // Time left to play in stage.
            resetTime = Math.max(milliseconds -
                                 node.timer.getTimeSince('step', true), 0);

            reconOptions.plot.timer = resetTime;
        }

        reconCb = this.plot.getProperty(curStage, 'reconnect');

        if (reconCb) {
            // Res contains the reconnect options for the step,
            // or false to abort reconnection.
            res = reconCb.call(this, code, reconOptions);
            if (res === false) {
                node.warn('Reconnect Cb returned false');
                disposeClient(node, p);
                return;
            }
        }

        // Add player to player list.
        node.game.pl.add(p);

        // Start the step on reconnecting client.
        // Unless differently specified by the reconnect callback,
        // target step is what is more advanced between the logic step,
        // and the step when the client disconnected.
        if (!reconOptions.targetStep) {
            // console.log(compareSteps, curStage, code.stage);
            // -1 means first param is ahead in game stage.
            // compareSteps = GameStage.compare(code.stage, curStage);
            if (compareSteps < 0) reconOptions.targetStep = discoStage;
            else reconOptions.targetStep = curStage;
        }

        node.remoteCommand('goto_step', p.id, reconOptions);

        // See if we have enough players now.
        res = node.game.sizeManager.changeHandler('pconnect', p);

        // If we are still missing more players pause reconnecting player.
        if (!res) node.remoteCommand('pause', p.id);

    });

    this.registerRoom();
}
593632
function newChannel() {
  let chan = new Channel();
  let result = chan.send.bind(chan);
  result._inst = chan;
  return result;
}
1358604
function( data ){

            var self = this
                ,candidates
                ;

            candidates = self.broadPhase();

            if ( candidates.length ){

                this._world.emit( this.options.channel, {
                    candidates: candidates
                });
            }
        }
321693
function ServerChannel(server, opts) {
  opts = opts || {};
  events.EventEmitter.call(this);

  this.server = server;
  this._endWritable = !!utils.getOption(opts, 'endWritable', true);
  this._prefix = normalizedPrefix(opts.scope);

  var cache = server._cache;
  var svc = server.service;
  var hash = svc.hash;
  if (!cache[hash]) {
    // Add the channel's protocol to the cache if it isn't already there. This
    // will save a handshake the first time on channels with the same protocol.
    cache[hash] = new Adapter(svc, svc, hash);
  }
  this._adapter = null;

  this.destroyed = false;
  this.draining = false;
  this.pending = 0;
  this.once('_eot', function (pending, err) {
    debug('server channel EOT');
    this.emit('eot', pending, err);
  });
}
1117144
function WebServer(options) {
  EventEmitter.call(this);

  this._options = options;

  this._username = options['username'];
  this._ip = options['ip'];
  this._port = options['port'];
  this._secret = options['secret'];
  this._triggerString = options['trigger_string'];

  this._server = null;
}
709546
function(client, relayServer, id) {
  this.client = client;
  this.relayServer = relayServer;
  this.id = id;

  debug("" + id + ": start player");

  var addPlayerToGame = function(data) {
    var game = this.relayServer.addPlayerToGame(this, data.gameId, data.data);
    if (!game) {
      // TODO: Make this URL set from some global so we can set it some place else.
      debug("game does not exist:", data.gameId);
      this.disconnect();
    } else {
      this.setGame(game);
    }
  }.bind(this);

  this.setGame = function(game) {
    this.game = game;
  }.bind(this);

  var assignAsServerForGame = function(data) {
    this.client.on('message', undefined);
    this.client.on('disconnect', undefined);
    this.relayServer.assignAsClientForGame(data, this.client);
  }.bind(this);

  var passMessageFromPlayerToGame = function(data) {
    if (!this.game) {
      console.warn("player " + this.id + " has no game");
      return;
    }
    this.game.send(this, {
      cmd: 'update',
      id: this.id,
      data: data,
    });
  }.bind(this);

  var messageHandlers = {
    'join':   addPlayerToGame,
    'server': assignAsServerForGame,
    'update': passMessageFromPlayerToGame,
  };

  var onMessage = function(message) {
    var cmd = message.cmd;
    var handler = messageHandlers[cmd];
    if (!handler) {
      console.error("unknown player message: " + cmd);
      return;
    }

    handler(message.data);
  };

  var onDisconnect = function() {
    debug("" + this.id + ": disconnected");
    if (this.game) {
      this.game.removePlayer(this);
    }
    this.disconnect();
  }.bind(this);

  client.on('message', onMessage);
  client.on('disconnect', onDisconnect);
}
293789
function Slider(options) {

	this.__proto__ = new Control();

	this.init = function(options) {
		this.type = options.type = 'Slider';
		this.parent = options.parent;
		this.defaults = {
			x:48, y:48,
			w:72, h:192,

			//value: 0,
			text: '',
			script: undefined,
			onload: undefined,
			fill:this.parent.fill,
			fill_highlight: this.parent.lighter(this.parent.stroke),
			stroke: this.parent.stroke,
			'stroke-width': this.parent.control_stroke,
			fontsize: this.parent.fontsize,
			repeat: 0,
			running: 0,
			corner: this.parent.button_corner,
			subtype: 'y',		// ***
			group: undefined,
			row: undefined,
			col: undefined,
			autorun: undefined,
			highlighttrue: undefined,
			source: undefined,
			refresh: 0,

			noreadout: undefined,
			min: 0, max: 255,
			xmin: 0, xmax: 255,
			ymin: 0, ymax: 255,
			recenter: undefined,
			value: 0,
			xvalue: 0,
			yvalue: 0,
			barw: 1,
			barh: this.barw
		};
		this.setoptions(options);
		//console.log('Slider:', this);
		this.render();
		return this;
	};

	this.layout = function() {
		if (this.subtype == 'xy') {
			this.slidew = options.slidew || 1+Math.floor(this.w / 12);
			this.slideh = options.slideh || 1+Math.floor(this.h / 12);
		}
		else if (this.subtype == 'x') {
			this.slidew = options.slidew || 1+Math.floor(this.w / 10);
			this.slideh = 0.8 * this.h;
		}
		else {
			this.ymin = options.min || this.ymin;
			this.ymax = options.max || this.ymax;
			this.value = options.value || this.value;
			this.slidew = 0.8 * this.w;
			this.slideh = options.slideh || 1+Math.floor(this.h / 10);
		}

		this.outerw = this.w; if (this.subtype != 'y') this.outerw += this.slidew;
		this.outerh = this.h; if (this.subtype != 'x') this.outerh += this.slideh;

		this.outerxmid = this.x + this.w/2;
		if (this.subtype !='y') this.outerxmid += (this.slidew/2);

		this.outerymid = this.y + this.h/2;
		if (this.subtype !='x') this.outerymid += (this.slideh/2);
	};

	this.render = function() {
		this.layout();
		this.outerrect = this.parent.paper.rect(this.x, this.y, this.outerw, this.outerh, 10)
			.attr({fill:this.fill, stroke:this.stroke, 'stroke-width':this.parent.control_stroke});
		this.elts.push(this.outerrect);

		if (this.subtype != 'y') {
			this.xbar = this.parent.paper.rect(this.x, this.outerymid, this.outerw, this.barh)
				.attr({fill:this.stroke, stroke:this.stroke});
			this.elts.push(this.xbar);
		}
		if (this.subtype != 'x') {
			this.ybar = this.parent.paper.rect(this.outerxmid, this.y, this.barw, this.outerh)
				.attr({fill:this.stroke, stroke:this.stroke});
			this.elts.push(this.ybar);
		}

		var self = this;
		this.slide = this.parent.paper.rect(this.slideXPos(), this.slideYPos(), this.slidew, this.slideh, 5)
			.attr({fill:this.stroke, stroke:this.stroke, 'stroke-width': this['stroke-width']})
			.drag(self.slideMove, self.slideStart, self.slideEnd, self, self, self);

		// OOPS don't want the slide decorated in sethandler(). see dedicated remove method
		//this.elts.push(this.slide);

		if (this.recenter) this.slideToCenter();

		this.label = this.parent.paper.text(this.outerxmid, this.y + this.outerh + this.fontsize*2, this.text)
			.attr({fill:this.stroke, stroke:this.stroke, 'font-size': this.fontsize});
		this.textelts.push(this.label);

		if (!this.noreadout) {
			if ((this.subtype == 'y') || (this.subtype == 'xy')) {
				this.yreadout = this.parent.paper
					.text(this.outerxmid, this.y + this.outerh + this.fontsize, ''+(this.value || this.xvalue || ''))
					.attr({fill:this.stroke, stroke:this.stroke, 'font-size': this.fontsize-2});
				this.textelts.push(this.yreadout);
			}

			if ((this.subtype == 'x') || (this.subtype == 'xy')) {
				 this.xreadout = this.parent.paper.text(this.x + this.outerw + this.fontsize, this.y + this.h/2, ''+(this.yvalue || ''))
					.attr({fill:this.stroke, stroke:this.stroke, 'font-size': this.fontsize-2});
				this.textelts.push(this.xreadout);
			}
		}
		this.sethandlers();
	};

	this.remove = function() {
		this.slide.remove();
		this.__proto__.remove.call(this);
	};

	this.move = function(x, y) {
		this.x = x;
		this.y = y;
		this.outerrect.attr({x:this.x, y:this.y, width:this.w, height:this.h});
		if (this.xbar) this.xbar.attr({x:this.x, y:this.y + this.outerh/2});
		if (this.ybar) this.ybar.attr({x:this.x + (this.w-this.barw)/2, y:this.y});
		this.slide.attr({x:this.x + (this.w - this.slidew)/2, y:this.slideYPos()});

		this.label.attr({x:this.x + this.w/2, y:this.y + this.outerh + this.fontsize*2});
		if (this.xreadout) this.xreadout.attr({x:this.x + this.outerw + this.fontsize, y:this.y + this.h/2});
		if (this.yreadout) this.yreadout.attr({x:this.x + this.w/2, y:this.y + this.outerh + this.fontsize});
	};

	this.slideStart = function(x, y, event) {
		//console.log('Slide start:', x, y, event);
		this.dragslide = {x:this.x, y:this.y};
		this.sliding = true;
		this.slide.attr({fill:this.fill});
	};

	this.slideMove = function(dx, dy, x, y, e) {
		//console.log('Slide move:', dx, dy, x, y, e);
		x = x - this.parent.x;
		y = y - this.parent.y;

		if (y < this.y) y = this.y;
		else if (y > this.y + this.h) y = this.y + this.h;
		if (x < this.x) x = this.x;
		else if (x > this.x + this.w) x = this.x + this.w;

		var xfraction = (x - this.x) / this.w;
		var xvalue = Math.floor(this.xmin + (xfraction) * (this.xmax - this.xmin));
		var yfraction = (y - this.y) / this.h;
		var yvalue = Math.floor(this.ymin + (1.0 - yfraction) * (this.ymax - this.ymin));

		if (this.subtype == 'xy') this.setValue(xvalue, yvalue);
		else if (this.subtype == 'x') this.setValue(xvalue);
		else this.setValue(yvalue);
		return this.slideFinish(e);
	};

	this.slideEnd = function(e) {
		//console.log('Slide end:', e);
		this.slide.attr({fill:this.stroke});
		return this.slideFinish(e);
	};

	this.slideFinish = function(e) {
		e.preventDefault();
		e.stopPropagation();
		delete this.dragslide;
		this.sliding = false;
		this.exec();
		var self = this;
		//console.log('slidefinish:', e, e.type);
		if (this.recenter && ((e.type == 'mouseup') || (e.type == 'touchend'))) {
			window.setTimeout(function() {
				self.slideToCenter();
			}, 10);
		}
		return false;
	};

	this.slideToCenter = function() {
		if (this.subtype == 'xy')
			this.setValue(Math.floor((this.xmax + this.xmin)/2),
				Math.floor((this.ymax + this.ymin)/2));
		else if (this.subtype == 'x') this.setValue(Math.floor((this.xmax + this.xmin)/2));
		else this.setValue(Math.floor((this.ymax + this.ymin)/2));
		this.exec();
	};

	this.slideXPos = function() {
		if (this.subtype == 'y') return this.x + (this.w - this.slidew)/2;
		if (this.xvalue < this.xmin) this.xvalue = this.xmin;
		if (this.xvalue > this.xmax) this.xvalue = this.xmax;
		var fraction = (this.xvalue - this.xmin) / (this.xmax - this.xmin);
		return Math.floor(this.x + this.w * fraction);
	};

	this.slideYPos = function() {
		if (this.subtype == 'x') return this.y + (this.h - this.slideh)/2;
		if (this.yvalue < this.ymin) this.yvalue = this.ymin;
		if (this.yvalue > this.ymax) this.yvalue = this.ymax;
		var fraction = (this.yvalue - this.ymin) / (this.ymax - this.ymin);
		return Math.floor(this.y + this.h * (1.0 - fraction));
	};

	this.handleClick = function() {
		// do nothing; this override prevents the flash that Button wants
	};

	this.setValue = function(value1, value2) {

		//console.log('slider set:', value1, value2, typeof value1, typeof value2);
		if (this.dragging) return;	// be the boss: ignore updates while dragging

		if (this.subtype == 'xy') {
			if (value1 !== undefined) this.xvalue = value1;
			if (value2 !== undefined) this.yvalue = value2;
			if (this.xreadout && (this.xvalue !== undefined)) this.xreadout.attr({text: ''+this.xvalue});
			if (this.yreadout && (this.yvalue !== undefined)) this.yreadout.attr({text: ''+this.yvalue});
			var slidex = this.slideXPos();
			var slidey = this.slideYPos();
			this.slide.attr({x:slidex, y:slidey});
			var update = {id: this.id, xvalue: this.xvalue, yvalue: this.yvalue};
			this.fire('update', update);
		}
		else if (this.subtype == 'x') {
			this.value = this.xvalue = value1;
			if (this.xreadout && (this.value !== undefined)) this.xreadout.attr({text: ''+this.value});
			var slidex = this.slideXPos();
			this.slide.attr({x:slidex});
			var update = {id: this.id, value: this.value};
			this.fire('update', update);
		}
		else {
			this.value = this.yvalue = value1;
			if (this.yreadout && (this.value !== undefined)) this.yreadout.attr({text: ''+this.value});
			var slidey = this.slideYPos();
			//console.log('slidey:', slidey);
			this.slide.attr({y:slidey});
			var update = {id: this.id, value: this.value};
			this.fire('update', update);
		}
	};

	return this.init(options || {});
}
355648
function(options) {
  var self = this;

  self.sounds = [];

  // Setup the options to define this sprite display.
  self._width = options.width;
  self._left = options.left;
  self._spriteMap = options.spriteMap;
  self._sprite = options.sprite;
  self.setupListeners();

  // Create our audio sprite definition.
  self.sound = new Howl({
    src: options.src,
    sprite: options.sprite
  });

  // Setup a resize event and fire it to setup our sprite overlays.
  window.addEventListener('resize', function() {
    self.resize();
  }, false);
  self.resize();

  // Begin the progress step tick.
  requestAnimationFrame(self.step.bind(self));
}
1103369
@Override
    public <T> Event<T> fire(Event<T> event, Channel... channels) {
        if (channels.length == 0) {
            channels = event.channels();
            if (channels.length == 0) {
                channels = new Channel[] { channel() };
            }
        }
        event.setChannels(channels);
        tree().fire(event, channels);
        return event;
    }
995930
public Optional<AlertChannel> create(AlertChannel channel)
    {
        return Optional.of(HTTP.POST("/v2/alerts_channels.json", channel, ALERT_CHANNELS).get().iterator().next());
    }
448823
function(options) {
    if (typeof options === 'undefined') {
      throw new Error('new StreamChannels(options) - options parameter missing');
    }
    else if (typeof options.track === 'undefined') {
      throw new Error('new StreamChannels(options) - options.track parameter missing');
    }
    else if (!(typeof options.track === 'object' || typeof options.track === 'string')) {
      throw new Error('new StreamChannels(options) - options.track must be an Object (representing your channels with there keywords), an Array (of keywords) or a String (with comma separeted keywords)');
    }
  }
1145351
function loadLevel(
  {
    number,
    description,
    tip,
    clue,
    floor: { size, stairs, warrior, units = [] },
  },
  playerCode,
) {
  const { width, height } = size;
  const stairsLocation = [stairs.x, stairs.y];
  const floor = new Floor(width, height, stairsLocation);

  loadWarrior(warrior, floor, playerCode);
  units.forEach(unit => loadUnit(unit, floor));

  return new Level(number, description, tip, clue, floor);
}
535068
public <T> NettyServerBuilder withChildOption(ChannelOption<T> option, T value) {
    this.channelOptions.put(option, value);
    return this;
  }