<commit_before>var API = require('api');
var Constants = require('constants');
var Display = require('display');
var Helpers = require('helpers');

var retriever = {
  getAttraction: function (id) {
    API.makeApiCall(Constants.ApiUrls.GetAttraction + id, function (data) {
      Display.displayAttraction(data);
    });
  },

  getParkHours: function () {
    var callback = function (data) {
      Display.displayParkHours(data, function (parkId) {
        retriever.getWaitTimes(parkId);
      });
    };

    API.makeApiCall(Constants.ApiUrls.GetParkHours, callback);
  },

  getTopWaitTimes: function () {
    var callback = function (data) {
      Display.displayWaitTimes(data, function (id) {
        retriever.getAttraction(id);
      });
    };

    API.makeApiCall(Constants.ApiUrls.GetTopAttractionWaitTimes, callback);
  },

  getWaitTimes: function (parkId) {
    var callback = function (data) {
      Display.displayWaitTimes(data, function (id) {
        retriever.getAttraction(id);
      });
    };

    API.makeApiCall(Constants.ApiUrls.GetWaitTimesByPark + parkId, callback);
  },

  getWeather: function () {
    API.makeApiCall(Constants.ApiUrls.GetWeather, function (data) {
      Display.displayWeather(data);
    });
  },

  getCurrentPositionForWhatsNearMe: function () {
    navigator.geolocation.getCurrentPosition(
      // success
      function (pos) {
        Helpers.logLocation(pos);

        var callback = function (data) {
          var onclickCallback = function (id) {
            retriever.getAttraction(id);
          };

          Display.displayWhatsNearMe(data.Attractions, onclickCallback);
        };

        //var url = "/Distance/WhatsNearMe?currLat=28.4188341691&currLong=-81.5781962872";
        var url = Constants.ApiUrls.GetWhatsNearMe + "?currLat=" + pos.coords.latitude + "&currLong=" + pos.coords.longitude;
        API.makeApiCall(url, callback);
      },
      // error
      Helpers.logLocationError,
      // options
      Constants.locationOptions
    );
  }
};

this.exports = retriever;<commit_msg>re-did wait times retrieval for code reuse<commit_after>var API = require('api');
var Constants = require('constants');
var Display = require('display');
var Helpers = require('helpers');

var retriever = {
  getAttraction: function (id) {
    API.makeApiCall(Constants.ApiUrls.GetAttraction + id, function (data) {
      Display.displayAttraction(data);
    });
  },

  getParkHours: function () {
    var callback = function (data) {
      Display.displayParkHours(data, function (parkId) {
        retriever.getWaitTimes(parkId);
      });
    };

    API.makeApiCall(Constants.ApiUrls.GetParkHours, callback);
  },

  retrieveWaitTimes: function (url) {
    var callback = function (data) {
      Display.displayWaitTimes(data, function (id) {
        retriever.getAttraction(id);
      });
    };

    API.makeApiCall(url, callback);
  },

  getTopWaitTimes: function () {
    retriever.retrieveWaitTimes(Constants.ApiUrls.GetTopAttractionWaitTimes);
  },

  getWaitTimes: function (parkId) {
    retriever.retrieveWaitTimes(Constants.ApiUrls.GetWaitTimesByPark + parkId);
  },

  getWeather: function () {
    API.makeApiCall(Constants.ApiUrls.GetWeather, function (data) {
      Display.displayWeather(data);
    });
  },

  getCurrentPositionForWhatsNearMe: function () {
    navigator.geolocation.getCurrentPosition(
      // success
      function (pos) {
        Helpers.logLocation(pos);

        var callback = function (data) {
          var onclickCallback = function (id) {
            retriever.getAttraction(id);
          };

          Display.displayWhatsNearMe(data.Attractions, onclickCallback);
        };

        //var url = "/Distance/WhatsNearMe?currLat=28.4188341691&currLong=-81.5781962872";
        var url = Constants.ApiUrls.GetWhatsNearMe + "?currLat=" + pos.coords.latitude + "&currLong=" + pos.coords.longitude;
        API.makeApiCall(url, callback);
      },
      // error
      Helpers.logLocationError,
      // options
      Constants.locationOptions
    );
  }
};

this.exports = retriever;<|endoftext|>


<commit_before>(
    function()
    {
        "use strict";

        // download all images from s3

        var R = require('ramda');
        var Q = require('q');

        var s3 = require('../s3client');

        var bucket = 'functal-images';

        s3.list(bucket).then(function(result)
        {
            // console.log(result.files[0]);

            var step = Q(); // jshint ignore:line

            R.forEach(function(img)
            {
                if (/png$/.test(img.Key))
                {
                    step = step.then(function()
                    {
                        return s3.download('functal-images', img.Key, 'downloads/' + img.Key);
                    });
                }
            }, result.files);

        });

    }()
);
<commit_msg>only download new<commit_after>(
    function()
    {
        "use strict";

        // download all images from s3

        // mogrify -quality 80 -format jpg *.png

        var R = require('ramda');
        var Q = require('q');
        var fs = require('fs');

        var s3 = require('../s3client');

        var bucket = 'functal-images';

        s3.list(bucket).then(function(result)
        {
            // console.log(result.files[0]);

            var step = Q(); // jshint ignore:line

            R.forEach(function(img)
            {
                if (/png$/.test(img.Key))
                {
                    if (!fs.existsSync('downloads/' + img.Key))
                    {
                        step = step.then(function()
                        {
                            return s3.download('functal-images', img.Key, 'downloads/' + img.Key);
                        });
                    }
                }
            }, result.files);

        });

    }()
);
<|endoftext|>


<commit_before>/**
 * title.js
 * State for the game title screen.
**/
'use strict';

var CONFIG = require('../config');
var STRINGS = require('../strings');
var _common = require('./_common');

var TitleState = function(){};

TitleState.prototype.preload = function() {
    _common.setGameScale(this.game);
    this.load.crossOrigin = 'anonymous';
    this.load.image('qr-code', window.qrCode);
}

TitleState.prototype.create = function() {

    this.add.sprite(0, 0, 'starfield');

    var clouds = this.add.sprite(0, 0, 'clouds');
    this.add.tween(clouds).to({ alpha: 0.5 }, 1000, Phaser.Easing.Sinusoidal.InOut, true, 0, -1).yoyo(true);

    this.add.sprite(0, 0, 'dusk-mask');
    this.add.sprite(0, 0, 'vignette');

    this.layers = [
        this.add.sprite(-400, 0, 'layer3'),
        this.add.sprite(-400, 0, 'layer2'),
        this.add.sprite(-400, 0, 'layer1')
    ];
    this.layers.forEach(function(layer) {
        this.game.physics.enable(layer, Phaser.Physics.ARCADE);
        layer.body.velocity.x = (Math.random() - 0.5) * 20;
    }, this);

    this.presentsTitle = this.add.text(this.game.world.centerX,
        50, STRINGS.titlePresents, CONFIG.font.smallStyle);
    this.presentsTitle.anchor.set(0.5);

    this.ghostTitle = this.add.sprite(400, 120, 'title-logo');
    this.ghostTitle.anchor.set(0.5);
    this.ghostTitle.alpha = 0.4;
    this.ghostTitle.tint = 0xffaacc;

    this.title = this.add.sprite(400, 120, 'title-logo');
    this.title.anchor.set(0.5);

    this.creditText = this.add.text(this.game.world.centerX,
        this.game.height - 10, STRINGS.titleCredit, CONFIG.font.smallStyle);
    this.creditText.anchor.setTo(0.5, 1);

    this.qr = this.add.sprite(250, 250, 'qr-code');
    this.qr.anchor.set(0.5);
    this.qr.scale.set(0.5);

    var style = { font: "18px VT323", fill: "#aaaaaa", wordWrap: true, wordWrapWidth: 180, align: "center" };
    this.info = this.add.text(430, 210, STRINGS.titleJoinPrompt + window.joinURL, style);

    this.socket = _common.socket;
    console.log(this.socket);
    this.socket.on('room', this.handleRoomStatus.bind(this));
    this.socket.emit('host', {
        game: window.game
    });
};

TitleState.prototype.update = function() {
    this.layers.forEach(function(layer) {
        if (layer.body.position.x < -800) {
            layer.body.velocity.x = (Math.random()) * 10;
        }
        if (layer.body.position.x >0) {
            layer.body.velocity.x = (Math.random()) * (-10);
        }
    });

    this.ghostTitle.position.x = 400 + this.game.rnd.integerInRange(-5, 5);
    this.ghostTitle.position.y = 120 + this.game.rnd.integerInRange(-5, 5);
};

TitleState.prototype.handleRoomStatus = function(data) {
    if (data.left != null && data.right != null) {
        this.state.start('PlayField');
    }
}

module.exports = TitleState;<commit_msg>Text align tweak<commit_after>/**
 * title.js
 * State for the game title screen.
**/
'use strict';

var CONFIG = require('../config');
var STRINGS = require('../strings');
var _common = require('./_common');

var TitleState = function(){};

TitleState.prototype.preload = function() {
    _common.setGameScale(this.game);
    this.load.crossOrigin = 'anonymous';
    this.load.image('qr-code', window.qrCode);
}

TitleState.prototype.create = function() {

    this.add.sprite(0, 0, 'starfield');

    var clouds = this.add.sprite(0, 0, 'clouds');
    this.add.tween(clouds).to({ alpha: 0.5 }, 1000, Phaser.Easing.Sinusoidal.InOut, true, 0, -1).yoyo(true);

    this.add.sprite(0, 0, 'dusk-mask');
    this.add.sprite(0, 0, 'vignette');

    this.layers = [
        this.add.sprite(-400, 0, 'layer3'),
        this.add.sprite(-400, 0, 'layer2'),
        this.add.sprite(-400, 0, 'layer1')
    ];
    this.layers.forEach(function(layer) {
        this.game.physics.enable(layer, Phaser.Physics.ARCADE);
        layer.body.velocity.x = (Math.random() - 0.5) * 20;
    }, this);

    this.presentsTitle = this.add.text(this.game.world.centerX,
        50, STRINGS.titlePresents, CONFIG.font.smallStyle);
    this.presentsTitle.anchor.set(0.5);

    this.ghostTitle = this.add.sprite(400, 120, 'title-logo');
    this.ghostTitle.anchor.set(0.5);
    this.ghostTitle.alpha = 0.4;
    this.ghostTitle.tint = 0xffaacc;

    this.title = this.add.sprite(400, 120, 'title-logo');
    this.title.anchor.set(0.5);

    this.creditText = this.add.text(this.game.world.centerX,
        this.game.height - 10, STRINGS.titleCredit, CONFIG.font.smallStyle);
    this.creditText.anchor.setTo(0.5, 1);

    this.qr = this.add.sprite(250, 250, 'qr-code');
    this.qr.anchor.set(0.5);
    this.qr.scale.set(0.5);

    var style = { font: "18px VT323", fill: "#aaaaaa", wordWrap: true, wordWrapWidth: 180, align: "center" };
    this.info = this.add.text(390, 210, STRINGS.titleJoinPrompt + window.joinURL, style);

    this.socket = _common.socket;
    console.log(this.socket);
    this.socket.on('room', this.handleRoomStatus.bind(this));
    this.socket.emit('host', {
        game: window.game
    });
};

