<commit_before>// Requirements
const mqtt = require('mqtt')
var Redis = require('redis')
var async = require('async')
const _ = require('lodash')
const express = require('express')

const rules = require('./homeautomation-js-lib/rules.js')
const logging = require('./homeautomation-js-lib/logging.js')

require('./homeautomation-js-lib/devices.js')
require('./homeautomation-js-lib/mqtt_helpers.js')
require('./homeautomation-js-lib/redis_helpers.js')

const utilities = require('./lib/utilities.js')
const schedule = require('./lib/scheduled-jobs.js')
const evaluation = require('./lib/evaluation.js')

const config_path = process.env.TRANSFORM_CONFIG_PATH

// Setup MQTT
global.client = mqtt.setupClient(function() {
    logging.info('MQTT Connected', {
        action: 'mqtt-connected'
    })
    global.client.subscribe('#')

}, function() {
    logging.error('Disconnected', {
        action: 'mqtt-disconnected'
    })
})

global.publishEvents = []

global.publish = function(rule_name, expression, valueOrExpression, topic, message) {
    global.client.publish(topic, message)

    var event = {}

    event.rule_name = rule_name
    event.expression = expression
    event.valueOrExpression = valueOrExpression
    event.topic = topic
    event.message = message
    event.date = new Date()

    global.publishEvents.push(event)
}

global.devices_to_monitor = []

var global_value_cache = {}

global.client.on('message', (topic, message) => {
    if (!global.devices_to_monitor.includes(topic))
        return

    message = utilities.convertToNumberIfNeeded(message)

    //logging.info(' ' + topic + ':' + message)
    var cachedValue = global_value_cache[topic]

    if (!_.isNil(cachedValue)) {
        if (('' + message).localeCompare(cachedValue) === 0) {
            logging.info(' => value not updated', {
                action: 'skipped-processing',
                reason: 'value-not-updated',
                topic: topic,
                message: message
            })
            return
        }
    }
    global_value_cache[topic] = message

    const redisStartTime = new Date().getTime()
    logging.info(' redis query', {
        action: 'redis-query-start',
        start_time: redisStartTime
    })

    global.redis.mget(global.devices_to_monitor, function(err, values) {
        logging.info(' redis query done', {
            action: 'redis-query-done',
            query_time: ((new Date().getTime()) - redisStartTime)
        })
        var context = {}

        for (var index = 0; index < global.devices_to_monitor.length; index++) {
            const key = global.devices_to_monitor[index]
            const value = values[index]
            const newKey = utilities.update_topic_for_expression(key)
            if (key === topic)
                context[newKey] = utilities.convertToNumberIfNeeded(message)
            else
                context[newKey] = utilities.convertToNumberIfNeeded(value)
        }

        context[utilities.update_topic_for_expression(topic)] = message

        const ruleStartTime = new Date().getTime()
        logging.info(' rule processing start ', {
            action: 'rule-processing-start',
            start_time: ruleStartTime
        })

        var ruleProcessor = function(rule, rule_name, callback) {
            //logging.debug('rule processor for rule: ' + rule_name)
            const watch = rule.watch

            if (!_.isNil(watch) && !_.isNil(watch.devices)) {
                if (watch.devices.indexOf(topic) !== -1) {
                    logging.info('matched topic to rule', {
                        action: 'rule-match',
                        rule_name: rule_name,
                        topic: topic,
                        message: utilities.convertToNumberIfNeeded(message),
                        rule: rule,
                        context: context
                    })

                    evaluation.evalulateValue(topic, context, rule_name, rule)
                }
            }

            callback()
        }

        var configProcessor = function(config, callback) {
            async.eachOf(config, ruleProcessor)
            callback()
        }

        async.each(rules.get_configs(), configProcessor)

        logging.info(' rule processing done ', {
            action: 'rule-processing-done',
            processing_time: ((new Date().getTime()) - ruleStartTime)
        })
    })
})

global.redis = Redis.setupClient(function() {
    logging.info('redis connected ', {
        action: 'redis-connected'
    })
    rules.load_path(config_path)
})

rules.on('rules-loaded', () => {
    global.devices_to_monitor = []

    rules.ruleIterator(function(rule_name, rule) {
        const watch = rule.watch
        if (!_.isNil(watch)) {
            const devices = watch.devices
            if (!_.isNil(devices)) {
                devices.forEach(function(device) {
                    global.devices_to_monitor.push(device)
                }, this)
            }
        }

        const rules = rule.rules
        if (!_.isNil(rules)) {
            const expression = rules.expression
            logging.debug('expression :' + expression)
            if (!_.isNil(expression)) {

                var foundDevices = expression.match(/\/([a-z,0-9,\-,_,/])*/g)

                if (!_.isNil(foundDevices)) {
                    foundDevices.forEach(function(device) {
                        global.devices_to_monitor.push(device)
                    }, this)
                }
            }
        }

        const actions = rule.actions
        if (!_.isNil(actions)) {
            Object.keys(actions).forEach(function(action) {
                const action_value = actions[action]

                var foundDevices = action_value.match(/\/([a-z,0-9,\-,_,/])*/g)

                if (!_.isNil(foundDevices)) {
                    foundDevices.forEach(function(device) {
                        global.devices_to_monitor.push(device)
                    }, this)
                }
            }, this)
        }

    })

    global.devices_to_monitor = utilities.unique(global.devices_to_monitor)

    logging.info('rules loaded ', {
        action: 'rules-loaded',
        devices_to_monitor: global.devices_to_monitor
    })

    global.redis.mget(global.devices_to_monitor, function(err, values) {
        logging.debug('devices :' + JSON.stringify(global.devices_to_monitor))
        logging.debug('values :' + JSON.stringify(values))
    })

    schedule.scheduleJobs()
})

// Config
const port = process.env.LISTENING_PORT

// Express
const app = express()

app.get('/rules/', function(req, res) {
    var allRules = {}

    var ruleProcessor = function(rule, rule_name, callback) {
        //logging.debug('rule processor for rule: ' + rule_name)
        allRules[rule_name] = rule

        callback()
    }

    var configProcessor = function(config, callback) {
        async.eachOf(config, ruleProcessor)
        callback()
    }

    async.each(rules.get_configs(), configProcessor, function(err) {
        var html = ''

        html += '<!DOCTYPE html>\n'
        html += '\n'
        html += '\n'

        html += ''

        html += '\n'
        html += '\n'
        html += '
Rules
\n'

        html += '
\n'

        html += '
\n'
        html += '
\n'

        html += '\n'
        html += 'Name'
        html += '	\n'

        html += '\n'
        html += 'Rule'
        html += '	\n'

        html += '
\n'
        html += '
\n'

        html += '
\n'

        Object.keys(allRules).forEach(function(rule_name) {
            const rule = allRules[rule_name]
            const performAfter = rule.perform_after
            const evalulateAfter = rule.evaluate_after
            html += '
\n'

            html += '\n'
            html += rule_name
            html += '	\n'
            html += '\n'
            if (!_.isNil(rule.schedule)) {
                _.attempt(function(selector) {
                    html += 'at scheduled times:
'

                    Object.keys(rule.schedule).forEach(function(schedule_name) {
                        const schedule = rule.schedule[schedule_name]
                        html += '&nbsp&nbsp&nbsp' + schedule_name + ': ' + schedule + '
'

                    }, this)
                    html += '
'
                })
            }
            if (!_.isNil(rule.watch)) {
                _.attempt(function(selector) {
                    html += 'when any of these devices update:
'
                    html += '&nbsp&nbsp&nbsp' + rule.watch.devices + '
'
                    html += '
'
                })
            }
            if (!_.isNil(rule.rules)) {
                _.attempt(function(selector) {
                    html += 'evaluate this expression'
                    if (!_.isNil(evalulateAfter))
                        html += ' after ' + evalulateAfter + ' seconds'
                    html += ':
'
                    html += '&nbsp&nbsp&nbsp' + rule.rules.expression + '
'
                    html += '
'
                })
            }
            if (!_.isNil(rule.actions)) {
                _.attempt(function(selector) {
                    html += 'perform these actions'
                    if (!_.isNil(performAfter))
                        html += ' after ' + performAfter + ' seconds'
                    html += ':
'

                    Object.keys(rule.actions).forEach(function(topic) {
                        const value = rule.actions[topic]
                        html += '&nbsp&nbsp&nbsp' + topic + ' => ' + value + '
'

                    }, this)
                    html += '
'
                })
            }
            if (!_.isNil(rule.allowed_times)) {
                _.attempt(function(selector) {
                    html += 'only during times:
'

                    rule.allowed_times.forEach(function(time) {
                        html += '&nbsp&nbsp&nbsp' + time + '
'
                    }, this)

                    html += '
'
                    html += '
'
                })
            }

            if (!_.isNil(rule.notify)) {
                _.attempt(function(selector) {
                    html += 'notify:
'
                    html += '&nbsp&nbsp title: ' + rule.notify.title + '
'
                    html += '&nbsp&nbsp message: ' + rule.notify.message + '
'
                    html += '
'
                })
            }

            html += '	\n'

            html += '
\n'
        })

        html += '
\n'

        html += '
\n'

        html += '\n'
        html += ''

        res.send(html)
    })
})

app.get('/events/', function(req, res) {
    var allRules = {}

    var ruleProcessor = function(rule, rule_name, callback) {
        //logging.debug('rule processor for rule: ' + rule_name)
        allRules[rule_name] = rule

        callback()
    }

    var configProcessor = function(config, callback) {
        async.eachOf(config, ruleProcessor)
        callback()
    }

    async.each(rules.get_configs(), configProcessor, function(err) {
        var html = ''

        html += '<!DOCTYPE html>\n'
        html += '\n'
        html += '\n'

        html += ''

        html += '\n'
        html += '\n'
        html += '
Events
\n'

        html += '
\n'

        html += '
\n'
        html += '
\n'

        html += '\n'
        html += 'Name'
        html += '	\n'

        html += '\n'
        html += 'Event'
        html += '	\n'

        html += '
\n'
        html += '
\n'

        html += '
\n'

        global.publishEvents.forEach(function(event) {
            const rule_name = event.rule_name
            const expression = event.expression
            const topic = event.topic
            const message = event.message
            const valueOrExpression = event.valueOrExpression
            const date = event.date
            var ruleExpression = null
            const rule = allRules[rule_name]

            if (!_.isNil(rule.rules)) {
                _.attempt(function(selector) {
                    ruleExpression = rule.rules.expression
                })
            }

            html += '
\n'

            html += '\n'
            html += rule_name
            html += '	\n'
            html += '\n'

            html += '' + date + '

'

            if (!_.isNil(rule.schedule)) {
                _.attempt(function(selector) {
                    html += 'at scheduled times:
'

                    Object.keys(rule.schedule).forEach(function(schedule_name) {
                        const schedule = rule.schedule[schedule_name]
                        html += '&nbsp&nbsp&nbsp' + schedule_name + ': ' + schedule + '
'

                    }, this)
                    html += '
'
                })
            }

            html += 'expression:
'
            html += '&nbsp&nbsp&nbsp' + ruleExpression + '

'

            html += 'publish expression:
'
            html += '&nbsp&nbsp&nbsp' + valueOrExpression + '

'

            html += 'result:
'
            html += '&nbsp&nbsp&nbsp' + topic + ' => ' + message + '

'

            html += '	\n'

            html += '
\n'
        })

        html += '
\n'

        html += '
\n'

        html += '\n'
        html += ''

        res.send(html)
    })
})

app.listen(port, function() {
    logging.log('MQTT Store listening on port: ', port)
})<commit_msg>Attempting rebuild<commit_after>// Requirements
const mqtt = require('mqtt')
var Redis = require('redis')
var async = require('async')
const _ = require('lodash')
const express = require('express')

