<commit_before>/*!
 *  Lang.js for Laravel localization in JavaScript.
 *
 *  @version 1.0.0
 *  @license MIT
 *  @site    https://github.com/rmariuzzo/Lang.js
 *  @author  Rubens Mariuzzo <rubens@mariuzzo.com>
 */

'use strict';

(function(root, factory) {

    if (typeof define === 'function' && define.amd) {
        // AMD support.
        define([], new(factory()));
    } else if (typeof exports === 'object') {
        // NodeJS support.
        module.exports = new(factory())();
    } else {
        // Browser global support.
        root.Lang = new(factory())();
    }

}(this, function() {

    // Default options //

    var defaults = {
        defaultLocale: 'en' /** The default locale if not set. */
    };

    // Constructor //

    var Lang = function(options) {
        options = options || {};
        this.defaultLocale = options.defaultLocale || defaults.defaultLocale;
    };

    // Methods //

    /**
     * Set messages source.
     *
     * @param messages {object} The messages source.
     *
     * @return void
     */
    Lang.prototype.setMessages = function(messages) {
        this.messages = messages;
    };

    /**
     * Returns a translation message.
     *
     * @param key {string} The key of the message.
     * @param replacements {object} The replacements to be done in the message.
     *
     * @return {string} The translation message, if not found the given key.
     */
    Lang.prototype.get = function(key, replacements) {
        if (!this.has(key)) {
            return key;
        }

        var message = this._getMessage(key, replacements);
        if (message === null) {
            return key;
        }

        if (replacements) {
            message = this._applyReplacements(message, replacements);
        }

        return message;
    };

    /**
     * Returns true if the key is defined on the messages source.
     *
     * @param key {string} The key of the message.
     *
     * @return {boolean} true if the given key is defined on the messages source, otherwise false.
     */
    Lang.prototype.has = function(key) {
        if (typeof key !== 'string' || !this.messages) {
            return false;
        }
        return this._getMessage(key) !== null;
    };

    /**
     * Gets the plural or singular form of the message specified based on an integer value.
     *
     * @param key {string} The key of the message.
     * @param count {integer} The number of elements.
     * @param replacements {object} The replacements to be done in the message.
     *
     * @return {string} The translation message according to an integer value.
     */
    Lang.prototype.choice = function(key, count, replacements) {
        // Set default values for parameters replace and locale
        replacements = typeof replacements !== 'undefined' ? replacements : {};

        // The count must be replaced if found in the message
        replacements['count'] = count;

        // Message to get the plural or singular
        var message = this.get(key, replacements);

        // Check if message is not null or undefined
        if (message === null || message === undefined) {
            return message;
        }

        // Separate the plural from the singular, if any
        var messageParts = message.split('|');

        // Get the explicit rules, If any
        var explicitRules = [];
        var regex = /{\d+}\s(.+)|\[\d+,\d+\]\s(.+)|\[\d+,Inf\]\s(.+)/;

        for (var i = 0; i < messageParts.length; i++) {
            messageParts[i] = messageParts[i].trim();

            if (regex.test(messageParts[i])) {
                var messageSpaceSplit = messageParts[i].split(/\s/);
                explicitRules.push(messageSpaceSplit.shift());
                messageParts[i] = messageSpaceSplit.join(' ');
            }
        }

        // Check if there's only one message
        if (messageParts.length === 1) {
            // Nothing to do here
            return message;
        }

        // Check the explicit rules
        for (var i = 0; i < explicitRules.length; i++) {
            if (this._testInterval(count, explicitRules[i])) {
                return messageParts[i];
            }
        }

        // Standard rules
        if (count > 1) {
            return messageParts[1];
        } else {
            return messageParts[0];
        }
    };

    /**
     * Set the current locale.
     *
     * @param locale {string} The locale to set.
     *
     * @return void
     */
    Lang.prototype.setLocale = function(locale) {
        this.locale = locale;
    };

    /**
     * Get the current locale.
     *
     * @return {string} The current locale.
     */
    Lang.prototype.getLocale = function() {
        return this.locale || this.defaultLocale;
    };

    /**
     * Parse a message key into components.
     *
     * @param key {string} The message key to parse.
     *
     * @return {object} A key object with source and entries properties.
     */
    Lang.prototype._parseKey = function(key) {
        if (typeof key !== 'string') {
            return null;
        }
        var segments = key.split('.');
        return {
            source: this.getLocale() + '.' + segments[0],
            entries: segments.slice(1)
        };
    };

    /**
     * Returns a translation message. Use `Lang.get()` method instead, this methods assumes the key exists.
     *
     * @param key {string} The key of the message.
     *
     * @return {string} The translation message for the given key.
     */
    Lang.prototype._getMessage = function(key) {

        key = this._parseKey(key);

        // Ensure message source exists.
        if (this.messages[key.source] === undefined) {
            return null;
        }

        // Get message text.
        var message = this.messages[key.source];
        while (key.entries.length && (message = message[key.entries.shift()]));

        if (typeof message !== 'string') {
            return null;
        }

        return message;
    };

    /**
     * Apply replacements to a string message containing placeholders.
     *
     * @param message {string} The text message.
     * @param replacements {object} The replacements to be done in the message.
     *
     * @return {string} The string message with replacements applied.
     */
    Lang.prototype._applyReplacements = function(message, replacements) {
        for (var replace in replacements) {
            message = message.split(':' + replace).join(replacements[replace]);
        }
        return message;
    };

    /**
     * Checks if the given `count` is within the interval defined by the {string} `interval`
     *
     * @param  count {int}  The amount of items.
     * @param  interval {string}    The interval to be compared with the count.
     * @return {boolean}    Returns true if count is within interval; false otherwise.
     */
    Lang.prototype._testInterval = function(count, interval) {
        /**
         * From the Symfony\Component\Translation\Interval Docs
         *
         * Tests if a given number belongs to a given math interval.
         * An interval can represent a finite set of numbers: {1,2,3,4}
         * An interval can represent numbers between two numbers: [1, +Inf] ]-1,2[
         * The left delimiter can be [ (inclusive) or ] (exclusive).
         * The right delimiter can be [ (exclusive) or ] (inclusive).
         * Beside numbers, you can use -Inf and +Inf for the infinite.
         */

        return false;
    };

    return Lang;

}));
<commit_msg>Update lang.js<commit_after>/*!
 *  Lang.js for Laravel localization in JavaScript.
 *
 *  @version 1.0.0
 *  @license MIT
 *  @site    https://github.com/rmariuzzo/Lang.js
 *  @author  Rubens Mariuzzo <rubens@mariuzzo.com>
 */

'use strict';

(function(root, factory) {

    if (typeof define === 'function' && define.amd) {
        // AMD support.
        define([], new(factory()));
    } else if (typeof exports === 'object') {
        // NodeJS support.
        module.exports = new(factory())();
    } else {
        // Browser global support.
        root.Lang = new(factory())();
    }

}(this, function() {

    // Default options //

    var defaults = {
        defaultLocale: 'en' /** The default locale if not set. */
    };

    // Constructor //

    var Lang = function(options) {
        options = options || {};
        this.defaultLocale = options.defaultLocale || defaults.defaultLocale;
    };

    // Methods //

    /**
     * Set messages source.
     *
     * @param messages {object} The messages source.
     *
     * @return void
     */
    Lang.prototype.setMessages = function(messages) {
        this.messages = messages;
    };

    /**
     * Returns a translation message.
     *
     * @param key {string} The key of the message.
     * @param replacements {object} The replacements to be done in the message.
     *
     * @return {string} The translation message, if not found the given key.
     */
    Lang.prototype.get = function(key, replacements) {
        if (!this.has(key)) {
            return key;
        }

        var message = this._getMessage(key);
        if (message === null) {
            return key;
        }

        if (replacements) {
            message = this._applyReplacements(message, replacements);
        }

        return message;
    };

    /**
     * Returns true if the key is defined on the messages source.
     *
     * @param key {string} The key of the message.
     *
     * @return {boolean} true if the given key is defined on the messages source, otherwise false.
     */
    Lang.prototype.has = function(key) {
        if (typeof key !== 'string' || !this.messages) {
            return false;
        }
        return this._getMessage(key) !== null;
    };

    /**
     * Gets the plural or singular form of the message specified based on an integer value.
     *
     * @param key {string} The key of the message.
     * @param count {integer} The number of elements.
     * @param replacements {object} The replacements to be done in the message.
     *
     * @return {string} The translation message according to an integer value.
     */
    Lang.prototype.choice = function(key, count, replacements) {
        // Set default values for parameters replace and locale
        replacements = typeof replacements !== 'undefined' ? replacements : {};

        // The count must be replaced if found in the message
        replacements['count'] = count;

        // Message to get the plural or singular
        var message = this.get(key, replacements);

        // Check if message is not null or undefined
        if (message === null || message === undefined) {
            return message;
        }

        // Separate the plural from the singular, if any
        var messageParts = message.split('|');

        // Get the explicit rules, If any
        var explicitRules = [];
        var regex = /{\d+}\s(.+)|\[\d+,\d+\]\s(.+)|\[\d+,Inf\]\s(.+)/;

        for (var i = 0; i < messageParts.length; i++) {
            messageParts[i] = messageParts[i].trim();

            if (regex.test(messageParts[i])) {
                var messageSpaceSplit = messageParts[i].split(/\s/);
                explicitRules.push(messageSpaceSplit.shift());
                messageParts[i] = messageSpaceSplit.join(' ');
            }
        }

        // Check if there's only one message
        if (messageParts.length === 1) {
            // Nothing to do here
            return message;
        }

        // Check the explicit rules
        for (var i = 0; i < explicitRules.length; i++) {
            if (this._testInterval(count, explicitRules[i])) {
                return messageParts[i];
            }
        }

        // Standard rules
        if (count > 1) {
            return messageParts[1];
        } else {
            return messageParts[0];
        }
    };

    /**
     * Set the current locale.
     *
     * @param locale {string} The locale to set.
     *
     * @return void
     */
    Lang.prototype.setLocale = function(locale) {
        this.locale = locale;
    };

    /**
     * Get the current locale.
     *
     * @return {string} The current locale.
     */
    Lang.prototype.getLocale = function() {
        return this.locale || this.defaultLocale;
    };

    /**
     * Parse a message key into components.
     *
     * @param key {string} The message key to parse.
     *
     * @return {object} A key object with source and entries properties.
     */
    Lang.prototype._parseKey = function(key) {
        if (typeof key !== 'string') {
            return null;
        }
        var segments = key.split('.');
        return {
            source: this.getLocale() + '.' + segments[0],
            entries: segments.slice(1)
        };
    };

    /**
     * Returns a translation message. Use `Lang.get()` method instead, this methods assumes the key exists.
     *
     * @param key {string} The key of the message.
     *
     * @return {string} The translation message for the given key.
     */
    Lang.prototype._getMessage = function(key) {

        key = this._parseKey(key);

        // Ensure message source exists.
        if (this.messages[key.source] === undefined) {
            return null;
        }

        // Get message text.
        var message = this.messages[key.source];
        while (key.entries.length && (message = message[key.entries.shift()]));

        if (typeof message !== 'string') {
            return null;
        }

        return message;
    };

    /**
     * Apply replacements to a string message containing placeholders.
     *
     * @param message {string} The text message.
     * @param replacements {object} The replacements to be done in the message.
     *
     * @return {string} The string message with replacements applied.
     */
    Lang.prototype._applyReplacements = function(message, replacements) {
        for (var replace in replacements) {
            message = message.split(':' + replace).join(replacements[replace]);
        }
        return message;
    };

    /**
     * Checks if the given `count` is within the interval defined by the {string} `interval`
     *
     * @param  count {int}  The amount of items.
     * @param  interval {string}    The interval to be compared with the count.
     * @return {boolean}    Returns true if count is within interval; false otherwise.
     */
    Lang.prototype._testInterval = function(count, interval) {
        /**
         * From the Symfony\Component\Translation\Interval Docs
         *
         * Tests if a given number belongs to a given math interval.
         * An interval can represent a finite set of numbers: {1,2,3,4}
         * An interval can represent numbers between two numbers: [1, +Inf] ]-1,2[
         * The left delimiter can be [ (inclusive) or ] (exclusive).
         * The right delimiter can be [ (exclusive) or ] (inclusive).
         * Beside numbers, you can use -Inf and +Inf for the infinite.
         */

        return false;
    };

    return Lang;

}));
<|endoftext|>


