<commit_before>"use strict";

var

fsmore = require('../util/fs-more'),
path = require('path'),
FTPClient = require('ftp'),
async = require("async"),
fs = require('fs'),
color = require('colors');

function traverseUpload(conn, localDir, remoteDir, cb){
    var remoteDir,cb;
    var tasks = [];

    console.log("uploading " +localDir + " -> " + remoteDir);

    tasks.push(function(done){
        process.stdout.write("mkdir "+remoteDir+" ");
        conn.mkdir(remoteDir,function(e){
            if(e){
                process.stdout.write(("fail "+e).red+"\r\n");
            }else{
                process.stdout.write("done".green+"\r\n");
            }
            done();
        });
    });

    fsmore.traverseDir(localDir,function(info){
        var task;
        var dest = path.join(remoteDir,info.relPath);
        if(info.isFile){
            task = function(done){
                process.stdout.write("upload "+dest+" ");
                conn.put(fs.createReadStream(info.fullPath),dest,function(e){
                    if(e){
                        process.stdout.write(("fail "+e).red+"\r\n");
                    }else{
                        process.stdout.write("done".green+"\r\n");
                    }
                    done();
                });
            }
        }

        if(info.isDirectory){
            task = function(done){
                process.stdout.write("mkdir "+dest+" ");
                conn.mkdir(dest,function(e){
                    if(e){
                        process.stdout.write(("fail "+e).red+"\r\n");
                    }else{
                        process.stdout.write("done".green+"\r\n");
                    }
                    done();
                });
            }
        }

        tasks.push(task);
    });

    async.series(tasks,cb);
};

/**
 * @param {Object} options {
        user: {string}
        password: {string}
        remoteDir: {string}
        localDir: {string}
    }
 */
function upload(options, callback){

    var conn = new FTPClient();

    conn.on('connect', function() {

        conn.auth(options.user, options.password, function(e) {
            if (e){
                throw e;
            }

            traverseUpload(conn, options.localDir, options.remoteDir, function(e){
                if(e){
                    console.log(e);
                }

                callback();
                conn.end();
            });
        });
    });

    conn.connect(options.port||21,options.host);
};

function traverseDownload(conn, remoteDir, localDir, callback){
    fsmore.mkdirSync(localDir);

    // default to root dir
    remoteDir = remoteDir || '/';

    var tasks = [];

    conn.list(remoteDir, function(e, entries) {
        if(e){
            throw e;
        }

        var i = 0, len = entries.length,
            entry;

        for (; i < len; ++i) {
            entry = entries[i];

            if (typeof entry === 'string'){
                // console.log('<raw entry>: ' + entries[i]);

            } else {
                if(entry.type === '-'){
                    (function(entry){
                        tasks.push(function(done){
                            downloadFile(conn, path.join(remoteDir, entry.name), path.join(localDir, entry.name), function(e, stream, data){
                                stream.on('success', function() {
                                    done();
                                });

                                stream.on('error', function(e) {
                                    conn.end();
                                    throw e;
                                });

                                stream.pipe(fs.createWriteStream(data.localName));
                            });
                        });
                    })(entry);

                }else if(entry.type === 'd' && entry.name !== '..' && entry.name !== '.'){

                    (function(entry){
                        tasks.push(function(done){
                            traverseDownload(conn, path.join(remoteDir, entry.name), path.join(localDir, entry.name), function(){
                                done();
                            });
                        });

                    })(entry);
                }
            }
        }

        async.series(tasks, callback);
    });
};

function downloadFile(conn, remoteName, localName, callback){
    conn.get(remoteName, function(e, stream) {
        callback(e, stream, {
            localName: localName
        });
    });
};

/**
 * @param {Object} options {
        user: {string}
        password: {string}
        remoteDir: {string}
        localDir: {string}
    }
 */
function download(options, callback){
    var conn = new FTPClient();

    conn.on('connect', function(){

        conn.auth(options.user, options.password, function(e){
            if(e){
                throw e;
            }

            traverseDownload(conn, options.remoteDir, options.localDir, function(e){
                if(e){
                    console.log(e);
                }
                callback();
                conn.end();
            });
        });
    });

    conn.connect(options.port || 21, options.host);
};

exports.upload = upload;
exports.download = download;<commit_msg>从ftp下载latest-pack，上传为success-pack，为ftp-handler增加exports uploadFiles,downloadFile,盲写未测试<commit_after>"use strict";

var

fsmore = require('../util/fs-more'),
path = require('path'),
FTPClient = require('ftp'),
async = require("async"),
fs = require('fs'),
color = require('colors');

function traverseUpload(conn, localDir, remoteDir, cb){
    var remoteDir,cb;
    var tasks = [];

    console.log("uploading " +localDir + " -> " + remoteDir);

    tasks.push(function(done){
        process.stdout.write("mkdir "+remoteDir+" ");
        conn.mkdir(remoteDir,function(e){
            if(e){
                process.stdout.write(("fail "+e).red+"\r\n");
            }else{
                process.stdout.write("done".green+"\r\n");
            }
            done();
        });
    });

    fsmore.traverseDir(localDir,function(info){
        var task;
        var dest = path.join(remoteDir,info.relPath);
        if(info.isFile){
            task = function(done){
                process.stdout.write("upload "+dest+" ");
                conn.put(fs.createReadStream(info.fullPath),dest,function(e){
                    if(e){
                        process.stdout.write(("fail "+e).red+"\r\n");
                    }else{
                        process.stdout.write("done".green+"\r\n");
                    }
                    done();
                });
            }
        }

        if(info.isDirectory){
            task = function(done){
                process.stdout.write("mkdir "+dest+" ");
                conn.mkdir(dest,function(e){
                    if(e){
                        process.stdout.write(("fail "+e).red+"\r\n");
                    }else{
                        process.stdout.write("done".green+"\r\n");
                    }
                    done();
                });
            }
        }

        tasks.push(task);
    });

    async.series(tasks,cb);
};

/**
 * @param {Object} options {
        user: {string}
        password: {string}
        remoteDir: {string}
        localDir: {string}
    }
 */
function upload(options, callback){

    var conn = new FTPClient();

    conn.on('connect', function() {

        conn.auth(options.user, options.password, function(e) {
            if (e){
                throw e;
            }

            traverseUpload(conn, options.localDir, options.remoteDir, function(e){
                if(e){
                    console.log(e);
                }

                callback();
                conn.end();
            });
        });
    });

    conn.connect(options.port||21,options.host);
};

function traverseDownload(conn, remoteDir, localDir, callback){
    fsmore.mkdirSync(localDir);

    // default to root dir
    remoteDir = remoteDir || '/';

    var tasks = [];

    conn.list(remoteDir, function(e, entries) {
        if(e){
            throw e;
        }

        var i = 0, len = entries.length,
            entry;

        for (; i < len; ++i) {
            entry = entries[i];

            if (typeof entry === 'string'){
                // console.log('<raw entry>: ' + entries[i]);

            } else {
                if(entry.type === '-'){
                    (function(entry){
                        tasks.push(function(done){
                            downloadFile(conn, path.join(remoteDir, entry.name), path.join(localDir, entry.name), function(e, stream, data){
                                stream.on('success', function() {
                                    done();
                                });

                                stream.on('error', function(e) {
                                    conn.end();
                                    throw e;
                                });

                                stream.pipe(fs.createWriteStream(data.localName));
                            });
                        });
                    })(entry);

                }else if(entry.type === 'd' && entry.name !== '..' && entry.name !== '.'){

                    (function(entry){
                        tasks.push(function(done){
                            traverseDownload(conn, path.join(remoteDir, entry.name), path.join(localDir, entry.name), function(){
                                done();
                            });
                        });

                    })(entry);
                }
            }
        }

        async.series(tasks, callback);
    });
};

function downloadFile(conn, remoteName, localName, callback){
    conn.get(remoteName, function(e, stream) {
        callback(e, stream, {
            localName: localName
        });
    });
};

/**
 * @param {Object} options {
        user: {string}
        password: {string}
        remoteDir: {string}
        localDir: {string}
    }
 */
function download(options, callback){
    var conn = new FTPClient();

    conn.on('connect', function(){

        conn.auth(options.user, options.password, function(e){
            if(e){
                throw e;
            }

            traverseDownload(conn, options.remoteDir, options.localDir, function(e){
                if(e){
                    console.log(e);
                }
                callback();
                conn.end();
            });
        });
    });

    conn.connect(options.port || 21, options.host);
};

exports.uploadFile = function(options,callback){

    var conn = new FTPClient();
    conn.on('connect', function(){
        var dest = options.remoteName;

            process.stdout.write("upload "+dest+" ");
            conn.put(fs.createReadStream(option.localName),dest,function(e){
                if(e){
                    process.stdout.write(("fail "+e).red+"\r\n");
                }else{
                    process.stdout.write("done".green+"\r\n");
                }
                callback();
                conn.end();
            });
    })
    conn.connect(options.port || 21, options.host);
};

exports.downloadFile = function(options,callback){
    var conn = new FTPClient();
    conn.on('connect', function(){
        conn.auth(options.user, options.password, function(e){
            if(e){
                throw e;
            }
            downloadFile(conn, options.remoteName, options.localName, function(e, stream, data){
                stream.on('success', function() {
                    callback();
                    conn.end();
                });
                stream.on('error', function(e) {
                    conn.end();
                    throw e;
                });
                stream.pipe(fs.createWriteStream(data.localName));
            });
        });
    });
    conn.connect(options.port || 21, options.host);
};
exports.upload = upload;
exports.download = download;<|endoftext|>


<commit_before>#!/bin/env node
'use strict';

var config = require('./config.js');

var fs = require('fs-extra');
var path = require('path');

var TelegramBot = require('node-telegram-bot-api');
var im = require('imagemagick');
var JSZip = require("jszip");
var async = require('async');

var token = config.token;
var bot = new TelegramBot(token, {polling: true});
im.convert.path = config.im_convert_path;

var messages = JSON.parse(fs.readFileSync(path.resolve('./lang/' + config.lang + '.json'), 'utf8'));

var ramdb = {};
// check storage path
var fspath = path.resolve(config.file_storage);
fs.stat(fspath, function(err, stats) {
    if (err && err.code === 'ENOENT') {
        console.log(messages.app.storagepathnotexist);
        fs.mkdirpSync(fspath);
    }
});

bot.onText(/\/newpack*/i, function (msg) {
    var chatId = msg.chat.id;
    if (ramdb[chatId] && ramdb[chatId].files.length > 0) {
        return bot.sendMessage(chatId, messages.msg.taskexist);
    }
    ramdb[chatId] = {
        start: msg.date,
        files: [],
        srcimg: [],
        destimg: [],
        islocked: false
    };
    bot.sendMessage(chatId, messages.msg.newpack.replace('%max%', config.maximages));
});

