<commit_before>/**
 * AMD loader
 *
 * @ver 1.1.0
 * @author Alex Hyrenko
 * @email alex.hyrenko@gmail.com
 */

(function (root, doc) {
    "use strict";

    const options = {
        baseUrl: '',
        paths: { },
        prefix: '',
        removeScriptTags: false,
        config: { },
        timeout: 10 * 1000
    };

    const delay = { };

    const ready = (function () {
        let deferred = Promise.defer();

        if (~['interactive', 'complete'].indexOf(doc.readyState)) {
            deferred.resolve();
            return deferred.promise;
        }

        doc.addEventListener('DOMContentLoaded', deferred.resolve);

        return deferred.promise;
    }());

    const registry = {
        modules: { },
        resolves: { },

        localModules: {
            module: function (name) {
                if (this.modules[name]) {
                    return {
                        name: name,
                        config: require.options.config[name] || { }
                    };
                }
            }
        },

        getDependencyPromise: function (name, parent) {
            if (this.localModules[name]) {
                return this.localModules[name].call(this, parent);
            }

            if (!this.modules[name]) {
                this.modules[name] = new Promise(function (resolve, reject) {
                    this.resolves[name] = resolve;

                    delay[name] = setTimeout(function () {
                        reject('Timeout error', name);
                    }, require.options.timeout);

                    return require.loader.load(name);
                }.bind(this));

                this.modules[name].then(clearTimeout.bind(null, delay[name]));
            }

            return this.modules[name]
        },

        resolve: function (name, value) {
            this.getDependencyPromise(name);
            this.resolves[name](value);
            delete this.resolves[name];
        }
    };

    const loader = (function () {

        function defaultLoader(src, resolve, reject) {
            let element = doc.createElement('script');

            element.async   = true;
            element.src     = src;
            element.onerror = reject.bind(this);
            element.onload  = resolve.bind(this);

            doc.body.appendChild(element);
        }

        return {
            loaders: {
                'default': defaultLoader
            },

            load: function (name) {
                let src = this.url(name, true),
                    ext = src.split('.').pop(),
                    loader = this.loaders[ext] || this.loaders.default;

                return ready.then(function () {
                    return new Promise(function (resolve, reject) {
                        loader.call(this, src, resolve, reject);
                    }.bind(this));
                }.bind(this));
            },

            set: function (ext, loader) {
                if (typeof ext !== 'string' || typeof loader !== 'function') {
                    return false;
                }

                this.loaders[ext] = loader;
                return this;
            },

            path(name) {
                let path = require.options.paths[name] || '';
                path = (require.options.baseUrl + path).replace(/(\/*)(.+[^\/])(\/*)/g, '$2');

                return path;
            },

            url(name, ext) {
                let regExp = /^([http|https]?\/\/)(.*)(\.js)$/,
                    path = this.path(name),
                    prefix, file;

                if (regExp.test(path)) {
                    return path;
                }

                prefix = require.options.prefix !== '' ? ('?' + require.options.prefix) : '';
                file = (~path.indexOf('.js') ? '' : name + (ext && '.js') + prefix);

                return path + (path ? '/' : '') + file;
            },

            get name() {
                let src = doc.currentScript.src.replace('.js', ''),
                    name = src.split('/').pop(),
                    path = this.path(name);

                return name;
                // TODO: URL parser
                //return src.slice(src.indexOf(path) + 1).substr(path.length);
            }
        }

    }());

    /**
     *  Executes a callback when dependencies are loaded
     *
     * @param {Array|String} dependencies
     * @param {Function} definition
     * @returns {Promise}
     */
    function require(dependencies, definition) {
        let parent = arguments[2];

        if (typeof dependencies === 'string') {
            dependencies = [dependencies];
        }

        return Promise.all(dependencies.map(function (name) {
            return registry.getDependencyPromise.call(this, name, parent);
        }, registry)).then(function (result) {
            if (typeof definition === 'function') {
                definition.apply(this, result);
            }
        });
    }

    /**
     * Defines a module when all dependencies are available
     *
     * @param {String|Array|Function|Object} name|dependencies|definition
     * @param {Array|Function|Object} [dependencies]
     * @param {Function|Object} [definition]
     * @returns {Promise}
     */
    function define(name, dependencies, definition) {
        if (arguments.length > 1) {
            !definition && (definition = dependencies) && (dependencies = [ ]);

            if (typeof name !== 'string') {
                definition = Array.isArray(name) && (dependencies = name) ? definition : name;
                name = loader.name;
            }
        } else {
            if (typeof name === 'function') {
                definition = name;
                dependencies = ['module'];
                name = loader.name;
            }
        }

        return require(dependencies || [ ], function () {
            registry.resolve(name, typeof definition === 'function' ? definition.apply(null, arguments) : definition);
        }, name);
    }

    /**
     * Define static methods for require
     */
    Object.defineProperties(require, {
        options: {
            value: options
        },

        loader: {
            value: loader
        },

        config: {
            value: function (options) {
                Object.keys(options).forEach(function (key) {
                    this.options[key] = options[key];
                }, this);

                return this;
            }
        },

        has: {
            value: function (name) {
                return registry.modules.hasOwnProperty(name);
            }
        }
    });

    /**
     * Load main and config scripts
     * with data-attributes
     */
    let data = doc.currentScript.dataset;

    if (data['config'] && data['main']) {
        Promise.all([ loader.load(data['config']), loader.load(data['main']) ]);
    } else if (data['main']) {
        loader.load(data['main']);
    }

    /**
     * Add methods to namespace
     * @namespace window
     */
    root.require = require;
    root.define = define;

}(window, document));<commit_msg>require lib modifed<commit_after>/**
 * AMD loader
 *
 * @ver 1.1.1
 * @author Alex Hyrenko
 * @email alex.hyrenko@gmail.com
 */

(function (root, doc) {
    "use strict";

    const options = {
        baseUrl: '',
        paths: { },
        prefix: '',
        removeScriptTags: false,
        config: { },
        timeout: 10 * 1000
    };

    const delay = { };

    /**
     * DOM ready promise
     */
    const ready = (function () {
        let deferred = Promise.defer();

        if (~['interactive', 'complete'].indexOf(doc.readyState)) {
            deferred.resolve();
            return deferred.promise;
        }

        doc.addEventListener('DOMContentLoaded', deferred.resolve);

        return deferred.promise;
    }());

    /**
     * Utilities to work with path string
     */
    const Path = {

        optimize: function (path) {
            if (!path) {
                return path;
            }

            this.link.href = path;
            return this.link.pathname.replace(/\/*([^\/]+)\/*/g, '/$1');
        },

        toURL: function (name, ext) {
            let regExp = /^([http|https]?\/\/)(.*)(\.js)$/,
                path = this.get(name),
                prefix, file;

            if (regExp.test(path)) {
                return path;
            }

            prefix = require.options.prefix !== '' ? ('?' + require.options.prefix) : '';
            file = (~path.indexOf('.js') ? '' : name + (ext && '.js') + prefix);

            if (name === 'test') {
                console.log(this.join(path, file))
            }

            return this.join(path, file);
        },

        join: function () {
            let args = Array.prototype.splice.call(arguments, 0);

            return this.optimize(args.reduce(function (prev, current) {
                if (!current) {
                    return prev;
                }

                return prev + (prev && '/') + current;
            }));
        },

        get: function (name) {
            return this.join(require.options.baseUrl, require.options.paths[name]);
        },

        ext: function (src) {
            return src.split('.').pop();
        },

        get current() {
            return doc.currentScript.src;
        },

        get toName() {
            let src = this.current.replace(/\.[a-zA-Z]+$/, ''),
                name = src.split('/').pop(),
                path = this.get(name);

            return this.optimize(src).substr(path.length + 1);
        },

        link: doc.createElement('a')
    };

    const registry = {
        modules: { },
        resolves: { },

        localModules: {
            module: function (name) {
                if (this.modules[name]) {
                    return {
                        name: name,
                        config: require.options.config[name] || { }
                    };
                }
            }
        },

        getDependencyPromise: function (name, parent) {
            if (this.localModules[name]) {
                return this.localModules[name].call(this, parent);
            }

            if (!this.modules[name]) {
                this.modules[name] = new Promise(function (resolve, reject) {
                    this.resolves[name] = resolve;

                    delay[name] = setTimeout(function () {
                        reject('Timeout error', name);
                    }, require.options.timeout);

                    return require.loader.load(name);
                }.bind(this));

                this.modules[name].then(clearTimeout.bind(null, delay[name]));
            }

            return this.modules[name]
        },

        resolve: function (name, value) {
            this.getDependencyPromise(name);
            this.resolves[name](value);
            delete this.resolves[name];
        }
    };

    const loader = (function () {

        function defaultLoader(src, resolve, reject) {
            let element = doc.createElement('script');

            element.async   = true;
            element.src     = src;
            element.onerror = reject.bind(this);
            element.onload  = resolve.bind(this);

            doc.body.appendChild(element);
        }

        return {
            loaders: {
                'default': defaultLoader
            },

            load: function (name) {
                let src = Path.toURL(name, true),
                    ext = Path.ext(src),
                    loader = this.loaders[ext] || this.loaders.default;

                return ready.then(function () {
                    return new Promise(function (resolve, reject) {
                        loader.call(this, src, resolve, reject);
                    }.bind(this));
                }.bind(this));
            },

            set: function (ext, loader) {
                if (typeof ext !== 'string' || typeof loader !== 'function') {
                    return false;
                }

                this.loaders[ext] = loader;
                return this;
            }
        }

    }());

    /**
     *  Executes a callback when dependencies are loaded
     *
     * @param {Array|String} dependencies
     * @param {Function} definition
     * @returns {Promise}
     */
    function require(dependencies, definition) {
        let parent = arguments[2];

        if (typeof dependencies === 'string') {
            dependencies = [dependencies];
        }

        return Promise.all(dependencies.map(function (name) {
            return registry.getDependencyPromise.call(this, name, parent);
        }, registry)).then(function (result) {
            if (typeof definition === 'function') {
                definition.apply(this, result);
            }
        });
    }

    /**
     * Defines a module when all dependencies are available
     *
     * @param {String|Array|Function|Object} name|dependencies|definition
     * @param {Array|Function|Object} [dependencies]
     * @param {Function|Object} [definition]
     * @returns {Promise}
     */
    function define(name, dependencies, definition) {
        if (arguments.length > 1) {
            !definition && (definition = dependencies) && (dependencies = [ ]);

            if (typeof name !== 'string') {
                definition = Array.isArray(name) && (dependencies = name) ? definition : name;
                name = Path.toName;
            }
        } else {
            if (typeof name === 'function') {
                definition = name;
                dependencies = ['module'];
                name = Path.toName;
            }
        }

        return require(dependencies || [ ], function () {
            registry.resolve(name, typeof definition === 'function' ? definition.apply(null, arguments) : definition);
        }, name);
    }

    /**
     * Define static methods for require
     */
    Object.defineProperties(require, {
        options: {
            value: options
        },

        loader: {
            value: loader
        },

        config: {
            value: function (options) {
                Object.keys(options).forEach(function (key) {
                    this.options[key] = options[key];
                }, this);

                return this;
            }
        },

        has: {
            value: function (name) {
                return registry.modules.hasOwnProperty(name);
            }
        }
    });

    /**
     * Load main and config scripts
     * with data-attributes
     */
    let data = doc.currentScript.dataset;

    if (data['config'] && data['main']) {
        Promise.all([ loader.load(data['config']), loader.load(data['main']) ]);
    } else if (data['main']) {
        loader.load(data['main']);
    }

    /**
     * Add methods to namespace
     * @namespace window
     */
    root.require = require;
    root.define = define;

}(window, document));<|endoftext|>


<commit_before>OC.L10N.register(
    "audioplayer",
    {
	"Welcome to" : "欢迎",
	"Audio Player" : "Audio Player",
	"Add new tracks to library" : "搜索音频",
	"Scan for new audio files" : "搜索新的音频",
	"New or updated audio files available" : "New or updated audio files available",
	"Help" : "帮助",
	"Sort playlist" : "播放清单排序",
	"Rename playlist" : "重新命名播放清单",
	"Delete playlist" : "刪除播放清单",
	"Add new tracks to playlist by drag and drop" : "Add new tracks to playlist by drag and drop",
	"No playlist selected!" : "请选择播放清单",
	"Sort modus active" : "排序",
	"Playlist successfully deleted!" : "成功刪除播放清单",
	"Start scanning…" : "开始搜索…",
	"Scanning finished! New Audios found!" : "搜索完成，找到新的音频!",
	"Yes" : "是",
	"No" : "否",
	"Error" : "错误",
	"Are you sure?" : "请确认",
	"Disc" : "唱片",
	"Track" : "曲目",
	"File" : "档案名",
	"Title" : "曲名",
	"Subtitle" : "副标题",
	"Artist" : "演出者",
	"Album Artist" : "Album Artist",
	"Year" : "年份",
	"Album" : "专辑",
	"Albums" : "专辑",
	"Composer" : "作曲者",
	"Edit metadata" : "编辑元数据",
	"Remove" : "删除",
	"Options" : "选项",
	"MIME type" : "MIME类型",
	"MIME type not supported by browser" : "浏览器不支持此音频格式",
	"Missing permission to edit metadata of track!" : "Missing permission to edit metadata of track!",
	"Existing Albums" : "现有的专辑",
	"New Album" : " 新专辑",
	"Genre" : "曲风",
	"Add as Album Cover" : "设定为专辑封面",
	"of" : "之",
	"Total" : "总数",
	"Select from cloud" : "由云端选择",
	"Edit" : "编辑",
	"Delete" : "刪除",
	"Upload" : "上传",
	"Drop picture" : "弃用照片",
	"Select picture" : "选择照片",
	"Picture generating, please wait…" : "图像生成, 请等待…",
	"Drag picture here!" : "拖动图片在这里!",
	"Settings" : "Settings",
	"Select a single folder with audio files" : "Select a single folder with audio files",
	"Invalid path!" : "Invalid path!",
	"saved" : "saved",
	"Reset library" : "Reset library",
	"Start resetting library…" : "Start resetting library…",
	"Resetting finished!" : "重设完成!",
	"All library entries will be deleted!" : "All library entries will be deleted!",
	"Close" : "关闭",
	"Play" : "播放",
	"Save" : "存储",
	"Existing Artists" : "已存在的艺人",
	"New Artist" : " 新艺人",
	"Existing Genres" : "现有的曲风",
	"New Genre" : " 新曲风",
	"Selected" : "选择",
	"Selected Album" : "选择的专辑",
	"Selected Artist" : "选择的藝人",
        "Selected Album Artist": "Selected Album Artist",
	"Selected Composer" : "选择的作曲者",
	"Selected Folder" : "选择的文件夹",
	"Selected Genre" : "选择的曲风",
	"Selected Playlist" : "选择的播放清单",
	"Selected Year" : "选择的年份",
	"Length" : "长度"
},
"");
<commit_msg>Editor and Playlist added<commit_after>OC.L10N.register(
    "audioplayer",
    {
	"Welcome to" : "欢迎",
	"Audio Player" : "Audio Player",
	"Add new tracks to library" : "搜索音频",
	"Scan for new audio files" : "搜索新的音频",
	"New or updated audio files available" : "New or updated audio files available",
	"Help" : "帮助",
	"Sort playlist" : "播放清单排序",
	"Rename playlist" : "重新命名播放清单",
	"Delete playlist" : "刪除播放清单",
	"Add new tracks to playlist by drag and drop" : "Add new tracks to playlist by drag and drop",
	"No playlist selected!" : "请选择播放清单",
	"Sort modus active" : "排序",
	"Playlist successfully deleted!" : "成功刪除播放清单",
	"Start scanning…" : "开始搜索…",
	"Scanning finished! New Audios found!" : "搜索完成，找到新的音频!",
	"Yes" : "是",
	"No" : "否",
	"Error" : "错误",
	"Are you sure?" : "请确认",
	"Disc" : "唱片",
	"Track" : "曲目",
	"File" : "档案名",
	"Title" : "曲名",
	"Subtitle" : "副标题",
	"Artist" : "演出者",
	"Album Artist" : "Album Artist",
	"Year" : "年份",
	"Album" : "专辑",
	"Albums" : "专辑",
	"Composer" : "作曲者",
	"Edit metadata" : "编辑元数据",
	"No ID3 editor installed" : "No ID3 editor installed",
	"No playlist entry" : "No playlist entry",
	"Remove" : "删除",
	"Options" : "选项",
	"MIME type" : "MIME类型",
	"MIME type not supported by browser" : "浏览器不支持此音频格式",
	"Missing permission to edit metadata of track!" : "Missing permission to edit metadata of track!",
	"Existing Albums" : "现有的专辑",
	"New Album" : " 新专辑",
	"Genre" : "曲风",
	"Add as Album Cover" : "设定为专辑封面",
	"of" : "之",
	"Total" : "总数",
	"Select from cloud" : "由云端选择",
	"Edit" : "编辑",
	"Delete" : "刪除",
	"Upload" : "上传",
	"Drop picture" : "弃用照片",
	"Select picture" : "选择照片",
	"Picture generating, please wait…" : "图像生成, 请等待…",
	"Drag picture here!" : "拖动图片在这里!",
	"Settings" : "Settings",
	"Select a single folder with audio files" : "Select a single folder with audio files",
	"Invalid path!" : "Invalid path!",
	"saved" : "saved",
	"Reset library" : "Reset library",
	"Start resetting library…" : "Start resetting library…",
	"Resetting finished!" : "重设完成!",
	"All library entries will be deleted!" : "All library entries will be deleted!",
	"Close" : "关闭",
	"Play" : "播放",
	"Save" : "存储",
	"Existing Artists" : "已存在的艺人",
	"New Artist" : " 新艺人",
	"Existing Genres" : "现有的曲风",
	"New Genre" : " 新曲风",
	"Selected" : "选择",
	"Selected Album" : "选择的专辑",
	"Selected Artist" : "选择的藝人",
	"Selected Album Artist" : "Selected Album Artist",
	"Selected Composer" : "选择的作曲者",
	"Selected Folder" : "选择的文件夹",
	"Selected Genre" : "选择的曲风",
	"Selected Playlist" : "选择的播放清单",
	"Selected Year" : "选择的年份",
	"Length" : "长度"
},
"");
<|endoftext|>


<commit_before>#!/usr/bin/env nodejs

var package = require(require('path').resolve(__dirname + '/../package.json'));

function channels(val, c) { c.push(val.split(':', 2)); return c; }

var program = require('commander');
program.version(package.version);
program.option('-s, --server [server]', 'Socket Server (Default: http://localhost:3000/)', 'http://localhost:3000/');
program.option('-c, --channels [value]', 'Channels to listen to (format is keyname:server)', channels, []);
program.parse(process.argv);

var client = new require('../index.js')();
client.setServer(program.server);
program.channels.forEach(function(val) {
  /* Start listening to Channels in config file */
  client.addChannel(val[0], val[1]);
});
client.start();
<commit_msg>providing channels on the command line wasn't properly handling colons<commit_after>#!/usr/bin/env nodejs

var package = require(require('path').resolve(__dirname + '/../package.json'));

function channels(val, c) {
  var vals = val.split(':');
  c.push([vals.shift(), vals.join(':')]);
  return c;
}

var program = require('commander');
program.version(package.version);
program.option('-s, --server [server]', 'Socket Server (Default: http://localhost:3000/)', 'http://localhost:3000/');
program.option('-c, --channels [value]', 'Channels to listen to (format is keyname:server)', channels, []);
program.parse(process.argv);

var client = new require('../index.js')();
client.setServer(program.server);
program.channels.forEach(function(val) {
  /* Start listening to Channels in config file */
  client.addChannel(val[0], val[1]);
});
client.start();
<|endoftext|>


<commit_before>accountingnotes = (function ()
{
var instance;

//record widget constructor
function record_widget (Width, Heigth)
{
    Gwt.Gui.HBox.call (this, 0);
    this.SetSize (Width, Heigth);
    this.SetClassName ("record_widget");
    this.Rpc = new Gwt.Core.Rpc ("/accountingnotes/");

    this.code = new Gwt.Gui.Entry ("Código");
    this.code.SetExpand (false);
    this.code.SetWidth (120);
    this.name = new Gwt.Gui.StaticText ("Nombre");
    this.name.SetExpand (false);
    this.name.SetWidth (this.GetWidth() - 360);
    this.name.SetValign (Gwt.Gui.Contrib.Valign.Middle);
    this.debit = new Gwt.Gui.Entry ("Debe");
    this.debit.SetExpand (false);
    this.debit.SetWidth (120);
    this.debit.ChangeToMonetary();
    this.debit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)
    this.credit = new Gwt.Gui.Entry ("Haber");
    this.credit.SetExpand (false);
    this.credit.SetWidth (120);
    this.credit.ChangeToMonetary();
    this.credit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)

    this.Add (this.code);
    this.Add (this.name);
    this.Add (this.debit);
    this.Add (this.credit);

    this.code.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.check_code.bind(this));
}

record_widget.prototype = new Gwt.Gui.HBox ();
record_widget.prototype.constructor = record_widget;

//record widget destructor
record_widget.prototype._record_widget = function ()
{
    this.code._Entry();
    this.name._StaticText();
    this.debit._Entry();
    this.credit._Entry();

    this.code = null;
    this.name = null;
    this.debit = null;
    this.credit = null;
};

//reset
record_widget.prototype.Reset = function ()
{
    this.code.Reset ();
    this.name.SetText ("Nombre");
    this.debit.Reset ();
    this.credit.Reset ();
};

//check code
record_widget.prototype.check_code = function (event)
{
    if(event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        this.Rpc.Send ({Method: "CheckCode", Code: this.code.GetText()}, this.autocomplete.bind(this));
    }
};

//autocomplete
record_widget.prototype.autocomplete = function (Res)
{
    if (Res.length > 0)
    {
        this.name.SetText (Res[0].Name);
    }
    else
    {
        this.name.SetText ("Nombre");
    }
};

//equal sums widget
function equal_sums_widget (Width, Heigth)
{
    Gwt.Gui.HBox.call (this, 0);
    this.SetSize (Width, Heigth);
    this.SetClassName ("equal_sums_widget");

    this.label = new Gwt.Gui.StaticText ("Sumas Iguales");
    this.name.SetExpand (false);
    this.name.SetWidth (this.GetWidth() - 240);
    this.name.SetValign (Gwt.Gui.Contrib.Valign.Middle);
    this.debit = new Gwt.Gui.Entry ("Debe");
    this.debit.SetExpand (false);
    this.debit.SetWidth (120);
    this.debit.ChangeToMonetary();
    this.debit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)
    this.credit = new Gwt.Gui.Entry ("Haber");
    this.credit.SetExpand (false);
    this.credit.SetWidth (120);
    this.credit.ChangeToMonetary();
    this.credit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)

    this.Add (this.label);
    this.Add (this.debit);
    this.Add (this.credit);
}

equal_sums_widget.prototype = new Gwt.Gui.HBox ();
equal_sums_widget.prototype.constructor = equal_sums_widget;

//accountingnotes
function accountingnotes()
{
    Gwt.Gui.Window.call (this, "Nota Contable");

    this.SetSize (840, 508);
    this.SetPosition (Gwt.Gui.WIN_POS_CENTER);
    this.SetBorderSpacing (12);
    this.Rpc = new Gwt.Core.Rpc ("/accountingnotes/");

    this.EnableMenu ();
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.cabinet.in.svg", "Guardar", this.Insert.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.refresh.svg", "Actualizar", this.Update.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.delete.svg", "Eliminar", this.Delete.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.printer.svg", "Imprimir", this.Print.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.power.svg", "Salir", function(){window.accountingnotes.close(); window.gcontrol.open();}, Gwt.Gui.MENU_QUIT_APP);

    this.layout = new Gwt.Gui.VBox ();
    this.SetLayout (this.layout);

    this.slider = new Gwt.Gui.Slider (5);
    this.slider.SetSize (this.layout.GetWidth (), this.layout.GetHeight ()-48);
    this.slider.Setup ();
    this.layout.Add (this.slider);

    this.equal_sums = new equal_sums_widget (this.layout.GetWidth (), 48);
    this.layout.Add (this.equal_sums);

    this.number = new Gwt.Gui.Entry ("Número");
    this.date = new Gwt.Gui.Date ("Creación");
    this.date.Now ();
    this.concept = new Gwt.Gui.Text ("Concepto");
    this.Report = null;

    this.records = [];
    for (var i = 0; i <= 45; i++)
    {
        this.records[i] = new record_widget (this.slider.GetWidth (), 24);
    }

    this.slider.AddSlotWidget (0, this.number);
    this.slider.AddSlotWidget (0, this.date);
    this.slider.AddSlotWidget (0, this.concept);

    for (var i=0; i<this.records.length; i++)
    {
        if (i<=5)
        {
            this.slider.AddSlotWidget (0, this.records[i]);
        }
        else if (i>=6 && i<=15)
        {
            this.slider.AddSlotWidget (1, this.records[i]);
        }
        else if (i>=16 && i<=25)
        {
            this.slider.AddSlotWidget (2, this.records[i]);
        }
        else if (i>=26 && i<=35)
        {
            this.slider.AddSlotWidget (3, this.records[i]);
        }
        else if (i>=36 && i<=45)
        {
            this.slider.AddSlotWidget (4, this.records[i]);
        }
    }

    this.number.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.CheckNumber.bind(this));
}

accountingnotes.prototype = new Gwt.Gui.Window ();
accountingnotes.prototype.constructor = accountingnotes;

//accountingnotes destructor
accountingnotes.prototype._App = function ()
{
    this.number._Entry ();
    this.date._Date ();
    this.concept._Text ();
    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i]._record_widget();
        this.records[i] = null;
    }
    this.slider._Slider ();
    this.Report === null ? null : this.Report.close ();
    this.layout._VBox ();

    this.number = null;
    this.date = null;
    this.concept = null;
    this.records = null;
    this.slider = null;
    this.layout = null;
    this.Report = null;
};