<commit_before>var mtdict = {
  "zh-TW":
    {
      "auth-diglog-button": "驗證",
      "auth-diglog-body": "你必須要先驗證Google帳戶才能編輯這個行事曆",
      "auth-diglog-title": "驗證你的Google帳戶",
      "new_event": "新增事件",
      "table_action": "動作",
      "table_summary": "摘要",
      "cal_name": "日曆名稱",
      "cal_timezone": "此日曆時區",
      "msg_time": "以下已轉換為本地時間",
      "event_list": "事件列表",
      "table_start_time": "開始時間",
      "table_end_time": "結束時間",
      "table_duration": "持續",
      "table_left": "距離該活動剩下",
      "new_event-dialog-title": "新增事件",
      "new_event-dialog-time-msg": "以下時間使用該日曆時區",
      "new_event-dialog-summary": "摘要",
      "new_event-dialog-summary-self": "請輸入摘要",
      "new_event-dialog-allday": "整天",
      "new_event-dialog-allday-checkbox": "是",
      "new_event-dialog-start-time": "開始時間",
      "new_event-dialog-end-time": "結束時間",
      "new_event-dialog-detail": "詳細內容",
      "new_event-dialog-detail-self": "此事件詳細描述",
      "new_event-dialog-cancel": "取消",
      "new_event-dialog-add": "新增事件",
      "delete-diglog-title": "刪除事件",
      "delete-diglog-body": "你確定要刪除這個事件嗎?",
      "delete-diglog-cancel": "取消",
      "delete-diglog-delete": "刪除",
      "edit-dialog-title": "編輯事件",
      "edit-dialog-time-msg": "以下時間使用該日曆時區",
      "edit-dialog-summary": "摘要",
      "edit-dialog-summary-self": "請輸入摘要",
      "edit-dialog-allday": "整天",
      "edit-dialog-allday-checkbox": "是",
      "edit-dialog-start-time": "開始時間",
      "edit-dialog-end-time": "結束時間",
      "edit-dialog-detail": "詳細內容",
      "edit-dialog-detail-self": "此事件詳細描述",
      "edit-dialog-cancel": "取消",
      "edit-dialog-edit": "確定編輯"
    },
  "en-US":
    {
      "auth-diglog-button": "Authorize",
      "auth-diglog-body": "You need to sign in to edit the calendar",
      "auth-diglog-title": "Authorize",
      "new_event": "Add a new event",
      "table_action": "Action",
      "table_summary": "Summary",
      "cal_name": "Calendar Name",
      "cal_timezone": "Timezone of Calendar",
      "msg_time": "The following date time has been converted to your local timezone.",
      "event_list": "Event Lisjt",
      "table_start_time": "Start Time",
      "table_end_time": "End Time",
      "table_duration": "Duration",
      "table_left": "Left",
      "new_event-dialog-title": "Add a new event",
      "new_event-dialog-time-msg": "待翻譯",
      "new_event-dialog-summary": "Summary",
      "new_event-dialog-summary-self": "待翻譯",
      "new_event-dialog-allday": "All day event?",
      "new_event-dialog-allday-checkbox": "Yes",
      "new_event-dialog-start-time": "Start Time",
      "new_event-dialog-end-time": "End Time",
      "new_event-dialog-detail": "Detail",
      "new_event-dialog-detail-self": "待翻譯",
      "new_event-dialog-cancel": "Cancel",
      "new_event-dialog-add": "Add",
      "delete-diglog-title": "Confirm delete",
      "delete-diglog-body": "待翻譯",
      "delete-diglog-cancel": "Cancel",
      "delete-diglog-delete": "Confirm",
      "edit-dialog-title": "Edit this event",
      "edit-dialog-time-msg": "待翻譯",
      "edit-dialog-summary": "Summary",
      "edit-dialog-summary-self": "待翻譯",
      "edit-dialog-allday": "All day event",
      "edit-dialog-allday-checkbox": "Yes",
      "edit-dialog-start-time": "Start Time",
      "edit-dialog-end-time": "End Time",
      "edit-dialog-detail": "Detail",
      "edit-dialog-detail-self": "待翻譯",
      "edit-dialog-cancel": "Cancel",
      "edit-dialog-edit": "Edit"

    }
};

var lang = window.navigator.language;
if (mtdict[lang] == undefined){
    lang = 'en-US';
}
switchLang(lang)

function mt(e) {
  var v = dict[e];
  return (v===undefined)?e:v;
}

function switchLang(pLang) {
  lang = pLang;
  dict = mtdict[lang];
  $( "[data-lang]" ).each(function() {
      var e = $(this).data("lang");
      if ($(this).attr("placeholder") === undefined) {
            $(this).text(mt(e));
          } else {
                $(this).attr("placeholder", mt(e));
              }
    });
}

<commit_msg>Fixed worng word<commit_after>var mtdict = {
  "zh-TW":
    {
      "auth-diglog-button": "驗證",
      "auth-diglog-body": "你必須要先驗證Google帳戶才能編輯這個行事曆",
      "auth-diglog-title": "驗證你的Google帳戶",
      "new_event": "新增事件",
      "table_action": "動作",
      "table_summary": "摘要",
      "cal_name": "日曆名稱",
      "cal_timezone": "此日曆時區",
      "msg_time": "以下已轉換為本地時間",
      "event_list": "事件列表",
      "table_start_time": "開始時間",
      "table_end_time": "結束時間",
      "table_duration": "持續",
      "table_left": "距離該活動剩下",
      "new_event-dialog-title": "新增事件",
      "new_event-dialog-time-msg": "以下時間使用該日曆時區",
      "new_event-dialog-summary": "摘要",
      "new_event-dialog-summary-self": "請輸入摘要",
      "new_event-dialog-allday": "整天",
      "new_event-dialog-allday-checkbox": "是",
      "new_event-dialog-start-time": "開始時間",
      "new_event-dialog-end-time": "結束時間",
      "new_event-dialog-detail": "詳細內容",
      "new_event-dialog-detail-self": "此事件詳細描述",
      "new_event-dialog-cancel": "取消",
      "new_event-dialog-add": "新增事件",
      "delete-diglog-title": "刪除事件",
      "delete-diglog-body": "你確定要刪除這個事件嗎?",
      "delete-diglog-cancel": "取消",
      "delete-diglog-delete": "刪除",
      "edit-dialog-title": "編輯事件",
      "edit-dialog-time-msg": "以下時間使用該日曆時區",
      "edit-dialog-summary": "摘要",
      "edit-dialog-summary-self": "請輸入摘要",
      "edit-dialog-allday": "整天",
      "edit-dialog-allday-checkbox": "是",
      "edit-dialog-start-time": "開始時間",
      "edit-dialog-end-time": "結束時間",
      "edit-dialog-detail": "詳細內容",
      "edit-dialog-detail-self": "此事件詳細描述",
      "edit-dialog-cancel": "取消",
      "edit-dialog-edit": "確定編輯"
    },
  "en-US":
    {
      "auth-diglog-button": "Authorize",
      "auth-diglog-body": "You need to sign in to edit the calendar",
      "auth-diglog-title": "Authorize",
      "new_event": "Add a new event",
      "table_action": "Action",
      "table_summary": "Summary",
      "cal_name": "Calendar Name",
      "cal_timezone": "Timezone of Calendar",
      "msg_time": "The following date time has been converted to your local timezone.",
      "event_list": "Event List",
      "table_start_time": "Start Time",
      "table_end_time": "End Time",
      "table_duration": "Duration",
      "table_left": "Left",
      "new_event-dialog-title": "Add a new event",
      "new_event-dialog-time-msg": "待翻譯",
      "new_event-dialog-summary": "Summary",
      "new_event-dialog-summary-self": "待翻譯",
      "new_event-dialog-allday": "All day event?",
      "new_event-dialog-allday-checkbox": "Yes",
      "new_event-dialog-start-time": "Start Time",
      "new_event-dialog-end-time": "End Time",
      "new_event-dialog-detail": "Detail",
      "new_event-dialog-detail-self": "待翻譯",
      "new_event-dialog-cancel": "Cancel",
      "new_event-dialog-add": "Add",
      "delete-diglog-title": "Confirm delete",
      "delete-diglog-body": "待翻譯",
      "delete-diglog-cancel": "Cancel",
      "delete-diglog-delete": "Confirm",
      "edit-dialog-title": "Edit this event",
      "edit-dialog-time-msg": "待翻譯",
      "edit-dialog-summary": "Summary",
      "edit-dialog-summary-self": "待翻譯",
      "edit-dialog-allday": "All day event",
      "edit-dialog-allday-checkbox": "Yes",
      "edit-dialog-start-time": "Start Time",
      "edit-dialog-end-time": "End Time",
      "edit-dialog-detail": "Detail",
      "edit-dialog-detail-self": "待翻譯",
      "edit-dialog-cancel": "Cancel",
      "edit-dialog-edit": "Edit"

    }
};

var lang = window.navigator.language;
if (mtdict[lang] == undefined){
    lang = 'en-US';
}
switchLang(lang)

function mt(e) {
  var v = dict[e];
  return (v===undefined)?e:v;
}

function switchLang(pLang) {
  lang = pLang;
  dict = mtdict[lang];
  $( "[data-lang]" ).each(function() {
      var e = $(this).data("lang");
      if ($(this).attr("placeholder") === undefined) {
            $(this).text(mt(e));
          } else {
                $(this).attr("placeholder", mt(e));
              }
    });
}

<|endoftext|>


<commit_before>'use strict';

var fnTrue = () => true;
var fnSelf = x => x;

class Enumerable {
    constructor(arr = []) {
        this.arr = arr;
        this.index = 0;
    }

    [Symbol.iterator]() {
        return this;
    }

    next() {
        if (this.index < this.arr.length) {
            return {
                value: this.arr[this.index++],
                done: false
            };
        }

        return {
            done: true
        };
    }