const rules = require('./homeautomation-js-lib/rules.js')
const logging = require('./homeautomation-js-lib/logging.js')

require('./homeautomation-js-lib/devices.js')
require('./homeautomation-js-lib/mqtt_helpers.js')
require('./homeautomation-js-lib/redis_helpers.js')

const utilities = require('./lib/utilities.js')
const schedule = require('./lib/scheduled-jobs.js')
const evaluation = require('./lib/evaluation.js')

const config_path = process.env.TRANSFORM_CONFIG_PATH

// Setup MQTT
global.client = mqtt.setupClient(function() {
    logging.info('MQTT Connected', {
        action: 'mqtt-connected'
    })
    global.client.subscribe('#')

}, function() {
    logging.error('Disconnected', {
        action: 'mqtt-disconnected'
    })
})

global.publishEvents = []

global.publish = function(rule_name, expression, valueOrExpression, topic, message) {
    global.client.publish(topic, message)

    var event = {}

    event.rule_name = rule_name
    event.expression = expression
    event.valueOrExpression = valueOrExpression
    event.topic = topic
    event.message = message
    event.date = new Date()

    global.publishEvents.push(event)
}

global.devices_to_monitor = []

var global_value_cache = {}

global.client.on('message', (topic, message) => {
    if (!global.devices_to_monitor.includes(topic))
        return

    message = utilities.convertToNumberIfNeeded(message)

    //logging.info(' ' + topic + ':' + message)
    var cachedValue = global_value_cache[topic]

    if (!_.isNil(cachedValue)) {
        if (('' + message).localeCompare(cachedValue) === 0) {
            logging.info(' => value not updated', {
                action: 'skipped-processing',
                reason: 'value-not-updated',
                topic: topic,
                message: message
            })
            return
        }
    }
    global_value_cache[topic] = message

    const redisStartTime = new Date().getTime()
    logging.info(' redis query', {
        action: 'redis-query-start',
        start_time: redisStartTime
    })

    global.redis.mget(global.devices_to_monitor, function(err, values) {
        logging.info(' redis query done', {
            action: 'redis-query-done',
            query_time: ((new Date().getTime()) - redisStartTime)
        })
        var context = {}

        for (var index = 0; index < global.devices_to_monitor.length; index++) {
            const key = global.devices_to_monitor[index]
            const value = values[index]
            const newKey = utilities.update_topic_for_expression(key)
            if (key === topic)
                context[newKey] = utilities.convertToNumberIfNeeded(message)
            else
                context[newKey] = utilities.convertToNumberIfNeeded(value)
        }

        context[utilities.update_topic_for_expression(topic)] = message

        const ruleStartTime = new Date().getTime()
        logging.info(' rule processing start ', {
            action: 'rule-processing-start',
            start_time: ruleStartTime
        })

        var ruleProcessor = function(rule, rule_name, callback) {
            //logging.debug('rule processor for rule: ' + rule_name)
            const watch = rule.watch

            if (!_.isNil(watch) && !_.isNil(watch.devices)) {
                if (watch.devices.indexOf(topic) !== -1) {
                    logging.info('matched topic to rule', {
                        action: 'rule-match',
                        rule_name: rule_name,
                        topic: topic,
                        message: utilities.convertToNumberIfNeeded(message),
                        rule: rule,
                        context: context
                    })

                    evaluation.evalulateValue(topic, context, rule_name, rule)
                }
            }

            callback()
        }

        var configProcessor = function(config, callback) {
            async.eachOf(config, ruleProcessor)
            callback()
        }

        async.each(rules.get_configs(), configProcessor)

        logging.info(' rule processing done ', {
            action: 'rule-processing-done',
            processing_time: ((new Date().getTime()) - ruleStartTime)
        })
    })
})

global.redis = Redis.setupClient(function() {
    logging.info('redis connected ', {
        action: 'redis-connected'
    })
    rules.load_path(config_path)
})

rules.on('rules-loaded', () => {
    global.devices_to_monitor = []

    rules.ruleIterator(function(rule_name, rule) {
        const watch = rule.watch
        if (!_.isNil(watch)) {
            const devices = watch.devices
            if (!_.isNil(devices)) {
                devices.forEach(function(device) {
                    global.devices_to_monitor.push(device)
                }, this)
            }
        }

        const rules = rule.rules
        if (!_.isNil(rules)) {
            const expression = rules.expression
            logging.debug('expression :' + expression)
            if (!_.isNil(expression)) {

                var foundDevices = expression.match(/\/([a-z,0-9,\-,_,/])*/g)

                if (!_.isNil(foundDevices)) {
                    foundDevices.forEach(function(device) {
                        global.devices_to_monitor.push(device)
                    }, this)
                }
            }
        }

        const actions = rule.actions
        if (!_.isNil(actions)) {
            Object.keys(actions).forEach(function(action) {
                const action_value = actions[action]

                var foundDevices = action_value.match(/\/([a-z,0-9,\-,_,/])*/g)

                if (!_.isNil(foundDevices)) {
                    foundDevices.forEach(function(device) {
                        global.devices_to_monitor.push(device)
                    }, this)
                }
            }, this)
        }

    })

    global.devices_to_monitor = utilities.unique(global.devices_to_monitor)

    logging.info('rules loaded ', {
        action: 'rules-loaded',
        devices_to_monitor: global.devices_to_monitor
    })

    global.redis.mget(global.devices_to_monitor, function(err, values) {
        logging.debug('devices :' + JSON.stringify(global.devices_to_monitor))
        logging.debug('values :' + JSON.stringify(values))
    })

    schedule.scheduleJobs()
})

// Config
const port = process.env.LISTENING_PORT

// Express
const app = express()

app.get('/rules/', function(req, res) {
    var allRules = {}

    var ruleProcessor = function(rule, rule_name, callback) {
        //logging.debug('rule processor for rule: ' + rule_name)
        allRules[rule_name] = rule

        callback()
    }

    var configProcessor = function(config, callback) {
        async.eachOf(config, ruleProcessor)
        callback()
    }

    async.each(rules.get_configs(), configProcessor, function(err) {
        var html = ''

        html += '<!DOCTYPE html>\n'
        html += '\n'
        html += '\n'

        html += ''

        html += '\n'
        html += '\n'
        html += '
Rules
\n'

        html += '
\n'

        html += '
\n'
        html += '
\n'

        html += '\n'
        html += 'Name'
        html += '	\n'

        html += '\n'
        html += 'Rule'
        html += '	\n'

        html += '
\n'
        html += '
\n'

        html += '
\n'

        Object.keys(allRules).forEach(function(rule_name) {
            const rule = allRules[rule_name]
            const performAfter = rule.perform_after
            const evalulateAfter = rule.evaluate_after
            html += '
\n'

            html += '\n'
            html += rule_name
            html += '	\n'
            html += '\n'
            if (!_.isNil(rule.schedule)) {
                _.attempt(function(selector) {
                    html += 'at scheduled times:
'

                    Object.keys(rule.schedule).forEach(function(schedule_name) {
                        const schedule = rule.schedule[schedule_name]
                        html += '&nbsp&nbsp&nbsp' + schedule_name + ': ' + schedule + '
'

                    }, this)
                    html += '
'
                })
            }
            if (!_.isNil(rule.watch)) {
                _.attempt(function(selector) {
                    html += 'when any of these devices update:
'
                    html += '&nbsp&nbsp&nbsp' + rule.watch.devices + '
'
                    html += '
'
                })
            }
            if (!_.isNil(rule.rules)) {
                _.attempt(function(selector) {
                    html += 'evaluate this expression'
                    if (!_.isNil(evalulateAfter))
                        html += ' after ' + evalulateAfter + ' seconds'
                    html += ':
'
                    html += '&nbsp&nbsp&nbsp' + rule.rules.expression + '
'
                    html += '
'
                })
            }
            if (!_.isNil(rule.actions)) {
                _.attempt(function(selector) {
                    html += 'perform these actions'
                    if (!_.isNil(performAfter))
                        html += ' after ' + performAfter + ' seconds'
                    html += ':
'

                    Object.keys(rule.actions).forEach(function(topic) {
                        const value = rule.actions[topic]
                        html += '&nbsp&nbsp&nbsp' + topic + ' => ' + value + '
'

                    }, this)
                    html += '
'
                })
            }
            if (!_.isNil(rule.allowed_times)) {
                _.attempt(function(selector) {
                    html += 'only during times:
'

                    rule.allowed_times.forEach(function(time) {
                        html += '&nbsp&nbsp&nbsp' + time + '
'
                    }, this)

                    html += '
'
                    html += '
'
                })
            }

            if (!_.isNil(rule.notify)) {
                _.attempt(function(selector) {
                    html += 'notify:
'
                    html += '&nbsp&nbsp title: ' + rule.notify.title + '
'
                    html += '&nbsp&nbsp message: ' + rule.notify.message + '
'
                    html += '
'
                })
            }

            html += '	\n'

            html += '
\n'
        })

        html += '
\n'

        html += '
\n'

        html += '\n'
        html += ''

        res.send(html)
    })
})

app.get('/events/', function(req, res) {
    var allRules = {}

    var ruleProcessor = function(rule, rule_name, callback) {
        //logging.debug('rule processor for rule: ' + rule_name)
        allRules[rule_name] = rule

        callback()
    }

    var configProcessor = function(config, callback) {
        async.eachOf(config, ruleProcessor)
        callback()
    }

    async.each(rules.get_configs(), configProcessor, function(err) {
        var html = ''

        html += '<!DOCTYPE html>\n'
        html += '\n'
        html += '\n'

        html += ''

        html += '\n'
        html += '\n'
        html += '
Events
\n'

        html += '
\n'

        html += '
\n'
        html += '
\n'

        html += '\n'
        html += 'Name'
        html += '	\n'

        html += '\n'
        html += 'Event'
        html += '	\n'

        html += '
\n'
        html += '
\n'

        html += '
\n'

        global.publishEvents.forEach(function(event) {
            const rule_name = event.rule_name
            const expression = event.expression
            const topic = event.topic
            const message = event.message
            const valueOrExpression = event.valueOrExpression
            const date = event.date
            var ruleExpression = null
            const rule = allRules[rule_name]

            if (!_.isNil(rule.rules)) {
                _.attempt(function(selector) {
                    ruleExpression = rule.rules.expression
                })
            }

            html += '
\n'

            html += '\n'
            html += rule_name
            html += '	\n'
            html += '\n'

            html += '' + date + '

'

            if (!_.isNil(rule.schedule)) {
                _.attempt(function(selector) {
                    html += 'at scheduled times:
'

                    Object.keys(rule.schedule).forEach(function(schedule_name) {
                        const schedule = rule.schedule[schedule_name]
                        html += '&nbsp&nbsp&nbsp' + schedule_name + ': ' + schedule + '
'

                    }, this)
                    html += '
'
                })
            }

            html += 'expression:
'
            html += '&nbsp&nbsp&nbsp' + ruleExpression + '

'

            html += 'publish expression:
'
            html += '&nbsp&nbsp&nbsp' + valueOrExpression + '

'

            html += 'result:
'
            html += '&nbsp&nbsp&nbsp' + topic + ' => ' + message + '

'

            html += '	\n'

            html += '
\n'
        })

        html += '
\n'
        html += '
\n'

        html += '\n'
        html += ''

        res.send(html)
    })
})

app.listen(port, function() {
    logging.log('MQTT Store listening on port: ', port)
})<|endoftext|>