bot.onText(/\/finish\s?(png)?\s?(\d+)?/i, function (msg, match) {
    var chatId = msg.chat.id;
    var format = match[1];
    var width = match[2];
    if (ramdb[chatId] && ramdb[chatId].files.length > 0) {
        console.log('[' + chatId + '] Starting pack task...');
        ramdb[chatId].islocked = true;
        var packpath = config.file_storage + '/' + chatId,
            srcpath = packpath + '/src/',
            imgpath = packpath + '/img/';
        fs.mkdirpSync(path.resolve(packpath));
        fs.mkdirpSync(path.resolve(srcpath));
        fs.mkdirpSync(path.resolve(imgpath));
        async.series([
            function (cb) {
                console.log('[' + chatId + '] Downloading files...');
                bot.sendMessage(chatId, messages.msg.downloading);
                async.eachSeries(ramdb[chatId].files, function (fileId, callback) {
                    bot.downloadFile(fileId, path.resolve(srcpath))
                            .then(function (srcimg) {
                                console.log('[' + chatId + '] File ' + fileId + ' saved to disk.');
                                ramdb[chatId].srcimg.push(srcimg);
                                callback();
                            });
                    }, function () {
                        cb();
                    });
            },
            function (cb) {
                console.log('[' + chatId + '] Converting images...');
                bot.sendMessage(chatId, messages.msg.converting);
                async.eachSeries(ramdb[chatId].srcimg, function (src, callback) {
                    var imarg = [src];
                    var destimg = path.resolve(imgpath + '/' + path.basename(src, 'webp') + 'jpg');
                    if (width && width < 512) {
                        imarg.push('-resize', width + 'x' + width);
                    }
                    if (format === 'png') {
                        destimg = path.resolve(imgpath + '/' + path.basename(src, 'webp') + 'png');
                        imarg.push(destimg);
                    } else {
                        // use -flatten to add white background to jpg files
                        imarg.push('-flatten', destimg)
                    }
                    console.log('[' + chatId + '] Convert command:', im.convert.path, imarg.join(' '));
                    im.convert(imarg, function (err, stdout) {
                        ramdb[chatId].destimg.push(destimg);
                        callback(err);
                    });
                }, function (err) {
                    if (err) {
                        bot.sendMessage(chatId, messages.msg.error);
                        return cleanup(chatId);
                    }
                    cb();
                });
            },
            function (cb) {
                bot.sendMessage(chatId, messages.msg.packaging);
                console.log('[' + chatId + '] Adding files to package...');
                var zip = new JSZip();
                ramdb[chatId].srcimg.forEach(function (src) {
                    var fname = chatId + '/src/' + path.basename(src);
                    console.log('[' + chatId + '] Adding file ', fname);
                    zip.file(fname, fs.readFileSync(path.resolve(src)));
                });
                ramdb[chatId].destimg.forEach(function (dest) {
                    var fname = chatId + '/img/' + path.basename(dest);
                    console.log('[' + chatId + '] Adding file ', fname);
                    zip.file(fname, fs.readFileSync(path.resolve(dest)));
                });
                console.log('[' + chatId + '] Packaging files...');
                zip.generateAsync({
                    compression: 'DEFLATE',
                    type: 'nodebuffer',
                    comment: 'Created by stickerimagebot',
                    platform: process.platform
                })
                    .then(function (content) {
                        cb(null, content);
                    });
            }],
            function (err, res) {
                bot.sendMessage(chatId, messages.msg.sending);
                bot.sendDocument(chatId, res[2]);
                console.log('[' + chatId + '] Sending zip file...');
                // clear task
                cleanup(chatId);
                console.log('[' + chatId + '] Task finished.');
            }
        );
    } else {
        bot.sendMessage(chatId, messages.msg.nosticker);
    }
});

bot.on('message', function (msg) {
    var chatId = msg.chat.id;

    if (msg.sticker && ramdb[chatId] && !ramdb[chatId].islocked) {
        ramdb[chatId].files.push(msg.sticker.file_id);
        bot.sendMessage(chatId, messages.msg.saved.replace('%remain%', config.maximages - ramdb[chatId].files.length));
    } else if (ramdb[chatId] && ramdb[chatId].islocked) {

    } else {
        if (!/(\/(finish|newpack))/i.exec(msg.text)) {
            bot.sendMessage(chatId, messages.msg.start);
        }
    }
});

function cleanup(id) {
    console.log('[' + id + '] Cleaning up...');
    ramdb[id] = undefined;
    fs.removeSync(path.resolve(config.file_storage + '/' + id));
}
<commit_msg>add task lock message<commit_after>#!/bin/env node
'use strict';

var config = require('./config.js');

var fs = require('fs-extra');
var path = require('path');

var TelegramBot = require('node-telegram-bot-api');
var im = require('imagemagick');
var JSZip = require("jszip");
var async = require('async');

var token = config.token;
var bot = new TelegramBot(token, {polling: true});
im.convert.path = config.im_convert_path;

var messages = JSON.parse(fs.readFileSync(path.resolve('./lang/' + config.lang + '.json'), 'utf8'));

var ramdb = {};
// check storage path
var fspath = path.resolve(config.file_storage);
fs.stat(fspath, function(err, stats) {
    if (err && err.code === 'ENOENT') {
        console.log(messages.app.storagepathnotexist);
        fs.mkdirpSync(fspath);
    }
});

bot.onText(/\/newpack*/i, function (msg) {
    var chatId = msg.chat.id;
    if (ramdb[chatId] && ramdb[chatId].files.length > 0) {
        return bot.sendMessage(chatId, messages.msg.taskexist);
    }
    ramdb[chatId] = {
        start: msg.date,
        files: [],
        srcimg: [],
        destimg: [],
        islocked: false
    };
    bot.sendMessage(chatId, messages.msg.newpack.replace('%max%', config.maximages));
});

bot.onText(/\/finish\s?(png)?\s?(\d+)?/i, function (msg, match) {
    var chatId = msg.chat.id;
    var format = match[1];
    var width = match[2];
    if (ramdb[chatId] && ramdb[chatId].files.length > 0) {
        console.log('[' + chatId + '] Starting pack task...');
        ramdb[chatId].islocked = true;
        var packpath = config.file_storage + '/' + chatId,
            srcpath = packpath + '/src/',
            imgpath = packpath + '/img/';
        fs.mkdirpSync(path.resolve(packpath));
        fs.mkdirpSync(path.resolve(srcpath));
        fs.mkdirpSync(path.resolve(imgpath));
        async.series([
            function (cb) {
                console.log('[' + chatId + '] Downloading files...');
                bot.sendMessage(chatId, messages.msg.downloading);
                async.eachSeries(ramdb[chatId].files, function (fileId, callback) {
                    bot.downloadFile(fileId, path.resolve(srcpath))
                            .then(function (srcimg) {
                                console.log('[' + chatId + '] File ' + fileId + ' saved to disk.');
                                ramdb[chatId].srcimg.push(srcimg);
                                callback();
                            });
                    }, function () {
                        cb();
                    });
            },
            function (cb) {
                console.log('[' + chatId + '] Converting images...');
                bot.sendMessage(chatId, messages.msg.converting);
                async.eachSeries(ramdb[chatId].srcimg, function (src, callback) {
                    var imarg = [src];
                    var destimg = path.resolve(imgpath + '/' + path.basename(src, 'webp') + 'jpg');
                    if (width && width < 512) {
                        imarg.push('-resize', width + 'x' + width);
                    }
                    if (format === 'png') {
                        destimg = path.resolve(imgpath + '/' + path.basename(src, 'webp') + 'png');
                        imarg.push(destimg);
                    } else {
                        // use -flatten to add white background to jpg files
                        imarg.push('-flatten', destimg)
                    }
                    console.log('[' + chatId + '] Convert command:', im.convert.path, imarg.join(' '));
                    im.convert(imarg, function (err, stdout) {
                        ramdb[chatId].destimg.push(destimg);
                        callback(err);
                    });
                }, function (err) {
                    if (err) {
                        bot.sendMessage(chatId, messages.msg.error);
                        return cleanup(chatId);
                    }
                    cb();
                });
            },
            function (cb) {
                bot.sendMessage(chatId, messages.msg.packaging);
                console.log('[' + chatId + '] Adding files to package...');
                var zip = new JSZip();
                ramdb[chatId].srcimg.forEach(function (src) {
                    var fname = chatId + '/src/' + path.basename(src);
                    console.log('[' + chatId + '] Adding file ', fname);
                    zip.file(fname, fs.readFileSync(path.resolve(src)));
                });
                ramdb[chatId].destimg.forEach(function (dest) {
                    var fname = chatId + '/img/' + path.basename(dest);
                    console.log('[' + chatId + '] Adding file ', fname);
                    zip.file(fname, fs.readFileSync(path.resolve(dest)));
                });
                console.log('[' + chatId + '] Packaging files...');
                zip.generateAsync({
                    compression: 'DEFLATE',
                    type: 'nodebuffer',
                    comment: 'Created by stickerimagebot',
                    platform: process.platform
                })
                    .then(function (content) {
                        cb(null, content);
                    });
            }],
            function (err, res) {
                bot.sendMessage(chatId, messages.msg.sending);
                bot.sendDocument(chatId, res[2]);
                console.log('[' + chatId + '] Sending zip file...');
                // clear task
                cleanup(chatId);
                console.log('[' + chatId + '] Task finished.');
            }
        );
    } else {
        bot.sendMessage(chatId, messages.msg.nosticker);
    }
});

bot.on('message', function (msg) {
    var chatId = msg.chat.id;

    if (msg.sticker && ramdb[chatId] && !ramdb[chatId].islocked) {
        ramdb[chatId].files.push(msg.sticker.file_id);
        bot.sendMessage(chatId, messages.msg.saved.replace('%remain%', config.maximages - ramdb[chatId].files.length));
    } else if (ramdb[chatId] && ramdb[chatId].islocked) {
        return bot.sendMessage(chatId, messages.msg.taskexist);
    } else {
        if (!/(\/(finish|newpack))/i.exec(msg.text)) {
            bot.sendMessage(chatId, messages.msg.start);
        }
    }
});

function cleanup(id) {
    console.log('[' + id + '] Cleaning up...');
    ramdb[id] = undefined;
    fs.removeSync(path.resolve(config.file_storage + '/' + id));
}
<|endoftext|>


<commit_before>/**
 * Created by tungtouch on 2/5/15.
 */

/*
* Listen UDP from Device: 128.199.126.250
* */

var dgram = require("dgram");
var colors = require('colors');
var Dequeue = require('dequeue')
var async = require('async');
var redis = require("redis");
var rClient = redis.createClient();
var fifo = new Dequeue();
//var ports = [4000, 4001, 4002, 3333, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011];
var ports = [4444];
var r = 0;

var client = dgram.createSocket('udp4');

rClient.on("error", function (err) {
    console.log("Error " + err);
});

fetcher();
for(var i=0; i < ports.length; i++){

    console.log("Start listen port ",i,":", ports[i]);

    client.on("error", function (err) {
        console.log("Server error:\n".red + err.stack);
        client.close();
    });

    client.on("message", function (msg, rinfo) {
        //console.log("Message:", msg);
        fifo.push(msg);

    });

    client.bind(ports[i]);

}
function fetcher() {
    console.log("Fetcher Run:", FIFO);
    while (fifo.length > 0)
    {
        var msg = fifo.shift();
        console.log("Message: ", msg);
        process.nextTick(fetcher);
    }
    //setImmediate(fetcher); //make this function continuously run
}<commit_msg>Update UDPefef<commit_after>/**
 * Created by tungtouch on 2/5/15.
 */

/*
* Listen UDP from Device: 128.199.126.250
* */