    first(selector = fnTrue) {
        for (let item of this) {
            if (selector(item)) {
                return item;
            }
        }

        throw new Error('Sequence contains no matching elements');
    }

    firstOrDefault(selector = fnTrue) {
        try {
            return this.first(selector);
        } catch (e) {
            return undefined;
        }
    }

    single(seletor = fnTrue) {
        var matched;
        for (let item of this) {
            if (fn(item)) {
                if (matched) {
                    throw Error('Sequence contains more than one matching element');
                } else {
                    matched = item;
                }
            }
        }
        if (matched) {
            return matched;
        }

        throw Error('Sequence contains no matching element');
    }

    singleOrDefault(selector = fnTrue) {
        try {
            return this.single(selector);
        } catch (e) {
            if (e.message === 'Sequence contains no matching elements') {
                return undefined;
            }
            throw e;
        }
    }

    all(fn = fnTrue) {
        for (let x of this) {
            if (!fn(x)) {
                return false;
            }
        }
        return true;
    }

    any(fn = fnTrue) {
        for (let x of this) {
            if (fn(x)) {
                return true;
            }
        }
        return false;
    }

    count(fn = fnTrue) {
        var count = 0;
        for (let i of this) {
            if (fn(i)) {
                count++;
            }
        }
        return count;
    }

    aggregate(seed, fn, selector) {
        var it = this;

        switch (arguments.length) {
            case 1:
                fn = seed;
                seed = it.next().value;
                break;

            case 2:
                if (typeof seed === 'function') {
                    selector = fn;
                    fn = seed;
                    seed = it.next().value;
                }
                break;
        }
        for (let item of it) {
            seed = fn(seed, item);
        }

        if (selector) {
            return selector(seed);
        }
        return seed;
    }

    average(fn = fnSelf) {
        var totl = 0;
        var count = 0;

        for (let item of this) {
            total += fn(item);
            count++;
        }

        if (count) {
            return total / count;
        }

        throw Error('Sequence contains no elements');
    }

    concat(col) {
        return new ConcatEnumerable(this, col);
    }

    contains(value, tester = fnTrue) {
        var it = this;

        for (let item of it) {
            if (tester(item, value)) {
                return true;
            }
        }
        return false;
    }

    where(selector) {
        return new WhereEnumerable(this, selector);
    }

    select(fn = fnSelf) {
        return new SelectEnumerable(this, fn);
    }

    selectMany(fn = fnSelf) {
        return new SelectManyEnumerable(fn);
    }

    take(count = 0) {
        return new TakeEnumerable(this, count);
    }

    takeWhile(fn = 0) {
        if (fn === 0) {
            return this.take();
        }
        return new TakeEnumerable(this, fn);
    }

    skip(count = 0) {
        return new SkipEnumerable(this, count);
    }

    skipWhile(fn = 0) {
        if (fn === 0) {
            return this.skip();
        }
        return new SkipEnumerable(this, fn);
    }

    toArray() {
        var arr = [];
        for (let i of this) {
            arr.push(i);
        }
        return arr;
    }

    static range(start = 0, end = 0) {
        return new RangeEnumerable(start, end);
    }

    static repeat(item, count = 0) {
        return new RepeatEnumerable(item, count);
    }
}

class ConcatEnumerable extends Enumerable {
    constructor(arr, col) {
        super();
        this.arr = arr;
        this.col = Array.isArray(col) ? col.asEnumerable() : col;
    }

    next() {
        var value = this.arr.next();
        if (!value.done) {
            return value;
        }

        value = this.col.next();
        return value;
    }
}

class WhereEnumerable extends Enumerable {
    constructor(arr, selector) {
        super();
        this.arr = arr;
        this.selector = selector;
    }

    next() {
        var val = this.arr.next();
        if (val.done) {
            return val;
        }

        if (this.selector(val.value)) {
            return val;
        }

        return this.next();
    }
}

class SelectEnumerable extends Enumerable {
    constructor(arr, fn) {
        super();
        this.arr = arr;
        this.fn = fn;
        this._index = 0;
    }

    next() {
        var value = this.arr.next();
        if (value.done) {
            return value;
        }
        return {
            value: this.fn(value.value, this._index++),
            done: false
        };
    }
}

class SelectManyEnumerable extends Enumerable {
    constructor(arr, colSelector, resultSelector) {
        super();
        this.arr = arr;
        this.colSelector = colSelector;
        this.resultSelector = resultSelector || ((_, x) => x);
        this._index = 0;
    }

    next() {
        var value = this;
        if (value.done) {
            return value;
        }
        let arr = this.colSelector(value.value, this._index++);
        return {
            value: resultSelector(arr, arr[i]),
            done: false
        };
    }
}

class RangeEnumerable extends Enumerable {
    constructor(start, count) {
        super();
        this.count = count;
        this.index = 0;
        this.start = start;
    }

    next() {
        if (this.index === this.count) {
            return {
                done: true
            };
        }

        var value = this.start;
        this.start++;
        this.index++;
        return {
            value: value,
            done: false
        };
    }
}

class TakeEnumerable extends Enumerable {
    constructor(arr, selector) {
        super();
        this.arr = arr;
        this.selector = selector;
        this.index = 0;
    }

    next() {
        var item = this.arr.next();
        if (item.done) {
            return item;
        }

        if (typeof this.selector === 'number') {
            if (this.index < this.selector) {
                this.index++;
                return item;
            } else {
                return {
                    done: true
                };
            }
        } else {
            if (this.selector(item.value, this.index)) {
                this.index++;
                return item;
            } else {
                return {
                    done: true
                };
            }
        }
    }
}

class SkipEnumerable extends Enumerable {
    constructor(arr, selector) {
        super();
        this.arr = arr;
        this.selector = selector;
        this.index = 0;
    }

    next() {
        var item = this.arr.next();
        if (item.done) {
            return item;
        }

        if (typeof this.selector === 'number') {
            if (this.index >= this.selector) {
                this.index++;
                return item;
            } else {
                return this.next();
            }
        } else {
            if (this.selector(item.value, this.index)) {
                return this.next();
            } else {
                return item;
            }
        }
    }
}

class RepeatEnumerable extends Enumerable {
    constructor(item, count) {
        super();
        this.item = item;
        this.count = count;
        this.index = 0;
    }

    next() {
        if (this.index === this.count) {
            return {
                done: true
            };
        }

        var stripped = JSON.stringify(this.item);
        this.index++;
        return {
            value: JSON.parse(stripped),
            done: false
        };
    }
}

// extension methods
Array.prototype.asEnumerable = function() {
    return new Enumerable(this);
};

export default Enumerable;<commit_msg>Fixing bug in average<commit_after>'use strict';

var fnTrue = () => true;
var fnSelf = x => x;

class Enumerable {
    constructor(arr = []) {
        this.arr = arr;
        this.index = 0;
    }

    [Symbol.iterator]() {
        return this;
    }

    next() {
        if (this.index < this.arr.length) {
            return {
                value: this.arr[this.index++],
                done: false
            };
        }

        return {
            done: true
        };
    }

    first(selector = fnTrue) {
        for (let item of this) {
            if (selector(item)) {
                return item;
            }
        }

        throw new Error('Sequence contains no matching elements');
    }

    firstOrDefault(selector = fnTrue) {
        try {
            return this.first(selector);
        } catch (e) {
            return undefined;
        }
    }

    single(seletor = fnTrue) {
        var matched;
        for (let item of this) {
            if (fn(item)) {
                if (matched) {
                    throw Error('Sequence contains more than one matching element');
                } else {
                    matched = item;
                }
            }
        }
        if (matched) {
            return matched;
        }

        throw Error('Sequence contains no matching element');
    }

    singleOrDefault(selector = fnTrue) {
        try {
            return this.single(selector);
        } catch (e) {
            if (e.message === 'Sequence contains no matching elements') {
                return undefined;
            }
            throw e;
        }
    }

    all(fn = fnTrue) {
        for (let x of this) {
            if (!fn(x)) {
                return false;
            }
        }
        return true;
    }

    any(fn = fnTrue) {
        for (let x of this) {
            if (fn(x)) {
                return true;
            }
        }
        return false;
    }

    count(fn = fnTrue) {
        var count = 0;
        for (let i of this) {
            if (fn(i)) {
                count++;
            }
        }
        return count;
    }

    aggregate(seed, fn, selector) {
        var it = this;

        switch (arguments.length) {
            case 1:
                fn = seed;
                seed = it.next().value;
                break;

            case 2:
                if (typeof seed === 'function') {
                    selector = fn;
                    fn = seed;
                    seed = it.next().value;
                }
                break;
        }
        for (let item of it) {
            seed = fn(seed, item);
        }

        if (selector) {
            return selector(seed);
        }
        return seed;
    }

    average(fn = fnSelf) {
        var total = 0;
        var count = 0;

        for (let item of this) {
            total += fn(item);
            count++;
        }

        if (count) {
            return total / count;
        }

        throw Error('Sequence contains no elements');
    }

    concat(col) {
        return new ConcatEnumerable(this, col);
    }

    contains(value, tester = fnTrue) {
        var it = this;

        for (let item of it) {
            if (tester(item, value)) {
                return true;
            }
        }
        return false;
    }

    where(selector) {
        return new WhereEnumerable(this, selector);
    }

    select(fn = fnSelf) {
        return new SelectEnumerable(this, fn);
    }

    selectMany(fn = fnSelf) {
        return new SelectManyEnumerable(fn);
    }

    take(count = 0) {
        return new TakeEnumerable(this, count);
    }

    takeWhile(fn = 0) {
        if (fn === 0) {
            return this.take();
        }
        return new TakeEnumerable(this, fn);
    }

    skip(count = 0) {
        return new SkipEnumerable(this, count);
    }

    skipWhile(fn = 0) {
        if (fn === 0) {
            return this.skip();
        }
        return new SkipEnumerable(this, fn);
    }

    toArray() {
        var arr = [];
        for (let i of this) {
            arr.push(i);
        }
        return arr;
    }

    static range(start = 0, end = 0) {
        return new RangeEnumerable(start, end);
    }

    static repeat(item, count = 0) {
        return new RepeatEnumerable(item, count);
    }
}

class ConcatEnumerable extends Enumerable {
    constructor(arr, col) {
        super();
        this.arr = arr;
        this.col = Array.isArray(col) ? col.asEnumerable() : col;
    }

    next() {
        var value = this.arr.next();
        if (!value.done) {
            return value;
        }

        value = this.col.next();
        return value;
    }
}

class WhereEnumerable extends Enumerable {
    constructor(arr, selector) {
        super();
        this.arr = arr;
        this.selector = selector;
    }

    next() {
        var val = this.arr.next();
        if (val.done) {
            return val;
        }

        if (this.selector(val.value)) {
            return val;
        }

        return this.next();
    }
}

class SelectEnumerable extends Enumerable {
    constructor(arr, fn) {
        super();
        this.arr = arr;
        this.fn = fn;
        this._index = 0;
    }

    next() {
        var value = this.arr.next();
        if (value.done) {
            return value;
        }
        return {
            value: this.fn(value.value, this._index++),
            done: false
        };
    }
}