TitleState.prototype.update = function() {
    this.layers.forEach(function(layer) {
        if (layer.body.position.x < -800) {
            layer.body.velocity.x = (Math.random()) * 10;
        }
        if (layer.body.position.x >0) {
            layer.body.velocity.x = (Math.random()) * (-10);
        }
    });

    this.ghostTitle.position.x = 400 + this.game.rnd.integerInRange(-5, 5);
    this.ghostTitle.position.y = 120 + this.game.rnd.integerInRange(-5, 5);
};

TitleState.prototype.handleRoomStatus = function(data) {
    if (data.left != null && data.right != null) {
        this.state.start('PlayField');
    }
}

module.exports = TitleState;<|endoftext|>


<commit_before><commit_msg>Improved aesthetics of JS addNote()<commit_after><|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var Q = require('q'),
    _ = require('busyman'),
    zclId = require('zcl-id'),
    proving = require('proving'),
    ZSC = require('zstack-constants');

var Endpoint  = require('../model/endpoint'),
    Coordpoint  = require('../model/coordpoint'),
    zutils = require('./zutils');

var controller,
    querie = {};

/*************************************************************************************************/
/*** Public APIs                                                                               ***/
/*************************************************************************************************/
querie.coordInfo = function (callback) {
    var info = controller.getNetInfo();
    return querie.device(info.ieeeAddr, info.nwkAddr, callback);
};

querie.coordState = function (callback) {
    return querie.network('DEV_STATE', callback);
};

querie.network = function (param, callback) {
    if (_.isFunction(param)) {
        callback = param;
        param = null;
    }

    if (param)
        return querie._network(param, callback);    // return value
    else
        return querie._networkAll(callback);        // return { state, channel, panId, extPanId, ieeeAddr, nwkAddr }
};

querie.device = function (ieeeAddr, nwkAddr, callback) {
    var devInfo = {
            type: null,
            ieeeAddr: ieeeAddr,
            nwkAddr: nwkAddr,
            manufId: null,
            epList: null
        };

    proving.string(ieeeAddr, 'ieeeAddr should be a string.');
    proving.number(nwkAddr, 'nwkAddr should be a number.');

    return controller.request('ZDO', 'nodeDescReq', { dstaddr: nwkAddr, nwkaddrofinterest: nwkAddr }).then(function (rsp) {
        // rsp: { srcaddr, status, nwkaddr, logicaltype_cmplxdescavai_userdescavai, ..., manufacturercode, ... }
        devInfo.type = devType(rsp.logicaltype_cmplxdescavai_userdescavai & 0x07);  // logical type: bit0-2
        devInfo.manufId = rsp.manufacturercode;
        return controller.request('ZDO', 'activeEpReq', { dstaddr: nwkAddr, nwkaddrofinterest: nwkAddr });
    }).then(function(rsp) {
        // rsp: { srcaddr, status, nwkaddr, activeepcount, activeeplist }
        devInfo.epList = bufToArray(rsp.activeeplist, 'uint8');
        return devInfo;
    }).nodeify(callback);
};

querie.endpoint = function (nwkAddr, epId, callback) {
    proving.number(nwkAddr, 'nwkAddr should be a number.');

    return controller.request('ZDO', 'simpleDescReq', { dstaddr: nwkAddr, nwkaddrofinterest: nwkAddr, endpoint: epId }).then(function (rsp) {
        // rsp: { ..., endpoint, profileid, deviceid, deviceversion, numinclusters, inclusterlist, numoutclusters, outclusterlist }
        return {
            profId: rsp.profileid || 0,
            epId: rsp.endpoint,
            devId: rsp.deviceid || 0,
            inClusterList: bufToArray(rsp.inclusterlist, 'uint16'),
            outClusterList: bufToArray(rsp.outclusterlist, 'uint16')
        };
    }).nodeify(callback);
};

querie.deviceWithEndpoints = function (nwkAddr, ieeeAddr, callback) {
    var deferred = Q.defer(),
        epQueries = [],
        fullDev;

    querie.device(ieeeAddr, nwkAddr).then(function (devInfo) {
        fullDev = devInfo;

        _.forEach(fullDev.epList, function (epId) {
            var epQuery = {func: querie.endpoint, nwkAddr: nwkAddr, epId: epId};
            epQueries.push(epQuery);
        });

		var result = Q();
		var resultArray = [];
		epQueries.forEach(function (f) {
			result = result.then(function(){
				return f.func(f.nwkAddr, f.epId).then(res => resultArray.push(res));
			});
		});
		return result.then(() => resultArray);

    }).then(function (epInfos) {
		fullDev.endpoints = epInfos;
		deferred.resolve(fullDev);
    }).fail(function (err) {
        deferred.reject(err);
    }).done();

    return deferred.promise.nodeify(callback);
};

querie.setBindingEntry = function (bindMode, srcEp, cId, dstEpOrGrpId, callback) {
    var deferred = Q.defer(),
        cIdItem = zclId.cluster(cId),
        bindParams,
        dstEp,
        grpId,
        req;

    if (!((srcEp instanceof Endpoint) || (srcEp instanceof Coordpoint)))
        throw new TypeError('srcEp should be an instance of Endpoint class.');

    proving.defined(cIdItem, 'Invalid cluster id: ' + cId + '.');

    if (_.isNumber(dstEpOrGrpId) && !_.isNaN(dstEpOrGrpId))
        grpId = dstEpOrGrpId;
    else if (dstEpOrGrpId instanceof Endpoint || dstEpOrGrpId instanceof Coordpoint)
        dstEp = dstEpOrGrpId;
    else
        throw new TypeError('dstEpOrGrpId should be an instance of Endpoint class or a number of group id.');

    bindParams = {
        dstaddr: srcEp.getNwkAddr(),
        srcaddr: srcEp.getIeeeAddr(),
        srcendpoint: srcEp.getEpId(),
        clusterid: cIdItem.value,
        dstaddrmode: dstEp ? ZSC.AF.addressMode.ADDR_64BIT : ZSC.AF.addressMode.ADDR_GROUP,
        addr_short_long: dstEp ? dstEp.getIeeeAddr() : zutils.toLongAddrString(grpId),
        dstendpoint: dstEp ? dstEp.getEpId() : 0xFF
    };

    if (bindMode === 0 || bindMode === 'bind') {
        req = function () { return controller.request('ZDO', 'bindReq', bindParams); };
    } else if (bindMode === 1 || bindMode === 'unbind') {
        req = function () { return controller.request('ZDO', 'unbindReq', bindParams); };
    }

    req().then(function (rsp) {
        deferred.resolve();
    }).fail(function (err) {
        deferred.reject(err);
    }).done();

    return deferred.promise.nodeify(callback);
};

/*************************************************************************************************/
/*** Protected Methods                                                                         ***/
/*************************************************************************************************/
querie._network = function (param, callback) {
    var prop = ZSC.SAPI.zbDeviceInfo[param];

    return Q.fcall(function () {
        if (_.isNil(prop))
            return Q.reject(new Error('Unknown network property.'));
        else
            return controller.request('SAPI', 'getDeviceInfo', { param: prop });
    }).then(function (rsp) {
        switch (param) {
            case 'DEV_STATE':
            case 'CHANNEL':
                return rsp.value.readUInt8(0);
            case 'IEEE_ADDR':
            case 'PARENT_IEEE_ADDR':
            case 'EXT_PAN_ID':
                return addrBuf2Str(rsp.value);
            case 'SHORT_ADDR':
            case 'PARENT_SHORT_ADDR':
                return rsp.value.readUInt16LE(0);
            case 'PAN_ID':
                return zutils.toHexString(rsp.value.readUInt16LE(0), 'uint16');
        }
    }).nodeify(callback);
};

querie._networkAll = function (callback) {
    var paramsInfo = [
            { param: 'DEV_STATE',  name: 'state'   }, { param: 'IEEE_ADDR',  name: 'ieeeAddr' },
            { param: 'SHORT_ADDR', name: 'nwkAddr' }, { param: 'CHANNEL',    name: 'channel'  },
            { param: 'PAN_ID',     name: 'panId'   }, { param: 'EXT_PAN_ID', name: 'extPanId' }
        ],
        net = {
            state: null,
            channel: null,
            panId: null,
            extPanId: null,
            ieeeAddr: null,
            nwkAddr: null
        },
        steps = [];

    _.forEach(paramsInfo, function (paramInfo) {
        steps.push(function (net) {
            return querie._network(paramInfo.param).then(function (value) {
                net[paramInfo.name] = value;
                return net;
            });
        });
    });

    return steps.reduce(function (soFar, fn) {
        return soFar.then(fn);
    }, Q(net)).nodeify(callback);
};

function devType(type) {
    var DEVTYPE = ZSC.ZDO.deviceLogicalType;

    switch (type) {
        case DEVTYPE.COORDINATOR:
            return 'Coordinator';
        case DEVTYPE.ROUTER:
            return 'Router';
        case DEVTYPE.ENDDEVICE:
            return 'EndDevice';
        case DEVTYPE.COMPLEX_DESC_AVAIL:
            return 'ComplexDescAvail';
        case DEVTYPE.USER_DESC_AVAIL:
            return 'UserDescAvail';
        default:
            break;
    }
}

function addrBuf2Str(buf) {
    var val,
        bufLen = buf.length,
        strChunk = '0x';

    for (var i = 0; i < bufLen; i += 1) {
        val = buf.readUInt8(bufLen - i - 1);

        if (val <= 15)
            strChunk += '0' + val.toString(16);
        else
            strChunk += val.toString(16);
    }

    return strChunk;
}

function bufToArray(buf, nip) {
    var i,
        nipArr = [];

    if (nip === 'uint8') {
        for (i = 0; i < buf.length; i += 1) {
            nipArr.push(buf.readUInt8(i));
        }
    } else if (nip === 'uint16') {
        for (i = 0; i < buf.length; i += 2) {
            nipArr.push(buf.readUInt16LE(i));
        }
    }

    return nipArr.sort(function (a, b) { return a - b; });
}