accountingnotes.prototype.CreateData = function ()
{
    var Data = {
        Number: this.number.GetText (),
        Date: this.date.GetText (),
        Concept: this.concept.GetText ()
    };

    Data.Records = [];

    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Data.Records.push({
                Debit: (this.records[i].debit.GetText () === "") ? 0 : this.records[i].debit.GetText (),
                Credit: (this.records[i].credit.GetText() === "") ? 0 : this.records[i].credit.GetText(),
                Number: this.number.GetText (),
                Code:this.records[i].code.GetText ()
            });
        }
    }

    return Data;
};

//insert
accountingnotes.prototype.Insert = function ()
{
    var Data = this.CreateData ();
    Data.Method = "Insert";
    this.Rpc.Send (Data, this.InsertResponse.bind(this));
};

//insert response
accountingnotes.prototype.InsertResponse = function (Res)
{
    if (Res.affected_rows === 1)
    {
        this.Print();
    }
};

//update
accountingnotes.prototype.Update = function ()
{
    var Data = this.CreateData ();
    Data.Method = "Update";
    console.log (Data);
    this.Rpc.Send (Data, this.UpdateResponse.bind(this));
}

//update response
accountingnotes.prototype.UpdateResponse = function (Res)
{
    if (Res.affected_rows === 1)
    {
        this.Print();
    }
};