class SelectManyEnumerable extends Enumerable {
    constructor(arr, colSelector, resultSelector) {
        super();
        this.arr = arr;
        this.colSelector = colSelector;
        this.resultSelector = resultSelector || ((_, x) => x);
        this._index = 0;
    }

    next() {
        var value = this;
        if (value.done) {
            return value;
        }
        let arr = this.colSelector(value.value, this._index++);
        return {
            value: resultSelector(arr, arr[i]),
            done: false
        };
    }
}

class RangeEnumerable extends Enumerable {
    constructor(start, count) {
        super();
        this.count = count;
        this.index = 0;
        this.start = start;
    }

    next() {
        if (this.index === this.count) {
            return {
                done: true
            };
        }

        var value = this.start;
        this.start++;
        this.index++;
        return {
            value: value,
            done: false
        };
    }
}

class TakeEnumerable extends Enumerable {
    constructor(arr, selector) {
        super();
        this.arr = arr;
        this.selector = selector;
        this.index = 0;
    }

    next() {
        var item = this.arr.next();
        if (item.done) {
            return item;
        }

        if (typeof this.selector === 'number') {
            if (this.index < this.selector) {
                this.index++;
                return item;
            } else {
                return {
                    done: true
                };
            }
        } else {
            if (this.selector(item.value, this.index)) {
                this.index++;
                return item;
            } else {
                return {
                    done: true
                };
            }
        }
    }
}

class SkipEnumerable extends Enumerable {
    constructor(arr, selector) {
        super();
        this.arr = arr;
        this.selector = selector;
        this.index = 0;
    }

    next() {
        var item = this.arr.next();
        if (item.done) {
            return item;
        }

        if (typeof this.selector === 'number') {
            if (this.index >= this.selector) {
                this.index++;
                return item;
            } else {
                return this.next();
            }
        } else {
            if (this.selector(item.value, this.index)) {
                return this.next();
            } else {
                return item;
            }
        }
    }
}

class RepeatEnumerable extends Enumerable {
    constructor(item, count) {
        super();
        this.item = item;
        this.count = count;
        this.index = 0;
    }

    next() {
        if (this.index === this.count) {
            return {
                done: true
            };
        }

        var stripped = JSON.stringify(this.item);
        this.index++;
        return {
            value: JSON.parse(stripped),
            done: false
        };
    }
}

// extension methods
Array.prototype.asEnumerable = function() {
    return new Enumerable(this);
};

export default Enumerable;<|endoftext|>


<commit_before>'Use strict';

var List = function(component) {
  this.component = component;
  this.items = [];
  this.active = 0;
  this.wrapper = document.createElement('div');
  this.wrapper.className = 'suggestions-wrapper';
  this.element = document.createElement('ul');
  this.element.className = 'suggestions';
  this.wrapper.appendChild(this.element);

  // selectingListItem is set to true in the time between the mousedown and mouseup when clicking an item in the list
  // mousedown on a list item will cause the input to blur which normally hides the list, so this flag is used to keep
  // the list open until the mouseup
  this.selectingListItem = false;

  component.el.parentNode.insertBefore(this.wrapper, component.el.nextSibling);
  return this;
};

List.prototype.show = function() {
  this.element.style.display = 'block';
};

List.prototype.hide = function() {
  this.element.style.display = 'none';
};

List.prototype.add = function(item) {
  this.items.push(item);
};

List.prototype.clear = function() {
  this.items = [];
  this.active = 0;
};

List.prototype.isEmpty = function() {
  return !this.items.length;
};

List.prototype.isVisible = function() {
  return this.element.style.display === 'block';
};

List.prototype.draw = function() {
  this.element.innerHTML = '';

  if (this.items.length === 0) {
    this.hide();
    return;
  }

  for (var i = 0; i < this.items.length; i++) {
    this.drawItem(this.items[i], this.active === i);
  }

  this.show();
};

List.prototype.drawItem = function(item, active) {
  var li = document.createElement('li'),
    a = document.createElement('a');

  if (active) li.className += ' active';

  a.innerHTML = item.string;

  li.appendChild(a);
  this.element.appendChild(li);

  li.addEventListener('mousedown', function() {
    this.selectingListItem = true;
  }.bind(this));

  li.addEventListener('mouseup', function() {
    this.handleMouseUp.call(this, item);
  }.bind(this));
};

List.prototype.handleMouseUp = function(item) {
  this.selectingListItem = false;
  this.component.value(item.original);
  this.clear();
  this.draw();
};

List.prototype.move = function(index) {
  this.active = index;
  this.draw();
};

List.prototype.previous = function() {
  this.move(this.active === 0 ? this.items.length - 1 : this.active - 1);
};

List.prototype.next = function() {
  this.move(this.active === this.items.length - 1 ? 0 : this.active + 1);
};

List.prototype.drawError = function(msg){
  var li = document.createElement('li');

  li.innerHTML = msg;

  this.element.appendChild(li);
  this.show();
}