module.exports = function (cntl) {
    controller = cntl;
    return querie;
};<commit_msg>Do Cluster Queries one after another, this fixed issues with some devices<commit_after>/* jshint node: true */
'use strict';

var Q = require('q'),
    _ = require('busyman'),
    zclId = require('zcl-id'),
    proving = require('proving'),
    ZSC = require('zstack-constants');

var Endpoint  = require('../model/endpoint'),
    Coordpoint  = require('../model/coordpoint'),
    zutils = require('./zutils');

var controller,
    querie = {};

/*************************************************************************************************/
/*** Public APIs                                                                               ***/
/*************************************************************************************************/
querie.coordInfo = function (callback) {
    var info = controller.getNetInfo();
    return querie.device(info.ieeeAddr, info.nwkAddr, callback);
};

querie.coordState = function (callback) {
    return querie.network('DEV_STATE', callback);
};

querie.network = function (param, callback) {
    if (_.isFunction(param)) {
        callback = param;
        param = null;
    }

    if (param)
        return querie._network(param, callback);    // return value
    else
        return querie._networkAll(callback);        // return { state, channel, panId, extPanId, ieeeAddr, nwkAddr }
};

querie.device = function (ieeeAddr, nwkAddr, callback) {
    var devInfo = {
            type: null,
            ieeeAddr: ieeeAddr,
            nwkAddr: nwkAddr,
            manufId: null,
            epList: null
        };

    proving.string(ieeeAddr, 'ieeeAddr should be a string.');
    proving.number(nwkAddr, 'nwkAddr should be a number.');

    return controller.request('ZDO', 'nodeDescReq', { dstaddr: nwkAddr, nwkaddrofinterest: nwkAddr }).then(function (rsp) {
        // rsp: { srcaddr, status, nwkaddr, logicaltype_cmplxdescavai_userdescavai, ..., manufacturercode, ... }
        devInfo.type = devType(rsp.logicaltype_cmplxdescavai_userdescavai & 0x07);  // logical type: bit0-2
        devInfo.manufId = rsp.manufacturercode;
        return controller.request('ZDO', 'activeEpReq', { dstaddr: nwkAddr, nwkaddrofinterest: nwkAddr });
    }).then(function(rsp) {
        // rsp: { srcaddr, status, nwkaddr, activeepcount, activeeplist }
        devInfo.epList = bufToArray(rsp.activeeplist, 'uint8');
        return devInfo;
    }).nodeify(callback);
};

querie.endpoint = function (nwkAddr, epId, callback) {
    proving.number(nwkAddr, 'nwkAddr should be a number.');

    return controller.request('ZDO', 'simpleDescReq', { dstaddr: nwkAddr, nwkaddrofinterest: nwkAddr, endpoint: epId }).then(function (rsp) {
        // rsp: { ..., endpoint, profileid, deviceid, deviceversion, numinclusters, inclusterlist, numoutclusters, outclusterlist }
        return {
            profId: rsp.profileid || 0,
            epId: rsp.endpoint,
            devId: rsp.deviceid || 0,
            inClusterList: bufToArray(rsp.inclusterlist, 'uint16'),
            outClusterList: bufToArray(rsp.outclusterlist, 'uint16')
        };
    }).nodeify(callback);
};

querie.deviceWithEndpoints = function (nwkAddr, ieeeAddr, callback) {
    var deferred = Q.defer(),
        epQueries = [],
        fullDev;

    querie.device(ieeeAddr, nwkAddr).then(function (devInfo) {
        fullDev = devInfo;

        _.forEach(fullDev.epList, function (epId) {
            var epQuery = querie.endpoint(nwkAddr, epId);
            epQueries.push(epQuery);
        });

        return Q.all(epQueries);
    }).then(function (epInfos) {
        fullDev.endpoints = epInfos;
        deferred.resolve(fullDev);
    }).fail(function (err) {
        deferred.reject(err);
    }).done();

    return deferred.promise.nodeify(callback);
};

querie.setBindingEntry = function (bindMode, srcEp, cId, dstEpOrGrpId, callback) {
    var deferred = Q.defer(),
        cIdItem = zclId.cluster(cId),
        bindParams,
        dstEp,
        grpId,
        req;

    if (!((srcEp instanceof Endpoint) || (srcEp instanceof Coordpoint)))
        throw new TypeError('srcEp should be an instance of Endpoint class.');

    proving.defined(cIdItem, 'Invalid cluster id: ' + cId + '.');

    if (_.isNumber(dstEpOrGrpId) && !_.isNaN(dstEpOrGrpId))
        grpId = dstEpOrGrpId;
    else if (dstEpOrGrpId instanceof Endpoint || dstEpOrGrpId instanceof Coordpoint)
        dstEp = dstEpOrGrpId;
    else
        throw new TypeError('dstEpOrGrpId should be an instance of Endpoint class or a number of group id.');

    bindParams = {
        dstaddr: srcEp.getNwkAddr(),
        srcaddr: srcEp.getIeeeAddr(),
        srcendpoint: srcEp.getEpId(),
        clusterid: cIdItem.value,
        dstaddrmode: dstEp ? ZSC.AF.addressMode.ADDR_64BIT : ZSC.AF.addressMode.ADDR_GROUP,
        addr_short_long: dstEp ? dstEp.getIeeeAddr() : zutils.toLongAddrString(grpId),
        dstendpoint: dstEp ? dstEp.getEpId() : 0xFF
    };

    if (bindMode === 0 || bindMode === 'bind') {
        req = function () { return controller.request('ZDO', 'bindReq', bindParams); };
    } else if (bindMode === 1 || bindMode === 'unbind') {
        req = function () { return controller.request('ZDO', 'unbindReq', bindParams); };
    }

    req().then(function (rsp) {
        deferred.resolve();
    }).fail(function (err) {
        deferred.reject(err);
    }).done();

    return deferred.promise.nodeify(callback);
};

/*************************************************************************************************/
/*** Protected Methods                                                                         ***/
/*************************************************************************************************/
querie._network = function (param, callback) {
    var prop = ZSC.SAPI.zbDeviceInfo[param];

    return Q.fcall(function () {
        if (_.isNil(prop))
            return Q.reject(new Error('Unknown network property.'));
        else
            return controller.request('SAPI', 'getDeviceInfo', { param: prop });
    }).then(function (rsp) {
        switch (param) {
            case 'DEV_STATE':
            case 'CHANNEL':
                return rsp.value.readUInt8(0);
            case 'IEEE_ADDR':
            case 'PARENT_IEEE_ADDR':
            case 'EXT_PAN_ID':
                return addrBuf2Str(rsp.value);
            case 'SHORT_ADDR':
            case 'PARENT_SHORT_ADDR':
                return rsp.value.readUInt16LE(0);
            case 'PAN_ID':
                return zutils.toHexString(rsp.value.readUInt16LE(0), 'uint16');
        }
    }).nodeify(callback);
};

querie._networkAll = function (callback) {
    var paramsInfo = [
            { param: 'DEV_STATE',  name: 'state'   }, { param: 'IEEE_ADDR',  name: 'ieeeAddr' },
            { param: 'SHORT_ADDR', name: 'nwkAddr' }, { param: 'CHANNEL',    name: 'channel'  },
            { param: 'PAN_ID',     name: 'panId'   }, { param: 'EXT_PAN_ID', name: 'extPanId' }
        ],
        net = {
            state: null,
            channel: null,
            panId: null,
            extPanId: null,
            ieeeAddr: null,
            nwkAddr: null
        },
        steps = [];

    _.forEach(paramsInfo, function (paramInfo) {
        steps.push(function (net) {
            return querie._network(paramInfo.param).then(function (value) {
                net[paramInfo.name] = value;
                return net;
            });
        });
    });

    return steps.reduce(function (soFar, fn) {
        return soFar.then(fn);
    }, Q(net)).nodeify(callback);
};

function devType(type) {
    var DEVTYPE = ZSC.ZDO.deviceLogicalType;

    switch (type) {
        case DEVTYPE.COORDINATOR:
            return 'Coordinator';
        case DEVTYPE.ROUTER:
            return 'Router';
        case DEVTYPE.ENDDEVICE:
            return 'EndDevice';
        case DEVTYPE.COMPLEX_DESC_AVAIL:
            return 'ComplexDescAvail';
        case DEVTYPE.USER_DESC_AVAIL:
            return 'UserDescAvail';
        default:
            break;
    }
}

function addrBuf2Str(buf) {
    var val,
        bufLen = buf.length,
        strChunk = '0x';

    for (var i = 0; i < bufLen; i += 1) {
        val = buf.readUInt8(bufLen - i - 1);

        if (val <= 15)
            strChunk += '0' + val.toString(16);
        else
            strChunk += val.toString(16);
    }

    return strChunk;
}

function bufToArray(buf, nip) {
    var i,
        nipArr = [];

    if (nip === 'uint8') {
        for (i = 0; i < buf.length; i += 1) {
            nipArr.push(buf.readUInt8(i));
        }
    } else if (nip === 'uint16') {
        for (i = 0; i < buf.length; i += 2) {
            nipArr.push(buf.readUInt16LE(i));
        }
    }

    return nipArr.sort(function (a, b) { return a - b; });
}

module.exports = function (cntl) {
    controller = cntl;
    return querie;
};
<|endoftext|>


<commit_before>"use strict"