//delete
accountingnotes.prototype.Delete = function ()
{
    this.Rpc.Send ({Method: "Delete", Number: this.number.GetText ()}, this.DeleteResponse.bind(this));
};

//delete response
accountingnotes.prototype.DeleteResponse = function (Res)
{
    if (Res.affected_rows === 1)
    {
        this.Reset ();
    }
};

//print
accountingnotes.prototype.Print = function (Res)
{
    var Records = 0;
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Records += 1;
        }
    }
    this.Report = Gwt.Core.Contrib.LoadDocument ("/documents/accountingnote.html?records=%0".replace("%0", Records));
    this.Report.addEventListener ("load", this.ReportLoad.bind (this));
};

//report load
accountingnotes.prototype.ReportLoad = function ()
{
    var doc = this.Report.contentWindow.document;
    doc.getElementById ("Number").textContent = Gwt.Core.Contrib.ZFill(this.number.GetText(), 4);
    doc.getElementById ("Date").textContent = this.date.GetText ();
    doc.getElementById ("Concept").textContent = this.concept.GetText ();

    var TotalDebit = 0;
    var TotalCredit = 0;

    var Records = [];
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            TotalDebit += Number(this.records[i].debit.GetText ());
            TotalCredit += Number(this.records[i].credit.GetText());
            Records.push({
                "Code": this.records[i].code.GetText (),
                "Name": this.records[i].name.GetText (),
                "Partial": Gwt.Core.Contrib.TextToMonetary (""),
                "Debit": Gwt.Core.Contrib.TextToMonetary (this.records[i].debit.GetText ()),
                "Credit": Gwt.Core.Contrib.TextToMonetary (this.records[i].credit.GetText())
            });
        }
    }

    var SortedRecords = this.SortData (Records);

    for (var i=0; i < SortedRecords.length; i++)
    {
        doc.getElementById ("Code"+i).textContent = SortedRecords[i].Code;
        doc.getElementById ("Name"+i).textContent = SortedRecords[i].Name;
        doc.getElementById ("Partial"+i).textContent = (SortedRecords[i].Partial === "$0") ? "" : SortedRecords[i].Partial;
        doc.getElementById ("Debit"+i).textContent = (SortedRecords[i].Debit  === "$0") ? "" : SortedRecords[i].Debit;
        doc.getElementById ("Credit"+i).textContent = (SortedRecords[i].Credit === "$0") ? "" : SortedRecords[i].Credit;
    }

    doc.getElementById ("EqSumDebit").textContent = Gwt.Core.Contrib.TextToMonetary(TotalDebit.toString());
    doc.getElementById ("EqSumCredit").textContent = Gwt.Core.Contrib.TextToMonetary(TotalCredit.toString());

    doc = undefined;
    this.Report = null;
    this.Reset ();
};

//check number
accountingnotes.prototype.CheckNumber = function (Event)
{
    if(Event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        if (this.number.GetText () === "")
        {
            this.Rpc.Send ({Method: "NextNumber"}, this.NextNumber.bind(this));
        }
        else
        {
            this.Rpc.Send ({Method: "AutoFill", Number: this.number.GetText ()}, this.AutoFill.bind(this));
        }
    }
};

//next number
accountingnotes.prototype.NextNumber = function (Res)
{
    if (Res.length > 0)
    {
        this.number.SetText(Number(Res[0].Number)+1);
    }
    else
    {
        this.number.SetText(Number(1));
    }
};

//autofill
accountingnotes.prototype.AutoFill = function (Res)
{
    if (Res.length > 0)
    {
        this.number.SetText (Res[0].Number);
        this.date.SetDate (Res[0].Date);
        this.concept.SetText (Res[0].Concept);

        for (var i = 0; i < Res.length; i++)
        {
            this.records[i].code.SetText (Res[i].Code);
            this.records[i].name.SetText (Res[i].Name);
            this.records[i].debit.SetText ((Res[i].Debit === 0 ? "" : Res[i].Debit));
            this.records[i].credit.SetText ((Res[i].Credit === 0 ? "" : Res[i].Credit));
        }
        for (i; i < this.records.length; i++)
        {
            this.records[i].Reset();
        }
    }
    else
    {
        this.Reset ();
    }
};

//reset
accountingnotes.prototype.Reset = function ()
{
    this.number.SetText ("");
    this.date.Now ();
    this.concept.SetText ("");

    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i].Reset ();
    }
};