var dgram = require("dgram");
var colors = require('colors');
var Dequeue = require('dequeue')
var async = require('async');
var redis = require("redis");
var rClient = redis.createClient();
var fifo = new Dequeue();
//var ports = [4000, 4001, 4002, 3333, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011];
var ports = [4444];
var r = 0;

var client = dgram.createSocket('udp4');

rClient.on("error", function (err) {
    console.log("Error " + err);
});

fetcher();
for(var i=0; i < ports.length; i++){

    console.log("Start listen port ",i,":", ports[i]);

    client.on("error", function (err) {
        console.log("Server error:\n".red + err.stack);
        client.close();
    });

    client.on("message", function (msg, rinfo) {
        //console.log("Message:", msg);
        fifo.push(msg);

    });

    client.bind(ports[i]);

}
function fetcher() {
    console.log("Fetcher Run:", fifo);
    while (fifo.length > 0)
    {
        var msg = fifo.shift();
        console.log("Message: ", msg);
        process.nextTick(fetcher);
    }
    //setImmediate(fetcher); //make this function continuously run
}<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2019 The Stdlib Authors.
*
* 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.
*/

'use strict';

// MAIN //

// TODO: remove once we have stdlib pkg equivalents
var GLOBALS = {
	'Array': Array,
	'Boolean': Boolean,
	'Date': Date,
	'Function': Function,
	'Object': Object,
	'parseFloat': parseFloat,
	'parseInt': parseInt,
	'RegExp': RegExp,
	'String': String,

	// TODO: BigInt, DataView, Map, Set, Promise, Reflect(?), WeakMap, WeakSet, WebAssembly

	'Error': Error,
	'EvalError': EvalError,
	'RangeError': RangeError,
	'ReferenceError': ReferenceError,
	'SyntaxError': SyntaxError,
	'TypeError': TypeError,
	'URIError': URIError,

	'clearImmediate': clearImmediate,
	'clearInterval': clearInterval,
	'clearTimeout': clearTimeout,
	'setImmediate': setImmediate,
	'setInterval': setInterval,
	'setTimeout': setTimeout
};

// EXPORTS //

module.exports = GLOBALS;
<commit_msg>Remove Function from list of globals<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2019 The Stdlib Authors.
*
* 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.
*/

'use strict';

// MAIN //

// TODO: remove once we have stdlib pkg equivalents
var GLOBALS = {
	'Array': Array,
	'Boolean': Boolean,
	'Date': Date,
	'Object': Object,
	'parseFloat': parseFloat,
	'parseInt': parseInt,
	'RegExp': RegExp,
	'String': String,

	// TODO: BigInt, DataView, Map, Set, Promise, Reflect(?), WeakMap, WeakSet, WebAssembly

	'Error': Error,
	'EvalError': EvalError,
	'RangeError': RangeError,
	'ReferenceError': ReferenceError,
	'SyntaxError': SyntaxError,
	'TypeError': TypeError,
	'URIError': URIError,

	'clearImmediate': clearImmediate,
	'clearInterval': clearInterval,
	'clearTimeout': clearTimeout,
	'setImmediate': setImmediate,
	'setInterval': setInterval,
	'setTimeout': setTimeout
};

// EXPORTS //

module.exports = GLOBALS;
<|endoftext|>


<commit_before>import React from 'react';

class App extends React.Component {
  render() {
    return
{this.props.testprop}

    // return React.createElement('h1', null, 'Hello world');
  }
}

App.propTypes = {
  testprop: React.PropTypes.string,
  truc: React.PropTypes.number.isRequired
}

App.defaultProps = {
  truc: 2
}

export default App
<commit_msg>finish step 7<commit_after>import React from 'react';

// class App extends React.Component {
//   render() {
//     return
<Heart testCustomValidation="Test56" /> {this.props.testprop}

//     // return React.createElement('h1', null, 'Hello world');
//   }
// }

class App extends React.Component {
  constructor() {
    super();
    this.state = {currentEvent: '---'}
    this.update = this.update.bind(this)
  }

  update(event) {
    this.setState({currentEvent: event.type})
  }

  render() {
    return (

        <textarea
          onKeyPress={this.update}
          onCopy={this.update}
          onCut={this.update}
          onPaste={this.update}
          onFocus={this.update}
          onBlur={this.update}
          onDoubleClick={this.update}
          onClick={this.update}
          onTouchStart={this.update}
          onTouchMove={this.update}
          onTouchEnd={this.update}
          cols="30"
          rows="10">
        </textarea>

{this.state.currentEvent}

    )
  }
}

class Heart extends React.Component {
  render() {
    return ♥ {this.props.testCustomValidation};
  }
}

Heart.propTypes = {
  testCustomValidation(props, propName, component) {
    if (!(propName in props)) {
      return new Error(`${propName} n'est pas défini`)
    }

    if (props[propName].length < 6) {
      return new Error(`${propName} too short`)
    }
  }
}

App.propTypes = {
  testprop: React.PropTypes.string,
  truc: React.PropTypes.number.isRequired,
}

App.defaultProps = {
  truc: 2
}

export default App
<|endoftext|>


<commit_before>//BaconHawkJS Bot Frame Work by Bacon_Space & NiteHawk Please refer to https://github.com/BaconHawk/BaconHawkJS for help!

var chalk = require("chalk");
var logError = chalk.red('ERR!') + chalk.white
var log = console.log
var version = "v0.0.1"
var copyr = '© BaconHawk 2017'

try{
	var Discord = require("discord.js");
} catch(e) {
	log(logError(e.stack));
	log(logError(process.version));
	log('Please run npm install and make sure it passes with NO errors!');
	process.exit();
}

log('Starting BaconHawkJS\nBaconHawkJS version: ' + version + '\nDiscordJS version: v' + Discord.version);

//Get Auth Data from Auth.json
try{
	var AuthData = require("./auth.json");
} catch(e) {
	log(logError('Please create an auth.json file in the main directory based off of the auth.json.example file!\n' + e.stack));
	process.exit();
}

//Get Config Data from config.json
try{
	var Config = require("./config.json");
} catch(e) {
	log(logError('Please create an config.json file in the main directory based off of the config.json.example file!\n' + e.stack));
	process.exit();
}

var commands = {
	"ping": {
		run: function(bot,suffix,msg) {
			msg.reply('Pong!');
		}
	}
}

var bot = new Discord.Client();

function checkForCommand(msg) {
	if(msg.author.id != bot.user.id && msg.content.startsWith(Config.prefix)){

		var cmdTxt = msg.content.split(" ")[0].substring(Config.prefix.length);
		var suffix = msg.content.substring(cmdTxt.length+Config.prefix.length+1);

		log('Running ' + cmdTxt + `, from ${msg.author.id}, as a command!`);

		var cmd = commands[cmdTxt];

		if(cmd){
			try{
				cmd.run(bot,suffix,msg);
			} catch(e) {
				var msgTxt = 'Command ' + cmdTxt + ' was unable to run!';
				msg.channel.sendMessage(msgTxt);
			}
		}
	}
}

bot.on("message", msg => checkForCommand(msg, false));

if(AuthData.bot_token){
	bot.login(AuthData.bot_token);
} else{
	log(logError('Please Provide a bot token in auth.json'));
}
<commit_msg>Added bhlog instead of log<commit_after>//BaconHawkJS Bot Frame Work by Bacon_Space & NiteHawk Please refer to https://github.com/BaconHawk/BaconHawkJS for help!

var chalk = require("chalk");
var logError = chalk.red('ERR!') + chalk.white
var bhlog = console.log
var version = "v0.0.1"
var copyr = '© BaconHawk 2017'

try{
	var Discord = require("discord.js");
} catch(e) {
	bhlog(logError(e.stack));
	bhlog(logError(process.version));
	bhlog('Please run npm install and make sure it passes with NO errors!');
	process.exit();
}

bhlog('Starting BaconHawkJS\nBaconHawkJS version: ' + version + '\nDiscordJS version: v' + Discord.version);

//Get Auth Data from Auth.json
try{
	var AuthData = require("./auth.json");
} catch(e) {
	bhlog(logError('Please create an auth.json file in the main directory based off of the auth.json.example file!\n' + e.stack));
	process.exit();
}

//Get Config Data from config.json
try{
	var Config = require("./config.json");
} catch(e) {
	bhlog(logError('Please create an config.json file in the main directory based off of the config.json.example file!\n' + e.stack));
	process.exit();
}

var commands = {
	"ping": {
		run: function(bot,suffix,msg) {
			msg.reply('Pong!');
		}
	}
}

var bot = new Discord.Client();

function checkForCommand(msg) {
	if(msg.author.id != bot.user.id && msg.content.startsWith(Config.prefix)){

		var cmdTxt = msg.content.split(" ")[0].substring(Config.prefix.length);
		var suffix = msg.content.substring(cmdTxt.length+Config.prefix.length+1);

		bhlog('Running ' + cmdTxt + `, from ${msg.author.id}, as a command!`);

		var cmd = commands[cmdTxt];

		if(cmd){
			try{
				cmd.run(bot,suffix,msg);
			} catch(e) {
				var msgTxt = 'Command ' + cmdTxt + ' was unable to run!';
				msg.channel.sendMessage(msgTxt);
			}
		}
	}
}

bot.on("message", msg => checkForCommand(msg, false));

if(AuthData.bot_token){
	bot.login(AuthData.bot_token);
} else{
	bhlog(logError('Please Provide a bot token in auth.json'));
}
<|endoftext|>


<commit_before>// adventure
// art
// beauty
// celebrating
// challenge
// connection
// crafting
// creation
// debate
// discussion
// fun
// investigating
// kindness??
// knitting
// learning
// meeting
// music
// nature
// peace
// performance
// rendezvous
// restoration
// stealth
// teamwork
// visions
// volunteering

var most_recent_item = null;
var fuzzfactor = {};

function make_fuzzfactor(){
  var xfuzz = Math.random() * 0.05 - 0.025;
  var yfuzz = Math.random() * 0.05 - 0.025;
  return [xfuzz, yfuzz];
}

// item - an item on the map
function item(city, tag, title, thumb_url, lat, lng, atags, latch, comm, req, x){
  tag = tag.replace('Person__', '').replace('Landmark__', '');

  // ignore items if this stream can't communicate with them
  var via_sys = Agents.via_sys(tag, comm);
  if (!Agents.reachable(tag, via_sys)) return null;

  // ignore items without lat+lng
  if (!lat || !lng || lat == 0 || lng == 0) return null;

  // country state state city zip
  if (x && (x.acc == 'zip' || x.acc == 'city') && lat && lng) {
    if (!fuzzfactor[tag]) fuzzfactor[tag] = make_fuzzfactor();
    lat = Number(lat) + fuzzfactor[tag][0];
    lng = Number(lng) + fuzzfactor[tag][1];
  }
  return most_recent_item = Resource.add_or_update(tag, {
    city_id: city,
    title: title,
    thumb_url: thumb_url,
    lat: lat,
    lng: lng,
    atags: atags,
    latch: latch,
    comm: comm,
    req: req,
    via_sys: via_sys
  }, x);
}

function off(tag){
  if (!tag) return;
  tag = tag.replace('Person__', '').replace('Landmark__', '');
  if (tag.resource_type() == 'Person') {
    Agents.remove(tag);
    This.agents = Agents.here();
    Facebar.populate(This.agents);
  } else if (tag.resource_type() == 'Landmark') {
    Landmarks.remove(tag);
  }
  Map.site_remove(MapMarkers.type(tag), tag);
}