module.exports = List;
<commit_msg>Fixed casing 'use strict' (#36)<commit_after>'use strict';

var List = function(component) {
  this.component = component;
  this.items = [];
  this.active = 0;
  this.wrapper = document.createElement('div');
  this.wrapper.className = 'suggestions-wrapper';
  this.element = document.createElement('ul');
  this.element.className = 'suggestions';
  this.wrapper.appendChild(this.element);

  // selectingListItem is set to true in the time between the mousedown and mouseup when clicking an item in the list
  // mousedown on a list item will cause the input to blur which normally hides the list, so this flag is used to keep
  // the list open until the mouseup
  this.selectingListItem = false;

  component.el.parentNode.insertBefore(this.wrapper, component.el.nextSibling);
  return this;
};

List.prototype.show = function() {
  this.element.style.display = 'block';
};

List.prototype.hide = function() {
  this.element.style.display = 'none';
};

List.prototype.add = function(item) {
  this.items.push(item);
};

List.prototype.clear = function() {
  this.items = [];
  this.active = 0;
};

List.prototype.isEmpty = function() {
  return !this.items.length;
};

List.prototype.isVisible = function() {
  return this.element.style.display === 'block';
};

List.prototype.draw = function() {
  this.element.innerHTML = '';

  if (this.items.length === 0) {
    this.hide();
    return;
  }

  for (var i = 0; i < this.items.length; i++) {
    this.drawItem(this.items[i], this.active === i);
  }

  this.show();
};

List.prototype.drawItem = function(item, active) {
  var li = document.createElement('li'),
    a = document.createElement('a');

  if (active) li.className += ' active';

  a.innerHTML = item.string;

  li.appendChild(a);
  this.element.appendChild(li);

  li.addEventListener('mousedown', function() {
    this.selectingListItem = true;
  }.bind(this));

  li.addEventListener('mouseup', function() {
    this.handleMouseUp.call(this, item);
  }.bind(this));
};

List.prototype.handleMouseUp = function(item) {
  this.selectingListItem = false;
  this.component.value(item.original);
  this.clear();
  this.draw();
};

List.prototype.move = function(index) {
  this.active = index;
  this.draw();
};

List.prototype.previous = function() {
  this.move(this.active === 0 ? this.items.length - 1 : this.active - 1);
};

List.prototype.next = function() {
  this.move(this.active === this.items.length - 1 ? 0 : this.active + 1);
};

List.prototype.drawError = function(msg){
  var li = document.createElement('li');

  li.innerHTML = msg;

  this.element.appendChild(li);
  this.show();
}

module.exports = List;
<|endoftext|>


<commit_before>'use strict';

import init from './component/init';
import emitter from './module/emitter';
import insert from './component/insert';
import merge from './module/merge';
import css from './module/css';
import bind from './module/bind';

const defaults = {
  prefix: 'material',
  class: 'list',
  functions: ['render', 'select'],
  modules: [emitter, insert, bind],
  target: '.material-item',
  bind: {
    'wrapper.click': 'onSelect'
  }
};

/**
 * List view class
 * @class
 * @param {Object} options Default options for view
 * @extends {View}
 * @since 0.0.4
 * @author Jerome Vial
 *
 * @type {prime}
 */
class List {

  /**
   * init
   * @return {Object} The class options
   */
  constructor(options) {
    this.options = merge(defaults, options);

    this.init(this.options);
    this.build(this.options);

    if (this.options.bind) {
      //console.log('vind', this.options.bind);
      this.bind(this.options.bind);
    }

    return this;
  }

  /**
   * [_initView description]
   * @return  Class instance
   */
  init(options) {

    init(this);

    this.options.class = options.class;
    this.name = options.name;

    this.filters = [];
    this.data = [];
    this.items = [];

    // assign modules
    Object.assign(this, emitter, insert, bind);

    // init function
    this._initFunction(options.functions);

    return this;
  }

  /**
   * [_initFunction description]
   * @param  {?} functions [description]
   * @return {?}           [description]
   */
  _initFunction(functions) {

    for (var i = 0; i < functions.length; i++) {
      var name = functions[i];
      if (this.options[name]) {
        this[name] = this.options[name];
      }
    }
  }

  /**
   * [_initList description]
   * @param  {Object} options this class options
   * @return {Object} The class instance
   */
  build(options) {

    // define main tag
    var tag = this.options.tag || 'div';

    this.wrapper = document.createElement(tag);
    css.add(this.wrapper, 'material-' + this.options.class);

    if (options.name)
      css.add(this.wrapper, options.class + '-' + options.name);

    if (this.options.container) {
      this.insert(this.options.container);
    }

    // this.wrapper.addEventListener("click", function(e) {
    //   // console.log("list", this, e);
    //   // e.target was the clicked element
    // });

    return this;
  }

  /**
   * [onSelect description]
   * @param  {?} e [description]
   * @return {?}   [description]
   */
  onSelect(e) {
    //console.log('onSelect', e.target, this.options.target);
    if (e.target && e.target.matches(this.options.target)) {
      //console.log("item clicked: ", e.target);

      css.remove(this.item, 'is-selected');
      css.add(e.target, 'is-selected');

      this.item = e.target;

      if (this.select) {
        this.select(this.item, e);
      }
    }
  }

  /**
   * select
   * @param  {Element} item  [description]
   * @param  {event} event The caller event
   * @return        [description]
   */
  select(item, event) {
    console.log('select', item, event);
    this.item = item;

    this.emit('selected', item[0]);
  }

  /**
   * Setter
   * @param {string} prop
   * @param {string} value
   */
  set(prop, value, options) {
    switch (prop) {
      case 'list':
        this.setList(value, options);
        break;
      default:
        this.setList(prop, options);
    }

    return this;
  }

  /**
   * Set list
   * @param {Array} list List of info object
   * @return {Object} The class instance
   */
  setList(list) {
    for (var i = 0; i < list.length; i++) {
      var item = this.render(list[i]);

      //item.store('info', list[i]);

      this.addItem(item, i);
    }

    return this;
  }

  /**
   * [add description]
   * @param {Object} item [description]
   */
  addItem(item /*, index*/ ) {

    if (!item) {
      return;
    }

    var where = 'bottom';
    this.insertElement(item.wrapper, this.wrapper, where);
    //item.insert(this.wrapper, where);
    this.items.push(item);

    return item;
  }

  empty() {
    this.wrapper.innerHTML = '';
    this.items = [];
    this.item = null;
  }

  /**
   * Reverse the list order
   * @return {Object} The class instance
   */
  reverse() {
    this.list.reverse();
    this.update(this.list);

    return this;
  }
}

export default List;<commit_msg>st list if set in the options<commit_after>'use strict';

import init from './component/init';
import emitter from './module/emitter';
import insert from './component/insert';
import merge from './module/merge';
import css from './module/css';
import bind from './module/bind';

const defaults = {
  prefix: 'material',
  class: 'list',
  functions: ['render', 'select'],
  modules: [emitter, insert, bind],
  target: '.material-item',
  bind: {
    'wrapper.click': 'onSelect'
  }
};

/**
 * List view class
 * @class
 * @param {Object} options Default options for view
 * @extends {View}
 * @since 0.0.4
 * @author Jerome Vial
 *
 * @type {prime}
 */
class List {

  /**
   * init
   * @return {Object} The class options
   */
  constructor(options) {
    this.options = merge(defaults, options);

    this.init(this.options);
    this.build(this.options);

    if (this.options.bind) {
      //console.log('vind', this.options.bind);
      this.bind(this.options.bind);
    }

    return this;
  }

  /**
   * [_initView description]
   * @return  Class instance
   */
  init(options) {

    init(this);

    this.options.class = options.class;
    this.name = options.name;

    this.filters = [];
    this.data = [];
    this.items = [];

    // assign modules
    Object.assign(this, emitter, insert, bind);

    // init function
    this._initFunction(options.functions);

    return this;
  }

  /**
   * [_initFunction description]
   * @param  {?} functions [description]
   * @return {?}           [description]
   */
  _initFunction(functions) {

    for (var i = 0; i < functions.length; i++) {
      var name = functions[i];
      if (this.options[name]) {
        this[name] = this.options[name];
      }
    }
  }

  /**
   * [_initList description]
   * @param  {Object} options this class options
   * @return {Object} The class instance
   */
  build(options) {

    // define main tag
    var tag = this.options.tag || 'div';

    this.wrapper = document.createElement(tag);
    css.add(this.wrapper, 'material-' + this.options.class);

    if (options.name)
      css.add(this.wrapper, options.class + '-' + options.name);

    if (this.options.list)
      this.set('list', this.options.list);

    if (this.options.container) {
      this.insert(this.options.container);
    }

    // this.wrapper.addEventListener("click", function(e) {
    //   // console.log("list", this, e);
    //   // e.target was the clicked element
    // });

    return this;
  }

  /**
   * [onSelect description]
   * @param  {?} e [description]
   * @return {?}   [description]
   */
  onSelect(e) {
    //console.log('onSelect', e.target, this.options.target);
    if (e.target && e.target.matches(this.options.target)) {
      //console.log("item clicked: ", e.target);
      var current = this.item;

      this.item = e.target;

      if (this.select) {
        this.select(this.item, e, current);
      }
    }
  }

  /**
   * select
   * @param  {Element} item  [description]
   * @param  {event} event The caller event
   * @return        [description]
   */
  select(item, event) {
    console.log('select', item, event);
    this.item = item;

    this.emit('selected', item[0]);
  }

  /**
   * Setter
   * @param {string} prop
   * @param {string} value
   */
  set(prop, value, options) {
    switch (prop) {
      case 'list':
        this.setList(value, options);
        break;
      default:
        this.setList(prop, options);
    }

    return this;
  }

  /**
   * Set list
   * @param {Array} list List of info object
   * @return {Object} The class instance
   */
  setList(list) {
    for (var i = 0; i < list.length; i++) {
      var item = this.render(list[i]);

      //item.store('info', list[i]);

      this.addItem(item, i);
    }

    return this;
  }

  /**
   * [add description]
   * @param {Object} item [description]
   */
  addItem(item /*, index*/ ) {

    if (!item) {
      return;
    }

    var where = 'bottom';
    this.insertElement(item.wrapper, this.wrapper, where);
    //item.insert(this.wrapper, where);
    this.items.push(item);

    return item;
  }

  empty() {
    this.wrapper.innerHTML = '';
    this.items = [];
    this.item = null;
  }

  /**
   * Reverse the list order
   * @return {Object} The class instance
   */
  reverse() {
    this.list.reverse();
    this.update(this.list);

    return this;
  }
}

export default List;<|endoftext|>


<commit_before>var WebSocketServer = require('ws').Server
var util = require('util');
var events = require('events');

var eventEmitter = new events.EventEmitter();

var shutil = require(global.gBaseDir + '/src/shutil.js');
var shUser = require(global.gBaseDir + '/src/shuser.js');

gPort = 5102;

var live = exports;
var wss = null;

live.notify = function(gameId, data) {
	console.log('notify game: gameId = ' + gameId);
	eventEmitter.emit("notify.game."+gameId, data);
}

live.notifyUser = function(uid, data) {
	console.log('notify user: uid = ' + uid);
	eventEmitter.emit("notify.user."+uid, data);
}

function channel(name, id)
{
	return "notify." + name + "." + id;
}

live.start = function() {
  wss = new WebSocketServer({port: gPort});
	console.log("websocket listening: " + gPort)

	wss.on('connection', function(ws) {
		console.log("socket: connect")
		var wsUid = 0;
		var wsGames = [];

	  ws.on('message', function(message) {
			var req = {};
			var res = {};

			// fill in req.params
			req.params = JSON.parse(message);

			// fill in req.session
			shutil.fillSession(req, res, function(error, data) {
				if(error != 0) {
					ws.send(JSON.stringify(data));
					return;
				}
				// this will eventually move to a live.init command, but for now check listener array
				// SWD - don't change users on a socket - or we lose ability to remove the listener
				// used to clean up user listener
				wsUid = req.session.uid;
				// valid user - hook them into events
				var userChannel = channel("user", req.session.uid);
				if(eventEmitter.listeners(userChannel).indexOf(socketNotify) == -1) {
					eventEmitter.on(userChannel, socketNotify);
				}

				shutil.call(req.params.cmd, req, res, function(error, data) {
					console.log("back from call: " + req.params.cmd);
					var cmd = req.params.cmd;
					if(cmd == 'game.join' || cmd == 'gqueue.nextAvailable') {
						if(error == 0) {
							// let them listen for events, if joined, nextAvailable forwards to game.join
							// allow for rejoins to come in by checking listener array
							var gameChannel = channel("game.", req.params.gameId);
							if(eventEmitter.listeners(gameChannel).indexOf(socketNotify) == -1) {
								wsGames.push(req.params.gameId);
								eventEmitter.on(gameChannel, socketNotify);
							}
						}
					}
					ws.send(JSON.stringify(data));
					return;
				});
			});
		});

		ws.on('error', function(err) {
			console.log(err);
		})

		ws.on('close', function(ws) {
			console.log("socket: close")
			var userChannel = channel("user", wsUid);
			console.log("socket: close cleanup - " + userChannel)
			eventEmitter.removeAllListeners(userChannel, socketNotify);
			for(var i=0; i<wsGames.length; i++) {
				var gameChannel = channel("game", wsGames[i]);
				console.log("socket: close cleanup - " + gameChannel)
				eventEmitter.removeAllListeners(gameChannel, socketNotify);
			}
		});

		// helper functions in valid ws scope
		var socketNotify = function(message) {
			console.log("socket: socketNotify")
			if(ws.readyState == 1) {
				// 1 = OPEN - SWD: find this in ws module later
				ws.send(JSON.stringify(message));
			} else {
				console.log("socket: dead socket");
			}
		};

	});

	wss.on('error', function(err) {
		console.log(err);
	});
}
<commit_msg>fix channel name extra ".";<commit_after>var WebSocketServer = require('ws').Server
var util = require('util');
var events = require('events');

var eventEmitter = new events.EventEmitter();

var shutil = require(global.gBaseDir + '/src/shutil.js');
var shUser = require(global.gBaseDir + '/src/shuser.js');

gPort = 5102;

var live = exports;
var wss = null;

live.notify = function(gameId, data) {
	console.log('notify game: gameId = ' + gameId);
	eventEmitter.emit(channel("game", gameId), data);
}

live.notifyUser = function(uid, data) {
	console.log('notify user: uid = ' + uid);
	eventEmitter.emit(channel("user", uid), data);
}

function channel(name, id)
{
	return "notify." + name + "." + id;
}

live.start = function() {
  wss = new WebSocketServer({port: gPort});
	console.log("websocket listening: " + gPort)

	wss.on('connection', function(ws) {
		console.log("socket: connect")
		var wsUid = 0;
		var wsGames = [];

	  ws.on('message', function(message) {
			var req = {};
			var res = {};

			// fill in req.params
			req.params = JSON.parse(message);

			// fill in req.session
			shutil.fillSession(req, res, function(error, data) {
				if(error != 0) {
					ws.send(JSON.stringify(data));
					return;
				}
				// this will eventually move to a live.init command, but for now check listener array
				// SWD - don't change users on a socket - or we lose ability to remove the listener
				// used to clean up user listener
				wsUid = req.session.uid;
				// valid user - hook them into events
				var userChannel = channel("user", req.session.uid);
				if(eventEmitter.listeners(userChannel).indexOf(socketNotify) == -1) {
					eventEmitter.on(userChannel, socketNotify);
				}

				shutil.call(req.params.cmd, req, res, function(error, data) {
					console.log("back from call: " + req.params.cmd);
					var cmd = req.params.cmd;
					if(cmd == 'game.join' || cmd == 'gqueue.nextAvailable') {
						if(error == 0) {
							// let them listen for events, if joined, nextAvailable forwards to game.join
							// allow for rejoins to come in by checking listener array
							var gameChannel = channel("game", req.params.gameId);
							if(eventEmitter.listeners(gameChannel).indexOf(socketNotify) == -1) {
								console.log("add channel: "+gameChannel);
								wsGames.push(req.params.gameId);
								eventEmitter.on(gameChannel, socketNotify);
							}
						}
					}
					ws.send(JSON.stringify(data));
					return;
				});
			});
		});

		ws.on('error', function(err) {
			console.log(err);
		})

		ws.on('close', function(ws) {
			console.log("socket: close")
			var userChannel = channel("user", wsUid);
			console.log("socket: close cleanup - " + userChannel)
			eventEmitter.removeAllListeners(userChannel, socketNotify);
			for(var i=0; i<wsGames.length; i++) {
				var gameChannel = channel("game", wsGames[i]);
				console.log("socket: close cleanup - " + gameChannel)
				eventEmitter.removeAllListeners(gameChannel, socketNotify);
			}
		});

		// helper functions in valid ws scope
		var socketNotify = function(message) {
			console.log("socket: socketNotify")
			if(ws.readyState == 1) {
				// 1 = OPEN - SWD: find this in ws module later
				ws.send(JSON.stringify(message));
			} else {
				console.log("socket: dead socket");
			}
		};

	});

	wss.on('error', function(err) {
		console.log(err);
	});
}
<|endoftext|>


<commit_before>var namespace;
(function(ns){
	"use strict";
	ns.luhn = (function(){
		function validate(cardNumber){
			var trimmed = cardNumber.trim()
				, length = trimmed.length
				, iCCN = parseInt(trimmed, 10)
				, total = 0
				, calc
				, calc2;

				if (length === 0){
					return true;
				}

				if (isNaN(iCCN) || !/^[0-9]+$/.test(trimmed)) {
					return false;
				}

				for (var i = length; i > 0; i--) {
					calc = Math.floor(iCCN) % 10;
					total += calc;

					i--;

					iCCN = iCCN / 10;
					calc = Math.floor(iCCN) % 10;
					calc2 = calc * 2;

					switch (calc2) {
						case 10: calc2 = 1; break;
						case 12: calc2 = 3; break;
						case 14: calc2 = 5; break;
						case 16: calc2 = 7; break;
						case 18: calc2 = 9; break;
						default: calc2 = calc2;
					}
					iCCN = iCCN / 10;
					total += calc2;
				}

				return ((total % 10) === 0);
			}

			return {
				validate: validate
			};
	} ());
}((typeof window === "undefined") ? exports : namespace || window));<commit_msg>Make browserify compatible<commit_after>var namespace;
(function(ns){
	"use strict";
	ns.luhn = (function(){
		function validate(cardNumber){
			var trimmed = cardNumber.trim()
				, length = trimmed.length
				, iCCN = parseInt(trimmed, 10)
				, total = 0
				, calc
				, calc2;

				if (length === 0){
					return true;
				}

				if (isNaN(iCCN) || !/^[0-9]+$/.test(trimmed)) {
					return false;
				}

				for (var i = length; i > 0; i--) {
					calc = Math.floor(iCCN) % 10;
					total += calc;

					i--;

					iCCN = iCCN / 10;
					calc = Math.floor(iCCN) % 10;
					calc2 = calc * 2;

					switch (calc2) {
						case 10: calc2 = 1; break;
						case 12: calc2 = 3; break;
						case 14: calc2 = 5; break;
						case 16: calc2 = 7; break;
						case 18: calc2 = 9; break;
						default: calc2 = calc2;
					}
					iCCN = iCCN / 10;
					total += calc2;
				}

				return ((total % 10) === 0);
			}

			return {
				validate: validate
			};
	} ());
}((typeof exports !== "undefined") ? exports : namespace || window));<|endoftext|>


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

  angular
    .module('carte.routes')
    .config(routeConfig);

  routeConfig.$inject = ['$stateProvider'];

  function routeConfig($stateProvider) {
    $stateProvider
      .state('carte', {
        abstract: true,
        url: '/carte',
        template: '<ui-view/>'
      })
      .state('carte.list', {
        url: '',
        templateUrl: 'modules/carte/client/views/list-carte.client.view.html',
        controller: 'CarteListController',
        controllerAs: 'vm',
        data: {
          pageTitle: 'Carte List'
        }
      })
      .state('carte.view', {
        url: '/:carteId',
        templateUrl: 'modules/carte/client/views/view-carte.client.view.html',
        controller: 'CarteController',
        controllerAs: 'vm',
        resolve: {
          carteResolve: getArticle
        },
        data: {
          pageTitle: 'Carte {{ articleResolve.title }}'
        }
      }).state('carte.create', {
        url: '/create',
        templateUrl: 'modules/carte/client/views/form-carte.client.view.html',
        controller: 'CarteAdminController',
        controllerAs: 'vm',
        resolve: {
          carteResolve: newCarte
        }
      })
      .state('carte.edit', {
        url: '/:articleId/edit',
        templateUrl: 'modules/carte/client/views/form-carte.client.view.html',
        controller: 'CarteAdminController',
        controllerAs: 'vm',
        resolve: {
          carteResolve: getCarte
        }
      });
  }

  getCarte.$inject = ['$stateParams', 'CarteService'];

  function getCarte($stateParams, CarteService) {
    return CarteService.get({
      articleId: $stateParams.articleId
    }).$promise;
  }

  newCarte.$inject = ['CarteService'];

  function newCarte(CarteService) {
    return new CarteService();
  }

}());
<commit_msg>bug fixes4<commit_after>(function () {
  'use strict';

  angular
    .module('carte.routes')
    .config(routeConfig);

  routeConfig.$inject = ['$stateProvider'];

  function routeConfig($stateProvider) {
    $stateProvider
      .state('carte', {
        abstract: true,
        url: '/carte',
        template: '<ui-view/>'
      })
      .state('carte.list', {
        url: '',
        templateUrl: 'modules/carte/client/views/list-carte.client.view.html',
        controller: 'CarteListController',
        controllerAs: 'vm',
        data: {
          pageTitle: 'Carte List'
        }
      })
      .state('carte.view', {
        url: '/:carteId',
        templateUrl: 'modules/carte/client/views/view-carte.client.view.html',
        controller: 'CarteController',
        controllerAs: 'vm',
        resolve: {
          carteResolve: getCarte
        },
        data: {
          pageTitle: 'Carte {{ articleResolve.title }}'
        }
      }).state('carte.create', {
        url: '/create',
        templateUrl: 'modules/carte/client/views/form-carte.client.view.html',
        controller: 'CarteAdminController',
        controllerAs: 'vm',
        resolve: {
          carteResolve: newCarte
        }
      })
      .state('carte.edit', {
        url: '/:articleId/edit',
        templateUrl: 'modules/carte/client/views/form-carte.client.view.html',
        controller: 'CarteAdminController',
        controllerAs: 'vm',
        resolve: {
          carteResolve: getCarte
        }
      });
  }

  getCarte.$inject = ['$stateParams', 'CarteService'];

  function getCarte($stateParams, CarteService) {
    return CarteService.get({
      articleId: $stateParams.articleId
    }).$promise;
  }

  newCarte.$inject = ['CarteService'];

  function newCarte(CarteService) {
    return new CarteService();
  }

}());
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var passport = require('passport'),
  FacebookStrategy = require('passport-facebook').Strategy,
    path = require('path'),
    mongoose = require('mongoose'),
  users = require('../../controllers/users.server.controller');
  var User = mongoose.model('User');
  var FB = require('fb');
  var errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));