//sort data
accountingnotes.prototype.SortData = function (Res)
{
    var Debits = [];
    var Credits = [];

    var Sorted = [];

    for (var i = 0; i < Res.length; i++)
    {
        if (Number(Res[i].Debit) !== 0)
        {
            Debits.push (Res[i]);
        }
        else if (Number(Res[i].Credit) !== 0)
        {
            Credits.push (Res[i]);
        }
    }

    for (var i = 0; i < Debits.length; i++)
    {
        for (var j = 0; j < Res.length; j++)
        {
            if (Res[j].Code.startsWith(Debits[i].Code))
            {
                Sorted.push (Res[j]);
            }
        }
    }

    for (var i = 0; i < Credits.length; i++)
    {
        for (var j = 0; j < Res.length; j++)
        {
            if (Res[j].Code.startsWith(Credits[i].Code))
            {
                Sorted.push (Res[j]);
            }
        }
    }

    return Sorted;
};

return new function ()
{
    this.open = function()
    {
        if(instance === undefined)
        {
            instance = new accountingnotes();
            instance.Open ();
            Gwt.Core.Contrib.SetActiveApp (window.accountingnotes);
        }
        else
        {
            console.log ("%app yet opened".replace("%app", instance.__proto__.constructor.name));
        }
    };

    this.close = function ()
    {
        if(instance !== undefined)
        {
            instance.Close();
            instance = undefined;
            Gwt.Core.Contrib.RemoveActiveApp ();
        }
    };
};
})();
<commit_msg>actualizado<commit_after>accountingnotes = (function ()
{
var instance;

//record widget constructor
function record_widget (Width, Heigth)
{
    Gwt.Gui.HBox.call (this, 0);
    this.SetSize (Width, Heigth);
    this.SetClassName ("record_widget");
    this.Rpc = new Gwt.Core.Rpc ("/accountingnotes/");

    this.code = new Gwt.Gui.Entry ("Código");
    this.code.SetExpand (false);
    this.code.SetWidth (120);
    this.name = new Gwt.Gui.StaticText ("Nombre");
    this.name.SetExpand (false);
    this.name.SetWidth (this.GetWidth() - 360);
    this.name.SetValign (Gwt.Gui.Contrib.Valign.Middle);
    this.debit = new Gwt.Gui.Entry ("Debe");
    this.debit.SetExpand (false);
    this.debit.SetWidth (120);
    this.debit.ChangeToMonetary();
    this.debit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)
    this.credit = new Gwt.Gui.Entry ("Haber");
    this.credit.SetExpand (false);
    this.credit.SetWidth (120);
    this.credit.ChangeToMonetary();
    this.credit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)

    this.Add (this.code);
    this.Add (this.name);
    this.Add (this.debit);
    this.Add (this.credit);

    this.code.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.check_code.bind(this));
}

record_widget.prototype = new Gwt.Gui.HBox ();
record_widget.prototype.constructor = record_widget;

//record widget destructor
record_widget.prototype._record_widget = function ()
{
    this.code._Entry();
    this.name._StaticText();
    this.debit._Entry();
    this.credit._Entry();

    this.code = null;
    this.name = null;
    this.debit = null;
    this.credit = null;
};

//reset
record_widget.prototype.Reset = function ()
{
    this.code.Reset ();
    this.name.SetText ("Nombre");
    this.debit.Reset ();
    this.credit.Reset ();
};

//check code
record_widget.prototype.check_code = function (event)
{
    if(event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        this.Rpc.Send ({Method: "CheckCode", Code: this.code.GetText()}, this.autocomplete.bind(this));
    }
};

//autocomplete
record_widget.prototype.autocomplete = function (Res)
{
    if (Res.length > 0)
    {
        this.name.SetText (Res[0].Name);
    }
    else
    {
        this.name.SetText ("Nombre");
    }
};

//equal sums widget
function equal_sums_widget (Width, Heigth)
{
    Gwt.Gui.HBox.call (this, 0);
    this.SetSize (Width, Heigth);
    this.SetClassName ("equal_sums_widget");

    this.label = new Gwt.Gui.StaticText ("Sumas Iguales");
    this.label.SetExpand (false);
    this.label.SetWidth (this.GetWidth() - 240);
    this.label.SetValign (Gwt.Gui.Contrib.Valign.Middle);
    this.debit = new Gwt.Gui.Entry ("Debe");
    this.debit.SetExpand (false);
    this.debit.SetWidth (120);
    this.debit.ChangeToMonetary();
    this.debit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)
    this.credit = new Gwt.Gui.Entry ("Haber");
    this.credit.SetExpand (false);
    this.credit.SetWidth (120);
    this.credit.ChangeToMonetary();
    this.credit.TextAlign (Gwt.Gui.Contrib.TextAlign.Right)

    this.Add (this.label);
    this.Add (this.debit);
    this.Add (this.credit);
}

equal_sums_widget.prototype = new Gwt.Gui.HBox ();
equal_sums_widget.prototype.constructor = equal_sums_widget;

//accountingnotes
function accountingnotes()
{
    Gwt.Gui.Window.call (this, "Nota Contable");

    this.SetSize (840, 508);
    this.SetPosition (Gwt.Gui.WIN_POS_CENTER);
    this.SetBorderSpacing (12);
    this.Rpc = new Gwt.Core.Rpc ("/accountingnotes/");

    this.EnableMenu ();
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.cabinet.in.svg", "Guardar", this.Insert.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.refresh.svg", "Actualizar", this.Update.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.delete.svg", "Eliminar", this.Delete.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.printer.svg", "Imprimir", this.Print.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.power.svg", "Salir", function(){window.accountingnotes.close(); window.gcontrol.open();}, Gwt.Gui.MENU_QUIT_APP);

    this.layout = new Gwt.Gui.VBox ();
    this.SetLayout (this.layout);

    this.slider = new Gwt.Gui.Slider (5);
    this.slider.SetSize (this.layout.GetWidth (), this.layout.GetHeight ()-48);
    this.slider.Setup ();
    this.layout.Add (this.slider);

    this.equal_sums = new equal_sums_widget (this.layout.GetWidth (), 48);
    this.layout.Add (this.equal_sums);

    this.number = new Gwt.Gui.Entry ("Número");
    this.date = new Gwt.Gui.Date ("Creación");
    this.date.Now ();
    this.concept = new Gwt.Gui.Text ("Concepto");
    this.Report = null;

    this.records = [];
    for (var i = 0; i <= 45; i++)
    {
        this.records[i] = new record_widget (this.slider.GetWidth (), 24);
    }

    this.slider.AddSlotWidget (0, this.number);
    this.slider.AddSlotWidget (0, this.date);
    this.slider.AddSlotWidget (0, this.concept);

    for (var i=0; i<this.records.length; i++)
    {
        if (i<=5)
        {
            this.slider.AddSlotWidget (0, this.records[i]);
        }
        else if (i>=6 && i<=15)
        {
            this.slider.AddSlotWidget (1, this.records[i]);
        }
        else if (i>=16 && i<=25)
        {
            this.slider.AddSlotWidget (2, this.records[i]);
        }
        else if (i>=26 && i<=35)
        {
            this.slider.AddSlotWidget (3, this.records[i]);
        }
        else if (i>=36 && i<=45)
        {
            this.slider.AddSlotWidget (4, this.records[i]);
        }
    }

    this.number.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.CheckNumber.bind(this));
}

accountingnotes.prototype = new Gwt.Gui.Window ();
accountingnotes.prototype.constructor = accountingnotes;

//accountingnotes destructor
accountingnotes.prototype._App = function ()
{
    this.number._Entry ();
    this.date._Date ();
    this.concept._Text ();
    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i]._record_widget();
        this.records[i] = null;
    }
    this.slider._Slider ();
    this.Report === null ? null : this.Report.close ();
    this.layout._VBox ();

    this.number = null;
    this.date = null;
    this.concept = null;
    this.records = null;
    this.slider = null;
    this.layout = null;
    this.Report = null;
};

accountingnotes.prototype.CreateData = function ()
{
    var Data = {
        Number: this.number.GetText (),
        Date: this.date.GetText (),
        Concept: this.concept.GetText ()
    };

    Data.Records = [];

    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Data.Records.push({
                Debit: (this.records[i].debit.GetText () === "") ? 0 : this.records[i].debit.GetText (),
                Credit: (this.records[i].credit.GetText() === "") ? 0 : this.records[i].credit.GetText(),
                Number: this.number.GetText (),
                Code:this.records[i].code.GetText ()
            });
        }
    }

    return Data;
};

//insert
accountingnotes.prototype.Insert = function ()
{
    var Data = this.CreateData ();
    Data.Method = "Insert";
    this.Rpc.Send (Data, this.InsertResponse.bind(this));
};

//insert response
accountingnotes.prototype.InsertResponse = function (Res)
{
    if (Res.affected_rows === 1)
    {
        this.Print();
    }
};

//update
accountingnotes.prototype.Update = function ()
{
    var Data = this.CreateData ();
    Data.Method = "Update";
    console.log (Data);
    this.Rpc.Send (Data, this.UpdateResponse.bind(this));
}

//update response
accountingnotes.prototype.UpdateResponse = function (Res)
{
    if (Res.affected_rows === 1)
    {
        this.Print();
    }
};

//delete
accountingnotes.prototype.Delete = function ()
{
    this.Rpc.Send ({Method: "Delete", Number: this.number.GetText ()}, this.DeleteResponse.bind(this));
};

//delete response
accountingnotes.prototype.DeleteResponse = function (Res)
{
    if (Res.affected_rows === 1)
    {
        this.Reset ();
    }
};

//print
accountingnotes.prototype.Print = function (Res)
{
    var Records = 0;
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Records += 1;
        }
    }
    this.Report = Gwt.Core.Contrib.LoadDocument ("/documents/accountingnote.html?records=%0".replace("%0", Records));
    this.Report.addEventListener ("load", this.ReportLoad.bind (this));
};