$.extend(Resource.prototype, {
  in_city: function(city, more) {
    return this.find("=city_id " + city) || [];
  },

  here: function(n) {
    var result;
    if (This.city) {
      result = this.find("=city_id " + This.city_id) || [];
    } else {
      result = this.everything() || [];
    }
    if (This.q) {
      var query = This.q.toLowerCase();
      result = result.grep(function(x){
        var strings = (x.upfor + " " + x.has + " " + x.title).toLowerCase();
        return strings.match(query);
      });
    }
    if (n) result = result.slice(0, n);
    return result;
  },

  nearby: function(lat, lng, distance_in_meters) {
    var x = new GLatLng(lat, lng);
    return this.here().grep(function(thing){
      var y = new GLatLng(thing.lat, thing.lng);
      var distance = x.distanceFrom(y);
      return distance < distance_in_meters;
    });
  }

});

Persons = Agents = new Resource('Person', {
  enhancer: function(item) {
    item.recent_events = [];
    Item.calculate_fields(item);
  },
  changed: function(what_changed) {
    if (what_changed[This.user.tag]) $.extend(This.user, what_changed[This.user.tag]);
    if (App.loaded && This.agents) {
      if (Agents.something_added) {
        This.agents = Agents.here();
        if (Map.layer_visible['agents']) Map.layer_recalculate('agents');
      }
      if (Landmarks.something_added) {
        // Map.site_add('landmarks', )
      }
      Facebar.populate(This.agents);
      $.each(what_changed, function(k, v){
        if (This.item == k) {
          This._item = v;
          App.refresh_mapwindow();
        }
        if (Map.site_exists('agents', k)) {
          if (v.city_id == This.city_id) Map.site_move('agents', k, v.lat, v.lng);
          else Map.site_remove('agents', k);
        } else {
          $('#objects_nav').app_paint();
        }
      });
    }
  },
  init_manual: function() {
    // strip out unreachable agents
    $.each(Agents.everything() || [], function(i, item) {
      item.via_sys = Agents.via_sys(item.id, item.comm);
      if (!Agents.reachable(item.id, item.via_sys)) Agents.remove(item.id);
    });
  },
  via_sys: function(tag, comm) {
    var via_sys = (comm && comm.split(/ /)[3] || '');
    if (App.current_stream_systems().length > 0) {
      via_sys = via_sys.split('').intersect(App.current_stream_systems()).join('');
      if (window.demo && via_sys.length == 0) via_sys = App.current_stream_systems();
    }
    return via_sys;
  },
  reachable: function(tag, via_sys) {
    return (tag.resource_type() != 'Person' || via_sys.length > 0);
  },
  has_question: function(item) {
    return item && ("" + item.msg + item.update).contains('?');
  },
  has_problem: function(item) {
    return item && ("" + item.update).startsWith('problem:') && item.update_ts >= item.msg_ts;
  },
  concern: function(item) {
    return item.msg ? item.msg : item.update;
  }
});

Item = {

  atags_to_upfors: {
    conn: 'connection',
    // bene: 'kindness',
    // food: 'food',
    art: 'art',
    adv: 'adventure',
    // mgames: 'puzzles',
    vol: 'volunteering',
    stretchme: 'challenge',
    stealth: 'stealth',
    pchal: 'challenge',
    pgrowth: 'challenge',
    convo: 'discussion debate',
    beauty: 'nature quiet',
    // raok: 'kindness',
    cornerfun: 'strangeness'
  },

  calculate_fields: function(item) {
    $.each(Item.calculated_fields, function(){
      if (!item) return true;
      var field = this[0];
      var fn = this[1];
      item[field] = fn(item);
      return true;
    });
  },

  calculated_fields: [
    ['upfor', function(item) {
      if (!item || !item.atags) return null;
      return item.atags;
      // return item.atags.split(' ').map(function(x){ return Item.atags_to_upfors[x]; }).compact().uniq().join(' ');
    }],

    ['time_avail', function(item) {
      return ['20 MIN', '1 HR', '30 MIN', '5 MIN'].choose_random();
    }],

    ['immediate', function(item) {
      if (window.demo) return true;
      return item.via_sys && item.via_sys.length > 0 && item.via_sys != 'e';
    }],

    ['badges', function(item) {
      var badges = '';
      if (!item.immediate) badges += '';
      return badges;
    }],

    ['map_icon', function(item) {
      if (Selection.is_item_selected(item.id)) return 'sman';
      if (!item.latch || !item.comm) return 'brownman';
      var comm = item.comm.split(' ');
      var latch = item.latch.split(' ');
      if (latch.contains("latched")) {
        if (latch.contains(This.user.tag)) return 'brownman';
        else return 'grayman';
      }
      if (comm.contains('engaged')) {
        var current_time = Date.unix();
        var comm_time = Number(comm.pop());
        if (current_time - comm_time < 30 * 60) return "greenman";
        else return "wman";
      }
      if (comm.contains("green")) return "greenman";
      if (item.pgoal) return 'rgman';
      else return "wman";
    }],

    ['thumb_url', function(item) {
      if (item.thumb_url) return item.thumb_url.gcify_url();
      return 'i/swirl.jpg';
    }],

    ['last_ts_ago', function(item) {
      if (!item.comm) return 0;
      var comm  = item.comm.split(' ');
      var they_said_ts     = comm[1] || 0;
      var we_said_ts       = comm[2] || 0;
      return -Math.max(they_said_ts, we_said_ts);
    }],

    ['fab_state', function(item){
      // some backward compat fixes
      if (!item.transients) item.transients = {};
      if (!item.answers)    item.answers    = {};
      if (!item.latch || !item.comm)    return 'inaccessible';
      var comm  = item.comm.split(' ');
      var latch = item.latch.split(' ');
      if (comm.contains("unreachable")) return "inaccessible";
      if (latch.contains("unknown"))    return "unknown";

      // parse recent content
      var last_event         = item.recent_events && item.recent_events.last();
      var last_answer_and_ts = $values(item.answers).sort_by(function(x){ return -x[1]; })[0];
      var most_recent_answer = last_answer_and_ts && Date.within(last_answer_and_ts[1], 24*60*60) && last_answer_and_ts[0];

      // calculate timestamps
      var they_said_ts     = Number(comm[1] || 0);
      var we_said_ts       = Number(comm[2] || 0);
      var last_ts          = Math.max(they_said_ts, we_said_ts);
      var within_four_hrs  = Date.within(last_ts, 4 * 60 * 60);
      var within_three_min = Date.within(last_ts, 3 * 60);
      var latch_start = item.latch.to_mspec().start;
      var their_court = (
        (we_said_ts > they_said_ts + 2) ||
        (last_event && last_event.atype == 'accepted')
      );
      var our_court   = !(their_court);

      // bails
      if (item.transients['retired']) return 'retired';

      if (our_court) {

        if (Agents.has_question(item) || Agents.has_problem(item)) {
          if (!within_four_hrs)  return "addressable";
          if (!within_three_min) return "neglected";
          return "concerns";
        }

        if (latch.contains("unlatched")) {

          if (most_recent_answer) {
            if (most_recent_answer[0].match(/^yes/)) return "responded_yes";
            if (most_recent_answer[0].match(/^no/))  return "responded_no";
            return "responded";
          }
          return "available";

        } else {

          // if they were latched earlier, and then said something else
          if (latch_start && latch_start + 100 < they_said_ts) return "reporting";

          // else
          return "assigned";
        }

      }
      else if (their_court) {
        if (!Date.within(we_said_ts, 4 * 60 * 60))  return "available";
        if (!Date.within(last_ts, 30 * 60))         return "unresponsive";
        if (latch.contains("unlatched"))            return 'in_dialogue';
        if (item.latch.to_mspec().start && item.latch.to_mspec().start > they_said_ts) {
          return "pending";
        }

        return "assigned";
      }

      return "unknown";
    }]

  ]
};

// wants: function(item) {
//   if (!item.atags) return;
//   var readywords = item.atags.split(' ').map(function(x){ return Item.atags_to_upfors[x]; }).compact().join(' ').split(' ').uniq();
//   if (readywords.length == 0) return "???";
//   return readywords.choose_random().toUpperCase();
// },

// readywords: function(item) {
//   if (!item.atags) return;
//   return item.atags.split(' ').map(function(x){ return Item.atags_to_upfors[x]; }).compact();
// },

// locked: function(item) {
//   if (!item.latch) return false;
//   if (item.latch.split(' ').indexOf(This.user.tag) >= 0) return false;
//   return true;
// },
<commit_msg>use item#comm->msg_ts in place of heard_from_ts, if available<commit_after>// adventure
// art
// beauty
// celebrating
// challenge
// connection
// crafting
// creation
// debate
// discussion
// fun
// investigating
// kindness??
// knitting
// learning
// meeting
// music
// nature
// peace
// performance
// rendezvous
// restoration
// stealth
// teamwork
// visions
// volunteering

var most_recent_item = null;
var fuzzfactor = {};

function make_fuzzfactor(){
  var xfuzz = Math.random() * 0.05 - 0.025;
  var yfuzz = Math.random() * 0.05 - 0.025;
  return [xfuzz, yfuzz];
}

// item - an item on the map
function item(city, tag, title, thumb_url, lat, lng, atags, latch, comm, req, x){
  tag = tag.replace('Person__', '').replace('Landmark__', '');

  // ignore items if this stream can't communicate with them
  var via_sys = Agents.via_sys(tag, comm);
  if (!Agents.reachable(tag, via_sys)) return null;

  // ignore items without lat+lng
  if (!lat || !lng || lat == 0 || lng == 0) return null;

  // country state state city zip
  if (x && (x.acc == 'zip' || x.acc == 'city') && lat && lng) {
    if (!fuzzfactor[tag]) fuzzfactor[tag] = make_fuzzfactor();
    lat = Number(lat) + fuzzfactor[tag][0];
    lng = Number(lng) + fuzzfactor[tag][1];
  }
  return most_recent_item = Resource.add_or_update(tag, {
    city_id: city,
    title: title,
    thumb_url: thumb_url,
    lat: lat,
    lng: lng,
    atags: atags,
    latch: latch,
    comm: comm,
    req: req,
    via_sys: via_sys
  }, x);
}

function off(tag){
  if (!tag) return;
  tag = tag.replace('Person__', '').replace('Landmark__', '');
  if (tag.resource_type() == 'Person') {
    Agents.remove(tag);
    This.agents = Agents.here();
    Facebar.populate(This.agents);
  } else if (tag.resource_type() == 'Landmark') {
    Landmarks.remove(tag);
  }
  Map.site_remove(MapMarkers.type(tag), tag);
}

$.extend(Resource.prototype, {
  in_city: function(city, more) {
    return this.find("=city_id " + city) || [];
  },

  here: function(n) {
    var result;
    if (This.city) {
      result = this.find("=city_id " + This.city_id) || [];
    } else {
      result = this.everything() || [];
    }
    if (This.q) {
      var query = This.q.toLowerCase();
      result = result.grep(function(x){
        var strings = (x.upfor + " " + x.has + " " + x.title).toLowerCase();
        return strings.match(query);
      });
    }
    if (n) result = result.slice(0, n);
    return result;
  },

  nearby: function(lat, lng, distance_in_meters) {
    var x = new GLatLng(lat, lng);
    return this.here().grep(function(thing){
      var y = new GLatLng(thing.lat, thing.lng);
      var distance = x.distanceFrom(y);
      return distance < distance_in_meters;
    });
  }

});