module.exports = function (config) {
  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL,
      profileFields: ['id', 'name', 'displayName', 'emails', 'photos'],
      passReqToCallback: true
    },
    function (req, accessToken, refreshToken, profile, done) {
      // Set the provider data and include tokens
      var providerData = profile._json;
        var iframe = JSON.stringify(profile);
        console.log(JSON.stringify(profile));
      providerData.accessToken = accessToken;
      providerData.refreshToken = refreshToken;

        FB.setAccessToken(accessToken);

        var Friendslists ='';

        FB.api('/me/friends', function (res) {
            if (!res || res.error) {
                console.log(!res ? 'error occurred' : res.error);
                return;
            }

            show_results(res);

            console.log('FriendsList:' + JSON.stringify(res.data));
            console.log('Facebook.id:' + res.data[0].id);
            console.log('Friend.Name:' + res.data[0].name);
        });

        function show_results(results) {

           Friendslists = JSON.stringify(results.data).replace(/\"/g,"").replace(/name/g,'displayName');

            console.log('newFRIENDSlist::'+Friendslists);

            var parent = User.find({
                $or:Friendslists
            });

            console.log("parent::"+ parent);

            User.find(
            {"displayName":"Sky Skyees"}
            ).exec(function (err, person) {
                if (err) {
                    console.log("parent errpr"+errorHandler.getErrorMessage(err));
                    return errorHandler.getErrorMessage(err);
                }
                console.log('person:::%s .',person); // Space Ghost is a talk show host.
            });

          }

    setTimeout(function(){
      // Create the user OAuth profile
      var providerUserProfile = {
        firstName: profile.name.givenName,
        lastName: profile.name.familyName,
        displayName: profile.displayName,
        email: profile.emails ? profile.emails[0].value : undefined,
        username: profile.username || generateUsername(profile),
        profileImageURL: (profile.id) ? '//graph.facebook.com/' + profile.id + '/picture?type=large' : undefined,
        provider: 'facebook',
        friends:Friendslists,
        providerIdentifierField:'id',
        providerData: providerData
      };

      // Save the user OAuth profile
      users.saveOAuthUserProfile(req, providerUserProfile, done);

    },Math.random() * 2000);

      function generateUsername(profile) {
        var username = '';

        if (profile.emails) {
          username = profile.emails[0].value.split('@')[0];
        } else if (profile.name) {
          username = profile.name.givenName[0] + profile.name.familyName;
        }

        return username.toLowerCase() || undefined;
      }
    }
  ));
};
<commit_msg>global declaration<commit_after>'use strict';

/**
 * Module dependencies.
 */
var passport = require('passport'),
  FacebookStrategy = require('passport-facebook').Strategy,
    path = require('path'),
    mongoose = require('mongoose'),
  users = require('../../controllers/users.server.controller');
  var User = mongoose.model('User');
  var FB = require('fb');
  var errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));

module.exports = function (config) {
  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL,
      profileFields: ['id', 'name', 'displayName', 'emails', 'photos'],
      passReqToCallback: true
    },
    function (req, accessToken, refreshToken, profile, done) {
      // Set the provider data and include tokens
      var providerData = profile._json;
        var iframe = JSON.stringify(profile);
        console.log(JSON.stringify(profile));
      providerData.accessToken = accessToken;
      providerData.refreshToken = refreshToken;

        FB.setAccessToken(accessToken);

        var Friendslists ='';

        FB.api('/me/friends', function (res) {
            if (!res || res.error) {
                console.log(!res ? 'error occurred' : res.error);
                return;
            }

            show_results(res);

            console.log('FriendsList:' + JSON.stringify(res.data));
            console.log('Facebook.id:' + res.data[0].id);
            console.log('Friend.Name:' + res.data[0].name);
        });

        function show_results(results) {

           Friendslists = JSON.stringify(results.data).replace(/name/g,'displayName');

            console.log('newFRIENDSlist::'+Friendslists);

            var parent = User.find({
                $or:Friendslists
            });

            console.log("parent::"+ parent);

            User.find(
            {"displayName":"Sky Skyees"}
            ).exec(function (err, person) {
                if (err) {
                    console.log("parent errpr"+errorHandler.getErrorMessage(err));
                    return errorHandler.getErrorMessage(err);
                }
                console.log('person:::%s .',person); // Space Ghost is a talk show host.
            });

          }

    setTimeout(function(){
      // Create the user OAuth profile
      var providerUserProfile = {
        firstName: profile.name.givenName,
        lastName: profile.name.familyName,
        displayName: profile.displayName,
        email: profile.emails ? profile.emails[0].value : undefined,
        username: profile.username || generateUsername(profile),
        profileImageURL: (profile.id) ? '//graph.facebook.com/' + profile.id + '/picture?type=large' : undefined,
        provider: 'facebook',
        friends:Friendslists,
        providerIdentifierField:'id',
        providerData: providerData
      };

      // Save the user OAuth profile
      users.saveOAuthUserProfile(req, providerUserProfile, done);

    },Math.random() * 2000);

      function generateUsername(profile) {
        var username = '';

        if (profile.emails) {
          username = profile.emails[0].value.split('@')[0];
        } else if (profile.name) {
          username = profile.name.givenName[0] + profile.name.familyName;
        }

        return username.toLowerCase() || undefined;
      }
    }
  ));
};
<|endoftext|>