//report load
accountingnotes.prototype.ReportLoad = function ()
{
    var doc = this.Report.contentWindow.document;
    doc.getElementById ("Number").textContent = Gwt.Core.Contrib.ZFill(this.number.GetText(), 4);
    doc.getElementById ("Date").textContent = this.date.GetText ();
    doc.getElementById ("Concept").textContent = this.concept.GetText ();

    var TotalDebit = 0;
    var TotalCredit = 0;

    var Records = [];
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            TotalDebit += Number(this.records[i].debit.GetText ());
            TotalCredit += Number(this.records[i].credit.GetText());
            Records.push({
                "Code": this.records[i].code.GetText (),
                "Name": this.records[i].name.GetText (),
                "Partial": Gwt.Core.Contrib.TextToMonetary (""),
                "Debit": Gwt.Core.Contrib.TextToMonetary (this.records[i].debit.GetText ()),
                "Credit": Gwt.Core.Contrib.TextToMonetary (this.records[i].credit.GetText())
            });
        }
    }

    var SortedRecords = this.SortData (Records);

    for (var i=0; i < SortedRecords.length; i++)
    {
        doc.getElementById ("Code"+i).textContent = SortedRecords[i].Code;
        doc.getElementById ("Name"+i).textContent = SortedRecords[i].Name;
        doc.getElementById ("Partial"+i).textContent = (SortedRecords[i].Partial === "$0") ? "" : SortedRecords[i].Partial;
        doc.getElementById ("Debit"+i).textContent = (SortedRecords[i].Debit  === "$0") ? "" : SortedRecords[i].Debit;
        doc.getElementById ("Credit"+i).textContent = (SortedRecords[i].Credit === "$0") ? "" : SortedRecords[i].Credit;
    }

    doc.getElementById ("EqSumDebit").textContent = Gwt.Core.Contrib.TextToMonetary(TotalDebit.toString());
    doc.getElementById ("EqSumCredit").textContent = Gwt.Core.Contrib.TextToMonetary(TotalCredit.toString());

    doc = undefined;
    this.Report = null;
    this.Reset ();
};

//check number
accountingnotes.prototype.CheckNumber = function (Event)
{
    if(Event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        if (this.number.GetText () === "")
        {
            this.Rpc.Send ({Method: "NextNumber"}, this.NextNumber.bind(this));
        }
        else
        {
            this.Rpc.Send ({Method: "AutoFill", Number: this.number.GetText ()}, this.AutoFill.bind(this));
        }
    }
};

//next number
accountingnotes.prototype.NextNumber = function (Res)
{
    if (Res.length > 0)
    {
        this.number.SetText(Number(Res[0].Number)+1);
    }
    else
    {
        this.number.SetText(Number(1));
    }
};

//autofill
accountingnotes.prototype.AutoFill = function (Res)
{
    if (Res.length > 0)
    {
        this.number.SetText (Res[0].Number);
        this.date.SetDate (Res[0].Date);
        this.concept.SetText (Res[0].Concept);

        for (var i = 0; i < Res.length; i++)
        {
            this.records[i].code.SetText (Res[i].Code);
            this.records[i].name.SetText (Res[i].Name);
            this.records[i].debit.SetText ((Res[i].Debit === 0 ? "" : Res[i].Debit));
            this.records[i].credit.SetText ((Res[i].Credit === 0 ? "" : Res[i].Credit));
        }
        for (i; i < this.records.length; i++)
        {
            this.records[i].Reset();
        }
    }
    else
    {
        this.Reset ();
    }
};

//reset
accountingnotes.prototype.Reset = function ()
{
    this.number.SetText ("");
    this.date.Now ();
    this.concept.SetText ("");

    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i].Reset ();
    }
};

//sort data
accountingnotes.prototype.SortData = function (Res)
{
    var Debits = [];
    var Credits = [];

    var Sorted = [];

    for (var i = 0; i < Res.length; i++)
    {
        if (Number(Res[i].Debit) !== 0)
        {
            Debits.push (Res[i]);
        }
        else if (Number(Res[i].Credit) !== 0)
        {
            Credits.push (Res[i]);
        }
    }

    for (var i = 0; i < Debits.length; i++)
    {
        for (var j = 0; j < Res.length; j++)
        {
            if (Res[j].Code.startsWith(Debits[i].Code))
            {
                Sorted.push (Res[j]);
            }
        }
    }

    for (var i = 0; i < Credits.length; i++)
    {
        for (var j = 0; j < Res.length; j++)
        {
            if (Res[j].Code.startsWith(Credits[i].Code))
            {
                Sorted.push (Res[j]);
            }
        }
    }

    return Sorted;
};

return new function ()
{
    this.open = function()
    {
        if(instance === undefined)
        {
            instance = new accountingnotes();
            instance.Open ();
            Gwt.Core.Contrib.SetActiveApp (window.accountingnotes);
        }
        else
        {
            console.log ("%app yet opened".replace("%app", instance.__proto__.constructor.name));
        }
    };

    this.close = function ()
    {
        if(instance !== undefined)
        {
            instance.Close();
            instance = undefined;
            Gwt.Core.Contrib.RemoveActiveApp ();
        }
    };
};
})();
<|endoftext|>


<commit_before>#!/usr/bin/env node

const config = require('../config')
const fs = require('fs')
const get = require('simple-get')
const path = require('path')
const runParallelLimit = require('run-parallel-limit')
const semver = require('semver')

const TELEMETRY_PATH = path.join(config.logPath, 'telemetry')
const PARALLEL_LIMIT = 5

main()

function main () {
  // Find all files in the telemetry folder...
  fs.readdir(TELEMETRY_PATH, function (err, files) {
    if (err) throw err

    // Filter down to just log files...
    const logFiles = files
      .filter((f) => /\d{4}-\d{2}-\d{2}.log/.test(f))
      .sort()

    const summary = {}
    // Read them all and collect summary stats...
    loadTelemetrySummary(logFiles, onTelemetrySummary)

    function onTelemetrySummary (err, telemetry) {
      if (err) throw err

      summary.telemetry = telemetry

      // Load WebTorrent Desktop release history from Github...
      loadReleases(onLoadReleases)
    }

    function onLoadReleases (err, releases) {
      if (err) throw err

      summary.releases = releases
      summary.totalInstalls = releases
        .map((r) => r.installs)
        .reduce(function (a, b) {
          a.win32 += b.win32
          a.linux += b.linux
          a.darwin += b.darwin
          a.total += b.total
          return a
        }, { win32: 0, linux: 0, darwin: 0, total: 0 })

      // Finally, write summary.json
      const summaryPath = path.join(TELEMETRY_PATH, 'summary.json')
      const summaryJSON = JSON.stringify(summary, null, 2) // pretty print
      fs.writeFile(summaryPath, summaryJSON, function (err) {
        if (err) throw err
        console.log('Done!')
      })
    }
  })
}

// Reads telemetry log files in parallel, then produces a summary array, one
// entry for each day: [{date, actives, retention, ...}, ...]
function loadTelemetrySummary (logFiles, cb) {
  console.log('Summarizing ' + logFiles.length + ' telemetry log files')

  const tasks = logFiles.map(function (filename) {
    return function (cb) {
      // Read each telemetry log file, one per day...
      const filePath = path.join(TELEMETRY_PATH, filename)
      console.log('Reading ' + filename)
      fs.readFile(filePath, 'utf8', function (err, json) {
        if (err) return cb(err)

        // Each log file contains one JSON record per line
        console.log('Parsing ' + filename)

        const lines = json.trim().split('\n')
        const records = lines
          .map(function (line, i) {
            try {
              return JSON.parse(line)
            } catch (err) {
              console.error('Skipping invalid line %s:%d', filename, i + 1)
              console.error(err)
              return null
            }
          })
          .filter(Boolean)

        console.log('Read ' + records.length + ' rows from ' + filename)
        cb(null, summarizeDailyTelemetryLog(filename, records))
      })
    }
  })

  runParallelLimit(tasks, PARALLEL_LIMIT, function (err, days) {
    if (err) return cb(err)
    cb(null, combineDailyTelemetrySummaries(days))
  })
}

// Summarize a potentially huge (GB+) log file down to a few KB...
function summarizeDailyTelemetryLog (filename, records) {
  const uniqueUsers = {}
  const sessions = { total: 0, errored: 0, byVersion: {} }
  const errors = {}
  const versionByUser = {}

  records.forEach(function (record) {
    // Filter out *very* rare empty records that only have {ip}
    if (!record.system) return

    // Count unique users
    const version = (record.version || 'pre-0.12')
    const platform = record.system.osPlatform
    uniqueUsers[record.userID] = true
    versionByUser[record.userID] = { version, platform }

    // Approximate sessions by # of telemetry reports
    sessions.total++
    let byV = sessions.byVersion[version]
    if (!byV) byV = sessions.byVersion[version] = { total: 0, errored: 0 }
    byV.total++

    // Summarize uncaught errors
    const errs = record.uncaughtErrors
    if (!errs || errs.length === 0) return
    sessions.errored++
    byV.errored++

    errs.forEach(function (err) {
      const key = err.message ? err.message.substring(0, 30) : '<missing error message>'

      // Before 0.13, we didn't log the app version for each uncaught error
      // Before 0.12, we didn't log the app version altogether, and also
      // didn't redact stacktraces.
      const errVersion = err.version
        ? err.version
        : err.stack.includes('app.asar')
          ? 'pre-0.12'
          : versionCompare(version, '0.12.0') < 0
            ? version
            : '0.12.0'

      // 1. Either update the stats for an existing error...
      const error = errors[key]
      if (error) {
        error.count++
        addToSet(platform, error.platforms)
        addToSet(err.process, error.processes)
        addToSet(errVersion, error.versions, versionCompare)

        // Use the message and stack from the latest possible version
        if (errVersion === error.versions[error.versions.length - 1]) {
          error.message = err.message
          error.stack = err.stack
        }

        return
      }

      // 2. ...or create a new error
      errors[key] = {
        key: key,
        message: err.message,
        stack: err.stack,
        count: 1,
        versions: [errVersion],
        platforms: [platform],
        processes: [err.process]
      }
    })
  })

  // Summarize usage by app version and OS
  const usage = {
    version: {},
    platform: {},
    versionPlatform: {}
  }
  for (const uid in versionByUser) {
    const v = versionByUser[uid]
    const vp = v.version + '-' + v.platform
    usage.version[v.version] = (usage.version[v.version] || 0) + 1
    usage.platform[v.platform] = (usage.platform[v.platform] || 0) + 1
    usage.versionPlatform[vp] = (usage.versionPlatform[vp] || 0) + 1
  }

  return {
    date: filename.substring(0, 10), // YYYY-MM-DD
    sessions,
    uniqueUsers,
    errors,
    usage
  }
}

function versionCompare (a, b) {
  if (a === 'pre-0.12') return b === 'pre-0.12' ? 0 : -1
  if (b === 'pre-0.12') return 1
  return semver.compare(a, b)
}

// Adds an element to an array if it doesn't exist yet, the sorts the array
function addToSet (elem, arr, sortFn) {
  if (arr.includes(elem)) return
  arr.push(elem)
  arr.sort(sortFn)
}