define(['jquery', 'Bacon', 'consts', 'rz_bus', 'rz_core', 'textanalysis', 'view/completer', 'util'],
function($,        Bacon,   consts,   rz_bus,   rz_core,   textanalysis,        completer,   util) {

var text = "", // Last text of sentence
    element_name = '#textanalyser',
    element = $(element_name),
    element_raw = element[0],
    plus_button = $('#btn_add'),
    description = consts.description;

function get_svg__body_position(node_id)
{
    var item = document.getElementById(node_id),
        matrix = item.getScreenCTM();
    return {x: matrix.e, y: matrix.f};
}

var typeselection = function TypeSelectionDialog() {
    var e = $('.typeselection'),
        e_intro = e.find('#intro'),
        e_label = e.find('#chosentypelabel'),
        e_name = e.find('#chosentypename'),
        e_desc = e.find('#chosentypedesc'),
        typeselection = {};

    typeselection.analysisNodeStart = function(node_id) {
        typeselection.show(node_id);
    }
    function set_position(node_id)
    {
        var x,
            y,
            node_location;

        node_location = get_svg__body_position(node_id);
        x = node_location.x;
        y = node_location.y + 10;
        e.css({
            left: x,
            top: y,
        });
    }
    typeselection.show = function(node_id) {
        set_position(node_id);
        e_label.hide();
        e_desc.hide();
        e_intro.show();
        e.show();
    }
    typeselection.hide = function() {
        e.hide();
    }
    typeselection.showChosenType = function(node_id, nodetype) {
        var desc = description[nodetype];

        set_position(node_id);
        e_intro.hide();
        e_label.show();
        e_name.html(nodetype);
        if (desc) {
            e_desc.html(description[nodetype]);
            e_desc.show();
        } else {
            e_desc.hide();
        }
    }
    return typeselection;
}();

var analysisCompleter = completer(element, $('#input-suggestion'), {hideOnTab: false});

function analyzeSentence(spec)
{
    util.assert(spec.sentence !== undefined &&
                spec.finalize !== undefined,
                "bad input");

    var sentence = spec.sentence,
        finalize = spec.finalize,
        ret = textanalysis.textAnalyser(spec),
        lastnode;

    ret.applyToGraph({
        main_graph: rz_core.main_graph,
        edit_graph: rz_core.edit_graph,
        backend_commit: rz_config.backend_enabled,
    });

    switch (ret.state) {
    case textanalysis.ANALYSIS_NODE_START:
        lastnode = textanalysis.lastnode(rz_core.edit_graph, element_raw.selectionStart);
        if (lastnode !== null) {
            typeselection.analysisNodeStart(lastnode.id);
        }
        break;
    case textanalysis.ANALYSIS_LINK:
        typeselection.hide();
        break;
    }

    if (finalize || sentence.length == 0) {
        typeselection.hide();
    }
}

function textSelect(inp, s, e) {
    e = e || s;
    if (inp.createTextRange) {
        var r = inp.createTextRange();
        r.collapse(true);
        r.moveEnd('character', e);
        r.moveStart('character', s);
        r.select();
    } else if (inp.setSelectionRange) {
        inp.focus();
        inp.setSelectionRange(s, e);
    }
}

function changeType(arg) {
    var lastnode = textanalysis.lastnode(rz_core.edit_graph, element_raw.selectionStart),
        nodetype,
        id,
        name;

    if (!lastnode) {
        name = id = consts.NEW_NODE_NAME;
    } else {
        id = lastnode.id;
        name = lastnode.name;
    }
    nodetype = (arg === 'up'? textanalysis.selected_type_next() : textanalysis.selected_type_prev());

    rz_core.edit_graph.editType(id, nodetype);
    typeselection.showChosenType(id, nodetype);
    textanalysis.set_type(name, nodetype);
}

return {
    analyzeSentence: analyzeSentence,
    main:function () {
        if (element.length != 1) {
            return;
        }

        analysisCompleter.options.plug(textanalysis.suggestions_options);

        var document_keydown = new Bacon.Bus();
        rz_bus.ui_key.plug(document_keydown);

        element.keydown(function(e) {
            var ret = undefined;

            switch (e.keyCode) {
            case 13:
                if (!analysisCompleter.handleEnter()) {
                    submitNewSentence();
                } else {
                    analyzeSentence({
                        sentence: element.val(),
                        finalize: false,
                    });
                }
                ret = false;
                break;
            case 9: //TAB
                if (textanalysis.lastnode(rz_core.edit_graph, element_raw.selectionStart)) {
                    e.preventDefault();
                    changeType(e.shiftKey ? "up" : "down");
                    ret = false;
                }
                break;
            }
            document_keydown.push({where: consts.KEYSTROKE_WHERE_TEXTANALYSIS, keys: [e.keyCode]});
            return ret;
        });
        element.bind('input selectionchange click', function(e) {
            analysisCompleter.oninput(element_raw.value, element_raw.selectionStart);
            e.stopPropagation();
            e.preventDefault();
        });

        function submitNewSentence() {
            text = element.val();
            element.val("");
            analyzeSentence({
                sentence: text,
                finalize: true,
                });
            text = "";
        }

        // Click is required to prevent the default action - this is a form so that's a post,
        // and away we go.
        // The mousedown is required because CSS3 transitions eat some events sometimes. This is
        // the closest I've come to an explanation:
        //   http://stackoverflow.com/questions/15786891/browser-sometimes-ignores-a-jquery-click-event-during-a-css3-transform
        plus_button.bind("click mousedown", function(e) {
            console.dir(e);
            submitNewSentence();
            e.preventDefault();
        });

        var input = new Bacon.Bus();
        rz_bus.ui_input.plug(input);
        if ('oninput' in document.documentElement) {
            element.on('input', function(e) {
                text = element.val();
                analyzeSentence({
                    sentence: text,
                    finalize: false,
                });
                input.push({where: consts.INPUT_WHERE_TEXTANALYSIS, input: text});
            });
        } else {
            console.log('textanalysis.ui: fallback to polling');
            window.setInterval(function() {
                if (element.val() != text) {
                    if (text.length * 8 > 500) {
                        element.css('width', text.length * 8 + 20);
                    }
                    // text changed
                    text = element.val();
                    analyzeSentence(text, false);
                    suggestionChange = false;
                }
            }, 50);
        }
    }
};
}); // define
<commit_msg>client/textanalysis.ui: move main to it's own top level function<commit_after>"use strict"

define(['jquery', 'Bacon', 'consts', 'rz_bus', 'rz_core', 'textanalysis', 'view/completer', 'util'],
function($,        Bacon,   consts,   rz_bus,   rz_core,   textanalysis,        completer,   util) {

var text = "", // Last text of sentence
    element_name = '#textanalyser',
    element = $(element_name),
    element_raw = element[0],
    plus_button = $('#btn_add'),
    description = consts.description,
    input = new Bacon.Bus();

function get_svg__body_position(node_id)
{
    var item = document.getElementById(node_id),
        matrix = item.getScreenCTM();
    return {x: matrix.e, y: matrix.f};
}

var typeselection = function TypeSelectionDialog() {
    var e = $('.typeselection'),
        e_intro = e.find('#intro'),
        e_label = e.find('#chosentypelabel'),
        e_name = e.find('#chosentypename'),
        e_desc = e.find('#chosentypedesc'),
        typeselection = {};

    typeselection.analysisNodeStart = function(node_id) {
        typeselection.show(node_id);
    }
    function set_position(node_id)
    {
        var x,
            y,
            node_location;

        node_location = get_svg__body_position(node_id);
        x = node_location.x;
        y = node_location.y + 10;
        e.css({
            left: x,
            top: y,
        });
    }
    typeselection.show = function(node_id) {
        set_position(node_id);
        e_label.hide();
        e_desc.hide();
        e_intro.show();
        e.show();
    }
    typeselection.hide = function() {
        e.hide();
    }
    typeselection.showChosenType = function(node_id, nodetype) {
        var desc = description[nodetype];

        set_position(node_id);
        e_intro.hide();
        e_label.show();
        e_name.html(nodetype);
        if (desc) {
            e_desc.html(description[nodetype]);
            e_desc.show();
        } else {
            e_desc.hide();
        }
    }
    return typeselection;
}();

var analysisCompleter = completer(element, $('#input-suggestion'), {hideOnTab: false});

function analyzeSentence(spec)
{
    util.assert(spec.sentence !== undefined &&
                spec.finalize !== undefined,
                "bad input");

    var sentence = spec.sentence,
        finalize = spec.finalize,
        ret = textanalysis.textAnalyser(spec),
        lastnode;

    ret.applyToGraph({
        main_graph: rz_core.main_graph,
        edit_graph: rz_core.edit_graph,
        backend_commit: rz_config.backend_enabled,
    });

    switch (ret.state) {
    case textanalysis.ANALYSIS_NODE_START:
        lastnode = textanalysis.lastnode(rz_core.edit_graph, element_raw.selectionStart);
        if (lastnode !== null) {
            typeselection.analysisNodeStart(lastnode.id);
        }
        break;
    case textanalysis.ANALYSIS_LINK:
        typeselection.hide();
        break;
    }

    if (finalize || sentence.length == 0) {
        typeselection.hide();
    }
}

function textSelect(inp, s, e) {
    e = e || s;
    if (inp.createTextRange) {
        var r = inp.createTextRange();
        r.collapse(true);
        r.moveEnd('character', e);
        r.moveStart('character', s);
        r.select();
    } else if (inp.setSelectionRange) {
        inp.focus();
        inp.setSelectionRange(s, e);
    }
}

function changeType(arg) {
    var lastnode = textanalysis.lastnode(rz_core.edit_graph, element_raw.selectionStart),
        nodetype,
        id,
        name;

    if (!lastnode) {
        name = id = consts.NEW_NODE_NAME;
    } else {
        id = lastnode.id;
        name = lastnode.name;
    }
    nodetype = (arg === 'up'? textanalysis.selected_type_next() : textanalysis.selected_type_prev());

    rz_core.edit_graph.editType(id, nodetype);
    typeselection.showChosenType(id, nodetype);
    textanalysis.set_type(name, nodetype);
}

var main = function ()
{
    if (element.length != 1) {
        return;
    }

    analysisCompleter.options.plug(textanalysis.suggestions_options);

    var document_keydown = new Bacon.Bus();
    rz_bus.ui_key.plug(document_keydown);

    element.keydown(function(e) {
        var ret = undefined;

        switch (e.keyCode) {
        case 13:
            if (!analysisCompleter.handleEnter()) {
                submitNewSentence();
            } else {
                analyzeSentence({
                    sentence: element.val(),
                    finalize: false,
                });
            }
            ret = false;
            break;
        case 9: //TAB
            if (textanalysis.lastnode(rz_core.edit_graph, element_raw.selectionStart)) {
                e.preventDefault();
                changeType(e.shiftKey ? "up" : "down");
                ret = false;
            }
            break;
        }
        document_keydown.push({where: consts.KEYSTROKE_WHERE_TEXTANALYSIS, keys: [e.keyCode]});
        return ret;
    });
    element.bind('input selectionchange click', function(e) {
        analysisCompleter.oninput(element_raw.value, element_raw.selectionStart);
        e.stopPropagation();
        e.preventDefault();
    });

    function submitNewSentence() {
        text = element.val();
        element.val("");
        analyzeSentence({
            sentence: text,
            finalize: true,
            });
        text = "";
    }

    // Click is required to prevent the default action - this is a form so that's a post,
    // and away we go.
    // The mousedown is required because CSS3 transitions eat some events sometimes. This is
    // the closest I've come to an explanation:
    //   http://stackoverflow.com/questions/15786891/browser-sometimes-ignores-a-jquery-click-event-during-a-css3-transform
    plus_button.bind("click mousedown", function(e) {
        console.dir(e);
        submitNewSentence();
        e.preventDefault();
    });

    rz_bus.ui_input.plug(input);
    if ('oninput' in document.documentElement) {
        element.on('input', function(e) {
            analyze_element_text();
        });
    } else {
        console.log('textanalysis.ui: fallback to polling');
        window.setInterval(function() {
            analyze_element_text();
        }, 50);
    }
};

var analyze_element_text = function()
{
    if (element.val() == text) {
        return;
    }
    text = element.val();
    analyzeSentence({
        sentence: text,
        finalize: false,
    });
    input.push({where: consts.INPUT_WHERE_TEXTANALYSIS, input: text});
    //stretch_input_to_text_size();
}

function stretch_input_to_text_size()
{
    console.log('text.length = ' + text.length);
    if (text.length * 8 > 500) {
        element.css('width', text.length * 8 + 20);
    }
}

return {
        analyzeSentence: analyzeSentence,
        main: main
       };
}); // define
<|endoftext|>