<commit_before>var includeAll = require('include-all')
	, path = require('path');

/**
 * Gruntfile
 *
 * By default, the Gruntfile in new Sails projects comes with a `linker`
 * task, which will automatically inject client-side scripts, styles, and templates
 * from your `assets` folder into specific regions of certain EJS and HTML files
 * specified below.  This behavior is completely optional, but here for convenience.
 *
 * At the top part of this file, you'll find a few of the most commonly
 * configured options, but Sails' integration with Grunt is also fully
 * customizable.  If you'd like to work with your assets differently
 * you can change this file to do anything you like!
 *
 * More information on using Grunt to work with static assets:
 * http://gruntjs.com/configuring-tasks
 */

module.exports = function(grunt) {

	var TASK_DIR = './tasks';

	// Load Grunt tasks and store them in a big object.
	var tasks = loadTasks(path.resolve(__dirname, TASK_DIR));

	console.log(tasks);

};

/**
 * Load CommonJS submodules from the specified
 * relative path.
 *
 * @return {Object}
 */
function loadTasks(relPath) {
  return includeAll({
    dirname: path.resolve(__dirname, relPath),
    filter: /(.+)\.js$/
  });
}
<commit_msg>Update federated gruntfile.<commit_after>var includeAll = require('include-all')
	, path = require('path');

/**
 * Gruntfile
 *
 * By default, the Gruntfile in new Sails projects comes with a `linker`
 * task, which will automatically inject client-side scripts, styles, and templates
 * from your `assets` folder into specific regions of certain EJS and HTML files
 * specified below.  This behavior is completely optional, but here for convenience.
 *
 * At the top part of this file, you'll find a few of the most commonly
 * configured options, but Sails' integration with Grunt is also fully
 * customizable.  If you'd like to work with your assets differently
 * you can change this file to do anything you like!
 *
 * More information on using Grunt to work with static assets:
 * http://gruntjs.com/configuring-tasks
 */

module.exports = function(grunt) {

	// Load Grunt tasks from the `tasks` directory
	loadTasks('./tasks');

};

/**
 * Load CommonJS submodules from the specified
 * relative path.
 *
 * @return {Object}
 */
function loadTasks(relPath) {
  return includeAll({
    dirname: path.resolve(__dirname, relPath),
    filter: /(.+)\.js$/
  });
}
<|endoftext|>


<commit_before>define([
	"dojo/_base/kernel",
	"dojo/_base/declare",
	"./Container"
], function(kernel, declare, Container){

	kernel.deprecated("dojox/mobile/FixedSplitterPane", "Use dojox/mobile/Container instead", 2.0);

	// module:
	//		dojox/mobile/FixedSplitterPane

	return declare("dojox.mobile.FixedSplitterPane", Container, {
		// summary:
		//		Deprecated widget. Use dojox/mobile/Container instead.

		baseClass: "mblFixedSplitterPane"
	});
});
<commit_msg>remove deprecated FixedSplitterPane<commit_after><|endoftext|>


<commit_before>var console = require('./../utils/Logger');
var https = require('https');
var dns = require('dns');

function SystemEvent(defaultHandler) {
    this.handler = defaultHandler;
}

SystemEvent.prototype.handle = function (event, request) {
    var self = this;

    function callback(geoData, hostnames) {
        event.ip = geoData.ip;
        event.country_code = geoData.country_code;
        event.country_name = geoData.country_name;
        event.time_zone = geoData.time_zone;
        event.latitude = geoData.latitude;
        event.longitude = geoData.longitude;

        event.hostnames = hostnames;

        self.handler.handle(event);
    }

    var ip = startsWidth(request.ip, '::ffff:') ? request.ip.substring(7) : request.ip;

    if (ip == '127.0.0.1' || ip == '::1') {
        callback({
            ip: '127.0.0.1',
            country_name: 'localhost'
        });
        return;
    }

    dns.reverse(ip, function (error, hostnames) {
        if (error) {
            console.error(error.message);
            console.error(error.code);
            console.error(error.stack);
        }

        https.get('https://freegeoip.net/json/' + ip, function (response) {

            var body = '';
            response.on('data', function (data) {
                body += data;
            });
            response.on('end', function () {
                callback(JSON.parse(body), hostnames);
            });

            if (response.statusCode >= 400) {
                console.warn('statusCode: ' + response.statusCode);
                console.warn('headers: ' + JSON.stringify(response.headers));
            }
        }).on('error', function (error) {
            console.error(error.message);
            console.error(error.stack);
            console.error(error);
        });
    });
};

function startsWidth(actualString, searchString) {
    return actualString.indexOf(searchString, 0) === 0;
}

module.exports = SystemEvent;<commit_msg>remove user's personal information<commit_after>var console = require('./../utils/Logger');
var https = require('https');

function SystemEvent(defaultHandler) {
    this.handler = defaultHandler;
}

SystemEvent.prototype.handle = function (event, request) {
    var self = this;

    function callback(geoData) {
        event.country_code = geoData.country_code;
        event.country_name = geoData.country_name;
        event.time_zone = geoData.time_zone;
        event.region_name = geoData.region_name;
        event.city = geoData.city;

        self.handler.handle(event);
    }

    var ip = startsWidth(request.ip, '::ffff:') ? request.ip.substring(7) : request.ip;

    if (ip == '127.0.0.1' || ip == '::1') {
        callback({
            ip: '127.0.0.1',
            country_name: 'localhost'
        });
        return;
    }

    https.get('https://freegeoip.net/json/' + ip, function (response) {

        var body = '';
        response.on('data', function (data) {
            body += data;
        });
        response.on('end', function () {
            callback(JSON.parse(body));
        });

        if (response.statusCode >= 400) {
            console.warn('statusCode: ' + response.statusCode);
            console.warn('headers: ' + JSON.stringify(response.headers));
        }
    }).on('error', function (error) {
        console.error(error.message);
        console.error(error.stack);
        console.error(error);
    });
};

function startsWidth(actualString, searchString) {
    return actualString.indexOf(searchString, 0) === 0;
}

module.exports = SystemEvent;<|endoftext|>


<commit_before>'use strict';

const connection = require("../../database/database");
const config = require("../../config");
const Utils = require("../../util/utils");
const logger = require("../../util/logger");

const FeatureList = require("../../model/realtime/FeatureList");
const HttpError = require("../../util/HttpError");
const LineUtils = require("../line/LineUtils");

const GEOMETRY = "geometry";
const PROPERTIES = "properties";
const OPERATORS = {
    'eq': '=',
    'le': '<=',
    'lt': '<',
    'ne': '<>',
    'is_not_null': 'IS NOT NULL',
    'is_null': 'IS NULL',
    'ge': '>=',
    'gt': '>'
};
const DB_PARAMS = {
    bemerkung: "remark",
    delay_min: "ROUND(delay_sec / 60::DECIMAL)::INT",
    delay_sec: "delay_sec",
    fahrzeit: "(EXTRACT(EPOCH FROM TIMEZONE('Europe/Rome', NOW()))::INT - departure) % 86400",
    fgr_nr: "rec_frt.trip_time_group",
    fgr_text: "trip_time_group_text",
    frt_fid: "rec_frt.trip::INT",
    frt_start: "departure % 86400",
    fzg_depot: "depot",
    fzg_nr: "vehicle",
    gps_date: "gps_date",
    hexcolor: "upper(hex)",
    hexcolor2: "'hexcolor2'",
    hue: "hue",
    insert_date: "insert_date",
    leistungsart_nr: "rec_frt.service",
    leistungsart_text: "leistungsart_text",
    lid_verlauf: "JSON_AGG(lid_verlauf_paths.ort_nr ORDER BY lid_verlauf_paths.li_lfd_nr)",
    lidname: "line_name",
    li_lfd_nr: "vehicle_positions.li_lfd_nr + 1",
    li_nr: "rec_frt.line",
    li_ri_nr: "direction",
    li_zone: "SPLIT_PART(li_kuerzel, ' ', 2)",
    ort_name: "next_rec_ort.ort_name",
    ort_nr: "next_rec_ort.ort_nr",
    ort_ref_ort: "next_rec_ort.ort_ref_ort",
    ort_ref_ort_kuerzel: "next_rec_ort.ort_ref_ort_kuerzel",
    ort_ref_ort_name: "next_rec_ort.ort_ref_ort_name",
    str_li_var: "rec_frt.variant"
};

let includeHexColor2 = false;