// Combine all the per-day summaries into a single summary...
function combineDailyTelemetrySummaries (days) {
  console.log('Combining daily telemetry summaries...')

  const uniqueUsers = {} // Running set, all unique users so far
  const newUsersByDay = [] // First-time users each day

  // Loop thru all days since we started collecting telemetry...
  return days.map(function (day, i) {
    console.log('Processing ' + day.date + '...')
    // Sanity check: we should have consecutive days, correctly sorted
    if (i > 0) {
      const delta = new Date(day.date).getTime() -
                  new Date(days[i - 1].date).getTime()
      const deltaDays = delta / 24 / 3600 / 1000
      if (deltaDays !== 1) throw new Error('Missing telemetry before ' + day.date)
    }

    // Find out who installed the app that day
    const newUsers = {}
    Object.keys(day.uniqueUsers).forEach(function (user) {
      if (uniqueUsers[user]) return
      uniqueUsers[user] = true
      newUsers[user] = true
    })
    const numInstalls = Object.keys(newUsers).length
    newUsersByDay[i] = newUsers

    const errors = Object.keys(day.errors)
      .map((key) => day.errors[key])
      .sort((a, b) => b.count - a.count)

    return {
      date: day.date,
      actives: {
        today: computeActives(days, i, 1),
        last7: computeActives(days, i, 7),
        last30: computeActives(days, i, 30)
      },
      installs: numInstalls,
      retention: {
        day1: i < 2 ? null : computeRetention(days, i, 1, newUsersByDay[i - 1]),
        day7: i < 8 ? null : computeRetention(days, i, 1, newUsersByDay[i - 7]),
        day28: i < 29 ? null : computeRetention(days, i, 1, newUsersByDay[i - 28]),
        day30to60: i < 61 ? null : computeRetention(days, i, 30, newUsersByDay[i - 60])
      },
      usage: day.usage,
      errorRates: {
        last7: computeErrorRate(days, i, 7),
        today: computeErrorRate(days, i, 1),
        'today-latest': computeErrorRate(days, i, 1, true),
        'last7-latest': computeErrorRate(days, i, 7, true)
      },
      errors
    }
  })
}

// Finds the fraction of telemetry reports that contain an error
function computeErrorRate (days, index, n, latestVersionOnly) {
  if (index < n - 1) return null
  let total = 0
  let errored = 0
  for (let i = index - n + 1; i <= index; i++) {
    const day = days[i]

    // Use either *all* sessions from that UTC day, or only those sessions
    // which were at the latest released version as of the end of the day
    let sessions
    if (latestVersionOnly) {
      let latest = '0.12.0'
      Object.keys(day.usage.version).forEach(function (version) {
        if (version === 'pre-0.12') return
        if (semver.gt(version, latest)) latest = version
      })
      sessions = day.sessions.byVersion[latest] || { total: 0, errored: 0 }
    } else {
      sessions = day.sessions
    }

    total += sessions.total
    errored += sessions.errored
  }

  return total ? (errored / total) : null
}

// Finds the number of unique active users over the last n days
// ending with days[index]. Returns null if index < n - 1
function computeActives (days, index, n) {
  if (index < n - 1) return null
  const combined = {}
  for (let i = index - n + 1; i <= index; i++) {
    Object.assign(combined, days[i].uniqueUsers)
  }
  return Object.keys(combined).length
}

// Computes retention: the # of new users from some past day that used the
// app on this day.
function computeRetention (days, index, n, prevNewUsers) {
  const uniques = {}
  for (let i = index - n + 1; i <= index; i++) {
    Object.assign(uniques, days[i].uniqueUsers)
  }

  const numToday = Object.keys(uniques).length
  Object.assign(uniques, prevNewUsers)
  const numCombined = Object.keys(uniques).length
  const numPrev = Object.keys(prevNewUsers).length
  const numLost = numCombined - numToday
  return (numPrev - numLost) / numPrev
}

// Loads all WebTorrent Desktop releases
// Callback: (err, [{tag_name, published_at}, ...])
function loadReleases (cb) {
  const opts = {
    url: 'https://api.github.com/repos/webtorrent/webtorrent-desktop/releases',
    json: true,
    timeout: 30 * 1000,
    headers: {
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
    }
  }

  console.log('Fetching ' + opts.url)
  get.concat(opts, function (err, res, data) {
    if (err) return cb(err)
    console.log('Got ' + data.length + ' WebTorrent Desktop releases')
    const releases = data.map(function (d) {
      // Count total downloads
      let win32 = 0
      let darwin = 0
      let linux = 0
      d.assets.map(function (a) {
        if (a.name.endsWith('.dmg')) {
          darwin += a.download_count
        } else if (a.name.endsWith('.exe')) {
          win32 += a.download_count
        } else if (a.name.endsWith('.deb') ||
                   a.name.endsWith('linux-ia32.zip') ||
                   a.name.endsWith('linux-x64.zip')) {
          linux += a.download_count
        }
      })
      const total = win32 + darwin + linux
      const installs = { win32, darwin, linux, total }

      return { tag_name: d.tag_name, published_at: d.published_at, installs }
    })
    cb(null, releases)
  })
}
<commit_msg>reduce parallel limit<commit_after>#!/usr/bin/env node

const config = require('../config')
const fs = require('fs')
const get = require('simple-get')
const path = require('path')
const runParallelLimit = require('run-parallel-limit')
const semver = require('semver')

const TELEMETRY_PATH = path.join(config.logPath, 'telemetry')
const PARALLEL_LIMIT = 1

main()

function main () {
  // Find all files in the telemetry folder...
  fs.readdir(TELEMETRY_PATH, function (err, files) {
    if (err) throw err

    // Filter down to just log files...
    const logFiles = files
      .filter((f) => /\d{4}-\d{2}-\d{2}.log/.test(f))
      .sort()

    const summary = {}
    // Read them all and collect summary stats...
    loadTelemetrySummary(logFiles, onTelemetrySummary)

    function onTelemetrySummary (err, telemetry) {
      if (err) throw err

      summary.telemetry = telemetry

      // Load WebTorrent Desktop release history from Github...
      loadReleases(onLoadReleases)
    }

    function onLoadReleases (err, releases) {
      if (err) throw err

      summary.releases = releases
      summary.totalInstalls = releases
        .map((r) => r.installs)
        .reduce(function (a, b) {
          a.win32 += b.win32
          a.linux += b.linux
          a.darwin += b.darwin
          a.total += b.total
          return a
        }, { win32: 0, linux: 0, darwin: 0, total: 0 })

      // Finally, write summary.json
      const summaryPath = path.join(TELEMETRY_PATH, 'summary.json')
      const summaryJSON = JSON.stringify(summary, null, 2) // pretty print
      fs.writeFile(summaryPath, summaryJSON, function (err) {
        if (err) throw err
        console.log('Done!')
      })
    }
  })
}

// Reads telemetry log files in parallel, then produces a summary array, one
// entry for each day: [{date, actives, retention, ...}, ...]
function loadTelemetrySummary (logFiles, cb) {
  console.log('Summarizing ' + logFiles.length + ' telemetry log files')

  const tasks = logFiles.map(function (filename) {
    return function (cb) {
      // Read each telemetry log file, one per day...
      const filePath = path.join(TELEMETRY_PATH, filename)
      console.log('Reading ' + filename)
      fs.readFile(filePath, 'utf8', function (err, json) {
        if (err) return cb(err)

        // Each log file contains one JSON record per line
        console.log('Parsing ' + filename)

        const lines = json.trim().split('\n')
        const records = lines
          .map(function (line, i) {
            try {
              return JSON.parse(line)
            } catch (err) {
              console.error('Skipping invalid line %s:%d', filename, i + 1)
              console.error(err)
              return null
            }
          })
          .filter(Boolean)

        console.log('Read ' + records.length + ' rows from ' + filename)
        cb(null, summarizeDailyTelemetryLog(filename, records))
      })
    }
  })

  runParallelLimit(tasks, PARALLEL_LIMIT, function (err, days) {
    if (err) return cb(err)
    cb(null, combineDailyTelemetrySummaries(days))
  })
}

// Summarize a potentially huge (GB+) log file down to a few KB...
function summarizeDailyTelemetryLog (filename, records) {
  const uniqueUsers = {}
  const sessions = { total: 0, errored: 0, byVersion: {} }
  const errors = {}
  const versionByUser = {}

  records.forEach(function (record) {
    // Filter out *very* rare empty records that only have {ip}
    if (!record.system) return

    // Count unique users
    const version = (record.version || 'pre-0.12')
    const platform = record.system.osPlatform
    uniqueUsers[record.userID] = true
    versionByUser[record.userID] = { version, platform }

    // Approximate sessions by # of telemetry reports
    sessions.total++
    let byV = sessions.byVersion[version]
    if (!byV) byV = sessions.byVersion[version] = { total: 0, errored: 0 }
    byV.total++

    // Summarize uncaught errors
    const errs = record.uncaughtErrors
    if (!errs || errs.length === 0) return
    sessions.errored++
    byV.errored++

    errs.forEach(function (err) {
      const key = err.message ? err.message.substring(0, 30) : '<missing error message>'

      // Before 0.13, we didn't log the app version for each uncaught error
      // Before 0.12, we didn't log the app version altogether, and also
      // didn't redact stacktraces.
      const errVersion = err.version
        ? err.version
        : err.stack.includes('app.asar')
          ? 'pre-0.12'
          : versionCompare(version, '0.12.0') < 0
            ? version
            : '0.12.0'

      // 1. Either update the stats for an existing error...
      const error = errors[key]
      if (error) {
        error.count++
        addToSet(platform, error.platforms)
        addToSet(err.process, error.processes)
        addToSet(errVersion, error.versions, versionCompare)

        // Use the message and stack from the latest possible version
        if (errVersion === error.versions[error.versions.length - 1]) {
          error.message = err.message
          error.stack = err.stack
        }

        return
      }

      // 2. ...or create a new error
      errors[key] = {
        key: key,
        message: err.message,
        stack: err.stack,
        count: 1,
        versions: [errVersion],
        platforms: [platform],
        processes: [err.process]
      }
    })
  })

  // Summarize usage by app version and OS
  const usage = {
    version: {},
    platform: {},
    versionPlatform: {}
  }
  for (const uid in versionByUser) {
    const v = versionByUser[uid]
    const vp = v.version + '-' + v.platform
    usage.version[v.version] = (usage.version[v.version] || 0) + 1
    usage.platform[v.platform] = (usage.platform[v.platform] || 0) + 1
    usage.versionPlatform[vp] = (usage.versionPlatform[vp] || 0) + 1
  }

  return {
    date: filename.substring(0, 10), // YYYY-MM-DD
    sessions,
    uniqueUsers,
    errors,
    usage
  }
}

function versionCompare (a, b) {
  if (a === 'pre-0.12') return b === 'pre-0.12' ? 0 : -1
  if (b === 'pre-0.12') return 1
  return semver.compare(a, b)
}