Persons = Agents = new Resource('Person', {
  enhancer: function(item) {
    item.recent_events = [];
    Item.calculate_fields(item);
  },
  changed: function(what_changed) {
    if (what_changed[This.user.tag]) $.extend(This.user, what_changed[This.user.tag]);
    if (App.loaded && This.agents) {
      if (Agents.something_added) {
        This.agents = Agents.here();
        if (Map.layer_visible['agents']) Map.layer_recalculate('agents');
      }
      if (Landmarks.something_added) {
        // Map.site_add('landmarks', )
      }
      Facebar.populate(This.agents);
      $.each(what_changed, function(k, v){
        if (This.item == k) {
          This._item = v;
          App.refresh_mapwindow();
        }
        if (Map.site_exists('agents', k)) {
          if (v.city_id == This.city_id) Map.site_move('agents', k, v.lat, v.lng);
          else Map.site_remove('agents', k);
        } else {
          $('#objects_nav').app_paint();
        }
      });
    }
  },
  init_manual: function() {
    // strip out unreachable agents
    $.each(Agents.everything() || [], function(i, item) {
      item.via_sys = Agents.via_sys(item.id, item.comm);
      if (!Agents.reachable(item.id, item.via_sys)) Agents.remove(item.id);
    });
  },
  via_sys: function(tag, comm) {
    var via_sys = (comm && comm.split(/ /)[3] || '');
    if (App.current_stream_systems().length > 0) {
      via_sys = via_sys.split('').intersect(App.current_stream_systems()).join('');
      if (window.demo && via_sys.length == 0) via_sys = App.current_stream_systems();
    }
    return via_sys;
  },
  reachable: function(tag, via_sys) {
    return (tag.resource_type() != 'Person' || via_sys.length > 0);
  },
  has_question: function(item) {
    return item && ("" + item.msg + item.update).contains('?');
  },
  has_problem: function(item) {
    return item && ("" + item.update).startsWith('problem:') && item.update_ts >= item.msg_ts;
  },
  concern: function(item) {
    return item.msg ? item.msg : item.update;
  }
});

Item = {

  atags_to_upfors: {
    conn: 'connection',
    // bene: 'kindness',
    // food: 'food',
    art: 'art',
    adv: 'adventure',
    // mgames: 'puzzles',
    vol: 'volunteering',
    stretchme: 'challenge',
    stealth: 'stealth',
    pchal: 'challenge',
    pgrowth: 'challenge',
    convo: 'discussion debate',
    beauty: 'nature quiet',
    // raok: 'kindness',
    cornerfun: 'strangeness'
  },

  calculate_fields: function(item) {
    $.each(Item.calculated_fields, function(){
      if (!item) return true;
      var field = this[0];
      var fn = this[1];
      item[field] = fn(item);
      return true;
    });
  },

  calculated_fields: [
    ['upfor', function(item) {
      if (!item || !item.atags) return null;
      return item.atags;
      // return item.atags.split(' ').map(function(x){ return Item.atags_to_upfors[x]; }).compact().uniq().join(' ');
    }],

    ['time_avail', function(item) {
      return ['20 MIN', '1 HR', '30 MIN', '5 MIN'].choose_random();
    }],

    ['immediate', function(item) {
      if (window.demo) return true;
      return item.via_sys && item.via_sys.length > 0 && item.via_sys != 'e';
    }],

    ['badges', function(item) {
      var badges = '';
      if (!item.immediate) badges += '';
      return badges;
    }],

    ['map_icon', function(item) {
      if (Selection.is_item_selected(item.id)) return 'sman';
      if (!item.latch || !item.comm) return 'brownman';
      var comm = item.comm.split(' ');
      var latch = item.latch.split(' ');
      if (latch.contains("latched")) {
        if (latch.contains(This.user.tag)) return 'brownman';
        else return 'grayman';
      }
      if (comm.contains('engaged')) {
        var current_time = Date.unix();
        var comm_time = Number(comm.pop());
        if (current_time - comm_time < 30 * 60) return "greenman";
        else return "wman";
      }
      if (comm.contains("green")) return "greenman";
      if (item.pgoal) return 'rgman';
      else return "wman";
    }],

    ['thumb_url', function(item) {
      if (item.thumb_url) return item.thumb_url.gcify_url();
      return 'i/swirl.jpg';
    }],

    ['last_ts_ago', function(item) {
      if (!item.comm) return 0;
      var comm  = item.comm.split(' ');
      var they_said_ts     = comm[4] || comm[1] || 0;
      var we_said_ts       = comm[2] || 0;
      return -Math.max(they_said_ts, we_said_ts);
    }],

    ['fab_state', function(item){
      // some backward compat fixes
      if (!item.transients) item.transients = {};
      if (!item.answers)    item.answers    = {};
      if (!item.latch || !item.comm)    return 'inaccessible';
      var comm  = item.comm.split(' ');
      var latch = item.latch.split(' ');
      if (comm.contains("unreachable")) return "inaccessible";
      if (latch.contains("unknown"))    return "unknown";

      // parse recent content
      var last_event         = item.recent_events && item.recent_events.last();
      var last_answer_and_ts = $values(item.answers).sort_by(function(x){ return -x[1]; })[0];
      var most_recent_answer = last_answer_and_ts && Date.within(last_answer_and_ts[1], 24*60*60) && last_answer_and_ts[0];

      // calculate timestamps
      var they_said_ts     = Number(comm[4] || comm[1] || 0);
      var we_said_ts       = Number(comm[2] || 0);
      var last_ts          = Math.max(they_said_ts, we_said_ts);
      var within_four_hrs  = Date.within(last_ts, 4 * 60 * 60);
      var within_three_min = Date.within(last_ts, 3 * 60);
      var latch_start = item.latch.to_mspec().start;
      var their_court = (
        (we_said_ts > they_said_ts + 2) ||
        (last_event && last_event.atype == 'accepted')
      );
      var our_court   = !(their_court);

      // bails
      if (item.transients['retired']) return 'retired';

      if (our_court) {

        if (Agents.has_question(item) || Agents.has_problem(item)) {
          if (!within_four_hrs)  return "addressable";
          if (!within_three_min) return "neglected";
          return "concerns";
        }

        if (latch.contains("unlatched")) {

          if (most_recent_answer) {
            if (most_recent_answer[0].match(/^yes/)) return "responded_yes";
            if (most_recent_answer[0].match(/^no/))  return "responded_no";
            return "responded";
          }
          return "available";

        } else {

          // if they were latched earlier, and then said something else
          if (latch_start && latch_start + 100 < they_said_ts) return "reporting";

          // else
          return "assigned";
        }

      }
      else if (their_court) {
        if (!Date.within(we_said_ts, 4 * 60 * 60))  return "available";
        if (!Date.within(last_ts, 30 * 60))         return "unresponsive";
        if (latch.contains("unlatched"))            return 'in_dialogue';
        if (item.latch.to_mspec().start && item.latch.to_mspec().start > they_said_ts) {
          return "pending";
        }

        return "assigned";
      }

      return "unknown";
    }]

  ]
};

// wants: function(item) {
//   if (!item.atags) return;
//   var readywords = item.atags.split(' ').map(function(x){ return Item.atags_to_upfors[x]; }).compact().join(' ').split(' ').uniq();
//   if (readywords.length == 0) return "???";
//   return readywords.choose_random().toUpperCase();
// },

// readywords: function(item) {
//   if (!item.atags) return;
//   return item.atags.split(' ').map(function(x){ return Item.atags_to_upfors[x]; }).compact();
// },

// locked: function(item) {
//   if (!item.latch) return false;
//   if (item.latch.split(' ').indexOf(This.user.tag) >= 0) return false;
//   return true;
// },
<|endoftext|>


<commit_before>/* @flow */

import { StyleSheet, Dimensions } from 'react-native';

export const BTN_UNDERLAY_COLOR = '#E1E2E1';
export const ADDDRESS_BAR_HEIGHT = 70;
export const ADDDRESS_BAR_ROW_HEIGHT = 30;

const { width } = Dimensions.get('window');

// Used across all navigational components i.e StackRouteView
const globalStyles = StyleSheet.create({
  wrapper: {
    flex: 1,
  },
  navigationCard: {
    overflow: 'hidden',
    position: 'absolute',
    backgroundColor: '#E9E9EF',
    bottom: 0,
    left: 0,
    right: 0,
    top: 0,
  },
});

const addressBarStyles = StyleSheet.create({
  wrapper: {
    position: 'absolute',
    top: -ADDDRESS_BAR_HEIGHT,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'transparent',
  },
  addressBar: {
    position: 'absolute',
    height: ADDDRESS_BAR_HEIGHT,
    paddingTop: 18,
    top: 0,
    left: 0,
    right: 0,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: BTN_UNDERLAY_COLOR,
  },
  field: {
    flex: 1,
    height: 40,
    fontSize: 18,
    backgroundColor: '#FFFFFF',
    borderColor: '#C1C2C2',
    borderWidth: 1,
    padding: 4,
    alignSelf: 'center',
    borderRadius: 2,
    marginLeft: 6,
  },
  forwardBtn: {
    width: 34,
    alignItems: 'center',
  },
  forwardBtnText: {
    fontSize: 20,
    color: '#585858',
    marginTop: 6,
  },
  forwardBtnTextDisabled: {
    color: '#C1C2C2',
  },
  backBtn: {
    width: 34,
    alignItems: 'center',
    marginLeft: 6,
  },
  backBtnText: {
    fontSize: 20,
    color: '#585858',
    transform: [{ rotate: '180deg' }],
  },
  backBtnTextDisabled: {
    color: '#C1C2C2',
  },
  docsLink: {
    width: 60,
    fontSize: 16,
    textAlign: 'center',
    color: '#585858',
  },
});

const addressBarHistoryStyles = StyleSheet.create({
  container: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
  },
  backdrop: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
  },
  listViewWrapper: {
    position: 'absolute',
    marginBottom: 20,
    width: Math.max(width * 0.60, 180),
    marginLeft: 4,
    marginTop: ADDDRESS_BAR_HEIGHT - 2,
    shadowColor: '#929292',
    shadowOpacity: 1,
    shadowRadius: 2,
    shadowOffset: { width: 0, height: 0 },
    backgroundColor: '#FFFFFF',
  },
  listView: {
    flex: 1,
  },
  listViewContent: {
  },
  row: {
    paddingLeft: 10,
    lineHeight: 24,
    height: ADDDRESS_BAR_ROW_HEIGHT,
  },
});

export { globalStyles, addressBarStyles, addressBarHistoryStyles };
<commit_msg>use absoluteFillObject in styles<commit_after>/* @flow */

import { StyleSheet, Dimensions } from 'react-native';

export const BTN_UNDERLAY_COLOR = '#E1E2E1';
export const ADDDRESS_BAR_HEIGHT = 70;
export const ADDDRESS_BAR_ROW_HEIGHT = 30;

const { width } = Dimensions.get('window');

const { absoluteFillObject } = StyleSheet;