<commit_before><commit_msg>IL config file<commit_after><|endoftext|>


<commit_before>'use strict';

const assign = require('plover-util/lib/assign');

const Router = require('../util/router');
const RouteCache = require('../util/route-cache');

const logger = require('plover-logger')('plover:components/router');

class RouterComponent {

  /**
   * 路由
   *
   * 1. 将url处理成路由模型
   * 2. 暴露`addRoute`方法用于添加路由
   *
   * @param {PloverApplication} app  - Plover应用对象
   */
  constructor(app) {
    this.app = app;
    this.router = new Router();

    app.addMiddleware(createRouteComponent(this), 2);

    this.exports = ['addRoute'];
  }

  /**
   * 添加路由规则
   *
   * @param {String|RegExp} pattern - 匹配规则
   * @param {String} to             - 定位规则
   */
  addRoute(pattern, to) {
    this.router.add(pattern, to);
  }
}

module.exports = RouterComponent;

function createRouteComponent(self) {
  const router = self.router;
  const settings = self.app.settings;

  // 可以通过settings.disableDefaultRouter关闭默认路由规则
  const defaultRouter = settings.disableDefaultRouter ?
          null : createDefaultRouter();

  const routeCache = new RouteCache(self.app);

  return function* RouterComponentx(next) {
    // 如果有其他中间件能搞定这事就不管了
    if (this.route) {
      logger.debug('already routed: %o', this.route);
      yield* next;
      return;
    }

    const path = this.path;
    const method = this.method;
    const cacheKey = `${method} ${path}`;
    logger.debug('try route: %s', path);

    // 尝试从cache中获取，取不到再进行路由
    let route = routeCache.get(cacheKey);
    if (!route) {
      // 先走应用的自定义路由
      // 如果有默认路由，再走默认路由
      route = router.route(path, { method }) ||
          defaultRouter && defaultRouter.route(path, { method });
      if (route) {
        routeCache.set(cacheKey, route);
      }
    }

    if (route) {
      assign(route.query, this.query);
      logger.debug('route success: %o', route);
      this.route = route;
    } else {
      this.route = null;
    }

    yield* next;
  };
}

/*
 * 创建默认路由规则
 *
 * 默认支持以下url访问页面：
 * /                      访问 index:view
 * /module/action         访问 module:action
 * /module/action.html    同上
 * /module/getData.json   访问 module:getDta，期望以数据(json|jsonp)方式得到结果
 * /module                访问 index:view
 *
 * 默认路由规则的action名首字母必须为[a-zA-Z]，这样的设定是为了方便内部action的编写
 * 比如可以以 _ 开头的action不能通过url访问，却可以在模块中引用，可以方便地控制访问级别
 */
function createDefaultRouter() {
  const router = new Router();
  /* eslint-disable */
  router.add(/^\/([a-zA-Z][-\w]*?)(?:\/([a-zA-Z][-\w]*?))?(?:\.(?:html|htm|json|jsonp))?\/?$/,
      { module: '$1', action: '$2' });
  router.add(/^\/$/, { module: 'index', action: 'view' });
  /* eslint-enable */
  return router;
}

<commit_msg>fix: addRoute missing options<commit_after>'use strict';

const assign = require('plover-util/lib/assign');

const Router = require('../util/router');
const RouteCache = require('../util/route-cache');

const logger = require('plover-logger')('plover:components/router');

class RouterComponent {

  /**
   * 路由
   *
   * 1. 将url处理成路由模型
   * 2. 暴露`addRoute`方法用于添加路由
   *
   * @param {PloverApplication} app  - Plover应用对象
   */
  constructor(app) {
    this.app = app;
    this.router = new Router();

    app.addMiddleware(createRouteComponent(this), 2);

    this.exports = ['addRoute'];
  }

  /**
   * 添加路由规则
   *
   * @param {String|RegExp} pattern - 匹配规则
   * @param {String}        to      - 定位规则
   * @param {Objectd}       options - 额外的选项
   *
   * @see util/router.js
   */
  addRoute(pattern, to, options) {
    this.router.add(pattern, to, options);
  }
}

module.exports = RouterComponent;

function createRouteComponent(self) {
  const router = self.router;
  const settings = self.app.settings;

  // 可以通过settings.disableDefaultRouter关闭默认路由规则
  const defaultRouter = settings.disableDefaultRouter ?
          null : createDefaultRouter();

  const routeCache = new RouteCache(self.app);

  return function* RouterComponentx(next) {
    // 如果有其他中间件能搞定这事就不管了
    if (this.route) {
      logger.debug('already routed: %o', this.route);
      yield* next;
      return;
    }

    const path = this.path;
    const method = this.method;
    const cacheKey = `${method} ${path}`;
    logger.debug('try route: %s', path);

    // 尝试从cache中获取，取不到再进行路由
    let route = routeCache.get(cacheKey);
    if (!route) {
      // 先走应用的自定义路由
      // 如果有默认路由，再走默认路由
      route = router.route(path, { method }) ||
          defaultRouter && defaultRouter.route(path, { method });
      if (route) {
        routeCache.set(cacheKey, route);
      }
    }

    if (route) {
      assign(route.query, this.query);
      logger.debug('route success: %o', route);
      this.route = route;
    } else {
      this.route = null;
    }

    yield* next;
  };
}

/*
 * 创建默认路由规则
 *
 * 默认支持以下url访问页面：
 * /                      访问 index:view
 * /module/action         访问 module:action
 * /module/action.html    同上
 * /module/getData.json   访问 module:getDta，期望以数据(json|jsonp)方式得到结果
 * /module                访问 index:view
 *
 * 默认路由规则的action名首字母必须为[a-zA-Z]，这样的设定是为了方便内部action的编写
 * 比如可以以 _ 开头的action不能通过url访问，却可以在模块中引用，可以方便地控制访问级别
 */
function createDefaultRouter() {
  const router = new Router();
  /* eslint-disable */
  router.add(/^\/([a-zA-Z][-\w]*?)(?:\/([a-zA-Z][-\w]*?))?(?:\.(?:html|htm|json|jsonp))?\/?$/,
      { module: '$1', action: '$2' });
  router.add(/^\/$/, { module: 'index', action: 'view' });
  /* eslint-enable */
  return router;
}

<|endoftext|>


<commit_before>import _ from 'lodash'
import logger from 'winston'
import P from 'bluebird'
import config from 'config'
import fetch from 'node-fetch'
import querystring from 'querystring'
import { firebase } from '../../firebase'
import graphData from '../../graph/data'
import processMap from '../process-map'
import users from '../../store/users'

const db = firebase.database().ref()

module.exports = ({ data, resolve, reject }) => {
  const { from, to, latitude, longitude, timestamp } = data

  return P.coroutine(function* setConnection() {

    const qs = querystring.stringify({
      lat: latitude,
      lng: longitude,
      username: config.geonames.username,
      cities: 'cities15000',
    })

    const locationData = yield fetch(`http://api.geonames.org/findNearbyPlaceNameJSON?${qs}`)
      .then(res => res.json())
      .then(data => _.get(data, 'geonames.0', {}))

    const { adminCode1, adminName1, name, countryName } = locationData

    // Use the state abbreviation if we're in the United States
    const state = countryName === 'United States' ? adminCode1 : adminName1

    const connectionKey = [from, to].join('::::')
    const connection = {
      from,
      latitude,
      longitude,
      timestamp,
      to,
      city: name,
      country: countryName,
      state: state || '',
    }

    // Set the connection entry
    yield db.child(`connections/${connectionKey}`).set(connection)

    // Set the connection and set hasAccess true on both user objects
    const fromUpdate = {
      [`connections/${to}`]: timestamp,
      hasAccess: true,
    }

    const toUpdate = {
      [`connections/${from}`]: timestamp,
      hasAccess: true,
      from,
    }

    yield P.props({
      to: db.child(`users/${from}`).update(fromUpdate),
      from: db.child(`users/${to}`).update(toUpdate),
    })

    // Update the internal graph
    graphData.setConnection(connection)

    // Update the map representation
    yield processMap()

  })().then(resolve).catch((err) => {
    logger.error(err)

    const message = {
      type: 'CONNECTION_FAILED',
      timestamp: Date.now(),
    }

    // Set the failed messages to both connecting users
    return P.props({
      to: db.child(`messages/${to}/${from}`).set(message),
      from: db.child(`messages/${from}/${to}`).set(message),
    }).then(() => {
      return reject(err)
    })
  })
  .finally(() => {
    // Remove the beacons
    return P.props({
      removeBeaconFrom: db.child(`beacons/${from}`).set(null),
      removeBeaconLocationFrom: db.child(`beaconLocations/${from}`).set(null),
      removeBeaconTo: db.child(`beacons/${to}`).set(null),
      removeBeaconLocationTo: db.child(`beaconLocations/${to}`).set(null),
    })
  })
}
<commit_msg>Fix linting<commit_after>import _ from 'lodash'
import logger from 'winston'
import P from 'bluebird'
import config from 'config'
import fetch from 'node-fetch'
import querystring from 'querystring'
import { firebase } from '../../firebase'
import graphData from '../../graph/data'
import processMap from '../process-map'

const db = firebase.database().ref()