// Adds an element to an array if it doesn't exist yet, the sorts the array
function addToSet (elem, arr, sortFn) {
  if (arr.includes(elem)) return
  arr.push(elem)
  arr.sort(sortFn)
}

// Combine all the per-day summaries into a single summary...
function combineDailyTelemetrySummaries (days) {
  console.log('Combining daily telemetry summaries...')

  const uniqueUsers = {} // Running set, all unique users so far
  const newUsersByDay = [] // First-time users each day

  // Loop thru all days since we started collecting telemetry...
  return days.map(function (day, i) {
    console.log('Processing ' + day.date + '...')
    // Sanity check: we should have consecutive days, correctly sorted
    if (i > 0) {
      const delta = new Date(day.date).getTime() -
                  new Date(days[i - 1].date).getTime()
      const deltaDays = delta / 24 / 3600 / 1000
      if (deltaDays !== 1) throw new Error('Missing telemetry before ' + day.date)
    }

    // Find out who installed the app that day
    const newUsers = {}
    Object.keys(day.uniqueUsers).forEach(function (user) {
      if (uniqueUsers[user]) return
      uniqueUsers[user] = true
      newUsers[user] = true
    })
    const numInstalls = Object.keys(newUsers).length
    newUsersByDay[i] = newUsers

    const errors = Object.keys(day.errors)
      .map((key) => day.errors[key])
      .sort((a, b) => b.count - a.count)

    return {
      date: day.date,
      actives: {
        today: computeActives(days, i, 1),
        last7: computeActives(days, i, 7),
        last30: computeActives(days, i, 30)
      },
      installs: numInstalls,
      retention: {
        day1: i < 2 ? null : computeRetention(days, i, 1, newUsersByDay[i - 1]),
        day7: i < 8 ? null : computeRetention(days, i, 1, newUsersByDay[i - 7]),
        day28: i < 29 ? null : computeRetention(days, i, 1, newUsersByDay[i - 28]),
        day30to60: i < 61 ? null : computeRetention(days, i, 30, newUsersByDay[i - 60])
      },
      usage: day.usage,
      errorRates: {
        last7: computeErrorRate(days, i, 7),
        today: computeErrorRate(days, i, 1),
        'today-latest': computeErrorRate(days, i, 1, true),
        'last7-latest': computeErrorRate(days, i, 7, true)
      },
      errors
    }
  })
}

// Finds the fraction of telemetry reports that contain an error
function computeErrorRate (days, index, n, latestVersionOnly) {
  if (index < n - 1) return null
  let total = 0
  let errored = 0
  for (let i = index - n + 1; i <= index; i++) {
    const day = days[i]

    // Use either *all* sessions from that UTC day, or only those sessions
    // which were at the latest released version as of the end of the day
    let sessions
    if (latestVersionOnly) {
      let latest = '0.12.0'
      Object.keys(day.usage.version).forEach(function (version) {
        if (version === 'pre-0.12') return
        if (semver.gt(version, latest)) latest = version
      })
      sessions = day.sessions.byVersion[latest] || { total: 0, errored: 0 }
    } else {
      sessions = day.sessions
    }

    total += sessions.total
    errored += sessions.errored
  }

  return total ? (errored / total) : null
}

// Finds the number of unique active users over the last n days
// ending with days[index]. Returns null if index < n - 1
function computeActives (days, index, n) {
  if (index < n - 1) return null
  const combined = {}
  for (let i = index - n + 1; i <= index; i++) {
    Object.assign(combined, days[i].uniqueUsers)
  }
  return Object.keys(combined).length
}

// Computes retention: the # of new users from some past day that used the
// app on this day.
function computeRetention (days, index, n, prevNewUsers) {
  const uniques = {}
  for (let i = index - n + 1; i <= index; i++) {
    Object.assign(uniques, days[i].uniqueUsers)
  }

  const numToday = Object.keys(uniques).length
  Object.assign(uniques, prevNewUsers)
  const numCombined = Object.keys(uniques).length
  const numPrev = Object.keys(prevNewUsers).length
  const numLost = numCombined - numToday
  return (numPrev - numLost) / numPrev
}

// Loads all WebTorrent Desktop releases
// Callback: (err, [{tag_name, published_at}, ...])
function loadReleases (cb) {
  const opts = {
    url: 'https://api.github.com/repos/webtorrent/webtorrent-desktop/releases',
    json: true,
    timeout: 30 * 1000,
    headers: {
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
    }
  }

  console.log('Fetching ' + opts.url)
  get.concat(opts, function (err, res, data) {
    if (err) return cb(err)
    console.log('Got ' + data.length + ' WebTorrent Desktop releases')
    const releases = data.map(function (d) {
      // Count total downloads
      let win32 = 0
      let darwin = 0
      let linux = 0
      d.assets.map(function (a) {
        if (a.name.endsWith('.dmg')) {
          darwin += a.download_count
        } else if (a.name.endsWith('.exe')) {
          win32 += a.download_count
        } else if (a.name.endsWith('.deb') ||
                   a.name.endsWith('linux-ia32.zip') ||
                   a.name.endsWith('linux-x64.zip')) {
          linux += a.download_count
        }
      })
      const total = win32 + darwin + linux
      const installs = { win32, darwin, linux, total }

      return { tag_name: d.tag_name, published_at: d.published_at, installs }
    })
    cb(null, releases)
  })
}
<|endoftext|>


<commit_before>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2016 MIT
 * https://github.com/lkjashdflkjahsdf
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Looks blocks for Scratch (Horizontal)
 * @author rschamp@media.mit.edu <Ray Schamp>
 */
'use strict';

goog.provide('Blockly.Blocks.looks');

goog.require('Blockly.Blocks');