// Used across all navigational components i.e StackRouteView
const globalStyles = StyleSheet.create({
  wrapper: {
    flex: 1,
  },
  navigationCard: {
    ...absoluteFillObject,
    backgroundColor: '#E9E9EF',
    overflow: 'hidden',
  },
});

const addressBarStyles = StyleSheet.create({
  wrapper: {
    backgroundColor: 'transparent',
    bottom: 0,
    left: 0,
    position: 'absolute',
    right: 0,
    top: -ADDDRESS_BAR_HEIGHT,
  },
  addressBar: {
    alignItems: 'center',
    backgroundColor: BTN_UNDERLAY_COLOR,
    flexDirection: 'row',
    height: ADDDRESS_BAR_HEIGHT,
    justifyContent: 'center',
    left: 0,
    paddingTop: 18,
    position: 'absolute',
    right: 0,
    top: 0,
  },
  field: {
    alignSelf: 'center',
    backgroundColor: '#FFFFFF',
    borderColor: '#C1C2C2',
    borderRadius: 2,
    borderWidth: 1,
    flex: 1,
    fontSize: 18,
    height: 40,
    marginLeft: 6,
    padding: 4,
  },
  forwardBtn: {
    alignItems: 'center',
    width: 34,
  },
  forwardBtnText: {
    color: '#585858',
    fontSize: 20,
    marginTop: 6,
  },
  forwardBtnTextDisabled: {
    color: '#C1C2C2',
  },
  backBtn: {
    alignItems: 'center',
    marginLeft: 6,
    width: 34,
  },
  backBtnText: {
    color: '#585858',
    fontSize: 20,
    transform: [{ rotate: '180deg' }],
  },
  backBtnTextDisabled: {
    color: '#C1C2C2',
  },
  docsLink: {
    color: '#585858',
    fontSize: 16,
    textAlign: 'center',
    width: 60,
  },
});

const addressBarHistoryStyles = StyleSheet.create({
  container: {
    ...absoluteFillObject,
  },
  backdrop: {
    ...absoluteFillObject,
  },
  listViewWrapper: {
    backgroundColor: '#FFFFFF',
    marginBottom: 20,
    marginLeft: 4,
    marginTop: ADDDRESS_BAR_HEIGHT - 2,
    position: 'absolute',
    shadowColor: '#929292',
    shadowOffset: { width: 0, height: 0 },
    shadowOpacity: 1,
    shadowRadius: 2,
    width: Math.max(width * 0.60, 180),
  },
  listView: {
    flex: 1,
  },
  listViewContent: {
  },
  row: {
    height: ADDDRESS_BAR_ROW_HEIGHT,
    lineHeight: 24,
    paddingLeft: 10,
  },
});

export { globalStyles, addressBarStyles, addressBarHistoryStyles };
<|endoftext|>


<commit_before>Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    items: [
    {
        xtype: 'container',
        itemId: 'releaseDropDown',
        columnWidth: 1
    }
    ,
    {
        xtype: 'container',
        itemId: 'chart1',
        columnWidth: 1
    }

    ],

    launch: function() {
        // add the release dropdown selector
        this.down("#releaseDropDown").add( {
            xtype: 'rallyreleasecombobox',
            itemId : 'releaseSelector',
            listeners: {
                    select: this._onReleaseSelect,
    	            scope: this
            }
        });
        // used to save the selected release
        this.gRelease = null;
    },

    // called when a release is selected.
    _onReleaseSelect : function() {
        // get and save the selected release
        var value =  this.down('#releaseSelector').getRecord();
        this.gRelease = value.data;
        console.log("selected release record data",value.raw);

        // construct a query to get all releases in scope
        Ext.create('Rally.data.WsapiDataStore', {
            model: "Release",
            autoLoad : true,
            fetch: ["ObjectID","Name","ReleaseStartDate","ReleaseDate","Project"],
            filters: [
                {
                    property: 'Name',
                    value: value.data.Name
                }
            ],
            listeners: {
                // load: function(store, data, success) {
                //     console.log("data",data);
                // }
                scope : this,
                load : this._onReleases
            }
        });
    },

// called with all releases in scope
    _onReleases : function(store, data, success) {
        var that = this;
        console.log("data",data);

        var releaseIds = _.map(data, function(d) { return d.data.ObjectID; });
        console.log("Release IDs",releaseIds);
        // now we are going to retrieve snapshots for all releases ...
        Ext.create('Rally.data.lookback.SnapshotStore', {
            autoLoad : true,
            listeners: {
                load: this._onReleaseSnapShotData,
                scope : this
            },
            fetch: ['ObjectID','Name', 'State', '_ValidFrom','_ValidTo'],
            hydrate: ['State'],
            filters: [
                {
                    property: '_TypeHierarchy',
                    operator: 'in',
                    value: ['Defect']
                },
                {
                    property: 'Release',
                    operator: 'in',
                    value: releaseIds
                }
            ]
        });
    },

    // called with the snapshot data for all defects in the releases
    _onReleaseSnapShotData : function(store,data,success) {

        // we are going to use lumenize and the TimeSeriesCalculator to aggregate the data into
        // a time series.
        var lumenize = window.parent.Rally.data.lookback.Lumenize;
        var snapShotData = _.map(data,function(d){return d.data});
        console.log("snapShotData",snapShotData);

        // these values determine if a defect is open, closed or verified.
        var openValues = ['Submitted','Open'];
        var closedValues = ['Closed','Rejected','Duplicated'];
        var verifiedValues = ['Verified'];

        // can be used to 'knockout' holidays
        var holidays = [
            {year: 2014, month: 1, day: 1}  // Made up holiday to test knockout
        ];

        // metrics to chart
        var metrics = [
            {as: 'DefectOpenCount',     f: 'filteredCount', filterField: 'State', filterValues: openValues},
            {as: 'DefectClosedCount',   f: 'filteredCount', filterField: 'State', filterValues: closedValues},
            {as: 'DefectVerifiedCount', f: 'filteredCount', filterField: 'State', filterValues: verifiedValues},
        ];

        // not used yet
        var summaryMetricsConfig = [
        ];

        // not used yet
        var deriveFieldsOnInput = [
        ];

        // calculator config
        var config = {
          deriveFieldsOnInput: deriveFieldsOnInput,
          metrics: metrics,
          summaryMetricsConfig: summaryMetricsConfig,
          deriveFieldsAfterSummary: [],
          granularity: lumenize.Time.DAY,
          tz: 'America/Chicago',
          holidays: holidays,
          workDays: 'Monday,Tuesday,Wednesday,Thursday,Friday'
        };

        // release start and end dates
        var startOnISOString = new lumenize.Time(this.gRelease.ReleaseStartDate).getISOStringInTZ(config.tz)
        var upToDateISOString = new lumenize.Time(this.gRelease.ReleaseDate).getISOStringInTZ(config.tz)

        // create the calculator and add snapshots to it.
        calculator = new Rally.data.lookback.Lumenize.TimeSeriesCalculator(config);
        calculator.addSnapshots(snapShotData, startOnISOString, upToDateISOString);

        // create a high charts series config object, used to get the hc series data
        var hcConfig = [{ name: "label" }, { name : "DefectOpenCount" }, { name : "DefectClosedCount"},{name:"DefectVerifiedCount"}];
        var hc = lumenize.arrayOfMaps_To_HighChartsSeries(calculator.getResults().seriesData, hcConfig);

        // display the chart
        this._showChart(hc);

    },
    _showChart : function(series) {
        console.log("series",series);
        var chart = this.down("#chart1");
        chart.removeAll();

        var extChart = Ext.create('Rally.ui.chart.Chart', {
            width: 800,
            height: 500,
         chartData: {
            categories : series[0].data,
            series : [
                series[1],
                series[2],
                series[3]
            ]
         },
          chartConfig : {
                chart: {
                },
                title: {
                text: 'Release Defect Trend',
                x: -20 //center
                },
                xAxis: {
                    tickInterval : 3
                },
                yAxis: {
                    title: {
                        text: 'Count'
                    },
                    plotLines: [{
                        value: 0,
                        width: 1,
                        color: '#808080'
                    }]
                },
                tooltip: {
                    valueSuffix: ' Defects'
                },
                legend: {
                            align: 'center',
                            verticalAlign: 'bottom'
                }
            }
        });
        chart.add(extChart);
    }
});
<commit_msg>fixed lumenize reference<commit_after>Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    items: [
    {
        xtype: 'container',
        itemId: 'releaseDropDown',
        columnWidth: 1
    }
    ,
    {
        xtype: 'container',
        itemId: 'chart1',
        columnWidth: 1
    }

    ],

    launch: function() {
        // add the release dropdown selector
        this.down("#releaseDropDown").add( {
            xtype: 'rallyreleasecombobox',
            itemId : 'releaseSelector',
            listeners: {
                    select: this._onReleaseSelect,
    	            scope: this
            }
        });
        // used to save the selected release
        this.gRelease = null;
    },

    // called when a release is selected.
    _onReleaseSelect : function() {
        // get and save the selected release
        var value =  this.down('#releaseSelector').getRecord();
        this.gRelease = value.data;
        console.log("selected release record data",value.raw);

        // construct a query to get all releases in scope
        Ext.create('Rally.data.WsapiDataStore', {
            model: "Release",
            autoLoad : true,
            fetch: ["ObjectID","Name","ReleaseStartDate","ReleaseDate","Project"],
            filters: [
                {
                    property: 'Name',
                    value: value.data.Name
                }
            ],
            listeners: {
                // load: function(store, data, success) {
                //     console.log("data",data);
                // }
                scope : this,
                load : this._onReleases
            }
        });
    },