module.exports = ({ data, resolve, reject }) => {
  const { from, to, latitude, longitude, timestamp } = data

  return P.coroutine(function* setConnection() {

    const qs = querystring.stringify({
      lat: latitude,
      lng: longitude,
      username: config.geonames.username,
      cities: 'cities15000',
    })

    const locationData = yield fetch(`http://api.geonames.org/findNearbyPlaceNameJSON?${qs}`)
      .then(res => res.json())
      .then(data => _.get(data, 'geonames.0', {}))

    const { adminCode1, adminName1, name, countryName } = locationData

    // Use the state abbreviation if we're in the United States
    const state = countryName === 'United States' ? adminCode1 : adminName1

    const connectionKey = [from, to].join('::::')
    const connection = {
      from,
      latitude,
      longitude,
      timestamp,
      to,
      city: name,
      country: countryName,
      state: state || '',
    }

    // Set the connection entry
    yield db.child(`connections/${connectionKey}`).set(connection)

    // Set the connection and set hasAccess true on both user objects
    const fromUpdate = {
      [`connections/${to}`]: timestamp,
      hasAccess: true,
    }

    const toUpdate = {
      [`connections/${from}`]: timestamp,
      hasAccess: true,
      from,
    }

    yield P.props({
      to: db.child(`users/${from}`).update(fromUpdate),
      from: db.child(`users/${to}`).update(toUpdate),
    })

    // Update the internal graph
    graphData.setConnection(connection)

    // Update the map representation
    yield processMap()

  })().then(resolve).catch((err) => {
    logger.error(err)

    const message = {
      type: 'CONNECTION_FAILED',
      timestamp: Date.now(),
    }

    // Set the failed messages to both connecting users
    return P.props({
      to: db.child(`messages/${to}/${from}`).set(message),
      from: db.child(`messages/${from}/${to}`).set(message),
    }).then(() => {
      return reject(err)
    })
  })
  .finally(() => {
    // Remove the beacons
    return P.props({
      removeBeaconFrom: db.child(`beacons/${from}`).set(null),
      removeBeaconLocationFrom: db.child(`beaconLocations/${from}`).set(null),
      removeBeaconTo: db.child(`beacons/${to}`).set(null),
      removeBeaconLocationTo: db.child(`beaconLocations/${to}`).set(null),
    })
  })
}
<|endoftext|>