Blockly.Blocks['looks_say'] = {
  /**
   * Block to say something.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "looks_say",
      "message0": "%1 %2",
      "args0": [
        {
          "type": "field_image",
          "src": Blockly.mainWorkspace.options.pathToMedia + "icons/looks_say.svg",
          "width": 40,
          "height": 40,
          "alt": "say"
        },
        {
          "type": "input_value",
          "name": "MESSAGE",
          "check": "Number"
        }
      ],
      "inputsInline": true,
      "previousStatement": null,
      "nextStatement": null,
      "colour": '#6971E7',
      "tooltip": ""
    });

    this.setHelpUrl(function () {
        return 'halp me plz. k thx bye.';
    });
  }
};
<commit_msg>Correct type of say block input.<commit_after>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2016 MIT
 * https://github.com/lkjashdflkjahsdf
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Looks blocks for Scratch (Horizontal)
 * @author rschamp@media.mit.edu <Ray Schamp>
 */
'use strict';

goog.provide('Blockly.Blocks.looks');

goog.require('Blockly.Blocks');

Blockly.Blocks['looks_say'] = {
  /**
   * Block to say something.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "looks_say",
      "message0": "%1 %2",
      "args0": [
        {
          "type": "field_image",
          "src": Blockly.mainWorkspace.options.pathToMedia + "icons/looks_say.svg",
          "width": 40,
          "height": 40,
          "alt": "say"
        },
        {
          "type": "input_value",
          "name": "MESSAGE",
          "check": "String"
        }
      ],
      "inputsInline": true,
      "previousStatement": null,
      "nextStatement": null,
      "colour": '#6971E7',
      "tooltip": ""
    });

    this.setHelpUrl(function () {
        return 'halp me plz. k thx bye.';
    });
  }
};
<|endoftext|>


<commit_before>/*https://github.com/graphql/graphql-relay-js/
*/

import { Resource, Project } from './connectors';
import {
    GraphQLObjectType,
    GraphQLSchema,
    GraphQLNonNull,
    GraphQLString,
    GraphQLID,
    GraphQLInt,
    GraphQLList
} from 'graphql';
import { nodeDefinitions, fromGlobalId, globalIdField } from 'graphql-relay';

var { nodeInterface, nodeField } = nodeDefinitions(
    (globalId) => {
        var { type, id } = fromGlobalId(globalId);
        if (type === 'Resource') {
            return Resource.findOne({_id: id});
        } else if (type === 'Project') {
            return Project.findOne({ _id: id });
        } else {
            return null;
        }
    },
    (obj) => {
        if (obj instanceof Resource) {
            return ResourceType;
        } else if (obj instanceof Project) {
            return ProjectType;
        } else {
            return null;
        }
    }
);

var ResourceType = new GraphQLObjectType({
    name: 'Resource',
    fields: () => ({
    	id: globalIdField('Resource'),
        _dni: {
            type: new GraphQLNonNull(GraphQLID),
            resolve(resource) {
                return resource._dni;
            }
        },
        firstName: {
            type: GraphQLString,
            resolve(resource) {
                return resource.firstName;
            }
        },
        lastName: {
            type: GraphQLString,
            resolve(resource) {
                return resource.lastName;
            }
        }
    }),
    interfaces: [nodeInterface],
});

var ProjectType = new GraphQLObjectType({
    name: 'Project',
    fields: () => {
        return {
            id: {
                type: new GraphQLNonNull(GraphQLID),
                resolve(project) {
                    return project.id;
                }
            },
            title: {
                type: GraphQLString,
                resolve(project) {
                    return project.title;
                }
            },
            budget: {
                type: GraphQLInt,
                resolve(project) {
                    return project.budget;
                }
            },
            resources: {
                type: new GraphQLList(ResourceType),
                resolve(project) {
                    return Resource.find({ id: project.id });
                }
            }
        }
    }
});

var queryType = new GraphQLObjectType({
    name: 'Query',
    fields: function() {
        return {
            node: nodeField
,
            resource: {
                type: ResourceType,
                args: {
                    _dni: {
                        name: 'id',
                        type: new GraphQLNonNull(GraphQLID)
                    }
                },
                resolve: function(_, args) {
                    return Resource.findOne({ _dni: args._dni });
                }
            },
            resources: {
                type: new GraphQLList(ResourceType),
                resolve: function() {
                    return Resource.find({});
                }
            },
            projects: {
                type: new GraphQLList(ProjectType),
                resolve: function() {
                    return Project.find({});
                }
            },
        }
    }
});

var MutationAdd = {
    type: ResourceType,
    description: 'Add a Resource',
    args: {
        _dni: {
            name: 'DNI or any kind of ID',
            type: new GraphQLNonNull(GraphQLString)
        },
        firstName: {
            name: 'First Name',
            type: GraphQLString
        },
        lastName: {
            name: 'Last Name',
            type: GraphQLString
        }
    },
    resolve: (root, args) => {
        var newResource = new Resource({
            _dni: args._dni,
            lastName: args.lastName,
            firstName: args.firstName
        })

        return new Promise((resolve, reject) => {
            Resource.findOneAndUpdate({ _dni: newResource._dni }, {
                _dni: args._dni,
                lastName: args.lastName,
                firstName: args.firstName
            }, { upsert: true }, function(err) {
                if (err) reject(err)
                else resolve(newResource)
            })
        })
    }
}

var MutationType = new GraphQLObjectType({
    name: 'Mutation',
    fields: {
        add: MutationAdd
    }
});

module.exports = new GraphQLSchema({
    query: queryType,
    mutation: MutationType
});
<commit_msg>Promise adds<commit_after>/*https://github.com/graphql/graphql-relay-js/
 */

import { Resource, Project } from './connectors';
import {
    GraphQLObjectType,
    GraphQLSchema,
    GraphQLNonNull,
    GraphQLString,
    GraphQLID,
    GraphQLInt,
    GraphQLList
} from 'graphql';
import { nodeDefinitions, fromGlobalId, globalIdField } from 'graphql-relay';

var { nodeInterface, nodeField } = nodeDefinitions(
    (globalId) => {
        var { type, id } = fromGlobalId(globalId);
        if (type === 'Resource') {
            return new Promise((resolve, reject) => {
                setTimeout(() => reject('MongoDB timeout when fetching field  (timeout is 500ms)'), 500);
                Resource.findOne({ _id: id }).then((res) => resolve(res));
            })
        } else if (type === 'Project') {
            return Project.findOne({ _id: id });
        } else {
            return null;
        }
    },
    (obj) => {
        if (obj instanceof Resource) {
            return ResourceType;
        } else if (obj instanceof Project) {
            return ProjectType;
        } else {
            return null;
        }
    }
);

var ResourceType = new GraphQLObjectType({
    name: 'Resource',
    fields: () => ({
        id: globalIdField('Resource'),
        _dni: {
            type: new GraphQLNonNull(GraphQLID),
            resolve(resource) {
                return resource._dni;
            }
        },
        firstName: {
            type: GraphQLString,
            resolve(resource) {
                return resource.firstName;
            }
        },
        lastName: {
            type: GraphQLString,
            resolve(resource) {
                return resource.lastName;
            }
        }
    }),
    interfaces: [nodeInterface],
});

var ProjectType = new GraphQLObjectType({
    name: 'Project',
    fields: () => {
        return {
            id: {
                type: new GraphQLNonNull(GraphQLID),
                resolve(project) {
                    return project.id;
                }
            },
            title: {
                type: GraphQLString,
                resolve(project) {
                    return project.title;
                }
            },
            budget: {
                type: GraphQLInt,
                resolve(project) {
                    return project.budget;
                }
            },
            resources: {
                type: new GraphQLList(ResourceType),
                resolve(project) {
                    return Resource.find({ id: project.id });
                }
            }
        }
    }
});

var queryType = new GraphQLObjectType({
    name: 'Query',
    fields: function() {
        return {
            node: nodeField,
            resource: {
                type: ResourceType,
                args: {
                    _dni: {
                        name: 'id',
                        type: new GraphQLNonNull(GraphQLID)
                    }
                },
                resolve: function(_, args) {
                    return Resource.findOne({ _dni: args._dni });
                }
            },
            resources: {
                type: new GraphQLList(ResourceType),
                resolve: function() {
                    return Resource.find({});
                }
            },
            projects: {
                type: new GraphQLList(ProjectType),
                resolve: function() {
                    return Project.find({});
                }
            },
        }
    }
});

var MutationAdd = {
    type: ResourceType,
    description: 'Add a Resource',
    args: {
        _dni: {
            name: 'DNI or any kind of ID',
            type: new GraphQLNonNull(GraphQLString)
        },
        firstName: {
            name: 'First Name',
            type: GraphQLString
        },
        lastName: {
            name: 'Last Name',
            type: GraphQLString
        }
    },
    resolve: (root, args) => {
        var newResource = new Resource({
            _dni: args._dni,
            lastName: args.lastName,
            firstName: args.firstName
        })

        return new Promise((resolve, reject) => {
            Resource.findOneAndUpdate({ _dni: newResource._dni }, {
                _dni: args._dni,
                lastName: args.lastName,
                firstName: args.firstName
            }, { upsert: true }, function(err) {
                if (err) reject(err)
                else resolve(newResource)
            })
        })
    }
}

var MutationType = new GraphQLObjectType({
    name: 'Mutation',
    fields: {
        add: MutationAdd
    }
});

module.exports = new GraphQLSchema({
    query: queryType,
    mutation: MutationType
});
<|endoftext|>


<commit_before>var toTag = ".athlete-name.minimal, .athlete-name, .minimal, td.name>a"; //classes to tag

function loadTags(items) {
  function addTag(ele, tag) {
    ele.innerHTML += " \(" + tag + "\)";
  }
  function isUntagged(ele, tag) {
    return ele.innerHTML.indexOf(" \(" + tag + "\)") == -1;
  }

  var allTags = items;
  //console.log(allTags);

  //add tag to the user's page
  if (window.location.href.indexOf(".com/athletes/") > -1) {
    var desc = document.getElementsByClassName("description")[0];
    var name = desc.getElementsByTagName("h3")[0];
    var tagcontent = '[tag]';
    for (var tag in allTags) {
      if (window.location.href.indexOf(tag) > -1 ){
        tagcontent = allTags[tag];
      }
    }
    // Create the element
    var tagele = document.createElement('h6');
    tagele.textContent = tagcontent;
    tagele.ondblclick = function() {
      var newtag = prompt("Set tag");
      var userid = window.location.href.match(/athletes\/(\d+)/);
      if (userid !== null) {
        self.port.emit('newTag', {id: userid[1], tag: newtag});
      }
    };
    // Inserts after name
    desc.insertBefore(tagele, name.nextSibling);
  }

  function mapTags() {
    //load all athlete urls
    var urls = $(toTag);

    //iterate over athletes
    for (var i=0; i<urls.length; i++){

      //iterate over tags
      for (var tag in allTags) {
        //if our guy, tag
        if (urls[i].hasAttribute("href"))
          if (urls[i].getAttribute("href").indexOf(tag) > -1){
            //unless already tagged
            if (isUntagged(urls[i], allTags[tag]))
              addTag(urls[i], allTags[tag]);
          }
      }
    }
  }

  var curLength=0;
  setInterval(function(){
    if ($(toTag).length!=curLength){
      curLength=$(toTag).length;
      mapTags();
    }
  },1000);

}

// Receive tags from index.js
self.port.on("currentTags", function(tags) {
  loadTags(tags);
});

self.port.on('currentconnections', function(connections) {
  loadConnections(connections)
});

function loadConnections(connections) {
  var linksToAthlete = function(url, stravaid) {
    return url.hasAttribute('href') && url.getAttribute('href').indexOf(stravaid) > -1;
  };
  var isTagged = function(url, reddituser) {
    return false; // TODO
  };
  var addTag = function(url, reddituser) {
    var nextsib = url.nextSibling;
    var dad = url.parentNode;
    var redditlink = document.createElement('a');
    redditlink.href = 'https://www.reddit.com/u/' + reddituser;
    redditlink.textContent = '/u/' + reddituser;
    dad.insertBefore(redditlink, nextsib);
  };
  var urls = document.querySelectorAll(toTag);
  for (var i = 0; i < urls.length; i++) {
    for (var connection in connections) {
      if (linksToAthlete(urls[i], connection)) {
        if (! isTagged(urls[i], connections[connection])) {
          addTag(urls[i], connections[connection]);
        }
      }
    }
  }
}
<commit_msg>Tag in following/followers<commit_after>var toTag = ".athlete-name.minimal, .athlete-name, .minimal, td.name>a, li>div.h4.topless>a"; //classes to tag

function loadTags(items) {
  function addTag(ele, tag) {
    ele.innerHTML += " \(" + tag + "\)";
  }
  function isUntagged(ele, tag) {
    return ele.innerHTML.indexOf(" \(" + tag + "\)") == -1;
  }

  var allTags = items;
  //console.log(allTags);

  //add tag to the user's page
  if (window.location.href.indexOf(".com/athletes/") > -1) {
    var desc = document.getElementsByClassName("description")[0];
    var name = desc.getElementsByTagName("h3")[0];
    var tagcontent = '[tag]';
    for (var tag in allTags) {
      if (window.location.href.indexOf(tag) > -1 ){
        tagcontent = allTags[tag];
      }
    }
    // Create the element
    var tagele = document.createElement('h6');
    tagele.textContent = tagcontent;
    tagele.ondblclick = function() {
      var newtag = prompt("Set tag");
      var userid = window.location.href.match(/athletes\/(\d+)/);
      if (userid !== null) {
        self.port.emit('newTag', {id: userid[1], tag: newtag});
      }
    };
    // Inserts after name
    desc.insertBefore(tagele, name.nextSibling);
  }

  function mapTags() {
    //load all athlete urls
    var urls = $(toTag);

    //iterate over athletes
    for (var i=0; i<urls.length; i++){

      //iterate over tags
      for (var tag in allTags) {
        //if our guy, tag
        if (urls[i].hasAttribute("href"))
          if (urls[i].getAttribute("href").indexOf(tag) > -1){
            //unless already tagged
            if (isUntagged(urls[i], allTags[tag]))
              addTag(urls[i], allTags[tag]);
          }
      }
    }
  }

  var curLength=0;
  setInterval(function(){
    if ($(toTag).length!=curLength){
      curLength=$(toTag).length;
      mapTags();
    }
  },1000);

}

// Receive tags from index.js
self.port.on("currentTags", function(tags) {
  loadTags(tags);
});

self.port.on('currentconnections', function(connections) {
  loadConnections(connections)
});

function loadConnections(connections) {
  var linksToAthlete = function(url, stravaid) {
    return url.hasAttribute('href') && url.getAttribute('href').indexOf(stravaid) > -1;
  };
  var isTagged = function(url, reddituser) {
    return false; // TODO
  };
  var addTag = function(url, reddituser) {
    var nextsib = url.nextSibling;
    var dad = url.parentNode;
    var redditlink = document.createElement('a');
    redditlink.href = 'https://www.reddit.com/u/' + reddituser;
    redditlink.textContent = ' (/u/' + reddituser + ')';
    dad.insertBefore(redditlink, nextsib);
  };
  var urls = document.querySelectorAll(toTag);
  for (var i = 0; i < urls.length; i++) {
    for (var connection in connections) {
      if (linksToAthlete(urls[i], connection)) {
        if (! isTagged(urls[i], connections[connection])) {
          addTag(urls[i], connections[connection]);
        }
      }
    }
  }
}
<|endoftext|>