// called with all releases in scope
    _onReleases : function(store, data, success) {
        var that = this;
        console.log("data",data);

        var releaseIds = _.map(data, function(d) { return d.data.ObjectID; });
        console.log("Release IDs",releaseIds);
        // now we are going to retrieve snapshots for all releases ...
        Ext.create('Rally.data.lookback.SnapshotStore', {
            autoLoad : true,
            listeners: {
                load: this._onReleaseSnapShotData,
                scope : this
            },
            fetch: ['ObjectID','Name', 'State', '_ValidFrom','_ValidTo'],
            hydrate: ['State'],
            filters: [
                {
                    property: '_TypeHierarchy',
                    operator: 'in',
                    value: ['Defect']
                },
                {
                    property: 'Release',
                    operator: 'in',
                    value: releaseIds
                }
            ]
        });
    },

    // called with the snapshot data for all defects in the releases
    _onReleaseSnapShotData : function(store,data,success) {

        // we are going to use lumenize and the TimeSeriesCalculator to aggregate the data into
        // a time series.
        var lumenize = window.parent.Rally.data.lookback.Lumenize;
        var snapShotData = _.map(data,function(d){return d.data});
        console.log("snapShotData",snapShotData);

        // these values determine if a defect is open, closed or verified.
        var openValues = ['Submitted','Open'];
        var closedValues = ['Closed','Rejected','Duplicated'];
        var verifiedValues = ['Verified'];

        // can be used to 'knockout' holidays
        var holidays = [
            {year: 2014, month: 1, day: 1}  // Made up holiday to test knockout
        ];

        // metrics to chart
        var metrics = [
            {as: 'DefectOpenCount',     f: 'filteredCount', filterField: 'State', filterValues: openValues},
            {as: 'DefectClosedCount',   f: 'filteredCount', filterField: 'State', filterValues: closedValues},
            {as: 'DefectVerifiedCount', f: 'filteredCount', filterField: 'State', filterValues: verifiedValues},
        ];

        // not used yet
        var summaryMetricsConfig = [
        ];

        // not used yet
        var deriveFieldsOnInput = [
        ];

        // calculator config
        var config = {
          deriveFieldsOnInput: deriveFieldsOnInput,
          metrics: metrics,
          summaryMetricsConfig: summaryMetricsConfig,
          deriveFieldsAfterSummary: [],
          granularity: lumenize.Time.DAY,
          tz: 'America/Chicago',
          holidays: holidays,
          workDays: 'Monday,Tuesday,Wednesday,Thursday,Friday'
        };

        // release start and end dates
        var startOnISOString = new lumenize.Time(this.gRelease.ReleaseStartDate).getISOStringInTZ(config.tz)
        var upToDateISOString = new lumenize.Time(this.gRelease.ReleaseDate).getISOStringInTZ(config.tz)

        // create the calculator and add snapshots to it.
        //calculator = new Rally.data.lookback.Lumenize.TimeSeriesCalculator(config);
        calculator = new lumenize.TimeSeriesCalculator(config);
        calculator.addSnapshots(snapShotData, startOnISOString, upToDateISOString);

        // create a high charts series config object, used to get the hc series data
        var hcConfig = [{ name: "label" }, { name : "DefectOpenCount" }, { name : "DefectClosedCount"},{name:"DefectVerifiedCount"}];
        var hc = lumenize.arrayOfMaps_To_HighChartsSeries(calculator.getResults().seriesData, hcConfig);

        // display the chart
        this._showChart(hc);

    },
    _showChart : function(series) {
        console.log("series",series);
        var chart = this.down("#chart1");
        chart.removeAll();

        var extChart = Ext.create('Rally.ui.chart.Chart', {
            width: 800,
            height: 500,
         chartData: {
            categories : series[0].data,
            series : [
                series[1],
                series[2],
                series[3]
            ]
         },
          chartConfig : {
                chart: {
                },
                title: {
                text: 'Release Defect Trend',
                x: -20 //center
                },
                xAxis: {
                    tickInterval : 3
                },
                yAxis: {
                    title: {
                        text: 'Count'
                    },
                    plotLines: [{
                        value: 0,
                        width: 1,
                        color: '#808080'
                    }]
                },
                tooltip: {
                    valueSuffix: ' Defects'
                },
                legend: {
                            align: 'center',
                            verticalAlign: 'bottom'
                }
            }
        });
        chart.add(extChart);
    }
});
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE.txt or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

define(function(require, exports, module) {

var types = require('gcli/types');
var Conversion = types.Conversion;
var Type = types.Type;
var Status = types.Status;

/**
 * 'javascript' handles scripted input
 */
function JavascriptType(typeSpec) {
  if (typeSpec != null) {
    throw new Error('JavascriptType can not be customized');
  }
}

JavascriptType.prototype = Object.create(Type.prototype);

JavascriptType.prototype.stringify = function(value) {
  if (value == null) {
    return '';
  }
  return value.name;
};

JavascriptType.prototype.parse = function(arg) {
  var typed = arg.text;
  if (typed == null || typed === '') {
    return new Conversion(null, arg, Status.INCOMPLETE, '');
  }

  var scope = window;

  // In FX-land we need to unwrap. TODO: Enable in the browser.
  // scope = unwrap(scope);

  // Analyze the input text and find the beginning of the last part that
  // should be completed.
  var beginning = this._findCompletionBeginning(typed);

  // There was an error analyzing the string.
  if (beginning.err) {
    return new Conversion(typed, arg, Status.ERROR, beginning.err);
  }

  // If the current state is not ParseState.NORMAL, then we are inside of an string
  // which means that no completion is possible.
  if (beginning.state !== ParseState.NORMAL) {
    return new Conversion(typed, arg, Status.INCOMPLETE, '');
  }

  var completionPart = typed.substring(beginning.startPos);

  // Don't complete on just an empty string.
  if (completionPart.trim() === "") {
    return new Conversion(typed, arg, Status.INCOMPLETE, '');
  }

  var properties = completionPart.split('.');
  var matchProp;
  if (properties.length > 1) {
    matchProp = properties.pop().trimLeft();
    for (var i = 0; i < properties.length; i++) {
      var prop = properties[i].trim();

      // We can't complete on null.foo, so bail out
      if (scope == null) {
        return new Conversion(typed, arg, Status.ERROR, beginning.err);
      }

      // TODO: Re-enable this test
      // Check if prop is a getter function on obj. Functions can change other
      // stuff so we can't execute them to get the next object. Stop here.
      // if (isNonNativeGetter(scope, prop)) {
      //   return new Conversion(typed, arg);
      // }

      try {
        scope = scope[prop];
      }
      catch (ex) {
        return new Conversion(typed, arg, Status.ERROR, '' + ex);
      }
    }
  }
  else {
    matchProp = properties[0].trimLeft();
  }

  if (scope == null) {
    return new Conversion(typed, arg, Status.ERROR, beginning.err);
  }

  // Skip Iterators and Generators.
  if (this._isIteratorOrGenerator(scope)) {
    return null;
  }

  var prefix = typed.slice(0, -matchProp.length);
  var status = Status.INCOMPLETE;
  var matches = [];
  for (var prop in scope) {
    if (prop.indexOf(matchProp) === 0) {
      var description = '(' + typeof scope[prop] + ')';
      var incomplete = true;
      if (description === '(number)') {
        description = scope[prop] + ' (number)';
        incomplete = false;
      }
      else if (description === '(string)') {
        description = scope[prop] + ' (string)';
        incomplete = false;
      }
      matches.push({
        name: prefix + prop,
        value: {
          name: prefix + prop,
          description: description
        },
        incomplete: incomplete
      });
    }
    if (prop === matchProp) {
      status = Status.VALID;
    }
  }

  // Can we think of a better sort order than alpha? There are certainly some
  // properties that are far more commonly used ...
  matches.sort(function(p1, p2) {
    return p1.name.localeCompare(p2.name);
  });

  return new Conversion(typed, arg, status, '', matches);
};

var ParseState = {
  NORMAL: 0,
  QUOTE: 2,
  DQUOTE: 3
};

var OPEN_BODY = '{[('.split('');
var CLOSE_BODY = '}])'.split('');
var OPEN_CLOSE_BODY = {
  '{': '}',
  '[': ']',
  '(': ')'
};

/**
 * Analyzes a given string to find the last statement that is interesting for
 * later completion.
 * @param text A string to analyze
 * @return If there was an error in the string detected, then a object like
 *   { err: "ErrorMesssage" }
 * is returned, otherwise a object like
 *   {
 *     state: ParseState.NORMAL|ParseState.QUOTE|ParseState.DQUOTE,
 *     startPos: index of where the last statement begins
 *   }
 */
JavascriptType.prototype._findCompletionBeginning = function(text) {
  var bodyStack = [];

  var state = ParseState.NORMAL;
  var start = 0;
  var c;
  for (var i = 0; i < text.length; i++) {
    c = text[i];

    switch (state) {
      // Normal JS state.
      case ParseState.NORMAL:
        if (c === '"') {
          state = ParseState.DQUOTE;
        }
        else if (c === '\'') {
          state = ParseState.QUOTE;
        }
        else if (c === ';') {
          start = i + 1;
        }
        else if (c === ' ') {
          start = i + 1;
        }
        else if (OPEN_BODY.indexOf(c) != -1) {
          bodyStack.push({
            token: c,
            start: start
          });
          start = i + 1;
        }
        else if (CLOSE_BODY.indexOf(c) != -1) {
          var last = bodyStack.pop();
          if (!last || OPEN_CLOSE_BODY[last.token] != c) {
            return {
              err: "syntax error"
            };
          }
          if (c === '}') {
            start = i + 1;
          }
          else {
            start = last.start;
          }
        }
        break;

      // Double quote state > " <
      case ParseState.DQUOTE:
        if (c === '\\') {
          i ++;
        }
        else if (c === '\n') {
          return {
            err: "unterminated string literal"
          };
        }
        else if (c === '"') {
          state = ParseState.NORMAL;
        }
        break;

      // Single quote state > ' <
      case ParseState.QUOTE:
        if (c === '\\') {
          i ++;
        }
        else if (c === '\n') {
          return {
            err: "unterminated string literal"
          };
          return;
        }
        else if (c === '\'') {
          state = ParseState.NORMAL;
        }
        break;
    }
  }

  return {
    state: state,
    startPos: start
  };
};

/**
 * Return true if the passed object is either an iterator or a generator, and
 * false otherwise.
 * @param obj The object to check
 */
JavascriptType.prototype._isIteratorOrGenerator = function(obj) {
  if (obj === null) {
    return false;
  }

  if (typeof aObject === "object") {
    if (typeof obj.__iterator__ === "function" ||
        obj.constructor && obj.constructor.name === "Iterator") {
      return true;
    }

    try {
      var str = obj.toString();
      if (typeof obj.next === "function" &&
          str.indexOf("[object Generator") === 0) {
        return true;
      }
    }
    catch (ex) {
      // window.history.next throws in the typeof check above.
      return false;
    }
  }

  return false;
};

JavascriptType.prototype.name = 'javascript';

exports.JavascriptType = JavascriptType;

/**
 * Registration and de-registration.
 */
exports.startup = function() {
  types.registerType(JavascriptType);
};

exports.shutdown = function() {
  types.unregisterType(JavascriptType);
};

});
<commit_msg>Bug 672823 (part) - Provide better error messages on JS parse fail<commit_after>/*
 * Copyright 2009-2011 Mozilla Foundation and contributors
 * Licensed under the New BSD license. See LICENSE.txt or:
 * http://opensource.org/licenses/BSD-3-Clause
 */