<commit_before>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function (uid_day, uid_offering, callback) {
 	var numStud = 0;
 	con.query('SELECT COUNT(*) AS count FROM choices WHERE uid_offering = ? AND uid_day = ?', [uid_offering, uid_day], function(err, students) {
 		if(!err) {
	 		callback(students[0].count);
 		} else {
 			console.error("Cannot count students in offering.");
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, max_size, callback) {
    //	Gets the number of students in an offering
    module.exports.numStudents(uid_day, uid_offering, function(numStud) {
        //	Compares that number to the offering's maximum size
        //	CHANGE
        console.log((numStud >= max_size));
        if(numStud >= max_size) {
          callback(true);
        } else {
          callback(false);
        }
    });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list of Offering objects including a property for avalialability ('.disbaled')
 getOfferings: function (uid_day, callback) {
 	//	Join query to find a list of offerings on a certain day with the name of their teacher
 	con.query('SELECT * from offerings JOIN calendar on offerings.uid_offering = calendar.uid_offering JOIN teachers on teachers.uid_teacher = offerings.uid_teacher WHERE calendar.uid_day = ?', [uid_day], function(err, result) {
		//	Makes sure the join query didn't error or produce an empty set
		if (!err && result != undefined) {

			//	Loops through every offering to find whether or not it is full
			var j = 0;
		    for(var i = 0; i < result.length; i++) {
		      //	Uses isOfferingFull for every one, which will return either 'disabled' or 'able'
		      module.exports.isOfferingFull(uid_day, result[i].uid_offering, result[i].max_size, function(truth) {
				  //	Adds the availability of the offering as a property
				  result[j].disabled = truth;
				  j+=1;
				  //	Calls back the list once all the queries have run
				  if (j==result.length) {
					callback(result);
				  }
		      });
		    }
		} else {
			console.log("We're sorry. A join query produced an error and or an empty set.");
		}
	});
 },

 //	A middleware to get the uid and date of the next OppBlock
 nextOppblockDay: function(req, res, next) {
 	// Gets all Oppblock days
	con.query('SELECT * FROM opp_block_day ORDER BY day DESC', function(err, results){
		if(!err){
			var closest;
			var uid_day;
			//	Loops to find soonest Oppblock
			for (var i=0; i<results.length; i++) {
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and replaces it as the closest if so
				if (curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}
			//	Leaves the uid_day and moment date object in req.student for use by future middlewares
			req.student.uid_day = uid_day;
			req.student.day = closest;

			return next();
		} else {
			console.log("An error done occured.");
			res.render('error.html', {err:err});
		}
	});
 },

 //	A middleware
 isStudentExcluded: function(req, res, next) {

 },

 //	A middleware
 isStudentTime: function(req, res, next) {
 	// 	Creates Cutoff time variables relative to closest oppblock, based on admin settings
			var studentCutoff = moment(closest.add({hours:settings["hours_close_student"].value_int}));
			var teacherCutoff = moment(closest.add({hours:settings["hours_close_teacher"].value_int}));

			//	Checks to see whether the date is before or after the student and teacher cutoff times
			if (moment().isSameOrAfter(teacherCutoff)) {
				if (moment().isSameOrAfter(studentCutoff)) {
					callback(uid_day, true);
				} else {
					callback(uid_day, false);
				}
			} else {
				callback(null, null);
			}
 },

 //	A middleware
 isValidChoice: function(req, res, next) {

 },

 //	A middleware to determine whether an offering is full or not
 //	Used in the post request to make sure students don't sign up for closed offerings
 isOpenOffering: function(req,res,next){
 	con.query('SELECT max_size FROM offerings WHERE uid_offering = ?', [req.body.choice], function(err, result) {
 		if(!err && result != undefined && result.length != 0) {
 			//	Checks if the offering is full
		 	module.exports.isOfferingFull(req.body.uid_day, req.body.choice, result[0].max_size, function(truth) {
		 		if(truth == "able") {
		 			//	Keeps going if the offering is open
			 		return next();
			    } else {
			    	//	Redirects to student if the offering is full, thereby cancelling the student's form submission
			    	res.redirect('/student');
			 	}
		 	});
 		} else {
 			//	Renders an error page if one occured
			res.render('error.html', {err:err});
 		}
 	});
 },

 init: function(app) {
	app.get('/student', middleware.isStudent, function(req, res){
		// Gets Student's id from middleware
		var student = req.user.local[0];
		var uid_student = student.uid_student;

		// This query gets the student's first name for the display page, thereby checking whether the url contained a valid uid
		// This function finds the upcoming oppblock, whether it is time for students to choose, and whether it is past the cutoff time
		module.exports.getSoonestOppblockDay(function(uid_day, cutOff) {
		// Checks whether it is time for students to choose yet
			if (uid_day == null) {
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
			} else {
				// Knowing there is an upcoming oppblock day with choices, the system queries to find the student's current choice
				con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, currentChoice) { // only gets the uid not the name
					if(!err) {
						// Checks if the student is in the choice table at all, thereby seeing if he/she is excluded from the oppblock day
						if(currentChoice.length != 0) {
							//	Checks to see if the student hasn't chosen yet
							if (currentChoice[0].uid_offering == null) {
								// Checks to see if it is past the cutoff time for the students to choose
								if (cutOff) {
									// Renders the page with an admin's message for the student, as they have neglected to sign up.
									res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
								} else {
									// Gets all offerings for the user to choose from
									module.exports.getOfferings(uid_day, function(offerings) {
										// At last, renders the page with the lack of choice, and the choices table
										res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
									});
								}
							} else {
								//	Knowing the student has chosen, it gets the name of their choice
								con.query('SELECT * FROM offerings WHERE uid_offering = ?', [currentChoice[0].uid_offering], function(err, choice) {
									if(!err) {
										// Checks to see if it is past the cutoff time for the students to choose
										if (cutOff) {
											// Renders the page only with the user's current choice
											res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"The time for choosing has passed. At 2:45, head to " + choice[0].location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
										} else {
											// Gets all offerings for the user to choose from
											module.exports.getOfferings(uid_day, function(offerings) {
												// At last, renders the page with the current choice, and the choices table
												res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
											});
										}
									} else {
										res.render('error.html', {err:err});
									}
								});
							}
						} else {
							// Renders the page without any choices, since the student is excluded
							res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
						}
					} else {
						console.log("An error done occured.");
						res.render('error.html', {err:err});
					}
				});
			}
		});
	});

	//	The student post request serves to insert/update a student's choice in the database
	app.post('/student', middleware.isStudent, module.exports.isOpenOffering, function(req, res) {
		// Gets the student's uid, the uid of their offering of choice, and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_offering = req.body.choice;
		var uid_day = req.body.uid_day;

		// Makes sure the student has chosen something
		if(uid_offering != undefined) {
			// Updates their choice in the database
			con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [uid_offering, uid_student, uid_day], function(err, results) {
				if(!err) {
					//	Redirects back once the update has been carried out
					res.redirect('/student');
				} else {
					//	Renders an error page if one occured
					res.render('error.html', {err:err});
				}
			});
		} else {
			//	Redirects back if the student hasn't chosen anything
			res.redirect('/student');
		}

	});

	//	This post request is for when students are excluded wrongfully from an OppBlock Day
	app.post('/studentOverride', middleware.isStudent, function(req, res) {
		// Gets the student's uid and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_day = req.body.uid_day;

		// Overrides an excluded group by adding the student into the choice table
		con.query('INSERT INTO choices (uid_student, uid_day) values (?, ?)', [uid_student, uid_day], function(err) {
			if(!err) {
				//	Redirects back since the request has been carried out
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});
	return this;
 }
}
<commit_msg>Wrote Untested IsValidChoice Middleware; Added All Relevant Middlewares to Their Endpoints<commit_after>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function (uid_day, uid_offering, callback) {
 	var numStud = 0;
 	con.query('SELECT COUNT(*) AS count FROM choices WHERE uid_offering = ? AND uid_day = ?', [uid_offering, uid_day], function(err, students) {
 		if(!err) {
	 		callback(students[0].count);
 		} else {
 			console.error("Cannot count students in offering.");
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, max_size, callback) {
    //	Gets the number of students in an offering
    module.exports.numStudents(uid_day, uid_offering, function(numStud) {
        //	Compares that number to the offering's maximum size
        //	CHANGE
        console.log((numStud >= max_size));
        if(numStud >= max_size) {
          callback(true);
        } else {
          callback(false);
        }
    });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list of Offering objects including a property for avalialability ('.disbaled')
 getOfferings: function (uid_day, callback) {
 	//	Join query to find a list of offerings on a certain day with the name of their teacher
 	con.query('SELECT * from offerings JOIN calendar on offerings.uid_offering = calendar.uid_offering JOIN teachers on teachers.uid_teacher = offerings.uid_teacher WHERE calendar.uid_day = ?', [uid_day], function(err, result) {
		//	Makes sure the join query didn't error or produce an empty set
		if (!err && result != undefined) {

			//	Loops through every offering to find whether or not it is full
			var j = 0;
		    for(var i = 0; i < result.length; i++) {
		      //	Checks if every offering is full or not
		      module.exports.isOfferingFull(uid_day, result[i].uid_offering, result[i].max_size, function(truth) {
				  //	Adds the availability of the offering as a property
				  if(truth) {
				  	truth = "disabled";
				  } else {
				  	truth = "able";
				  }
				  result[j].disabled = truth;
				  j+=1;

				  //	Calls back the list once all the queries have run
				  if (j==result.length) {
					callback(result);
				  }
		      });
		    }
		} else {
			console.log("We're sorry. A join query produced an error and or an empty set.");
		}
	});
 },

 //	A middleware to get the uid and date of the next OppBlock for future use
 nextOppblockDay: function(req, res, next) {
 	// Gets all Oppblock days
	con.query('SELECT * FROM opp_block_day ORDER BY day DESC', function(err, results){
		if(!err){
			var closest;
			var uid_day;
			//	Loops to find soonest Oppblock
			for (var i=0; i<results.length; i++) {
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and replaces it as the closest if so
				if (curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}
			//	Leaves the uid_day and moment date object in req.student for use by future middlewares
			req.student.uid_day = uid_day;
			req.student.day = closest;

			return next();
		} else {
			//	Renders an error page if one occured
			res.render('error.html', {err:err});
		}
	});
 },

 //	A middleware checking if the student exists in the choices table; saves his/her choice for future use if so; otherwise renders the excluded student page
 isStudentExcluded: function(req, res, next) {
 	//	Gets student/day from req object
	var uid_student = req.user.local[0].uid_student;
 	var uid_day = req.student.uid_day;

 	con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, choice) { // only gets the uid not the name
 		if(!err) {
 			if (choice.length != 0) {
 				//	Leaves the choice in req.student for use by future middlewares
 				req.student.choice = choice[0].uid_offering;

 				return next();
 			} else {
 				// Renders the page without any choices, since the student is excluded
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
 			}
 		} else {
 			//	Renders an error page if one occured
			res.render('error.html', {err:err});
 		}
 	});
 },

 //	A middleware
 isStudentTime: function(req, res, next) {
 	/* 	Creates Cutoff time variables relative to closest oppblock, based on admin settings
			var studentCutoff = moment(closest.add({hours:settings["hours_close_student"].value_int}));
			var teacherCutoff = moment(closest.add({hours:settings["hours_close_teacher"].value_int}));

			//	Checks to see whether the date is before or after the student and teacher cutoff times
			if (moment().isSameOrAfter(teacherCutoff)) {
				if (moment().isSameOrAfter(studentCutoff)) {
					callback(uid_day, true);
				} else {
					callback(uid_day, false);
				}
			} else {
				callback(null, null);
			}
			*/
	return next();
 },

 //	A middleware to determine whether a choice is valid (a real offering, existing on the current day, that's not yet full)
 isValidChoice: function(req, res, next) {
 	var uid_offering = req.body.choice;
	var uid_day = req.student.uid_day;

 	// Makes sure the student has actually made a choice
	if(uid_offering != undefined) {
		//	Join query checks if the offering has a valid uid and is offered on the current day
		con.query('SELECT offerings.name, offerings.max_size calendar.uid_offering FROM calendar JOIN offerings ON calendar.uid_offering = offerings.uid_offering WHERE calendar.uid_offering = ? AND calendar.uid_day = ?', [uid_offering, uid_day], function(err, resultsOffering) {
			if(!err && resultsOffering != undefined && resultsOffering.length != 0 && ) {
				//	Checks if the offering is full
				isOfferingFull(uid_day, uid_offering, resultsOffering[0].max_size, function(full) {
					if(!full) {
						return next();
					} else {
						res.render('error.html', {err:"You tried to sign up for a full offering! Go back."});
					}
				});
	 		} else {
	 			//	Renders an error page if one occured OR if the user sent a malformed post request
				res.render('error.html', {err:err});
	 		}
		});
	} else {
		res.redirect('/student');
	}
 	return next();
 },

 init: function(app) {
	app.get('/student', middleware.isStudent, module.exports.nextOppblockDay, module.exports.isStudentExcluded, module.exports.isStudentTime, function(req, res){
		// Gets Student's id from middleware
		var student = req.user.local[0];
		var uid_student = student.uid_student;

		// This query gets the student's first name for the display page, thereby checking whether the url contained a valid uid
		// This function finds the upcoming oppblock, whether it is time for students to choose, and whether it is past the cutoff time
		module.exports.getSoonestOppblockDay(function(uid_day, cutOff) {
		// Checks whether it is time for students to choose yet
			if (uid_day == null) {
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
			} else {
				// Knowing there is an upcoming oppblock day with choices, the system queries to find the student's current choice
				con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, currentChoice) { // only gets the uid not the name
					if(!err) {
						// Checks if the student is in the choice table at all, thereby seeing if he/she is excluded from the oppblock day
						if(currentChoice.length != 0) {
							//	Checks to see if the student hasn't chosen yet
							if (currentChoice[0].uid_offering == null) {
								// Checks to see if it is past the cutoff time for the students to choose
								if (cutOff) {
									// Renders the page with an admin's message for the student, as they have neglected to sign up.
									res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
								} else {
									// Gets all offerings for the user to choose from
									module.exports.getOfferings(uid_day, function(offerings) {
										// At last, renders the page with the lack of choice, and the choices table
										res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
									});
								}
							} else {
								//	Knowing the student has chosen, it gets the name of their choice
								con.query('SELECT * FROM offerings WHERE uid_offering = ?', [currentChoice[0].uid_offering], function(err, choice) {
									if(!err) {
										// Checks to see if it is past the cutoff time for the students to choose
										if (cutOff) {
											// Renders the page only with the user's current choice
											res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"The time for choosing has passed. At 2:45, head to " + choice[0].location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
										} else {
											// Gets all offerings for the user to choose from
											module.exports.getOfferings(uid_day, function(offerings) {
												// At last, renders the page with the current choice, and the choices table
												res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
											});
										}
									} else {
										res.render('error.html', {err:err});
									}
								});
							}
						} else {

						}
					} else {
						console.log("An error done occured.");
						res.render('error.html', {err:err});
					}
				});
			}
		});
	});

	//	The student post request serves to insert/update a student's choice in the database
	app.post('/student', middleware.isStudent, module.exports.nextOppblockDay, module.exports.isStudentExcluded, module.exports.isStudentTime, module.exports.isValidChoice, function(req, res) {
		// Gets the student's uid, the uid of their offering of choice, and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_offering = req.body.choice;
		var uid_day = req.student.uid_day;

		// Updates the student's choice in the database
		con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [uid_offering, uid_student, uid_day], function(err, results) {
			if(!err) {
				//	Redirects back once the update has been carried out
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});

	//	This post request is for when students are excluded wrongfully from an OppBlock Day
	app.post('/studentOverride', middleware.isStudent, module.exports.nextOppblockDay, function(req, res) {
		// Gets the student's uid and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_day = req.student.uid_day;

		// Overrides an excluded group by adding the student into the choice table
		con.query('INSERT INTO choices (uid_student, uid_day) values (?, ?)', [uid_student, uid_day], function(err) {
			if(!err) {
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});
	return this;
 }
}
<|endoftext|>


<commit_before><commit_msg>remove empty files<commit_after><|endoftext|>


<commit_before>/* @flow */

import type { Warning } from '../../../../core/remote/warnings'

module.exports = {
  tosUpdated (): Warning {
    return {
      error: 'tos_updated',
      title: 'TOS Updated',
      details: 'TOS have been updated',
      links: {
        action: 'https://manager.cozycloud.cc/cozy/tos?domain=...'
      }
    }
  },

  list (): Warning[] {
    return [this.tosUpdated()]
  }
}
<commit_msg>test/support/builders: Effectively build warnings as an Error<commit_after>/* @flow */

import type { Warning } from '../../../../core/remote/warnings'

module.exports = {
  list (): {warnings: Warning[], err: Error} {
    const warnings = [tosUpdated()]
    const err = new Error(JSON.stringify({errors: warnings}))
    // $FlowFixMe
    err.status = 402

    return {warnings, err}
  }
}

function tosUpdated (): Warning {
  return {
    error: 'tos-updated',
    title: 'TOS Updated',
    detail: 'TOS have been updated',
    links: {
      self: 'https://manager.cozycloud.cc/cozy/tos?domain=...'
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>Hide more dashboard noise that's appeared recently.<commit_after><|endoftext|>


<commit_before>/**
 * jquery.plupload.queue.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

// JSLint defined globals
/*global plupload:false, jQuery:false */

(function($) {
	var uploaders = {};

	function _(str) {
		return plupload.translate(str) || str;
	}

	function renderUI(id, target) {
		// Remove all existing non plupload items
		target.contents().each(function(i, node) {
			node = $(node);

			if (!node.is('.plupload')) {
				node.remove();
			}
		});

		target.prepend(
			'
' +
				'
' +
					'
' +
						'
' +
							'
' +
								'
' + _('Select files') + '
' +
								'
' + _('Add files to the upload queue and click the start button.') + '
' +
							'
' +
						'
' +

						'
' +
							'
' +
								'
' + _('Filename') + '
' +
								'

' +
								'
' + _('Status') + '
' +
								'
' + _('Size') + '
' +
								'

' +
							'
' +

							'

' +

							'
' +
								'
' +
									'
' +
										'' + _('Add files') + '' +
										'' + _('Start upload') + '' +
									'
' +
									'' +
								'
' +
								'

' +
								'
0%
' +
								'
0 b
' +
								'
' +
									'
' +
										'

' +
									'
' +
								'
' +
								'

' +
							'
' +
						'
' +
					'
' +
				'
' +
				'<input type="hidden" id="' + id + '_count" name="' + id + '_count" value="0" />' +
			'
'
		);
	}

	$.fn.pluploadQueue = function(settings) {
		if (settings) {
			this.each(function() {
				var uploader, target, id;

				target = $(this);
				id = target.attr('id');

				if (!id) {
					id = plupload.guid();
					target.attr('id', id);
				}

				uploader = new plupload.Uploader($.extend({
					dragdrop : true,
					container : id
				}, settings));

				// Call setup function
				if (settings.setup) {
					settings.setup(uploader);
				}

				uploaders[id] = uploader;

				function handleStatus(file) {
					var actionClass;

					if (file.status == plupload.DONE) {
						actionClass = 'plupload_done';
					}

					if (file.status == plupload.FAILED) {
						actionClass = 'plupload_failed';
					}

					if (file.status == plupload.QUEUED) {
						actionClass = 'plupload_delete';
					}

					if (file.status == plupload.UPLOADING) {
						actionClass = 'plupload_uploading';
					}

					$('#' + file.id).attr('class', actionClass).find('a').css('display', 'block');
				}

				function updateTotalProgress() {
					$('span.plupload_total_status', target).html(uploader.total.percent + '%');
					$('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%');
					$('span.plupload_upload_status', target).text('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files');

					// All files are uploaded
					if (uploader.total.uploaded == uploader.files.length) {
						uploader.stop();
					}
				}

				function updateList() {
					var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML;

					$.each(uploader.files, function(i, file) {
						inputHTML = '';

						if (file.status == plupload.DONE) {
							if (file.target_name) {
								inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_tmpname" value="' + plupload.xmlEncode(file.target_name) + '" />';
							}

							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_name" value="' + plupload.xmlEncode(file.name) + '" />';
							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_status" value="' + (file.status == plupload.DONE ? 'done' : 'failed') + '" />';

							inputCount++;

							$('#' + id + '_count').val(inputCount);
						}

						fileList.append(
							'
' +
								'
' + file.name + '
' +
								'

' +
								'
' + file.percent + '%
' +
								'
' + plupload.formatSize(file.size) + '
' +
								'

' +
								inputHTML +
							'
'
						);

						handleStatus(file);

						$('#' + file.id + '.plupload_delete a').click(function(e) {
							$('#' + file.id).remove();
							uploader.removeFile(file);

							e.preventDefault();
						});
					});

					$('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size));

					if (uploader.total.queued === 0) {
						$('span.plupload_add_text', target).text(_('Add files.'));
					} else {
						$('span.plupload_add_text', target).text(uploader.total.queued + ' files queued.');
					}

					$('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length === 0);

					// Scroll to end of file list
					fileList[0].scrollTop = fileList[0].scrollHeight;

					updateTotalProgress();
				}

				uploader.bind("UploadFile", function(up, file) {
					$('#' + file.id).addClass('plupload_current_file');
				});

				uploader.bind('Init', function(up, res) {
					renderUI(id, target);

					$('a.plupload_add', target).attr('id', id + '_browse');

					up.settings.browse_button = id + '_browse';

					// Enable drag/drop
					if (up.features.dragdrop && up.settings.dragdrop) {
						up.settings.drop_element = id + '_filelist';
						$('#' + id + '_filelist').append('
' + _("Drag files here.") + '
');
					}

					$('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime);

					$('a.plupload_start', target).click(function(e) {
						if (!$(this).hasClass('plupload_disabled')) {
							uploader.start();
						}

						e.preventDefault();
					});

					$('a.plupload_stop', target).click(function(e) {
						uploader.stop();

						e.preventDefault();
					});

					$('a.plupload_start', target).addClass('plupload_disabled');
				});

				uploader.init();

				uploader.bind('StateChanged', function() {
					if (uploader.state === plupload.STARTED) {
						$('li.plupload_delete a,div.plupload_buttons', target).hide();
						$('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block');
						$('span.plupload_upload_status', target).text('Uploaded 0/' + uploader.files.length + ' files');
					} else {
						$('a.plupload_stop,div.plupload_progress', target).hide();
						$('a.plupload_delete', target).css('display', 'block');
					}
				});

				uploader.bind('QueueChanged', updateList);

				uploader.bind('StateChanged', function(up) {
					if (up.state == plupload.STOPPED) {
						updateList();
					}
				});

				uploader.bind('FileUploaded', function(up, file) {
					handleStatus(file);
				});

				uploader.bind("UploadProgress", function(up, file) {
					// Set file specific progress
					$('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%');

					handleStatus(file);
					updateTotalProgress();
				});
			});

			return this;
		} else {
			// Get uploader instance for specified element
			return uploaders[$(this[0]).attr('id')];
		}
	};
})(jQuery);
<commit_msg>Added preinit and moved post init event. Fixed so error status is displayed.<commit_after>/**
 * jquery.plupload.queue.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

// JSLint defined globals
/*global plupload:false, jQuery:false */

(function($) {
	var uploaders = {};

	function _(str) {
		return plupload.translate(str) || str;
	}

	function renderUI(id, target) {
		// Remove all existing non plupload items
		target.contents().each(function(i, node) {
			node = $(node);

			if (!node.is('.plupload')) {
				node.remove();
			}
		});

		target.prepend(
			'
' +
				'
' +
					'
' +
						'
' +
							'
' +
								'
' + _('Select files') + '
' +
								'
' + _('Add files to the upload queue and click the start button.') + '
' +
							'
' +
						'
' +

						'
' +
							'
' +
								'
' + _('Filename') + '
' +
								'

' +
								'
' + _('Status') + '
' +
								'
' + _('Size') + '
' +
								'

' +
							'
' +

							'

' +

							'
' +
								'
' +
									'
' +
										'' + _('Add files') + '' +
										'' + _('Start upload') + '' +
									'
' +
									'' +
								'
' +
								'

' +
								'
0%
' +
								'
0 b
' +
								'
' +
									'
' +
										'

' +
									'
' +
								'
' +
								'

' +
							'
' +
						'
' +
					'
' +
				'
' +
				'<input type="hidden" id="' + id + '_count" name="' + id + '_count" value="0" />' +
			'
'
		);
	}

	$.fn.pluploadQueue = function(settings) {
		if (settings) {
			this.each(function() {
				var uploader, target, id;

				target = $(this);
				id = target.attr('id');

				if (!id) {
					id = plupload.guid();
					target.attr('id', id);
				}

				uploader = new plupload.Uploader($.extend({
					dragdrop : true,
					container : id
				}, settings));

				// Call preinit function
				if (settings.preinit) {
					settings.preinit(uploader);
				}

				uploaders[id] = uploader;

				function handleStatus(file) {
					var actionClass;

					if (file.status == plupload.DONE) {
						actionClass = 'plupload_done';
					}

					if (file.status == plupload.FAILED) {
						actionClass = 'plupload_failed';
					}

					if (file.status == plupload.QUEUED) {
						actionClass = 'plupload_delete';
					}

					if (file.status == plupload.UPLOADING) {
						actionClass = 'plupload_uploading';
					}

					$('#' + file.id).attr('class', actionClass).find('a').css('display', 'block');
				}

				function updateTotalProgress() {
					$('span.plupload_total_status', target).html(uploader.total.percent + '%');
					$('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%');
					$('span.plupload_upload_status', target).text('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files');

					// All files are uploaded
					if (uploader.total.uploaded == uploader.files.length) {
						uploader.stop();
					}
				}

				function updateList() {
					var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML;

					$.each(uploader.files, function(i, file) {
						inputHTML = '';

						if (file.status == plupload.DONE) {
							if (file.target_name) {
								inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_tmpname" value="' + plupload.xmlEncode(file.target_name) + '" />';
							}

							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_name" value="' + plupload.xmlEncode(file.name) + '" />';
							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_status" value="' + (file.status == plupload.DONE ? 'done' : 'failed') + '" />';

							inputCount++;

							$('#' + id + '_count').val(inputCount);
						}

						fileList.append(
							'
' +
								'
' + file.name + '
' +
								'

' +
								'
' + file.percent + '%
' +
								'
' + plupload.formatSize(file.size) + '
' +
								'

' +
								inputHTML +
							'
'
						);

						handleStatus(file);

						$('#' + file.id + '.plupload_delete a').click(function(e) {
							$('#' + file.id).remove();
							uploader.removeFile(file);

							e.preventDefault();
						});
					});

					$('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size));

					if (uploader.total.queued === 0) {
						$('span.plupload_add_text', target).text(_('Add files.'));
					} else {
						$('span.plupload_add_text', target).text(uploader.total.queued + ' files queued.');
					}

					$('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length === 0);

					// Scroll to end of file list
					fileList[0].scrollTop = fileList[0].scrollHeight;

					updateTotalProgress();
				}

				uploader.bind("UploadFile", function(up, file) {
					$('#' + file.id).addClass('plupload_current_file');
				});

				uploader.bind('Init', function(up, res) {
					renderUI(id, target);

					$('a.plupload_add', target).attr('id', id + '_browse');

					up.settings.browse_button = id + '_browse';

					// Enable drag/drop
					if (up.features.dragdrop && up.settings.dragdrop) {
						up.settings.drop_element = id + '_filelist';
						$('#' + id + '_filelist').append('
' + _("Drag files here.") + '
');
					}

					$('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime);

					$('a.plupload_start', target).click(function(e) {
						if (!$(this).hasClass('plupload_disabled')) {
							uploader.start();
						}

						e.preventDefault();
					});

					$('a.plupload_stop', target).click(function(e) {
						uploader.stop();

						e.preventDefault();
					});

					$('a.plupload_start', target).addClass('plupload_disabled');
				});

				uploader.init();

				// Call setup function
				if (settings.setup) {
					settings.setup(uploader);
				}

				uploader.bind("Error", function(up, err) {
					var file = err.file;

					if (file) {
						$('#' + file.id).attr('class', 'plupload_failed').find('a').css('display', 'block').attr('title', err.message);
					}
				});

				uploader.bind('StateChanged', function() {
					if (uploader.state === plupload.STARTED) {
						$('li.plupload_delete a,div.plupload_buttons', target).hide();
						$('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block');
						$('span.plupload_upload_status', target).text('Uploaded 0/' + uploader.files.length + ' files');
					} else {
						$('a.plupload_stop,div.plupload_progress', target).hide();
						$('a.plupload_delete', target).css('display', 'block');
					}
				});

				uploader.bind('QueueChanged', updateList);

				uploader.bind('StateChanged', function(up) {
					if (up.state == plupload.STOPPED) {
						updateList();
					}
				});

				uploader.bind('FileUploaded', function(up, file) {
					handleStatus(file);
				});

				uploader.bind("UploadProgress", function(up, file) {
					// Set file specific progress
					$('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%');

					handleStatus(file);
					updateTotalProgress();
				});
			});

			return this;
		} else {
			// Get uploader instance for specified element
			return uploaders[$(this[0]).attr('id')];
		}
	};
})(jQuery);
<|endoftext|>