<commit_before>const restrictedList = {
    version: '1.4',
    cards: [
        'mirumoto-s-fury',
        'for-greater-glory',
        'against-the-waves',
        'forged-edict',
        'charge',
        'pathfinder-s-blade',
        'policy-debate',
        'iron-mine'
    ]
};

class RestrictedList {
    validate(cards) {
        let cardsOnRestrictedList = cards.filter(card => restrictedList.cards.includes(card.id));

        let errors = [];

        if(cardsOnRestrictedList.length > 1) {
            errors.push(`Contains more than 1 card on the FAQ v${restrictedList.version} restricted list: ${cardsOnRestrictedList.map(card => card.name).join(', ')}`);
        }

        return {
            version: restrictedList.version,
            valid: errors.length === 0,
            errors: errors,
            restrictedCards: cardsOnRestrictedList
        };
    }
}

module.exports = RestrictedList;
<commit_msg>Update the restricted list to 1.7 (#2678)<commit_after>const restrictedList = {
    version: '1.7',
    cards: [
        'guest-of-honor',
        'niten-master',
        'young-rumormongor',
        'rebuild',
        'mirumoto-s-fury',
        'for-greater-glory',
        'forged-edict',
        'charge',
        'pathfinder-s-blade',
        'feast-or-famine',
        'policy-debate',
        'a-fate-worse-than-death',
        'isawa-tadaka',
        'void-fist'
    ]
};

class RestrictedList {
    validate(cards) {
        let cardsOnRestrictedList = cards.filter(card => restrictedList.cards.includes(card.id));

        let errors = [];

        if(cardsOnRestrictedList.length > 1) {
            errors.push(`Contains more than 1 card on the FAQ v${restrictedList.version} restricted list: ${cardsOnRestrictedList.map(card => card.name).join(', ')}`);
        }

        return {
            version: restrictedList.version,
            valid: errors.length === 0,
            errors: errors,
            restrictedCards: cardsOnRestrictedList
        };
    }
}

module.exports = RestrictedList;
<|endoftext|>


<commit_before>const restrictedList = {
    version: '9',
    cards: [
        'guest-of-honor',
        'niten-master',
        'young-rumormonger',
        'rebuild',
        'steward-of-law',
        'mirumoto-s-fury',
        'for-greater-glory',
        'forged-edict',
        'charge',
        'embrace-the-void',
        'pathfinder-s-blade',
        'feast-or-famine',
        'policy-debate',
        'a-fate-worse-than-death',
        'isawa-tadaka',
        'secluded-shrine',
        'void-fist'
    ]
};

class RestrictedList {
    validate(cards) {
        let cardsOnRestrictedList = cards.filter(card => restrictedList.cards.includes(card.id));

        let errors = [];

        if(cardsOnRestrictedList.length > 1) {
            errors.push(`Contains more than 1 card on the FAQ v${restrictedList.version} restricted list: ${cardsOnRestrictedList.map(card => card.name).join(', ')}`);
        }

        return {
            version: restrictedList.version,
            valid: errors.length === 0,
            errors: errors,
            restrictedCards: cardsOnRestrictedList
        };
    }
}

module.exports = RestrictedList;
<commit_msg>Add spyglass to RL (#3335)<commit_after>const restrictedList = {
    version: '9',
    cards: [
        'guest-of-honor',
        'niten-master',
        'young-rumormonger',
        'rebuild',
        'steward-of-law',
        'mirumoto-s-fury',
        'for-greater-glory',
        'forged-edict',
        'spyglass',
        'charge',
        'embrace-the-void',
        'pathfinder-s-blade',
        'feast-or-famine',
        'policy-debate',
        'a-fate-worse-than-death',
        'isawa-tadaka',
        'secluded-shrine',
        'void-fist'
    ]
};

class RestrictedList {
    validate(cards) {
        let cardsOnRestrictedList = cards.filter(card => restrictedList.cards.includes(card.id));

        let errors = [];

        if(cardsOnRestrictedList.length > 1) {
            errors.push(`Contains more than 1 card on the FAQ v${restrictedList.version} restricted list: ${cardsOnRestrictedList.map(card => card.name).join(', ')}`);
        }

        return {
            version: restrictedList.version,
            valid: errors.length === 0,
            errors: errors,
            restrictedCards: cardsOnRestrictedList
        };
    }
}

module.exports = RestrictedList;
<|endoftext|>