module.exports = class Positions {

    constructor(outputFormat) {
        this.outputFormat = outputFormat || config.coordinate_wgs84;
    }

    setLines(lines) {
        this.lines = lines;
    }

    getBuses(urlParams) {
        return Promise.resolve()
            .then(() => {
                let sqlFilter = '';

                Object.keys(urlParams).sort().forEach(function (jsonParam) {
                    if (DB_PARAMS[jsonParam] == null || jsonParam.slice(-3) === "_op") {
                        return;
                    }

                    let dbParam = DB_PARAMS[jsonParam];
                    let urlValue = urlParams[jsonParam];
                    let opField = urlParams[jsonParam + "_op"];
                    let op = OPERATORS[opField];

                    if (opField == null && op == null) {
                        sqlFilter += ` AND ${DB_PARAMS[jsonParam]} IN (${urlValue.split(',').map(function (value) {
                            return `'${value}'`;
                        }).join()})`;
                    } else {
                        sqlFilter += ` AND ${DB_PARAMS[jsonParam]} ${op}`;

                        if (op !== 'IS NOT NULL' && op !== 'IS NULL') {
                            sqlFilter += ` '${urlValue}'`;
                        }
                    }
                });

                logger.info("SQL filter:" + sqlFilter);

                let lineFilter = '';

                if (!Utils.isEmptyArray(this.lines)) {
                    logger.info(`Line filter: '${JSON.stringify(this.lines)}'`);
                    lineFilter = " AND (" + LineUtils.buildForSql('rec_frt.line', 'rec_frt.variant', this.lines) + ")";
                }

                let select = '';
                let groupBy = '';
                let params = urlParams[PROPERTIES] == null ? null : urlParams[PROPERTIES].split(',');

                Object.keys(DB_PARAMS).sort().forEach(function (key) {
                    if (params == null || params.indexOf(key) > -1) {
                        select += `${DB_PARAMS[key]} AS ${key}, `;

                        if (key === "li_lfd_nr") {
                            key = "vehicle_positions.li_lfd_nr"
                        }

                        if (key === "ort_nr") {
                            key = "next_rec_ort.ort_nr"
                        }

                        if (key === "lid_verlauf") {
                            return
                        }

                        groupBy += `${key}, `;
                    }
                });

                return `
                    SELECT DISTINCT ON (vehicle) vehicle, ${select}
                        ST_AsGeoJSON(ST_Transform(vehicle_positions.the_geom, ${this.outputFormat})) AS json_geom,
                        ST_AsGeoJSON(ST_Transform(vehicle_positions.extrapolation_geom, ${this.outputFormat})) AS json_extrapolation_geom,
                        red AS li_r,
                        green AS li_g,
                        blue AS li_b

                    FROM data.vehicle_positions

                    INNER JOIN data.rec_frt
                        ON vehicle_positions.trip=rec_frt.teq

                    INNER JOIN data.rec_lid
                        ON rec_frt.line=rec_lid.line
                        AND rec_frt.variant=rec_lid.variant

                    LEFT JOIN data.lid_verlauf lid_verlauf_paths
                        ON lid_verlauf_paths.line=rec_frt.line
                        AND lid_verlauf_paths.variant=rec_frt.variant

                    LEFT JOIN data.lid_verlauf lid_verlauf_next
                        ON rec_frt.line=lid_verlauf_next.line
                        AND rec_frt.variant=lid_verlauf_next.variant
                        AND vehicle_positions.li_lfd_nr + 1 = lid_verlauf_next.li_lfd_nr

                    LEFT JOIN data.rec_ort next_rec_ort
                        ON lid_verlauf_next.onr_typ_nr=next_rec_ort.onr_typ_nr
                        AND lid_verlauf_next.ort_nr=next_rec_ort.ort_nr

                    LEFT JOIN data.line_colors
                        ON rec_frt.line=line_colors.line

                    LEFT JOIN data.menge_fgr
                        ON rec_frt.trip_time_group=menge_fgr.trip_time_group

                    LEFT JOIN data.menge_leistungsart
                        ON rec_frt.service=menge_leistungsart.service

                    LEFT JOIN data.rec_frt_bedienung
                        ON rec_frt.trip=rec_frt_bedienung.trip

                    WHERE gps_date > NOW() - INTERVAL '${config.realtime_bus_timeout_minutes} minute'

                    ${sqlFilter}
                    ${lineFilter}

                    GROUP BY ${groupBy}vehicle, json_geom, json_extrapolation_geom, li_r, li_g, li_b, gps_date

                    ORDER BY vehicle DESC, gps_date DESC
               `
            })
            .then(sql => connection.query(sql))
            .then(result => {
                let featureList = new FeatureList();
                let showGeom = urlParams[GEOMETRY];

                for (let row of result.rows) {
                    // noinspection EqualityComparisonWithCoercionJS
                    let geometry = row.json_extrapolation_geom != null ? JSON.parse(row.json_extrapolation_geom) : JSON.parse(row.json_geom);
                    let hex = ((1 << 24) + (row.li_r << 16) + (row.li_g << 8) + row.li_b).toString(16).slice(1);

                    if (row.hexcolor2 == "hexcolor2") {
                        row.hexcolor2 = hex.toUpperCase();
                    }

                    delete row.json_geom;
                    delete row.json_extrapolation_geom;

                    delete row.vehicle;

                    delete row.li_r;
                    delete row.li_g;
                    delete row.li_b;

                    switch (showGeom) {
                        case "false":
                            featureList.add(row, null);
                            break;
                        case "true":
                        case null:
                        case undefined:
                            featureList.add(row, geometry);
                            break;
                        default:
                            throw new HttpError(`Cannot set geometry to '${showGeom}'`, 400);
                    }
                }

                return featureList.getFeatureCollection();
            });
    }
};<commit_msg>Fixed bug<commit_after>'use strict';

const connection = require("../../database/database");
const config = require("../../config");
const Utils = require("../../util/utils");
const logger = require("../../util/logger");

const FeatureList = require("../../model/realtime/FeatureList");
const HttpError = require("../../util/HttpError");
const LineUtils = require("../line/LineUtils");

const GEOMETRY = "geometry";
const PROPERTIES = "properties";
const OPERATORS = {
    'eq': '=',
    'le': '<=',
    'lt': '<',
    'ne': '<>',
    'is_not_null': 'IS NOT NULL',
    'is_null': 'IS NULL',
    'ge': '>=',
    'gt': '>'
};
const DB_PARAMS = {
    bemerkung: "remark",
    delay_min: "ROUND(delay_sec / 60::DECIMAL)::INT",
    delay_sec: "delay_sec",
    fahrzeit: "(EXTRACT(EPOCH FROM TIMEZONE('Europe/Rome', NOW()))::INT) % 86400 - departure % 86400",
    fgr_nr: "rec_frt.trip_time_group",
    fgr_text: "trip_time_group_text",
    frt_fid: "rec_frt.trip::INT",
    frt_start: "departure % 86400",
    fzg_depot: "depot",
    fzg_nr: "vehicle",
    gps_date: "gps_date",
    hexcolor: "upper(hex)",
    hexcolor2: "'hexcolor2'",
    hue: "hue",
    insert_date: "insert_date",
    leistungsart_nr: "rec_frt.service",
    leistungsart_text: "leistungsart_text",
    lid_verlauf: "JSON_AGG(lid_verlauf_paths.ort_nr ORDER BY lid_verlauf_paths.li_lfd_nr)",
    lidname: "line_name",
    li_lfd_nr: "vehicle_positions.li_lfd_nr + 1",
    li_nr: "rec_frt.line",
    li_ri_nr: "direction",
    li_zone: "SPLIT_PART(li_kuerzel, ' ', 2)",
    ort_name: "next_rec_ort.ort_name",
    ort_nr: "next_rec_ort.ort_nr",
    ort_ref_ort: "next_rec_ort.ort_ref_ort",
    ort_ref_ort_kuerzel: "next_rec_ort.ort_ref_ort_kuerzel",
    ort_ref_ort_name: "next_rec_ort.ort_ref_ort_name",
    str_li_var: "rec_frt.variant"
};

let includeHexColor2 = false;

module.exports = class Positions {

    constructor(outputFormat) {
        this.outputFormat = outputFormat || config.coordinate_wgs84;
    }

    setLines(lines) {
        this.lines = lines;
    }

    getBuses(urlParams) {
        return Promise.resolve()
            .then(() => {
                let sqlFilter = '';

                Object.keys(urlParams).sort().forEach(function (jsonParam) {
                    if (DB_PARAMS[jsonParam] == null || jsonParam.slice(-3) === "_op") {
                        return;
                    }

                    let dbParam = DB_PARAMS[jsonParam];
                    let urlValue = urlParams[jsonParam];
                    let opField = urlParams[jsonParam + "_op"];
                    let op = OPERATORS[opField];

                    if (opField == null && op == null) {
                        sqlFilter += ` AND ${DB_PARAMS[jsonParam]} IN (${urlValue.split(',').map(function (value) {
                            return `'${value}'`;
                        }).join()})`;
                    } else {
                        sqlFilter += ` AND ${DB_PARAMS[jsonParam]} ${op}`;

                        if (op !== 'IS NOT NULL' && op !== 'IS NULL') {
                            sqlFilter += ` '${urlValue}'`;
                        }
                    }
                });

                logger.info("SQL filter:" + sqlFilter);

                let lineFilter = '';

                if (!Utils.isEmptyArray(this.lines)) {
                    logger.info(`Line filter: '${JSON.stringify(this.lines)}'`);
                    lineFilter = " AND (" + LineUtils.buildForSql('rec_frt.line', 'rec_frt.variant', this.lines) + ")";
                }

                let select = '';
                let groupBy = '';
                let params = urlParams[PROPERTIES] == null ? null : urlParams[PROPERTIES].split(',');

                Object.keys(DB_PARAMS).sort().forEach(function (key) {
                    if (params == null || params.indexOf(key) > -1) {
                        select += `${DB_PARAMS[key]} AS ${key}, `;

                        if (key === "li_lfd_nr") {
                            key = "vehicle_positions.li_lfd_nr"
                        }

                        if (key === "ort_nr") {
                            key = "next_rec_ort.ort_nr"
                        }

                        if (key === "lid_verlauf") {
                            return
                        }

                        groupBy += `${key}, `;
                    }
                });

                return `
                    SELECT DISTINCT ON (vehicle) vehicle, ${select}
                        ST_AsGeoJSON(ST_Transform(vehicle_positions.the_geom, ${this.outputFormat})) AS json_geom,
                        ST_AsGeoJSON(ST_Transform(vehicle_positions.extrapolation_geom, ${this.outputFormat})) AS json_extrapolation_geom,
                        red AS li_r,
                        green AS li_g,
                        blue AS li_b

                    FROM data.vehicle_positions

                    INNER JOIN data.rec_frt
                        ON vehicle_positions.trip=rec_frt.teq

                    INNER JOIN data.rec_lid
                        ON rec_frt.line=rec_lid.line
                        AND rec_frt.variant=rec_lid.variant

                    LEFT JOIN data.lid_verlauf lid_verlauf_paths
                        ON lid_verlauf_paths.line=rec_frt.line
                        AND lid_verlauf_paths.variant=rec_frt.variant

                    LEFT JOIN data.lid_verlauf lid_verlauf_next
                        ON rec_frt.line=lid_verlauf_next.line
                        AND rec_frt.variant=lid_verlauf_next.variant
                        AND vehicle_positions.li_lfd_nr + 1 = lid_verlauf_next.li_lfd_nr

                    LEFT JOIN data.rec_ort next_rec_ort
                        ON lid_verlauf_next.onr_typ_nr=next_rec_ort.onr_typ_nr
                        AND lid_verlauf_next.ort_nr=next_rec_ort.ort_nr

                    LEFT JOIN data.line_colors
                        ON rec_frt.line=line_colors.line

                    LEFT JOIN data.menge_fgr
                        ON rec_frt.trip_time_group=menge_fgr.trip_time_group

                    LEFT JOIN data.menge_leistungsart
                        ON rec_frt.service=menge_leistungsart.service

                    LEFT JOIN data.rec_frt_bedienung
                        ON rec_frt.trip=rec_frt_bedienung.trip

                    WHERE gps_date > NOW() - INTERVAL '${config.realtime_bus_timeout_minutes} minute'

                    ${sqlFilter}
                    ${lineFilter}

                    GROUP BY ${groupBy}vehicle, json_geom, json_extrapolation_geom, li_r, li_g, li_b, gps_date

                    ORDER BY vehicle DESC, gps_date DESC
               `
            })
            .then(sql => connection.query(sql))
            .then(result => {
                let featureList = new FeatureList();
                let showGeom = urlParams[GEOMETRY];

                for (let row of result.rows) {
                    // noinspection EqualityComparisonWithCoercionJS
                    let geometry = row.json_extrapolation_geom != null ? JSON.parse(row.json_extrapolation_geom) : JSON.parse(row.json_geom);
                    let hex = ((1 << 24) + (row.li_r << 16) + (row.li_g << 8) + row.li_b).toString(16).slice(1);

                    if (row.hexcolor2 == "hexcolor2") {
                        row.hexcolor2 = hex.toUpperCase();
                    }

                    delete row.json_geom;
                    delete row.json_extrapolation_geom;

                    delete row.vehicle;

                    delete row.li_r;
                    delete row.li_g;
                    delete row.li_b;

                    switch (showGeom) {
                        case "false":
                            featureList.add(row, null);
                            break;
                        case "true":
                        case null:
                        case undefined:
                            featureList.add(row, geometry);
                            break;
                        default:
                            throw new HttpError(`Cannot set geometry to '${showGeom}'`, 400);
                    }
                }

                return featureList.getFeatureCollection();
            });
    }
};<|endoftext|>