define(function(require, exports, module) {

var types = require('gcli/types');
var Conversion = types.Conversion;
var Type = types.Type;
var Status = types.Status;

/**
 * 'javascript' handles scripted input
 */
function JavascriptType(typeSpec) {
  if (typeSpec != null) {
    throw new Error('JavascriptType can not be customized');
  }
}

JavascriptType.prototype = Object.create(Type.prototype);

JavascriptType.prototype.stringify = function(value) {
  if (value == null) {
    return '';
  }
  return value.name;
};

JavascriptType.prototype.parse = function(arg) {
  var typed = arg.text;
  if (typed == null || typed === '') {
    return new Conversion(null, arg, Status.INCOMPLETE, '');
  }

  var scope = window;

  // In FX-land we need to unwrap. TODO: Enable in the browser.
  // scope = unwrap(scope);

  // Analyze the input text and find the beginning of the last part that
  // should be completed.
  var beginning = this._findCompletionBeginning(typed);

  // There was an error analyzing the string.
  if (beginning.err) {
    return new Conversion(typed, arg, Status.ERROR, beginning.err);
  }

  // If the current state is not ParseState.NORMAL, then we are inside of an string
  // which means that no completion is possible.
  if (beginning.state !== ParseState.NORMAL) {
    return new Conversion(typed, arg, Status.INCOMPLETE, '');
  }

  var completionPart = typed.substring(beginning.startPos);

  // Don't complete on just an empty string.
  if (completionPart.trim() === "") {
    return new Conversion(typed, arg, Status.INCOMPLETE, '');
  }

  var properties = completionPart.split('.');
  var matchProp;
  if (properties.length > 1) {
    matchProp = properties.pop().trimLeft();
    for (var i = 0; i < properties.length; i++) {
      var prop = properties[i].trim();

      // We can't complete on null.foo, so bail out
      if (scope == null) {
        return new Conversion(typed, arg, Status.ERROR, beginning.err);
      }

      // TODO: Re-enable this test
      // Check if prop is a getter function on obj. Functions can change other
      // stuff so we can't execute them to get the next object. Stop here.
      // if (isNonNativeGetter(scope, prop)) {
      //   return new Conversion(typed, arg);
      // }

      try {
        scope = scope[prop];
      }
      catch (ex) {
        return new Conversion(typed, arg, Status.ERROR, '' + ex);
      }
    }
  }
  else {
    matchProp = properties[0].trimLeft();
  }

  if (scope == null) {
    return new Conversion(typed, arg, Status.ERROR, beginning.err);
  }

  // Skip Iterators and Generators.
  if (this._isIteratorOrGenerator(scope)) {
    return null;
  }

  var prefix = typed.slice(0, -matchProp.length);
  var status = Status.INCOMPLETE;
  var message = 'Can\'t find property ' + matchProp;
  var matches = [];

  for (var prop in scope) {
    if (prop.indexOf(matchProp) === 0) {
      var description = '(' + typeof scope[prop] + ')';
      var incomplete = true;
      if (description === '(number)') {
        description = scope[prop] + ' (number)';
        incomplete = false;
      }
      else if (description === '(string)') {
        description = scope[prop] + ' (string)';
        incomplete = false;
      }
      matches.push({
        name: prefix + prop,
        value: {
          name: prefix + prop,
          description: description
        },
        incomplete: incomplete
      });
    }
    if (prop === matchProp) {
      status = Status.VALID;
      message = '';
    }
  }

  // Can we think of a better sort order than alpha? There are certainly some
  // properties that are far more commonly used ...
  matches.sort(function(p1, p2) {
    return p1.name.localeCompare(p2.name);
  });

  return new Conversion(typed, arg, status, message, matches);
};

var ParseState = {
  NORMAL: 0,
  QUOTE: 2,
  DQUOTE: 3
};

var OPEN_BODY = '{[('.split('');
var CLOSE_BODY = '}])'.split('');
var OPEN_CLOSE_BODY = {
  '{': '}',
  '[': ']',
  '(': ')'
};

/**
 * Analyzes a given string to find the last statement that is interesting for
 * later completion.
 * @param text A string to analyze
 * @return If there was an error in the string detected, then a object like
 *   { err: "ErrorMesssage" }
 * is returned, otherwise a object like
 *   {
 *     state: ParseState.NORMAL|ParseState.QUOTE|ParseState.DQUOTE,
 *     startPos: index of where the last statement begins
 *   }
 */
JavascriptType.prototype._findCompletionBeginning = function(text) {
  var bodyStack = [];

  var state = ParseState.NORMAL;
  var start = 0;
  var c;
  for (var i = 0; i < text.length; i++) {
    c = text[i];

    switch (state) {
      // Normal JS state.
      case ParseState.NORMAL:
        if (c === '"') {
          state = ParseState.DQUOTE;
        }
        else if (c === '\'') {
          state = ParseState.QUOTE;
        }
        else if (c === ';') {
          start = i + 1;
        }
        else if (c === ' ') {
          start = i + 1;
        }
        else if (OPEN_BODY.indexOf(c) != -1) {
          bodyStack.push({
            token: c,
            start: start
          });
          start = i + 1;
        }
        else if (CLOSE_BODY.indexOf(c) != -1) {
          var last = bodyStack.pop();
          if (!last || OPEN_CLOSE_BODY[last.token] != c) {
            return { err: "Syntax error" };
          }
          if (c === '}') {
            start = i + 1;
          }
          else {
            start = last.start;
          }
        }
        break;

      // Double quote state > " <
      case ParseState.DQUOTE:
        if (c === '\\') {
          i ++;
        }
        else if (c === '\n') {
          return { err: "Unterminated string literal" };
        }
        else if (c === '"') {
          state = ParseState.NORMAL;
        }
        break;

      // Single quote state > ' <
      case ParseState.QUOTE:
        if (c === '\\') {
          i ++;
        }
        else if (c === '\n') {
          return { err: "Unterminated string literal" };
          return;
        }
        else if (c === '\'') {
          state = ParseState.NORMAL;
        }
        break;
    }
  }

  return {
    state: state,
    startPos: start
  };
};

/**
 * Return true if the passed object is either an iterator or a generator, and
 * false otherwise.
 * @param obj The object to check
 */
JavascriptType.prototype._isIteratorOrGenerator = function(obj) {
  if (obj === null) {
    return false;
  }

  if (typeof aObject === "object") {
    if (typeof obj.__iterator__ === "function" ||
        obj.constructor && obj.constructor.name === "Iterator") {
      return true;
    }

    try {
      var str = obj.toString();
      if (typeof obj.next === "function" &&
          str.indexOf("[object Generator") === 0) {
        return true;
      }
    }
    catch (ex) {
      // window.history.next throws in the typeof check above.
      return false;
    }
  }

  return false;
};

JavascriptType.prototype.name = 'javascript';

exports.JavascriptType = JavascriptType;

/**
 * Registration and de-registration.
 */
exports.startup = function() {
  types.registerType(JavascriptType);
};

exports.shutdown = function() {
  types.unregisterType(JavascriptType);
};

});
<|endoftext|>


<commit_before>var ui = require('../ui')
var pull = require('pull-stream')
var Cat = require('pull-cat')
var sort = require('ssb-sort')
var ref = require('ssb-ref')
var h = require('hyperscript')
var u = require('../util')
var Scroller = require('pull-scroll')

function once (cont) {
  var ended = false
  return function (abort, cb) {
    if(abort) return cb(abort)
    else if (ended) return cb(ended)
    else
      cont(function (err, data) {
        if(err) return cb(ended = err)
        ended = true
        cb(null, data)
      })
  }
}

var plugs = require('../plugs')

var message_render = plugs.first(exports.message_render = [])
var message_compose = plugs.first(exports.message_compose = [])
var message_unbox = plugs.first(exports.message_unbox = [])

var sbot_get = plugs.first(exports.sbot_get = [])
var sbot_links = plugs.first(exports.sbot_links = [])

function getThread (root, cb) {
  //in this case, it's inconvienent that panel only takes
  //a stream. maybe it would be better to accept an array?

  sbot_get(root, function (err, value) {
    var msg = {key: root, value: value}
    if(value.content.root) return getThread(value.content.root, cb)

    pull(
      sbot_links({rel: 'root', dest: root, values: true, keys: true}),
      pull.collect(function (err, ary) {
        if(err) return cb(err)
        ary.unshift(msg)
        cb(null, ary)
      })
    )
  })

//  return pull(Cat([
//    once(function (cb) {
//      sbot_get(root, function (err, value) {
//        cb(err, {key: root, value: value})
//      })
//    }),
//    sbot_links({rel: 'root', dest: root, values: true, keys: true})
//  ]), pull.collect(cb))
}

exports.screen_view = function (id, sbot) {
  if(ref.isMsg(id)) {
    var meta = {
      type: 'post',
      root: id,
      branch: id //mutated when thread is loaded.
    }

    var content = h('div')
    var div = h('div.column',
      {style: {'overflow-y': 'auto'}},
      content,
      h('div.editor', message_compose(meta))
    )

    pull(
      sbot_links({
        rel: 'root', dest: id, keys: true, old: false
      }),
      pull.drain(function (msg) {
        loadThread() //redraw thread
      }, function () {} )
    )

    function loadThread () {
      getThread(id, function (err, thread) {
        //would probably be better keep an id for each message element
        //(i.e. message key) and then update it if necessary.
        //also, it may have moved (say, if you received a missing message)
        content.innerHTML = ''
        thread = thread.map(function (msg) {
          return 'string' === typeof msg.value.content ? message_unbox(msg) : msg
        })

        if(err) return content.appendChild(h('pre', err.stack))
        sort(thread).map(message_render).forEach(function (el) {
          content.appendChild(el)
        })

        var branches = sort.heads(thread)
        meta.branch = branches.length > 1 ? branches : branches[0]
        meta.root = thread[0].key

        var recps = thread[0].value.content.recps
        if(recps && thread[0].value.private)
          meta.recps = recps
      })
    }

    loadThread()
    return div
  }
}

<commit_msg>can show a single message, but reply should be in thread<commit_after>var ui = require('../ui')
var pull = require('pull-stream')
var Cat = require('pull-cat')
var sort = require('ssb-sort')
var ref = require('ssb-ref')
var h = require('hyperscript')
var u = require('../util')
var Scroller = require('pull-scroll')

function once (cont) {
  var ended = false
  return function (abort, cb) {
    if(abort) return cb(abort)
    else if (ended) return cb(ended)
    else
      cont(function (err, data) {
        if(err) return cb(ended = err)
        ended = true
        cb(null, data)
      })
  }
}

var plugs = require('../plugs')

var message_render = plugs.first(exports.message_render = [])
var message_compose = plugs.first(exports.message_compose = [])
var message_unbox = plugs.first(exports.message_unbox = [])

var sbot_get = plugs.first(exports.sbot_get = [])
var sbot_links = plugs.first(exports.sbot_links = [])

function getThread (root, cb) {
  //in this case, it's inconvienent that panel only takes
  //a stream. maybe it would be better to accept an array?

  sbot_get(root, function (err, value) {
    var msg = {key: root, value: value}
//    if(value.content.root) return getThread(value.content.root, cb)

    pull(
      sbot_links({rel: 'root', dest: root, values: true, keys: true}),
      pull.collect(function (err, ary) {
        if(err) return cb(err)
        ary.unshift(msg)
        cb(null, ary)
      })
    )
  })

}

exports.screen_view = function (id, sbot) {
  if(ref.isMsg(id)) {
    var meta = {
      type: 'post',
      root: id,
      branch: id //mutated when thread is loaded.
    }

    var content = h('div')
    var div = h('div.column',
      {style: {'overflow-y': 'auto'}},
      content,
      h('div.editor', message_compose(meta))
    )

    pull(
      sbot_links({
        rel: 'root', dest: id, keys: true, old: false
      }),
      pull.drain(function (msg) {
        loadThread() //redraw thread
      }, function () {} )
    )

    function loadThread () {
      getThread(id, function (err, thread) {
        //would probably be better keep an id for each message element
        //(i.e. message key) and then update it if necessary.
        //also, it may have moved (say, if you received a missing message)
        content.innerHTML = ''
        //decrypt
        thread = thread.map(function (msg) {
          return 'string' === typeof msg.value.content ? message_unbox(msg) : msg
        })

        if(err) return content.appendChild(h('pre', err.stack))
        sort(thread).map(message_render).forEach(function (el) {
          content.appendChild(el)
        })

        var branches = sort.heads(thread)
        meta.branch = branches.length > 1 ? branches : branches[0]
        meta.root = thread[0].value.content.root || thread[0].key

        var recps = thread[0].value.content.recps
        if(recps && thread[0].value.private)
          meta.recps = recps
      })
    }

    loadThread()
    return div
  }
}

<|endoftext|>