<commit_before>var merge = function _merge(target) {
    target = target || {};
    foreach(arguments, function(o) {
        if (o) {
            forIn(o, function(v, n) {
                target[n] = v;
            });
        }
    }, 1);
    return target;
}
var forIn = function _forIn(obj, callback) {
    for (var x in obj) {
        //if (obj.hasOwnProperty(x)) callback(obj[x], x);
        callback(obj[x], x);
    }
}
var foreach = function _foreach(arr, callback, start) {
    var cancelled;
    if (arr) {
        // javascript array
        arr = arr !== window &&
            (arr instanceof Array ||
            // arguments array, or nodelist (has .item and is not a dom element or window)
            (typeof(arr.length) === 'number' && (typeof(arr.callee) === "function" || (arr.item && typeof(arr.nodeType) === "undefined") && !arr.addEventListener && !arr.attachEvent)))
            ? arr : [arr];
        for (var i = start||0, l = arr.length; i < l; i++) {
            if (callback(arr[i], i)) {
                cancelled = true;
                break;
            }
        }
    }
    return !cancelled;
}
var callIf = function _callIf(obj, name, args) {
    // calls a function on an object if it exists, passing in the optional arguments
    var fn = obj[name],
        exists = typeof(fn) === "function";
    if (exists) fn.call(obj, args);
    return exists;
}
<commit_msg>Fix another unusual memory leak in IE. Avoid 'instanceof Array' on a dom element.<commit_after>var merge = function _merge(target) {
    target = target || {};
    foreach(arguments, function(o) {
        if (o) {
            forIn(o, function(v, n) {
                target[n] = v;
            });
        }
    }, 1);
    return target;
}
var forIn = function _forIn(obj, callback) {
    for (var x in obj) {
        //if (obj.hasOwnProperty(x)) callback(obj[x], x);
        callback(obj[x], x);
    }
}
var foreach = function _foreach(arr, callback, start) {
    var cancelled;
    if (arr) {
        // javascript array
        arr = arr !== window && typeof(arr.nodeType) === "undefined" &&
            (arr instanceof Array ||
            // arguments array, or nodelist (has .item and is not a dom element or window)
            (typeof(arr.length) === 'number' && (typeof(arr.callee) === "function" || (arr.item && typeof(arr.nodeType) === "undefined") && !arr.addEventListener && !arr.attachEvent)))
            ? arr : [arr];
        for (var i = start||0, l = arr.length; i < l; i++) {
            if (callback(arr[i], i)) {
                cancelled = true;
                break;
            }
        }
    }
    return !cancelled;
}
var callIf = function _callIf(obj, name, args) {
    // calls a function on an object if it exists, passing in the optional arguments
    var fn = obj[name],
        exists = typeof(fn) === "function";
    if (exists) fn.call(obj, args);
    return exists;
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import '../scss/_nav.scss';

class Nav extends Component {
  render() {
    const { user, avatar} = this.props;
    let signInOut;
    if (!user.id) {
      signInOut = Sign in with Google;
    } else {
      signInOut = Sign out;
    }
    return (

          <Link to="/">GitCooking</Link>
          <input placeholder="Search for recipes"></input>
          {signInOut}
          <Link to="/recipe">Recipe</Link>
          <Link to="/search">Search</Link>
          <Link to="/create">Create</Link>
          <Link to="/profile">

          </Link>

    );
  }
}

const mapStateToProps = (state) => {
  return {
    user: state.user,
    avatar: state.user.photos[0].value,
  };
};

export default connect(mapStateToProps)(Nav);
<commit_msg>Directly link to recipe in Nav<commit_after>import React, { Component } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import '../scss/_nav.scss';

class Nav extends Component {
  render() {
    const { user, avatar, recipeID, } = this.props;
    let signInOut;
    if (!user.id) {
      signInOut = Sign in with Google;
    } else {
      signInOut = Sign out;
    }
    return (

          <Link to="/">GitCooking</Link>
          <input placeholder="Search for recipes"></input>
          {signInOut}
          <Link to={`/recipe/${recipeID}`}>Recipe</Link>
          <Link to="/search">Search</Link>
          <Link to="/create">Create</Link>
          <Link to="/profile">

          </Link>

    );
  }
}

const mapStateToProps = (state) => {
  return {
    user: state.user,
    avatar: state.user.photos[0].value,
    recipeID: state.recipe.id,
  };
};

export default connect(mapStateToProps)(Nav);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { searchRecipes } from '../utils/utils.js';
import actions from '../actions/index.js';
import { push } from 'react-router-redux';
import { EMPTY_RECIPE } from '../constants/EmptyRecipe.js';
import '../scss/_nav.scss';

class Nav extends Component {
  render() {
    const { user, avatar, search, recipeID, navToCreate, dispatch } = this.props;
    let { searchString } = this.props;
    let signInOut, linkToProfile;
    if (!user.id) {
      signInOut = <button class="sign-in-btn"> Sign In </button>;
    } else {
      signInOut = Sign Out;
      linkToProfile = (
        <Link to={`/profile/${user.id}`}>

        </Link>);
    }
    return (

            <Link to="/">Forkful</Link>
            <input
              className="search-bar"
              placeholder="Search for recipes"
              onKeyDown={(e) => { e.keyCode === 13 ? search(searchString) : searchString = e.target.value }}
            ></input>
            <button
              onClick={(e) => {
                e.preventDefault();
                e.stopPropagation();
                navToCreate();
              }}> Create
            </button>
            <button>
              Discover
            </button>

              {signInOut}
              {linkToProfile}

          {/* <Link to={`/recipe/${recipeID}`}>Recipe</Link>*/}

    );
  }
}

const mapStateToProps = (state) => {
  return {
    user: state.user,
    avatar: state.user.photos[0].value,
    recipeID: state.recipe.id,
    // map a local variable to props
    searchString: '',
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    search: (query) => {
      searchRecipes(query, (recipeArray) => {
        dispatch(actions.setRecipeList(recipeArray));
        dispatch(push('/search'));
      });
    },
    navToCreate: () => {
      dispatch(actions.setRecipe(EMPTY_RECIPE));
      dispatch(push('/create'));
    },
    dispatch,
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Nav);
<commit_msg>Switch to forkful logo in navbar<commit_after>import React, { Component } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { searchRecipes } from '../utils/utils.js';
import actions from '../actions/index.js';
import { push } from 'react-router-redux';
import { EMPTY_RECIPE } from '../constants/EmptyRecipe.js';
import '../scss/_nav.scss';

class Nav extends Component {
  render() {
    const { user, avatar, search, recipeID, navToCreate, dispatch } = this.props;
    let { searchString } = this.props;
    let signInOut, linkToProfile;
    if (!user.id) {
      signInOut = <button class="sign-in-btn"> Sign In </button>;
    } else {
      signInOut = Sign Out;
      linkToProfile = (
        <Link to={`/profile/${user.id}`}>

        </Link>);
    }
    return (

            <Link to="/">
              <object style={{maxHeight: '24px'}} type="image/svg+xml" className="logo" data="../assets/forkful-very-long.svg">

              </object></Link>
            <input
              className="search-bar"
              placeholder="Search for recipes"
              onKeyDown={(e) => { e.keyCode === 13 ? search(searchString) : searchString = e.target.value }}
            ></input>
            <button
              onClick={(e) => {
                e.preventDefault();
                e.stopPropagation();
                navToCreate();
              }}> Create
            </button>
            <button>
              Discover
            </button>

              {signInOut}
              {linkToProfile}

          {/* <Link to={`/recipe/${recipeID}`}>Recipe</Link>*/}

    );
  }
}

const mapStateToProps = (state) => {
  return {
    user: state.user,
    avatar: state.user.photos[0].value,
    recipeID: state.recipe.id,
    // map a local variable to props
    searchString: '',
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    search: (query) => {
      searchRecipes(query, (recipeArray) => {
        dispatch(actions.setRecipeList(recipeArray));
        dispatch(push('/search'));
      });
    },
    navToCreate: () => {
      dispatch(actions.setRecipe(EMPTY_RECIPE));
      dispatch(push('/create'));
    },
    dispatch,
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Nav);
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var cors = require('cors');
var proxy = require('http-proxy-middleware');

var app = express();

app.use(express.static('dist'));
app.use(cors());
app.use('/api', proxy({
    target: `http://${process.env.BACKEND_HOST || 'localhost'}:${process.env.BACKEND_PORT || 3000}`,
    changeOrigin: true,
    pathRewrite: {
        '^/api': ''
    }
}));

app.listen(process.env.FRONTEND_PORT || 4000, function () {
    console.log('Production Express server running at ' + this.address().port);
});
<commit_msg>Fix bug when user directly navigates to different routes via URL change<commit_after>var express = require('express');
var path = require('path');
var cors = require('cors');
var proxy = require('http-proxy-middleware');

var app = express();

app.use(express.static('dist'));
app.use(cors());
app.use('/api', proxy({
    target: `http://${process.env.BACKEND_HOST || 'localhost'}:${process.env.BACKEND_PORT || 3000}`,
    changeOrigin: true,
    pathRewrite: {
        '^/api': ''
    }
}));

app.get('*', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

app.listen(process.env.FRONTEND_PORT || 4000, function () {
    console.log('Production Express server running at ' + this.address().port);
});
<|endoftext|>


<commit_before>Accounts.ui.config({
    passwordSignupFields : 'USERNAME_ONLY'
});

Accounts.onLogin(function () {
    Meteor.call('userHasGoal', function (err, userHasGoal) {
        if (userHasGoal) {
            Router.go('cryLevel');
        } else {
            Router.go('showGoals');
        }
    });
});<commit_msg>Fix routing for redirects<commit_after>Accounts.ui.config({
    passwordSignupFields : 'USERNAME_ONLY'
});

Accounts.onLogin(function () {
    Meteor.call('userHasGoal', function (err, userHasGoal) {
        var currentPath = Iron.Location.get().path;

        console.log('current', currentPath);
        if (userHasGoal &&
                (currentPath === '/cry-level' ||
                currentPath === '/goal-settings' ||
                currentPath === '/')) {

            Router.go('cryLevel');
        } else if (!userHasGoal) {
            Router.go('showGoals');
        }
    });
});<|endoftext|>


<commit_before>// @flow

import { schema } from 'normalizr';
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import routing from './routing';
import allowed from './allowed';
import form from './forms';
import companies from './companies';
import companySemesters from './companySemesters';
import emailLists from './emailLists';
import quotes from './quotes';
import galleryPictures from './galleryPictures';
import events from './events';
import articles from './articles';
import pools from './pools';
import registrations from './registrations';
import meetingsToken from './meetingsToken';
import restrictedMails from './restrictedMails';
import meetings from './meetings';
import meetingInvitations, {
  getMeetingInvitationId
} from './meetingInvitations';
import memberships from './memberships';
import search from './search';
import auth from './auth';
import users from './users';
import penalties from './penalties';
import emailUsers from './emailUsers';
import groups from './groups';
import { oauth2Applications, oauth2Grants } from './oauth2';
import toasts from './toasts';
import notificationsFeed from './notificationsFeed';
import notificationSettings from './notificationSettings';
import galleries from './galleries';
import comments from './comments';
import pages from './pages';
import companyInterest from './companyInterest';
import joblistings from './joblistings';
import announcements from './announcements';
import feedActivities from './feedActivities';
import feeds from './feeds';
import frontpage from './frontpage';
import surveys from './surveys';
import surveySubmissions from './surveySubmissions';
import fetchHistory from './fetchHistory';
import { User } from '../actions/ActionTypes';
import reduceReducers from 'app/utils/joinReducers';
import type { State, Action } from 'app/types';

const reducers = {
  allowed,
  quotes,
  events,
  restrictedMails,
  galleryPictures,
  articles,
  pools,
  registrations,
  meetingsToken,
  meetings,
  meetingInvitations,
  memberships,
  companyInterest,
  search,
  comments,
  auth,
  form,
  users,
  groups,
  emailUsers,
  oauth2Applications,
  oauth2Grants,
  emailLists,
  pages,
  galleries,
  toasts,
  notificationsFeed,
  notificationSettings,
  routing: reduceReducers(routing, routerReducer),
  joblistings,
  announcements,
  feedActivities,
  feeds,
  fetchHistory,
  frontpage,
  companies,
  companySemesters,
  surveys,
  surveySubmissions,
  penalties
};

export type Reducers = typeof reducers;

const appReducer = combineReducers(reducers);

export default function rootReducer(state: State, action: Action) {
  if (action.type === User.LOGOUT) {
    return appReducer(
      {
        routing: state.routing
      },
      action
    );
  }

  return appReducer(state, action);
}

export const restrictedMailSchema = new schema.Entity('restrictedMails');

export const groupSchema = new schema.Entity('groups');
export const penaltySchema = new schema.Entity('penalties', {});
export const userSchema = new schema.Entity('users', {
  abakusGroups: [groupSchema],
  penalties: [penaltySchema]
});
export const emailUserSchema = new schema.Entity('emailUsers', {
  user: userSchema
});
export const emailListSchema = new schema.Entity('emailLists', {
  users: [userSchema],
  groups: [groupSchema]
});

export const registrationSchema = new schema.Entity('registrations', {
  user: userSchema
});
export const poolSchema = new schema.Entity('pools', {
  registrations: [registrationSchema]
});
export const commentSchema = new schema.Entity('comments');
export const eventSchema = new schema.Entity('events', {
  pools: [poolSchema],
  comments: [commentSchema],
  waitingRegistrations: [registrationSchema]
});
export const eventAdministrateSchema = new schema.Entity('events', {
  pools: [poolSchema],
  unregistered: [registrationSchema],
  waitingRegistrations: [registrationSchema]
});
export const articleSchema = new schema.Entity('articles', {
  comments: [commentSchema],
  author: userSchema
});

export const galleryPictureSchema = new schema.Entity('galleryPictures', {
  comments: [commentSchema]
});

export const gallerySchema = new schema.Entity('galleries');

export const quoteSchema = new schema.Entity('quotes', {
  comments: [commentSchema]
});
export const pageSchema = new schema.Entity(
  'pages',
  {},
  { idAttribute: 'slug' }
);
export const companyInterestSchema = new schema.Entity('companyInterest');
export const companySchema = new schema.Entity('companies', {
  studentContact: userSchema,
  comments: [commentSchema]
});
export const companySemesterSchema = new schema.Entity('companySemesters');
export const joblistingsSchema = new schema.Entity('joblistings');
export const announcementsSchema = new schema.Entity('announcements');
export const feedActivitySchema = new schema.Entity('feedActivities');
export const oauth2ApplicationSchema = new schema.Entity('oauth2Application');
export const oauth2GrantSchema = new schema.Entity('oauth2Grant');
export const membershipSchema = new schema.Entity('memberships', {
  user: userSchema
});
export const meetingInvitationSchema = new schema.Entity(
  'meetingInvitations',
  {
    user: userSchema
  },
  {
    idAttribute: invite =>
      getMeetingInvitationId(invite.meeting, invite.user.username)
  }
);
export const meetingSchema = new schema.Entity('meetings', {
  invitations: [meetingInvitationSchema],
  reportAuthor: userSchema,
  createdBy: userSchema,
  comments: [commentSchema]
});
export const frontpageSchema = new schema.Entity('frontpage', {
  events: [eventSchema],
  articles: [articleSchema]
});
export const surveySchema = new schema.Entity('surveys', {
  event: eventSchema
});
export const surveySubmissionSchema = new schema.Entity('surveySubmissions', {
  user: userSchema
});
<commit_msg>Rename reduceReducers to joinReducers<commit_after>// @flow

import { schema } from 'normalizr';
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import routing from './routing';
import allowed from './allowed';
import form from './forms';
import companies from './companies';
import companySemesters from './companySemesters';
import emailLists from './emailLists';
import quotes from './quotes';
import galleryPictures from './galleryPictures';
import events from './events';
import articles from './articles';
import pools from './pools';
import registrations from './registrations';
import meetingsToken from './meetingsToken';
import restrictedMails from './restrictedMails';
import meetings from './meetings';
import meetingInvitations, {
  getMeetingInvitationId
} from './meetingInvitations';
import memberships from './memberships';
import search from './search';
import auth from './auth';
import users from './users';
import penalties from './penalties';
import emailUsers from './emailUsers';
import groups from './groups';
import { oauth2Applications, oauth2Grants } from './oauth2';
import toasts from './toasts';
import notificationsFeed from './notificationsFeed';
import notificationSettings from './notificationSettings';
import galleries from './galleries';
import comments from './comments';
import pages from './pages';
import companyInterest from './companyInterest';
import joblistings from './joblistings';
import announcements from './announcements';
import feedActivities from './feedActivities';
import feeds from './feeds';
import frontpage from './frontpage';
import surveys from './surveys';
import surveySubmissions from './surveySubmissions';
import fetchHistory from './fetchHistory';
import { User } from '../actions/ActionTypes';
import joinReducers from 'app/utils/joinReducers';
import type { State, Action } from 'app/types';

const reducers = {
  allowed,
  quotes,
  events,
  restrictedMails,
  galleryPictures,
  articles,
  pools,
  registrations,
  meetingsToken,
  meetings,
  meetingInvitations,
  memberships,
  companyInterest,
  search,
  comments,
  auth,
  form,
  users,
  groups,
  emailUsers,
  oauth2Applications,
  oauth2Grants,
  emailLists,
  pages,
  galleries,
  toasts,
  notificationsFeed,
  notificationSettings,
  routing: joinReducers(routing, routerReducer),
  joblistings,
  announcements,
  feedActivities,
  feeds,
  fetchHistory,
  frontpage,
  companies,
  companySemesters,
  surveys,
  surveySubmissions,
  penalties
};

export type Reducers = typeof reducers;

const appReducer = combineReducers(reducers);

export default function rootReducer(state: State, action: Action) {
  if (action.type === User.LOGOUT) {
    return appReducer(
      {
        routing: state.routing
      },
      action
    );
  }

  return appReducer(state, action);
}

export const restrictedMailSchema = new schema.Entity('restrictedMails');

export const groupSchema = new schema.Entity('groups');
export const penaltySchema = new schema.Entity('penalties', {});
export const userSchema = new schema.Entity('users', {
  abakusGroups: [groupSchema],
  penalties: [penaltySchema]
});
export const emailUserSchema = new schema.Entity('emailUsers', {
  user: userSchema
});
export const emailListSchema = new schema.Entity('emailLists', {
  users: [userSchema],
  groups: [groupSchema]
});

export const registrationSchema = new schema.Entity('registrations', {
  user: userSchema
});
export const poolSchema = new schema.Entity('pools', {
  registrations: [registrationSchema]
});
export const commentSchema = new schema.Entity('comments');
export const eventSchema = new schema.Entity('events', {
  pools: [poolSchema],
  comments: [commentSchema],
  waitingRegistrations: [registrationSchema]
});
export const eventAdministrateSchema = new schema.Entity('events', {
  pools: [poolSchema],
  unregistered: [registrationSchema],
  waitingRegistrations: [registrationSchema]
});
export const articleSchema = new schema.Entity('articles', {
  comments: [commentSchema],
  author: userSchema
});

export const galleryPictureSchema = new schema.Entity('galleryPictures', {
  comments: [commentSchema]
});

export const gallerySchema = new schema.Entity('galleries');

export const quoteSchema = new schema.Entity('quotes', {
  comments: [commentSchema]
});
export const pageSchema = new schema.Entity(
  'pages',
  {},
  { idAttribute: 'slug' }
);
export const companyInterestSchema = new schema.Entity('companyInterest');
export const companySchema = new schema.Entity('companies', {
  studentContact: userSchema,
  comments: [commentSchema]
});
export const companySemesterSchema = new schema.Entity('companySemesters');
export const joblistingsSchema = new schema.Entity('joblistings');
export const announcementsSchema = new schema.Entity('announcements');
export const feedActivitySchema = new schema.Entity('feedActivities');
export const oauth2ApplicationSchema = new schema.Entity('oauth2Application');
export const oauth2GrantSchema = new schema.Entity('oauth2Grant');
export const membershipSchema = new schema.Entity('memberships', {
  user: userSchema
});
export const meetingInvitationSchema = new schema.Entity(
  'meetingInvitations',
  {
    user: userSchema
  },
  {
    idAttribute: invite =>
      getMeetingInvitationId(invite.meeting, invite.user.username)
  }
);
export const meetingSchema = new schema.Entity('meetings', {
  invitations: [meetingInvitationSchema],
  reportAuthor: userSchema,
  createdBy: userSchema,
  comments: [commentSchema]
});
export const frontpageSchema = new schema.Entity('frontpage', {
  events: [eventSchema],
  articles: [articleSchema]
});
export const surveySchema = new schema.Entity('surveys', {
  event: eventSchema
});
export const surveySubmissionSchema = new schema.Entity('surveySubmissions', {
  user: userSchema
});
<|endoftext|>


<commit_before>"use strict";

import Request       from "superagent";
import User          from "../stores/user";
import Constants     from "../constants";
import Dispatcher    from "../dispatcher";
import SettingsStore from '../stores/settings';

const TIMEOUT = 10000;

var _pendingRequests = {};

function abortPendingRequests(key) {
  if(_pendingRequests[key]) {
    _pendingRequests[key]._callback = function() {};
    _pendingRequests[key].abort();
    _pendingRequests[key] = null;
  }
}

// Get the access token from the user
function token() {
  return User.token();
}

function makeUrl(part){
  if(part.indexOf("http") >= 0){
    return part;
  } else {
    return SettingsStore.current().apiUrl + '/' + part;
  }
}

// GET request with a token param
function get(url) {
  return Request
    .get(url)
    .timeout(TIMEOUT)
    .set('Accept', 'application/json')
    .query({
      authtoken: token()
    });
}

// POST request with a token param
function post(url, body) {
  return Request
    .post(url)
    .send(body)
    .set('Accept', 'application/json')
    .timeout(TIMEOUT)
    .query({
      authtoken: token()
    });
}

// PUT request with a token param
function put(url, body) {
  return Request
    .put(url)
    .send(body)
    .set('Accept', 'application/json')
    .timeout(TIMEOUT)
    .query({
      authtoken: token()
    });
}

// DELETER request with a token param
function del(url) {
  return Request
    .del(url)
    .set('Accept', 'application/json')
    .timeout(TIMEOUT)
    .query({
      authtoken: token()
    });
}

function dispatch(key, response) {
  Dispatcher.dispatch({
    action: key,
    data: response
  });
}

// Dispatch a response based on the server response
function dispatchResponse(key) {
  return function(err, response) {
    if(err && err.timeout === TIMEOUT) {
      dispatch(Constants.TIMEOUT, response);
    } else if(response.status === 400) {
      dispatch(Constants.NOT_AUTHORIZED, response);
    } else if(!response.ok) {
      dispatch(Constants.ERROR, response);
    } else {
      dispatch(key, response);
    }
  };
}

function doRequest(key, url, callback){
  abortPendingRequests(key);
  var request = _pendingRequests[key] = callback(makeUrl(url));
  request.end(dispatchResponse(key));
  return request;
}

export default {

  get(key, url){
    return doRequest(key, url, function(fullUrl){
      return get(fullUrl);
    });
  },

  post(key, url, body){
    return doRequest(key, url, function(fullUrl){
      return post(fullUrl, body);
    });
  },

  put(key, url, body){
    return doRequest(key, url, function(fullUrl){
      return put(fullUrl, body);
    });
  },

  del(key, url){
    return doRequest(key, url, function(fullUrl){
      return del(fullUrl);
    });
  }

};
<commit_msg>extra `/` in the request url<commit_after>"use strict";

import Request       from "superagent";
import User          from "../stores/user";
import Constants     from "../constants";
import Dispatcher    from "../dispatcher";
import SettingsStore from '../stores/settings';

const TIMEOUT = 10000;

var _pendingRequests = {};

function abortPendingRequests(key) {
  if(_pendingRequests[key]) {
    _pendingRequests[key]._callback = function() {};
    _pendingRequests[key].abort();
    _pendingRequests[key] = null;
  }
}

// Get the access token from the user
function token() {
  return User.token();
}

function makeUrl(part){
  if(part.indexOf("http") >= 0){
    return part;
  } else {
    return SettingsStore.current().apiUrl + part;
  }
}

// GET request with a token param
function get(url) {
  return Request
    .get(url)
    .timeout(TIMEOUT)
    .set('Accept', 'application/json')
    .query({
      authtoken: token()
    });
}

// POST request with a token param
function post(url, body) {
  return Request
    .post(url)
    .send(body)
    .set('Accept', 'application/json')
    .timeout(TIMEOUT)
    .query({
      authtoken: token()
    });
}

// PUT request with a token param
function put(url, body) {
  return Request
    .put(url)
    .send(body)
    .set('Accept', 'application/json')
    .timeout(TIMEOUT)
    .query({
      authtoken: token()
    });
}

// DELETER request with a token param
function del(url) {
  return Request
    .del(url)
    .set('Accept', 'application/json')
    .timeout(TIMEOUT)
    .query({
      authtoken: token()
    });
}

function dispatch(key, response) {
  Dispatcher.dispatch({
    action: key,
    data: response
  });
}

// Dispatch a response based on the server response
function dispatchResponse(key) {
  return function(err, response) {
    if(err && err.timeout === TIMEOUT) {
      dispatch(Constants.TIMEOUT, response);
    } else if(response.status === 400) {
      dispatch(Constants.NOT_AUTHORIZED, response);
    } else if(!response.ok) {
      dispatch(Constants.ERROR, response);
    } else {
      dispatch(key, response);
    }
  };
}

function doRequest(key, url, callback){
  abortPendingRequests(key);
  var request = _pendingRequests[key] = callback(makeUrl(url));
  request.end(dispatchResponse(key));
  return request;
}

export default {

  get(key, url){
    return doRequest(key, url, function(fullUrl){
      return get(fullUrl);
    });
  },

  post(key, url, body){
    return doRequest(key, url, function(fullUrl){
      return post(fullUrl, body);
    });
  },

  put(key, url, body){
    return doRequest(key, url, function(fullUrl){
      return put(fullUrl, body);
    });
  },

  del(key, url){
    return doRequest(key, url, function(fullUrl){
      return del(fullUrl);
    });
  }

};
<|endoftext|>


<commit_before>// @flow

import { union, find } from 'lodash';
import { createSelector } from 'reselect';
import { User, Event } from '../actions/ActionTypes';
import createEntityReducer from 'app/utils/createEntityReducer';
import { normalize } from 'normalizr';
import { eventSchema, registrationSchema } from 'app/reducers';
import mergeObjects from 'app/utils/mergeObjects';

export type UserEntity = {
  id: number,
  username: string,
  fullName: string,
  firstName: string,
  lastName: string,
  gender: string,
  profilePicture: string,
  emailListsEnabled?: boolean
};

export default createEntityReducer({
  key: 'users',
  types: {
    fetch: User.FETCH
  },
  mutate(state, action) {
    switch (action.type) {
      case Event.SOCKET_EVENT_UPDATED: {
        const users =
          normalize(action.payload, eventSchema).entities.users || {};
        return {
          ...state,
          byId: mergeObjects(state.byId, users),
          items: union(state.items, Object.keys(users))
        };
      }
      case Event.SOCKET_REGISTRATION.SUCCESS:
      case Event.ADMIN_REGISTER.SUCCESS: {
        const users = normalize(action.payload, registrationSchema).entities
          .users;
        return {
          ...state,
          byId: mergeObjects(state.byId, users),
          items: union(state.items, [action.payload.id])
        };
      }
      case User.CONFIRM_STUDENT_USER.SUCCESS: {
        return {
          ...state,
          byId: mergeObjects(state.byId, action.payload)
        };
      }
      default:
        return state;
    }
  }
});

export const selectUserById = createSelector(
  state => state.users.byId,
  (state, props) => props.userId,
  (usersById, userId) => usersById[userId] || {}
);

export const selectUserByUsername = createSelector(
  state => state.users.byId,
  (state, props) => props.username,
  (usersById, username) => find(usersById, ['username', username])
);

export const selectUserWithGroups = createSelector(
  selectUserByUsername,
  state => state.groups.byId,
  (user, groupsById) => {
    if (!user) return;
    return {
      ...user,
      abakusGroups: user.abakusGroups
        ? user.abakusGroups.map(groupId => groupsById[groupId])
        : []
    };
  }
);
<commit_msg>Fix two bugs in user reducer. One where IDs would be converted from int to string, and one where the wrong ID was being put into items.<commit_after>// @flow

import { union, find } from 'lodash';
import { createSelector } from 'reselect';
import { User, Event } from '../actions/ActionTypes';
import createEntityReducer from 'app/utils/createEntityReducer';
import { normalize } from 'normalizr';
import { eventSchema, registrationSchema } from 'app/reducers';
import mergeObjects from 'app/utils/mergeObjects';

export type UserEntity = {
  id: number,
  username: string,
  fullName: string,
  firstName: string,
  lastName: string,
  gender: string,
  profilePicture: string,
  emailListsEnabled?: boolean
};

export default createEntityReducer({
  key: 'users',
  types: {
    fetch: User.FETCH
  },
  mutate(state, action) {
    switch (action.type) {
      case Event.SOCKET_EVENT_UPDATED: {
        const users =
          normalize(action.payload, eventSchema).entities.users || {};
        return {
          ...state,
          byId: mergeObjects(state.byId, users),
          items: union(state.items, Object.values(users).map(u => u.id))
        };
      }
      case Event.SOCKET_REGISTRATION.SUCCESS:
      case Event.ADMIN_REGISTER.SUCCESS: {
        const users = normalize(action.payload, registrationSchema).entities
          .users;
        return {
          ...state,
          byId: mergeObjects(state.byId, users),
          items: union(state.items, Object.values(users).map(u => u.id))
        };
      }
      case User.CONFIRM_STUDENT_USER.SUCCESS: {
        return {
          ...state,
          byId: mergeObjects(state.byId, action.payload)
        };
      }
      default:
        return state;
    }
  }
});

export const selectUserById = createSelector(
  state => state.users.byId,
  (state, props) => props.userId,
  (usersById, userId) => usersById[userId] || {}
);

export const selectUserByUsername = createSelector(
  state => state.users.byId,
  (state, props) => props.username,
  (usersById, username) => find(usersById, ['username', username])
);

export const selectUserWithGroups = createSelector(
  selectUserByUsername,
  state => state.groups.byId,
  (user, groupsById) => {
    if (!user) return;
    return {
      ...user,
      abakusGroups: user.abakusGroups
        ? user.abakusGroups.map(groupId => groupsById[groupId])
        : []
    };
  }
);
<|endoftext|>


<commit_before>import { Meteor }                  from 'meteor/meteor';
import { check, Match }            from 'meteor/check';
import { Auth }                    from '../../auth';
import { CapacityPlanReleases }    from '../../capacity_plans/capacity_plan_releases';
import { Releases }                from '../releases';
import { ReleaseIntegrationLinks } from '../release_integration_links';

Meteor.methods({
  /**
   * Add a capacity plan release
   * @param title
   * @param versionNumber (optional)
   * @param isReleased (optional)
   */
  addRelease (title, versionNumber, isReleased) {
    console.log('addRelease:', title, versionNumber, isReleased);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(title, String);

    // Validate that the current user is an administrator
    if (user.isManager()) {
      return Releases.insert({
        title        : title,
        versionNumber: versionNumber,
        isReleased   : isReleased
      })
    } else {
      console.error('Non-manager tried to add a release:', user.username, title);
      throw new Meteor.Error(403);
    }
  },

  /**
   * Remove a capacity plan release
   * @param releaseId
   */
  deleteRelease (releaseId) {
    console.log('deleteRelease:', releaseId);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(releaseId, String);

    // Validate that the current user is an administrator
    if (user.isAdmin()) {
      // Delete everything linked to this release
      CapacityPlanReleases.find({ releaseId: releaseId }).forEach((planRelease) => {
        // Remove all of the blocks for this release
        CapacityPlanSprintBlocks.remove({ dataId: planRelease._id });
      });

      Releases.remove(releaseId);
    } else {
      console.error('Non-manager tried to delete a release:', user.username, releaseId);
      throw new Meteor.Error(403);
    }
  },

  /**
   * Edit a capacity plan release record
   * @param releaseId
   * @param key
   * @param value
   */
  editRelease (releaseId, key, value) {
    console.log('editRelease:', releaseId, key);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(releaseId, String);
    check(key, String);
    check(value, Match.Any);

    // Get the capacity plan release record to make sure this is authorized
    let release = Releases.findOne(releaseId);

    // Validate that the current user is an administrator
    if (user.isManager()) {
      if (release) {
        let update    = {};
        update[ key ] = value;

        // update the record
        Releases.update(releaseId, { $set: update });
      } else {
        throw new Meteor.Error(404);
      }
    } else {
      console.error('Non-manager tried to edit a release:', user.username, key, releaseId);
      throw new Meteor.Error(403);
    }
  },

  /**
   * Link an integration release to a release
   * @param releaseId
   * @param serverId
   * @param projectId
   * @param integrationReleaseId (optional)
   */
  linkIntegrationRelease (releaseId, serverId, projectId, integrationReleaseId) {
    console.log('linkIntegrationRelease:', releaseId, serverId, projectId, integrationReleaseId);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(releaseId, String);
    check(serverId, String);
    check(projectId, String);

    // Validate that the current user is an administrator
    if (user.isManager()) {
      // Create/update the link
      if (integrationReleaseId != null) {
        // update the record
        ReleaseIntegrationLinks.upsert({
          releaseId: releaseId,
          serverId : serverId,
          projectId: projectId
        }, {
          $set: {
            releaseId           : releaseId,
            serverId            : serverId,
            projectId           : projectId,
            integrationReleaseId: integrationReleaseId
          }
        });
      } else {
        // Remove the link
        ReleaseIntegrationLinks.remove({
          releaseId: releaseId,
          serverId : serverId,
          projectId: projectId
        });
      }
    } else {
      console.error('Non-manager tried to edit a release:', user.username, releaseId, serverId, projectId, integrationReleaseId);
      throw new Meteor.Error(403);
    }
  }
});
<commit_msg>Fixed bug in deleting releases<commit_after>import { Meteor }                   from 'meteor/meteor';
import { check, Match }             from 'meteor/check';
import { Auth }                     from '../../auth';
import { CapacityPlanReleases }     from '../../capacity_plans/capacity_plan_releases';
import { CapacityPlanSprintBlocks } from '../../capacity_plans/capacity_plan_sprint_blocks';
import { Releases }                 from '../releases';
import { ReleaseIntegrationLinks }  from '../release_integration_links';

Meteor.methods({
  /**
   * Add a capacity plan release
   * @param title
   * @param versionNumber (optional)
   * @param isReleased (optional)
   */
  addRelease (title, versionNumber, isReleased) {
    console.log('addRelease:', title, versionNumber, isReleased);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(title, String);

    // Validate that the current user is an administrator
    if (user.isManager()) {
      return Releases.insert({
        title        : title,
        versionNumber: versionNumber,
        isReleased   : isReleased
      })
    } else {
      console.error('Non-manager tried to add a release:', user.username, title);
      throw new Meteor.Error(403);
    }
  },

  /**
   * Remove a capacity plan release
   * @param releaseId
   */
  deleteRelease (releaseId) {
    console.log('deleteRelease:', releaseId);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(releaseId, String);

    // Validate that the current user is an administrator
    if (user.isAdmin()) {
      // Delete everything linked to this release
      CapacityPlanReleases.find({ releaseId: releaseId }).forEach((planRelease) => {
        // Remove all of the blocks for this release
        CapacityPlanSprintBlocks.remove({ dataId: planRelease._id });
      });

      CapacityPlanReleases.remove({ releaseId: releaseId });
      ReleaseIntegrationLinks.remove({ releaseId: releaseId });

      Releases.remove(releaseId);
    } else {
      console.error('Non-manager tried to delete a release:', user.username, releaseId);
      throw new Meteor.Error(403);
    }
  },

  /**
   * Edit a capacity plan release record
   * @param releaseId
   * @param key
   * @param value
   */
  editRelease (releaseId, key, value) {
    console.log('editRelease:', releaseId, key);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(releaseId, String);
    check(key, String);
    check(value, Match.Any);

    // Get the capacity plan release record to make sure this is authorized
    let release = Releases.findOne(releaseId);

    // Validate that the current user is an administrator
    if (user.isManager()) {
      if (release) {
        let update    = {};
        update[ key ] = value;

        // update the record
        Releases.update(releaseId, { $set: update });
      } else {
        throw new Meteor.Error(404);
      }
    } else {
      console.error('Non-manager tried to edit a release:', user.username, key, releaseId);
      throw new Meteor.Error(403);
    }
  },

  /**
   * Link an integration release to a release
   * @param releaseId
   * @param serverId
   * @param projectId
   * @param integrationReleaseId (optional)
   */
  linkIntegrationRelease (releaseId, serverId, projectId, integrationReleaseId) {
    console.log('linkIntegrationRelease:', releaseId, serverId, projectId, integrationReleaseId);
    let user = Auth.requireAuthentication();

    // Validate the data is complete
    check(releaseId, String);
    check(serverId, String);
    check(projectId, String);

    // Validate that the current user is an administrator
    if (user.isManager()) {
      // Create/update the link
      if (integrationReleaseId != null) {
        // update the record
        ReleaseIntegrationLinks.upsert({
          releaseId: releaseId,
          serverId : serverId,
          projectId: projectId
        }, {
          $set: {
            releaseId           : releaseId,
            serverId            : serverId,
            projectId           : projectId,
            integrationReleaseId: integrationReleaseId
          }
        });
      } else {
        // Remove the link
        ReleaseIntegrationLinks.remove({
          releaseId: releaseId,
          serverId : serverId,
          projectId: projectId
        });
      }
    } else {
      console.error('Non-manager tried to edit a release:', user.username, releaseId, serverId, projectId, integrationReleaseId);
      throw new Meteor.Error(403);
    }
  }
});
<|endoftext|>


<commit_before>var config = require('config');
var mapModule = require('map');
var plugins = require('./leaflet_plugins');
var polyUtil = require('./polyline_encoded.js');
var routeboxer = require('./leaflet_routeboxer.js');
var leaflet_label = require('./leaflet_label/leaflet.label-src.js');
var rbush = require('./rbush.js');
var collision = require('./leaflet_layergroup_collision.js');
var session = require('session');

var center = config.geocode().center.split(',').map(parseFloat)
if (config.map_provider && config.map_provider() !== 'AmigoCloud') {
  L.mapbox.accessToken = config.mapbox_access_token();
}

module.exports = function(el) {
  var map, realtime, southWest, northEast, blurLayer;

  if (config.map_provider && config.map_provider() === 'AmigoCloud') {
    southWest = L.latLng(35.946877085397,-123.480610897013);
    northEast = L.latLng(40.763279543715,-118.789317362500);
    map = (new L.amigo.map(el, {
      amigoLogo: 'right',
      loadAmigoLayers: false,
      inertia: false,
      zoomAnimation: $('.hide-map').css('display') !== 'none',
      maxBounds: L.latLngBounds(southWest, northEast),
      minZoom: 8
    })).setView([center[1], center[0]], config.geocode().zoom);

    L.amigo.auth.setToken(config.support_data_token());

    blurLayer = L.tileLayer(
    'https://www.amigocloud.com/api/v1/users/'+
	'23/projects/3019/datasets/23835/tiles/{z}/{x}/{y}.png?' +
	'token=' + config.support_data_token(),
      {
        name: 'Uncovered Area'
      }
    );

    map.addAuthLayer({
      id: config.mapbox_map_id(),
      accessToken: config.mapbox_access_token(),
      name: 'Gray',
      provider: 'mapbox'
    });
    map.addBaseLayer(L.amigo.AmigoGray);
    map.layersControl.addBaseLayer(
      L.bingLayer(
        config.bing_key(),
	{
	  type: 'Road',
	  attribution: 'Bing Maps'
	}
      ),
      'Bing Road'
    );
    map.layersControl.addOverlay(blurLayer);
    blurLayer.addTo(map);

    module.exports.activeMap = map;

    map.realtimeControl = L.control.toggleRealTime().addTo(map);

    realtime = mapModule.realtime();

  } else {

    map = L.mapbox.map(el, config.mapbox_map_id(), {
      attributionControl: false,
      inertia: false,
      zoomAnimation: false
    }).setView([center[1], center[0]], config.geocode().zoom);
  }

  return map;
};

module.exports.getMap = function () {
  return this.activeMap;
};

module.exports.cleanRoute = function() {
    module.exports.activeRoute.removeLayer();
    module.exports.activeRoute = null;
};

module.exports.polyline_creadas = [];
module.exports.marker_creadas = [];
module.exports.makerpoint_creadas;

module.exports.getpolyline_creadas = function () {
  return this.polyline_creadas;
};

module.exports.getMarker_creadas = function () {
  return this.marker_creadas;
};

module.exports.cleanPolyline = function() {
    var polyline_creadas = this.getpolyline_creadas();
    var map = this.activeMap;
    for (i in polyline_creadas) {
        try {
                map.removeLayer(polyline_creadas[i]);

            } catch (e) {
                console.log("problema al eliminar " + e);
            }

  }
  this.polyline_creadas = [];

};

module.exports.cleanMarker = function() {
    var map = this.activeMap;
    for (i in this.marker_creadas) {
        try {
                map.removeLayer(this.marker_creadas[i]);

            } catch (e) {
                console.log("problema al eliminar " + e);
            }
    }

  this.marker_creadas = [];

};

module.exports.cleanMarkerpoint = function() {
    var map = this.activeMap;
    for (i in this.makerpoint_creadas) {
        try {
                map.removeLayer(this.makerpoint_creadas[i]);

            } catch (e) {
                console.log("problema al eliminar " + e);
            }
    }

  //this.makerpoint_creadas = [];

};

module.exports.marker_map = function(from, to){
     var IconStart = L.icon({
        iconUrl: 'assets/images/graphics/start.svg',
        iconSize: [40, 55],
        iconAnchor: [20, 50],
        popupAnchor:  [0, -50]
    });
    var IconEnd = L.icon({
        iconUrl: 'assets/images/graphics/end.svg',
        iconSize: [40, 55],
        iconAnchor: [20, 50],
        popupAnchor:  [0, -50]
    });

    var markerform = new L.marker([from[0],from[1]], {icon: IconStart, draggable: true})
        .addTo(this.activeMap);
    var markerto = new L.marker([to[0],to[1]], {icon: IconEnd, draggable: true})
        .addTo(this.activeMap);
    var _this = this;

    markerform.on('dragend', function(e){
       var marker = e.target;
       var result = marker.getLatLng();
       _this.cleanPolyline();
       _this.cleanMarkerpoint();
       var plan = session.plan();

            plan.setAddress('from', result.lng + ',' + result.lat, function(err, rees) {
                plan.updateRoutes();
          });
    });

    markerto.on('dragend', function(e){
       var marker = e.target;
       var result = marker.getLatLng();
       _this.cleanPolyline();
       _this.cleanMarkerpoint();
       var plan = session.plan();
            plan.setAddress('to', result.lng + ',' + result.lat, function(err, rees) {
                plan.updateRoutes();
          });
    });

    this.marker_creadas.push(markerform);
    this.marker_creadas.push(markerto);
};

module.exports.marker_map_point = function(to, map){

    var name = to[2];

    var IconEnd = L.icon({
        iconUrl: 'assets/images/graphics/icono.png',
        iconSize: [20, 20],
        iconAnchor: [0, 0],
        popupAnchor:  [-3, -76]
    });
    /*
    var markers = [
      L.marker([to[0], to[1]], {icon: IconEnd}).bindLabel(name)
    ];*/

    var marker = L.marker([to[0], to[1]], {icon: IconEnd}).bindLabel(name);

    //var layer = L.layerGroup(markers).addTo(map).eachLayer(function(layer){layer.showLabel()});

    //this.makerpoint_creadas.push(layer);
    this.makerpoint_creadas.addLayer(marker);
    //this.polyline_creadas.push(circle);
};

module.exports.drawRouteAmigo = function(legs,mode) {

    this.makerpoint_creadas = L.LayerGroup.collision({margin:5});
    console.log("Modo de transporte ->", mode);
    var route = legs.legGeometry.points;
    var circle_from = [legs.from.lat, legs.from.lon, legs.from.name];
    var circle_to = [legs.to.lat, legs.to.lon, legs.to.name];
    var color = '#000';
    var weight = 5;
    var dasharray= '';

        if (mode=="CAR") {
            color = '#9E9E9E';
            dasharray= '6';
            weight = 3;

        }else if(mode=="BICYCLE") {
            color = '#FF0000';
            if(!(legs.routeColor === undefined)) {
                color = "#"+legs.routeColor;
             }
            dasharray= '6';
            weight = 3;

        }else if(mode=="SUBWAY" || mode=="RAIL") {
             if(!(legs.routeColor === undefined)) {
                color = "#"+legs.routeColor;
             }
             weight = 8;
             this.marker_map_point(circle_from, this.activeMap);
             this.marker_map_point(circle_to, this.activeMap);

        }
        else if(mode == "WALK") {
            color = '#0BC8F4';
            dasharray= '6';
             weight = 3;
        }

        else if(mode=="BUS") {
            //color = '#FEF0B5';
            if(!(legs.routeColor === undefined)) {
                color = "#"+legs.routeColor;
             }
             weight = 5;
             this.marker_map_point(circle_from, this.activeMap);
             this.marker_map_point(circle_to, this.activeMap);
        }

       var color_options = {
            color: color,
            opacity: 1,
            weight: weight,
            dashArray: dasharray
        };

      route = new L.Polyline(L.PolylineUtil.decode(route, 5), color_options);
      this.polyline_creadas.push(route);
      var boxes = L.RouteBoxer.box(route, 5);
      //var bounds = new L.LatLngBounds([]);
      //var bounds = [];
      var boxpolys = new Array(boxes.length);
      /*
      for (var i = 0; i < boxes.length; i++) {
        //bounds.extend(boxes[i]);
        bounds.push(boxes[i]);
      }*/

      route.addTo(this.activeMap);
      console.log("aqui grupo");
      this.makerpoint_creadas.addTo(this.activeMap);
      //this.activeMap.fitBounds(bounds);
};

<commit_msg>debig<commit_after>var config = require('config');
var mapModule = require('map');
var plugins = require('./leaflet_plugins');
var polyUtil = require('./polyline_encoded.js');
var routeboxer = require('./leaflet_routeboxer.js');
var leaflet_label = require('./leaflet_label/leaflet.label-src.js');
var rbush = require('./rbush.js');
var collision = require('./leaflet_layergroup_collision.js');
var session = require('session');

var center = config.geocode().center.split(',').map(parseFloat)
if (config.map_provider && config.map_provider() !== 'AmigoCloud') {
  L.mapbox.accessToken = config.mapbox_access_token();
}

module.exports = function(el) {
  var map, realtime, southWest, northEast, blurLayer;

  if (config.map_provider && config.map_provider() === 'AmigoCloud') {
    southWest = L.latLng(35.946877085397,-123.480610897013);
    northEast = L.latLng(40.763279543715,-118.789317362500);
    map = (new L.amigo.map(el, {
      amigoLogo: 'right',
      loadAmigoLayers: false,
      inertia: false,
      zoomAnimation: $('.hide-map').css('display') !== 'none',
      maxBounds: L.latLngBounds(southWest, northEast),
      minZoom: 8
    })).setView([center[1], center[0]], config.geocode().zoom);

    L.amigo.auth.setToken(config.support_data_token());

    blurLayer = L.tileLayer(
    'https://www.amigocloud.com/api/v1/users/'+
	'23/projects/3019/datasets/23835/tiles/{z}/{x}/{y}.png?' +
	'token=' + config.support_data_token(),
      {
        name: 'Uncovered Area'
      }
    );

    map.addAuthLayer({
      id: config.mapbox_map_id(),
      accessToken: config.mapbox_access_token(),
      name: 'Gray',
      provider: 'mapbox'
    });
    map.addBaseLayer(L.amigo.AmigoGray);
    map.layersControl.addBaseLayer(
      L.bingLayer(
        config.bing_key(),
	{
	  type: 'Road',
	  attribution: 'Bing Maps'
	}
      ),
      'Bing Road'
    );
    map.layersControl.addOverlay(blurLayer);
    blurLayer.addTo(map);

    module.exports.activeMap = map;

    map.realtimeControl = L.control.toggleRealTime().addTo(map);

    realtime = mapModule.realtime();

  } else {

    map = L.mapbox.map(el, config.mapbox_map_id(), {
      attributionControl: false,
      inertia: false,
      zoomAnimation: false
    }).setView([center[1], center[0]], config.geocode().zoom);
  }

  return map;
};

module.exports.getMap = function () {
  return this.activeMap;
};

module.exports.cleanRoute = function() {
    module.exports.activeRoute.removeLayer();
    module.exports.activeRoute = null;
};

module.exports.polyline_creadas = [];
module.exports.marker_creadas = [];
module.exports.makerpoint_creadas;

module.exports.getpolyline_creadas = function () {
  return this.polyline_creadas;
};

module.exports.getMarker_creadas = function () {
  return this.marker_creadas;
};

module.exports.cleanPolyline = function() {
    var polyline_creadas = this.getpolyline_creadas();
    var map = this.activeMap;
    for (i in polyline_creadas) {
        try {
                map.removeLayer(polyline_creadas[i]);

            } catch (e) {
                console.log("problema al eliminar " + e);
            }

  }
  this.polyline_creadas = [];

};

module.exports.cleanMarker = function() {
    var map = this.activeMap;
    for (i in this.marker_creadas) {
        try {
                map.removeLayer(this.marker_creadas[i]);

            } catch (e) {
                console.log("problema al eliminar " + e);
            }
    }

  this.marker_creadas = [];

};

module.exports.cleanMarkerpoint = function() {
    var map = this.activeMap;
    for (i in this.makerpoint_creadas) {
        try {
                map.removeLayer(this.makerpoint_creadas[i]);

            } catch (e) {
                console.log("problema al eliminar " + e);
            }
    }

  //this.makerpoint_creadas = [];

};

module.exports.marker_map = function(from, to){
     var IconStart = L.icon({
        iconUrl: 'assets/images/graphics/start.svg',
        iconSize: [40, 55],
        iconAnchor: [20, 50],
        popupAnchor:  [0, -50]
    });
    var IconEnd = L.icon({
        iconUrl: 'assets/images/graphics/end.svg',
        iconSize: [40, 55],
        iconAnchor: [20, 50],
        popupAnchor:  [0, -50]
    });

    var markerform = new L.marker([from[0],from[1]], {icon: IconStart, draggable: true})
        .addTo(this.activeMap);
    var markerto = new L.marker([to[0],to[1]], {icon: IconEnd, draggable: true})
        .addTo(this.activeMap);
    var _this = this;

    markerform.on('dragend', function(e){
       var marker = e.target;
       var result = marker.getLatLng();
       _this.cleanPolyline();
       _this.cleanMarkerpoint();
       var plan = session.plan();

            plan.setAddress('from', result.lng + ',' + result.lat, function(err, rees) {
                plan.updateRoutes();
          });
    });

    markerto.on('dragend', function(e){
       var marker = e.target;
       var result = marker.getLatLng();
       _this.cleanPolyline();
       _this.cleanMarkerpoint();
       var plan = session.plan();
            plan.setAddress('to', result.lng + ',' + result.lat, function(err, rees) {
                plan.updateRoutes();
          });
    });

    this.marker_creadas.push(markerform);
    this.marker_creadas.push(markerto);
};

module.exports.marker_map_point = function(to, map){

    var name = to[2];

    var IconEnd = L.icon({
        iconUrl: 'assets/images/graphics/icono.png',
        iconSize: [20, 20],
        iconAnchor: [0, 0],
        popupAnchor:  [-3, -76]
    });
    /*
    var markers = [
      L.marker([to[0], to[1]], {icon: IconEnd}).bindLabel(name)
    ];*/

    var marker = L.marker([to[0], to[1]], {icon: IconEnd}).bindLabel(name);

    //var layer = L.layerGroup(markers).addTo(map).eachLayer(function(layer){layer.showLabel()});

    //this.makerpoint_creadas.push(layer);
    this.makerpoint_creadas.addLayer(marker);
    //this.polyline_creadas.push(circle);
};

module.exports.drawRouteAmigo = function(legs,mode) {

    this.makerpoint_creadas = L.LayerGroup.collision({margin:5});
    console.log("Modo de transporte ->", mode);
    var route = legs.legGeometry.points;
    var circle_from = [legs.from.lat, legs.from.lon, legs.from.name];
    var circle_to = [legs.to.lat, legs.to.lon, legs.to.name];
    var color = '#000';
    var weight = 5;
    var dasharray= '';

        if (mode=="CAR") {
            color = '#9E9E9E';
            dasharray= '6';
            weight = 3;

        }else if(mode=="BICYCLE") {
            color = '#FF0000';
            if(!(legs.routeColor === undefined)) {
                color = "#"+legs.routeColor;
             }
            dasharray= '6';
            weight = 3;

        }else if(mode=="SUBWAY" || mode=="RAIL") {
             if(!(legs.routeColor === undefined)) {
                color = "#"+legs.routeColor;
             }
             weight = 8;
             this.marker_map_point(circle_from, this.activeMap);
             this.marker_map_point(circle_to, this.activeMap);

        }
        else if(mode == "WALK") {
            color = '#0BC8F4';
            dasharray= '6';
             weight = 3;
        }

        else if(mode=="BUS") {
            //color = '#FEF0B5';
            if(!(legs.routeColor === undefined)) {
                color = "#"+legs.routeColor;
             }
             weight = 5;
             this.marker_map_point(circle_from, this.activeMap);
             this.marker_map_point(circle_to, this.activeMap);
        }

       var color_options = {
            color: color,
            opacity: 1,
            weight: weight,
            dashArray: dasharray
        };

      route = new L.Polyline(L.PolylineUtil.decode(route, 5), color_options);
      this.polyline_creadas.push(route);
      var boxes = L.RouteBoxer.box(route, 5);
      //var bounds = new L.LatLngBounds([]);
      //var bounds = [];
      var boxpolys = new Array(boxes.length);
      /*
      for (var i = 0; i < boxes.length; i++) {
        //bounds.extend(boxes[i]);
        bounds.push(boxes[i]);
      }*/

      route.addTo(this.activeMap);
      console.log("aqui grupo ->", this.makerpoint_creadas);
      this.makerpoint_creadas.addTo(this.activeMap);
      //this.activeMap.fitBounds(bounds);
};

<|endoftext|>


<commit_before>import angularMeteor from 'angular-meteor';
import { Players } from '/imports/api/players.js';
import { Teams } from '/imports/api/teams.js';
import { Games } from '/imports/api/games.js';

class GameScoreService {
  constructor() {
    // Maximum movement of ELO in 1 match
    this.maxEloMovement = 75;
  }

  scored(teamId, player, inprogress) {
    if (inprogress.teamRed._id == teamId) // red scored
    {
      if (inprogress.teamRed.attacker._id == player) {
        inprogress.teamRed.attacker.goals++;
        Games.update(inprogress._id, {
          $inc: { teamRedScore: 1 },
          $set: { teamRed: inprogress.teamRed }
        });
      } else {
        inprogress.teamRed.defender.goals++;
        Games.update(inprogress._id, {
          $inc: { teamRedScore: 1 },
          $set: { teamRed: inprogress.teamRed }
        });
      }
      if (inprogress.teamRedScore++ > 5) {
        var eloChange = this.updateELO(inprogress.teamRed._id, inprogress.teamBlue._id);
        Games.update(inprogress._id, {
          $set: {
            winner: inprogress.teamRed._id,
            endDate: Date.now(),
            eloChange: eloChange
          }
        });

        console.log('red won!');
      }
    } else {
      if (inprogress.teamBlue.attacker._id == player) {
        inprogress.teamBlue.attacker.goals++;
        Games.update(inprogress._id, {
          $inc: { teamBlueScore: 1 },
          $set: { teamBlue: inprogress.teamBlue }
        });
      } else {
        inprogress.teamBlue.defender.goals++;
        Games.update(inprogress._id, {
          $inc: { teamBlueScore: 1 },
          $set: { teamBlue: inprogress.teamBlue }
        });
      }
      if (inprogress.teamBlueScore++ > 5) {

        var eloChange = this.updateELO(inprogress.teamBlue._id, inprogress.teamRed._id);
        Games.update(inprogress._id, {
          $set: {
            winner: inprogress.teamBlue,
            endDate: Date.now(),
            eloChange: eloChange
          }
        });
        console.log('blue won!');
      }
    }
  }

  updateELO(winTeamId, looseTeamId) {

    let eloChange = this.getTeamEloOnWin(winTeamId, looseTeamId).win;
    console.log('ELO changed by: ', eloChange);
    let winTeam = Teams.findOne({ _id: winTeamId });
    let looseTeam = Teams.findOne({ _id: looseTeamId });
    let winp1 = Players.findOne({ _id: winTeam.players[0] });
    let winp2 = Players.findOne({ _id: winTeam.players[1] });
    let loosep1 = Players.findOne({ _id: looseTeam.players[0] });
    let loosep2 = Players.findOne({ _id: looseTeam.players[1] });

    Players.update({ _id: winp1._id },
      {
        $inc: { elo: eloChange }
      }
    )
    Players.update({ _id: winp2._id },
      {
        $inc: { elo: eloChange }
      }
    )
    Players.update({ _id: loosep1._id },
      {
        $inc: { elo: -eloChange }
      }
    )
    Players.update({ _id: loosep2._id },
      {
        $inc: { elo: -eloChange }
      }
    )

    let teamEloChanged = this.calculateELORatingChange(winTeam.teamElo, looseTeam.teamElo, this.maxEloMovement);
    console.log('Team ELO change by: ', teamEloChanged);

    Teams.update({ _id: winTeam._id },
      {
        $inc: { teamElo: teamEloChanged.win }
      }
    );
    Teams.update({ _id: looseTeam._id },
      {
        $inc: { teamElo: teamEloChanged.loss }
      }
    );

    return eloChange;
  }

  getTeamEloOnWin(winTeamId, looseTeamId) {
    let winTeam = Teams.findOne({ _id: winTeamId });
    let looseTeam = Teams.findOne({ _id: looseTeamId });
    let winp1 = Players.findOne({ _id: winTeam.players[0] });
    let winp2 = Players.findOne({ _id: winTeam.players[1] });
    let loosep1 = Players.findOne({ _id: looseTeam.players[0] });
    let loosep2 = Players.findOne({ _id: looseTeam.players[1] });

    let winelo = (winp1.elo + winp2.elo) / 2;
    let looseelo = (loosep1.elo + loosep2.elo) / 2;

    let eloChanged = this.calculateELORatingChange(winelo, looseelo, this.maxEloMovement);
    return eloChanged;
  }
  /**
   * This method will calculate the change in a player's
   * Elo rating after playing a single game against another player.
   * The value K is the maximum change in rating.
   **/
  calculateELORatingChange(elo1, elo2, k) {
    var percentage = 1 / (1 + Math.pow(10, (elo2 - elo1) / 400));

    return {
      win: Math.round(k * (1 - percentage)),
      draw: Math.round(k * (.5 - percentage)),
      loss: Math.round(k * (0 - percentage)),
      percent: Math.round(percentage * 100)
    };
  }

  static factory(){
    return new GameScoreService();
  }
}

export default angular.module('gameservice', [
  angularMeteor
])
  .factory('gameScoreService', GameScoreService.factory);
<commit_msg>Use iso date as end date on game<commit_after>import angularMeteor from 'angular-meteor';
import { Players } from '/imports/api/players.js';
import { Teams } from '/imports/api/teams.js';
import { Games } from '/imports/api/games.js';

class GameScoreService {
  constructor() {
    // Maximum movement of ELO in 1 match
    this.maxEloMovement = 75;
  }

  scored(teamId, player, inprogress) {
    if (inprogress.teamRed._id == teamId) // red scored
    {
      if (inprogress.teamRed.attacker._id == player) {
        inprogress.teamRed.attacker.goals++;
        Games.update(inprogress._id, {
          $inc: { teamRedScore: 1 },
          $set: { teamRed: inprogress.teamRed }
        });
      } else {
        inprogress.teamRed.defender.goals++;
        Games.update(inprogress._id, {
          $inc: { teamRedScore: 1 },
          $set: { teamRed: inprogress.teamRed }
        });
      }
      if (inprogress.teamRedScore++ > 5) {
        var eloChange = this.updateELO(inprogress.teamRed._id, inprogress.teamBlue._id);
        Games.update(inprogress._id, {
          $set: {
            winner: inprogress.teamRed._id,
            endDate: new Date(),
            eloChange: eloChange
          }
        });

        console.log('red won!');
      }
    } else {
      if (inprogress.teamBlue.attacker._id == player) {
        inprogress.teamBlue.attacker.goals++;
        Games.update(inprogress._id, {
          $inc: { teamBlueScore: 1 },
          $set: { teamBlue: inprogress.teamBlue }
        });
      } else {
        inprogress.teamBlue.defender.goals++;
        Games.update(inprogress._id, {
          $inc: { teamBlueScore: 1 },
          $set: { teamBlue: inprogress.teamBlue }
        });
      }
      if (inprogress.teamBlueScore++ > 5) {

        var eloChange = this.updateELO(inprogress.teamBlue._id, inprogress.teamRed._id);
        Games.update(inprogress._id, {
          $set: {
            winner: inprogress.teamBlue,
            endDate: new Date(),
            eloChange: eloChange
          }
        });
        console.log('blue won!');
      }
    }
  }

  updateELO(winTeamId, looseTeamId) {

    let eloChange = this.getTeamEloOnWin(winTeamId, looseTeamId).win;
    console.log('ELO changed by: ', eloChange);
    let winTeam = Teams.findOne({ _id: winTeamId });
    let looseTeam = Teams.findOne({ _id: looseTeamId });
    let winp1 = Players.findOne({ _id: winTeam.players[0] });
    let winp2 = Players.findOne({ _id: winTeam.players[1] });
    let loosep1 = Players.findOne({ _id: looseTeam.players[0] });
    let loosep2 = Players.findOne({ _id: looseTeam.players[1] });

    Players.update({ _id: winp1._id },
      {
        $inc: { elo: eloChange }
      }
    )
    Players.update({ _id: winp2._id },
      {
        $inc: { elo: eloChange }
      }
    )
    Players.update({ _id: loosep1._id },
      {
        $inc: { elo: -eloChange }
      }
    )
    Players.update({ _id: loosep2._id },
      {
        $inc: { elo: -eloChange }
      }
    )

    let teamEloChanged = this.calculateELORatingChange(winTeam.teamElo, looseTeam.teamElo, this.maxEloMovement);
    console.log('Team ELO change by: ', teamEloChanged);

    Teams.update({ _id: winTeam._id },
      {
        $inc: { teamElo: teamEloChanged.win }
      }
    );
    Teams.update({ _id: looseTeam._id },
      {
        $inc: { teamElo: teamEloChanged.loss }
      }
    );

    return eloChange;
  }

  getTeamEloOnWin(winTeamId, looseTeamId) {
    let winTeam = Teams.findOne({ _id: winTeamId });
    let looseTeam = Teams.findOne({ _id: looseTeamId });
    let winp1 = Players.findOne({ _id: winTeam.players[0] });
    let winp2 = Players.findOne({ _id: winTeam.players[1] });
    let loosep1 = Players.findOne({ _id: looseTeam.players[0] });
    let loosep2 = Players.findOne({ _id: looseTeam.players[1] });

    let winelo = (winp1.elo + winp2.elo) / 2;
    let looseelo = (loosep1.elo + loosep2.elo) / 2;

    let eloChanged = this.calculateELORatingChange(winelo, looseelo, this.maxEloMovement);
    return eloChanged;
  }
  /**
   * This method will calculate the change in a player's
   * Elo rating after playing a single game against another player.
   * The value K is the maximum change in rating.
   **/
  calculateELORatingChange(elo1, elo2, k) {
    var percentage = 1 / (1 + Math.pow(10, (elo2 - elo1) / 400));

    return {
      win: Math.round(k * (1 - percentage)),
      draw: Math.round(k * (.5 - percentage)),
      loss: Math.round(k * (0 - percentage)),
      percent: Math.round(percentage * 100)
    };
  }

  static factory(){
    return new GameScoreService();
  }
}

export default angular.module('gameservice', [
  angularMeteor
])
  .factory('gameScoreService', GameScoreService.factory);
<|endoftext|>