<commit_before>var term = require( 'terminal-kit' ).terminal ;
var child_process = require('child_process');

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function term_grab() {
    term.grabInput( { mouse: 'motion' } ) ;
    term.hideCursor(true);
}

function term_release() {
    term.hideCursor( false );
    term.grabInput( false ) ;
}

function terminate() {
    term_release();
    // Add a 100ms delay, so the terminal will be ready when the process effectively exit, preventing bad escape sequences drop
    setTimeout( function() { process.exit() ; } , 100 ) ;
}

async function choice(items, pre_select=0, pad_last=0) {

    term_grab();

    var button_padding = 4;
    var top_left = "┌";
    var top_bar = "─";
    var top_right = "┐";
    var bar_left = "│";
    var bar_right = "│";
    var bottom_left = "└";
    var bottom_bar = "─";
    var bottom_right = "┘";

    // get longest word
    var longest = 0;
    for(var i=0; i<items.length; i++) {
        if(items[i][0].length > longest) longest = items[i][0].length;
    }
    longest += 6; // Add button inside padding

    // create formatted_items
    var menu_height = 0;
    var formatted_items = [];
    for(var i=0; i<items.length; i++) {
        var padlength = longest - items[i][0].length;
        var fstr =
                " ".repeat(button_padding) + top_left + top_bar.repeat(longest)
                    + top_right + "\n" +
                " ".repeat(button_padding) + bar_left + " ".repeat(Math.floor(padlength/2)) + items[i][0]
                    + " ".repeat(Math.floor((padlength+1)/2)) + bar_right + "\n" +
                " ".repeat(button_padding) + bottom_left + bottom_bar.repeat(longest)
                    + bottom_right + " ".repeat(button_padding);
        formatted_items.push(fstr);
        menu_height += 3;
    }
    for( var i=0; i<pad_last; i++) {
        // add line before last
        formatted_items[items.length-1] = "\n" + formatted_items[items.length-1];
        menu_height ++;
    }

    // if negative count back from the last
    if(pre_select<0) pre_select = formatted_items.length + pre_select;

    const extra_lines = 2
    menu_height += extra_lines;

    // make space for menu (term.nextLine seems to be buggy or not scroll correctly)
    for(var i=0; i<menu_height; i++)
        term("\n");
    // go up again
    term.previousLine(menu_height);

    function clean_up() {
        term_release();
        term.up(menu_height-extra_lines); // why is extra_lines needed here?
        term.eraseDisplayBelow();
    }

    term.singleColumnMenu( formatted_items,
        {
            leftPadding: "",
            selectedLeftPadding: "",
            cancelable: true,
            selectedIndex: pre_select,
            itemMaxWidth: 2*(button_padding+1)+longest,
            extraLines: extra_lines,
            style: term.bgBrightWhite.black,
            selectedStyle: term.bgGreen.black,
            submittedStyle: term.bgWhite.black,
            exitOnUnexpectedKey: true, // catch other keys
            continueOnSubmit: false
        } ,
        function( error , response ) {
            // term( '\n' ).eraseLineAfter.green(
            //     "#%s" ,
            //     response.selectedIndex
            // );
            clean_up();
            if(response.unexpectedKey != undefined) {
                function check_key(name, key, cb) {
                    if(name.toUpperCase() === key.toUpperCase()) {
                        cb();
                        return true;
                    }
                    return false;
                }

                var name = response.unexpectedKey;
                for(var i=0; i<items.length; i++) {
                    if(items[i][1] instanceof Array) {
                        for(var k of items[i][1]) {
                            if(check_key(name, k, items[i][2])) return; // match found
                        }
                    } else {
                        if(check_key(name, items[i][1], items[i][2])) return; // match found
                    }
                } // end for
                // not returned, so wo need to end as not matched
                terminate();
            } else {
                if(response.selectedIndex == undefined) terminate();
                else {
                    var cb = items[response.selectedIndex][2];
                    if(cb == undefined) { terminate(); }
                    else { cb(); }
                }
            }
        }
    ) ;
    // Attention: this is Javascript, so execution directly continues here,
    // so everything needs to be done in callbacks and via recursion if
    // deterministic behavior is expected
    // Careful: while menu is running, cursor changes all the time, so
    // nothing can decently be printed (maybe modal)
}

function run_command(command, directory = null) {
    var args = ['-q', '-e', '-c', command, '/dev/null' ];
//    if(directory)
//        cmd = 'cd "' + directory + '"; ' + cmd;
    term.wrap("\nRunning ", command, "\n\n");
    var result = child_process.spawnSync("script", args,
                    { stdio: [0,0,0], cwd: directory });
    if( result.status == 0) {
        term.green.wrap('\nThe command ',command,' seems to have completed successful. OK to continue.\n');
        choice([
            ["OK, continue (O, Enter)", "O", terminate]
        ], pre_select=-1);
    } else {
        term.red.wrap('\nAn error occurred running ',command,'. Check output, continue, and eventually try again later.\n');
        choice([
            ["Continue (C, Enter)", "C", terminate]
        ], pre_select=-1);
    }
}

function shell_command(question, command, directory = null) {
    if(question) {
        term.wrap("\n", question, "\n");

        choice([
            ["Yes, run " + command + " (Y)", "Y", function() { run_command(command, directory); } ],
            ["No, go back (N)", "N", terminate]
        ], pre_select=-1);
    } else {
        term("\n\n");
        run_command(command, directory);
    }
}

function shell_command_in_path(before_path, after_path, command) {
    term.wrap('\n\n', before_path, '\n');
    var d = process.env.ACTIVE_DIR;
    var fulldir = d;
    if(!d) {
        d = process.cwd();
        fulldir = d;
    }
    // Strip home directory
    var home = process.env.HOME;
    if(d.startsWith(home)) d = d.slice(home.length+1);
    term.wrap(d,'\n');

    shell_command(after_path, command, fulldir);
}

function deploy() {
    shell_command_in_path('You are about to deploy from the following path:',
        'Are you sure?', "deploy");
}

function compile() {
    shell_command_in_path('You are about to run compile in the following path:',
        'Are you sure?', "compile");
}

function initialize() {
    shell_command_in_path('You are about to initialize from the following path:',
        'Are you sure and have you successfully put one node in adoption mode?',
        "initialize");
}

function create_node_template() {
    shell_command_in_path("You are about to create a folder called new-node"
        + " to configure a new node. Do not forget to rename this folder after"
        + " this creation. you might have to refresh cloudcmd to see the newly"
        + " created folder after this action. It will be created in the following path:",
        'Are you sure?',
        "create_node_template");
}

function upgrade() {
    shell_command("This will get the newest version of ulnoiot out of the internet."
        + " Are you sure you want to run this?", "upgrade");
}

function initialize_serial() {
    shell_command_in_path('You are about to initialize'
        + ' a device that is locally connected to the gateway via usb or serial'
        + ' from the following path:',
        'Are you sure, and have you connected only one node to the gateway?',
        "initialize serial");
}

function pre_flash_wemos() {
    shell_command('You are about to flash a connected Wemos D1 mini with'
        + ' a default ulnoiot firmware. Are you sure, and have you connected '
        + 'exactly one Wemos D1 mini via USB to the gateway?',
        "pre_flash_wemos");
}

function shell_escape() {
    shell_command_in_path("Starting the shell (bash) now. "
        + "Remember to type exit to leave. Initial path will be:",
        null, "bash");
}

function poweroff() {
    shell_command("This will cleanly shut down the gateway. "
        + "Are you sure you want to shutdown and poweroff the gateway?",
        "sudo poweroff");
}

function advanced() {
    choice([
        ["Pre-Flash Wemos D1 mini (P)", "P", pre_flash_wemos],
        ["Initialize Serial (I)", "I", initialize_serial],
        // confusing - better through shell ["Compile (C)", "C", compile],
        ["Upgrade (U)", "U", upgrade],
        ["Shell Escape (S)", "S", shell_escape],
        ["Shutdown/Poweroff (O)", "O", poweroff],
        ["Back (B,X,ESC)", ["B","X"], menu_default]
    ], pre_select=-1, pad_last=1);
}

function menu_default() {
    //term.clear();
    term("\n\n");
    term.bgBrightWhite.black.wrap( '^+ul^rno^-^kiot^: Simple Shell\n' ) ;
    term("\n");
    term.wrap('Use mouse, arrow keys, enter, or shortcut key to select.\n')
    term("\n");

    choice([
        ["Deploy (D)", "D", deploy],
        ["Initialize (I)", "I", initialize],
        ["Create New Node Folder (N)", "N", create_node_template],
        ["Advanced (A)", "A", advanced],
    //    "Exit (X,ESC)"
    ], pre_select=0, pad_last=0);
}

menu_default();<commit_msg>allow wifi configuration in simple shell<commit_after>var term = require( 'terminal-kit' ).terminal ;
var child_process = require('child_process');

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function term_grab() {
    term.grabInput( { mouse: 'motion' } ) ;
    term.hideCursor(true);
}

function term_release() {
    term.hideCursor( false );
    term.grabInput( false ) ;
}

function terminate() {
    term_release();
    // Add a 100ms delay, so the terminal will be ready when the process effectively exit, preventing bad escape sequences drop
    setTimeout( function() { process.exit() ; } , 100 ) ;
}

async function choice(items, pre_select=0, pad_last=0) {

    term_grab();

    var button_padding = 4;
    var top_left = "┌";
    var top_bar = "─";
    var top_right = "┐";
    var bar_left = "│";
    var bar_right = "│";
    var bottom_left = "└";
    var bottom_bar = "─";
    var bottom_right = "┘";

    // get longest word
    var longest = 0;
    for(var i=0; i<items.length; i++) {
        if(items[i][0].length > longest) longest = items[i][0].length;
    }
    longest += 6; // Add button inside padding

    // create formatted_items
    var menu_height = 0;
    var formatted_items = [];
    for(var i=0; i<items.length; i++) {
        var padlength = longest - items[i][0].length;
        var fstr =
                " ".repeat(button_padding) + top_left + top_bar.repeat(longest)
                    + top_right + "\n" +
                " ".repeat(button_padding) + bar_left + " ".repeat(Math.floor(padlength/2)) + items[i][0]
                    + " ".repeat(Math.floor((padlength+1)/2)) + bar_right + "\n" +
                " ".repeat(button_padding) + bottom_left + bottom_bar.repeat(longest)
                    + bottom_right + " ".repeat(button_padding);
        formatted_items.push(fstr);
        menu_height += 3;
    }
    for( var i=0; i<pad_last; i++) {
        // add line before last
        formatted_items[items.length-1] = "\n" + formatted_items[items.length-1];
        menu_height ++;
    }

    // if negative count back from the last
    if(pre_select<0) pre_select = formatted_items.length + pre_select;

    const extra_lines = 2
    menu_height += extra_lines;

    // make space for menu (term.nextLine seems to be buggy or not scroll correctly)
    for(var i=0; i<menu_height; i++)
        term("\n");
    // go up again
    term.previousLine(menu_height);

    function clean_up() {
        term_release();
        term.up(menu_height-extra_lines); // why is extra_lines needed here?
        term.eraseDisplayBelow();
    }

    term.singleColumnMenu( formatted_items,
        {
            leftPadding: "",
            selectedLeftPadding: "",
            cancelable: true,
            selectedIndex: pre_select,
            itemMaxWidth: 2*(button_padding+1)+longest,
            extraLines: extra_lines,
            style: term.bgBrightWhite.black,
            selectedStyle: term.bgGreen.black,
            submittedStyle: term.bgWhite.black,
            exitOnUnexpectedKey: true, // catch other keys
            continueOnSubmit: false
        } ,
        function( error , response ) {
            // term( '\n' ).eraseLineAfter.green(
            //     "#%s" ,
            //     response.selectedIndex
            // );
            clean_up();
            if(response.unexpectedKey != undefined) {
                function check_key(name, key, cb) {
                    if(name.toUpperCase() === key.toUpperCase()) {
                        cb();
                        return true;
                    }
                    return false;
                }

                var name = response.unexpectedKey;
                for(var i=0; i<items.length; i++) {
                    if(items[i][1] instanceof Array) {
                        for(var k of items[i][1]) {
                            if(check_key(name, k, items[i][2])) return; // match found
                        }
                    } else {
                        if(check_key(name, items[i][1], items[i][2])) return; // match found
                    }
                } // end for
                // not returned, so wo need to end as not matched
                terminate();
            } else {
                if(response.selectedIndex == undefined) terminate();
                else {
                    var cb = items[response.selectedIndex][2];
                    if(cb == undefined) { terminate(); }
                    else { cb(); }
                }
            }
        }
    ) ;
    // Attention: this is Javascript, so execution directly continues here,
    // so everything needs to be done in callbacks and via recursion if
    // deterministic behavior is expected
    // Careful: while menu is running, cursor changes all the time, so
    // nothing can decently be printed (maybe modal)
}

function run_command(command, directory = null) {
    var args = ['-q', '-e', '-c', command, '/dev/null' ];
//    if(directory)
//        cmd = 'cd "' + directory + '"; ' + cmd;
    term.wrap("\nRunning ", command, "\n\n");
    var result = child_process.spawnSync("script", args,
                    { stdio: [0,0,0], cwd: directory });
    if( result.status == 0) {
        term.green.wrap('\nThe command ',command,' seems to have completed successful. OK to continue.\n');
        choice([
            ["OK, continue (O, Enter)", "O", terminate]
        ], pre_select=-1);
    } else {
        term.red.wrap('\nAn error occurred running ',command,'. Check output, continue, and eventually try again later.\n');
        choice([
            ["Continue (C, Enter)", "C", terminate]
        ], pre_select=-1);
    }
}

function shell_command(question, command, directory = null) {
    if(question) {
        term.wrap("\n", question, "\n");

        choice([
            ["Yes, run " + command + " (Y)", "Y", function() { run_command(command, directory); } ],
            ["No, go back (N)", "N", terminate]
        ], pre_select=-1);
    } else {
        term("\n\n");
        run_command(command, directory);
    }
}

function shell_command_in_path(before_path, after_path, command) {
    term.wrap('\n\n', before_path, '\n');
    var d = process.env.ACTIVE_DIR;
    var fulldir = d;
    if(!d) {
        d = process.cwd();
        fulldir = d;
    }
    // Strip home directory
    var home = process.env.HOME;
    if(d.startsWith(home)) d = d.slice(home.length+1);
    term.wrap(d,'\n');

    shell_command(after_path, command, fulldir);
}

function deploy() {
    shell_command_in_path('You are about to deploy from the following path:',
        'Are you sure?', "deploy");
}

function compile() {
    shell_command_in_path('You are about to run compile in the following path:',
        'Are you sure?', "compile");
}

function initialize() {
    shell_command_in_path('You are about to initialize from the following path:',
        'Are you sure and have you successfully put one node in adoption mode?',
        "initialize");
}

function create_node_template() {
    shell_command_in_path("You are about to create a folder called new-node"
        + " to configure a new node. Do not forget to rename this folder after"
        + " this creation. you might have to refresh cloudcmd to see the newly"
        + " created folder after this action. It will be created in the following path:",
        'Are you sure?',
        "create_node_template");
}

function upgrade() {
    shell_command("This will get the newest version of ulnoiot out of the internet."
        + " Are you sure you want to run this?", "upgrade");
}

function initialize_serial() {
    shell_command_in_path('You are about to initialize'
        + ' a device that is locally connected to the gateway via usb or serial'
        + ' from the following path:',
        'Are you sure, and have you connected only one node to the gateway?',
        "initialize serial");
}

function pre_flash_wemos() {
    shell_command('You are about to flash a connected Wemos D1 mini with'
        + ' a default ulnoiot firmware. Are you sure, and have you connected '
        + 'exactly one Wemos D1 mini via USB to the gateway?',
        "pre_flash_wemos");
}

function shell_escape() {
    shell_command_in_path("Starting the shell (bash) now. "
        + "Remember to type exit to leave. Initial path will be:",
        null, "bash");
}

function poweroff() {
    shell_command("This will cleanly shut down the gateway. "
        + "Are you sure you want to shutdown and power off the gateway?",
        "sudo poweroff");
}

function wifi_config() {
    shell_command("This will open an editor with the WiFi-router configuration."
        + " Please make corresponding changes. You will have to power off and on"
        + " the gateway after this edit to activate the new configuration. "
        + "\nDo you want to continue editing the WiFi-router configuration?",
        "sudo /usr/bin/mcedit /boot/wifi.txt");
}

function advanced() {
    choice([
        ["Pre-Flash Wemos D1 mini (P)", "P", pre_flash_wemos],
        ["Initialize Serial (I)", "I", initialize_serial],
        // confusing - better through shell ["Compile (C)", "C", compile],
        ["Upgrade (U)", "U", upgrade],
        ["Change Wifi-Router Configuration (W)", "W", wifi_config],
        ["Shell Escape (S)", "S", shell_escape],
        ["Shutdown/Poweroff (O)", "O", poweroff],
        ["Back (B,X,ESC)", ["B","X"], menu_default]
    ], pre_select=-1, pad_last=1);
}

function menu_default() {
    //term.clear();
    term("\n\n");
    term.bgBrightWhite.black.wrap( '^+ul^rno^-^kiot^: Simple Shell\n' ) ;
    term("\n");
    term.wrap('Use mouse, arrow keys, enter, or shortcut key to select.\n')
    term("\n");

    choice([
        ["Deploy (D)", "D", deploy],
        ["Initialize (I)", "I", initialize],
        ["Create New Node Folder (N)", "N", create_node_template],
        ["Advanced (A)", "A", advanced],
    //    "Exit (X,ESC)"
    ], pre_select=0, pad_last=0);
}

menu_default();<|endoftext|>


<commit_before>var straw = require('../../../lib/straw.js')

/*
 * emits cumulative count of messages received.
 */

module.exports = straw.node.extend({
  title: 'Count',
  total: 0,
  process: function(msg, done) {
    this.total ++;
    this.output(
      {count: this.total},
      function(err){
        done(err);
      });
    process.nextTick(done);
  }
});
<commit_msg>Fixed callback<commit_after>var straw = require('../../../lib/straw.js')

/*
 * emits cumulative count of messages received.
 */

module.exports = straw.node.extend({
  title: 'Count',
  total: 0,
  process: function(msg, done) {
    this.total ++;
    this.output({count: this.total}, done);
  }
});
<|endoftext|>


<commit_before>const key = '__ember_cli_documents__';

export default (owner, fn) => {
  if(!owner) {
    return;
  }
  if(!owner.willDestroy) {
    return;
  }
  let array = owner.willDestroy[key];
  if(!array) {
    array = [];
    let willDestroy = owner.willDestroy;
    owner.willDestroy = function() {
      for(let i = 0; i < array.length; i++) {
        let fn = array[i];
        fn();
      }
      willDestroy.apply(owner, arguments);
    }
    owner.willDestroy[key] = array;
  }
  array.push(fn);
};
<commit_msg>destroyRegistered along with registerDestroy<commit_after>import Ember from 'ember';
const key = '__ember_cli_documents__';

const {
  A
} = Ember;

export const destroyRegistered = (owner, fn) => {
  if(!owner) {
    return;
  }
  if(!owner.willDestroy) {
    return;
  }
  let array = owner.willDestroy[key];
  array.removeObject(fn);
  fn();
}

export const registerDestroy = (owner, fn) => {
  if(!owner) {
    return;
  }
  if(!owner.willDestroy) {
    return;
  }
  let array = owner.willDestroy[key];
  if(!array) {
    array = A();
    let willDestroy = owner.willDestroy;
    owner.willDestroy = function() {
      for(let i = 0; i < array.length; i++) {
        let fn = array[i];
        fn();
      }
      willDestroy.apply(owner, arguments);
    }
    owner.willDestroy[key] = array;
  }
  array.push(fn);
  return fn;
};
<|endoftext|>


<commit_before>/**
 * Created by truthlighting on 9/20/2016.
 */
module.exports =
{
    initSpawnQue: function()
    {
        if(Memory.spawnQue == undefined)
            Memory.spawnQue = [ ];
    },

    addToQue: function(creep, unshift)
    {
        this.initSpawnQue();

        if(unshift != undefined && unshift === true)
            Memory.spawnQue.unshift(creep);
        else
            Memory.spawnQue.push(creep);
    },

    spawnNextInQue: function()
    {
        this.initSpawnQue();

        if(!Memory.spawnQue.length)
            return;

        var spawns = Game.rooms['W2N48'].find(FIND_MY_SPAWNS, {
            filter: function(spawn)
            {
                return spawn.spawning === undefined || spawn.spawning === null;
            }
        });
        //console.log(spawns);

        if(!spawns.length)
            return;

        var role = Memory.spawnQue[0];

        if(typeof role == "string")
        {
            role = { type: role, memory: { } };
        }

        var me = this;
        var toSpawnAt = spawns.filter(function(spawn)
        {
            return me.canSpawn(spawn, role.type);
        });

        if(! toSpawnAt.length)
            return;

        toSpawnAt = toSpawnAt[0];

        this.spawn(role.type, role.memory, toSpawnAt);

        Memory.spawnQue.shift();
    },

    spawn: function(role, memory, spawnPoint)
    {
        if(!spawnPoint)
            spawnPoint = Game.spawns['Harmony'];

        var manager = require('roleManager');

        if(!manager.roleExists(role))
        {
            return;
        }

        if(!this.canSpawn(spawnPoint, role))
        {
            return;
        }
        console.log(spawnPoint);
        if(memory == undefined)
            memory = { };

        memory['role'] = role;

        var nameCount = 0;
        var name = null;
        while(name == null)
        {
            nameCount++;
            var tryName = role + nameCount;
            if(Game.creeps[tryName] == undefined)
                name = tryName;
        }

        console.log('Spawning ' + role);
        spawnPoint.createCreep(manager.getRoleBodyParts(role), name, memory);
    },

    canSpawn: function(spawnPoint, role)
    {
        if(typeof spawnPoint == "string" && role == undefined)
        {
            role = spawnPoint;
            spawnPoint = Game.spawns['Harmony'];
        }
        //console.log(role);
        return spawnPoint.energy >= this.spawnCost(role)
            && (spawnPoint.spawning == null
            || spawnPoint.spawning == undefined);
    },

    spawnCost: function(role)
    {
        var manager = require('roleManager');
        var parts = manager.getRoleBodyParts(role);

        var total = 0;
        for(var index in parts)
        {
            var part = parts[index];
            switch(part)
            {
                case Game.MOVE:
                    total += 50
                    break;

                case Game.WORK:
                    total += 100
                    break;

                case Game.CARRY:
                    total += 50
                    break;

                case Game.ATTACK:
                    total += 80
                    break;

                case Game.RANGED_ATTACK:
                    total += 150
                    break;

                case Game.HEAL:
                    total += 250
                    break;

                case Game.TOUGH:
                    total += 10
                    break;

                case Game.CLAIM:
                    total += 600
            }
        }
        //console.log(total);
        return total;
    },

    killAll: function(role)
    {
        for(var i in Game.creeps) {
            if(role == undefined || Game.creeps[i].memory.role == role)
                Game.creeps[i].suicide();
        }
    }
}<commit_msg>Starting the long process of fixing old code<commit_after>/**
 * Created by truthlighting on 9/20/2016.
 */
module.exports =
{
    initSpawnQue: function()
    {
        if(Memory.spawnQue == undefined)
            Memory.spawnQue = [ ];
    },

    addToQue: function(creep, unshift)
    {
        this.initSpawnQue();

        if(unshift != undefined && unshift === true)
            Memory.spawnQue.unshift(creep);
        else
            Memory.spawnQue.push(creep);
    },

    spawnNextInQue: function()
    {
        this.initSpawnQue();

        if(!Memory.spawnQue.length)
            return;

        var spawns = Game.rooms['W2N48'].find(FIND_MY_SPAWNS, {
            filter: function(spawn)
            {
                return spawn.spawning === undefined || spawn.spawning === null;
            }
        });
        //console.log(spawns);

        if(!spawns.length)
            return;

        var role = Memory.spawnQue[0];

        if(typeof role == "string")
        {
            role = { type: role, memory: { } };
        }

        var me = this;
        var toSpawnAt = spawns.filter(function(spawn)
        {
            return me.canSpawn(spawn, role.type);
        });

        if(! toSpawnAt.length)
            return;

        toSpawnAt = toSpawnAt[0];

        this.spawn(role.type, role.memory, toSpawnAt);

        Memory.spawnQue.shift();
    },

    spawn: function(role, memory, spawnPoint)
    {
        if(!spawnPoint)
            spawnPoint = Game.spawns['Harmony'];

        var manager = require('roleManager');

        if(!manager.roleExists(role))
        {
            return;
        }

        if(!this.canSpawn(spawnPoint, role))
        {
            return;
        }

        if(memory == undefined)
            memory = { };

        memory['role'] = role;

        var nameCount = 0;
        var name = null;
        while(name == null)
        {
            nameCount++;
            var tryName = role + nameCount;
            if(Game.creeps[tryName] == undefined)
                name = tryName;
        }

        console.log('Spawning ' + role);
        console.log(spawnPoint.createCreep(manager.getRoleBodyParts(role), name, memory));
    },

    canSpawn: function(spawnPoint, role)
    {
        if(typeof spawnPoint == "string" && role == undefined)
        {
            role = spawnPoint;
            spawnPoint = Game.spawns['Harmony'];
        }
        //console.log(role);
        return spawnPoint.energy >= this.spawnCost(role)
            && (spawnPoint.spawning == null
            || spawnPoint.spawning == undefined);
    },

    spawnCost: function(role)
    {
        var manager = require('roleManager');
        var parts = manager.getRoleBodyParts(role);

        var total = 0;
        for(var index in parts)
        {
            var part = parts[index];
            switch(part)
            {
                case Game.MOVE:
                    total += 50
                    break;

                case Game.WORK:
                    total += 100
                    break;

                case Game.CARRY:
                    total += 50
                    break;

                case Game.ATTACK:
                    total += 80
                    break;

                case Game.RANGED_ATTACK:
                    total += 150
                    break;

                case Game.HEAL:
                    total += 250
                    break;

                case Game.TOUGH:
                    total += 10
                    break;

                case Game.CLAIM:
                    total += 600
            }
        }
        //console.log(total);
        return total;
    },

    killAll: function(role)
    {
        for(var i in Game.creeps) {
            if(role == undefined || Game.creeps[i].memory.role == role)
                Game.creeps[i].suicide();
        }
    }
}<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {Editor, EditorState, CompositeDecorator} from 'draft-js';
import writeGood from 'write-good'

let suggestions = []
const SuggestionSpan = (props) => {
  //let data = Entity.get(props.entityKey).getData()
  let indexMatch = props.children[0].props.start //wtf
  let suggestion = suggestions.find(suggestion => suggestion.index === indexMatch)
  //console.log(props)
  let style = {
    backgroundColor:'#ffeee6',
    border: '1px solid #ffddcc',
    color: 666
  }
  return {props.children};
};

const suggestionStrategy = function(contentBlock, callback){
  suggestions.forEach((suggestion)=>{
    callback(suggestion.index, suggestion.index + suggestion.offset, suggestion)
  })
}

const compositeDecorator = new CompositeDecorator([
  {
    strategy: suggestionStrategy,
    component: SuggestionSpan,
  },
]);

function cleanBlock(block){
  let cleanCharacterList = block.characterList.map(character => {
    return character.set('entity', null)
  })
  return block.set('characterList', cleanCharacterList)
}
class App extends Component {
  onChange = (editorState) =>{
    return this.setState({editorState: editorState},()=>{
      suggestions = this.computesuggestions(this.state.editorState)
    })
  }

  constructor(props) {
    super(props);
    this.state = {
      suggestions:[],
      editorState: EditorState.createEmpty(compositeDecorator)
    };
  }
  computesuggestions(editorState){
    let plainText = editorState.getCurrentContent().getPlainText()
    return writeGood(plainText) || []
  }
  render() {
    const {editorState} = this.state;
    return (

        <Editor
          spellCheck={true}
          editorState={editorState}
          onChange={this.onChange} />

    )
  }
}

export default App;
<commit_msg>delete unused code<commit_after>import React, { Component } from 'react';
import {Editor, EditorState, CompositeDecorator} from 'draft-js';
import writeGood from 'write-good'

let suggestions = []
const SuggestionSpan = (props) => {
  let indexMatch = props.children[0].props.start //wtf
  let suggestion = suggestions.find(suggestion => suggestion.index === indexMatch)
  let style = {
    backgroundColor:'#ffeee6',
    border: '1px solid #ffddcc',
    color: 666
  }
  return {props.children};
};

const suggestionStrategy = function(contentBlock, callback){
  suggestions.forEach((suggestion)=>{
    callback(suggestion.index, suggestion.index + suggestion.offset, suggestion)
  })
}

const compositeDecorator = new CompositeDecorator([
  {
    strategy: suggestionStrategy,
    component: SuggestionSpan,
  },
]);

class App extends Component {
  onChange = (editorState) =>{
    return this.setState({editorState: editorState},()=>{
      suggestions = this.computesuggestions(this.state.editorState)
    })
  }

  constructor(props) {
    super(props);
    this.state = {
      suggestions:[],
      editorState: EditorState.createEmpty(compositeDecorator)
    };
  }
  computesuggestions(editorState){
    let plainText = editorState.getCurrentContent().getPlainText()
    return writeGood(plainText) || []
  }
  render() {
    const {editorState} = this.state;
    return (

        <Editor
          spellCheck={true}
          editorState={editorState}
          onChange={this.onChange} />

    )
  }
}

export default App;
<|endoftext|>


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

const Workshopper = require('workshopper-jlord'),
      path = require('path')

process.env.LANG = 'en_US.UTF-8'

Workshopper({
  name: 'git-it',
  title: 'GIT + GITHUB : VERSION CONTROL + SOCIAL CODING',
  appDir: __dirname,
  helpFile: path.join(__dirname, 'help.txt'),
  menu: {
    fg: /^win/.test(process.platform) ? 'white' : 231,
    bg: /^win/.test(process.platform) ? 'blue'  : 33
  }
}).init()
<commit_msg>use bundled English langauge pack, C<commit_after>#!/usr/bin/env node

const Workshopper = require('workshopper-jlord'),
      path = require('path')

process.env.LANG = 'C'

Workshopper({
  name: 'git-it',
  title: 'GIT + GITHUB : VERSION CONTROL + SOCIAL CODING',
  appDir: __dirname,
  helpFile: path.join(__dirname, 'help.txt'),
  menu: {
    fg: /^win/.test(process.platform) ? 'white' : 231,
    bg: /^win/.test(process.platform) ? 'blue'  : 33
  }
}).init()
<|endoftext|>


<commit_before>import algolia from 'algoliasearch';
import icons from '../dist/icons.json';
import tags from '../src/tags.json';

const ALGOLIA_APP_ID = '5EEOG744D0';

if (
  process.env.TRAVIS_PULL_REQUEST === 'false' &&
  process.env.TRAVIS_BRANCH === 'master'
) {
  syncAlgolia();
} else {
  console.log('Skipped Algolia sync.');
}

function syncAlgolia() {
  // ALGOLIA_ADMIN_KEY must be added as an environment variable in Travis CI
  const client = algolia(ALGOLIA_APP_ID, process.env.ALGOLIA_ADMIN_KEY);

  console.log('Initializing target and temporary indexes...');
  const index = client.initIndex('icons');
  const indexTmp = client.initIndex('icons_tmp');

  indexTmp.setSettings({
    searchableAttributes: ['unordered(name)', 'unordered(tags)'],
    customRanking: ['asc(name)'],
  });

  const records = Object.keys(icons).map(name => ({
    name,
    tags: tags[name] || [],
  }));

  console.log('Pushing data to the temporary index...');
  indexTmp.addObjects(records, err => {
    if (err) throw err;
  });

  console.log('Moving temporary index to target index...');
  client.moveIndex(indexTmp.indexName, index.indexName, err => {
    if (err) throw err;
  });
}
<commit_msg>build: Use promises in algolia script<commit_after>import algolia from 'algoliasearch';
import icons from '../dist/icons.json';
import tags from '../src/tags.json';

const ALGOLIA_APP_ID = '5EEOG744D0';

if (
  process.env.TRAVIS_PULL_REQUEST === 'false' &&
  process.env.TRAVIS_BRANCH === 'master'
) {
  syncAlgolia();
} else {
  console.log('Skipped Algolia sync.');
}

function syncAlgolia() {
  // ALGOLIA_ADMIN_KEY must be added as an environment variable in Travis CI
  const client = algolia(ALGOLIA_APP_ID, process.env.ALGOLIA_ADMIN_KEY);

  console.log('Initializing target and temporary indexes...');
  const index = client.initIndex('icons');
  const indexTmp = client.initIndex('icons_tmp');

  console.log(
    "Copying target index's settings, synonyms and rules into temporary index...",
  );
  scopedCopyIndex(client, index.indexName, indexTmp.indexName)
    .then(() => {
      const objects = Object.keys(icons).map(name => ({
        name,
        tags: tags[name] || [],
      }));

      console.log('Adding objects to the temporary index...');
      return addObjects(indexTmp, objects);
    })
    .then(() => {
      console.log('Moving temporary index to target index...');
      return moveIndex(client, indexTmp.indexName, index.indexName);
    });
}

function scopedCopyIndex(
  client,
  indexNameSrc,
  indexNameDest,
  scope = ['settings', 'synonyms', 'rules'],
) {
  return new Promise((resolve, reject) => {
    client.copyIndex(indexNameSrc, indexNameDest, scope, (error, contents) => {
      if (error) reject(error);
      resolve(contents);
    });
  });
}

function addObjects(index, objects) {
  return new Promise((resolve, reject) => {
    index.addObjects(objects, (error, contents) => {
      if (error) reject(error);
      resolve(contents);
    });
  });
}

function moveIndex(client, indexNameSrc, indexNameDest) {
  return new Promise((resolve, reject) => {
    client.moveIndex(indexNameSrc, indexNameDest, (error, contents) => {
      if (error) reject(error);
      resolve(contents);
    });
  });
}
<|endoftext|>


<commit_before>define(function(require) {

	'use strict';

	var _    = require('underscore');
	var PIXI = require('pixi');

	var PixiView       = require('common/pixi/view');
	var Colors         = require('common/colors/colors');
	var PiecewiseCurve = require('common/math/piecewise-curve');
	var Rectangle      = require('common/math/rectangle');

	var Constants      = require('constants');

	var defaultMovementConstraintBounds = new Rectangle(
		Number.NEGATIVE_INFINITY,
		Number.NEGATIVE_INFINITY,
		Number.POSITIVE_INFINITY,
		Number.POSITIVE_INFINITY
	);

	/**
	 * A view that represents an element model
	 */
	var ElementView = PixiView.extend({

		events: {
			'touchstart      .displayObject': 'dragStart',
			'mousedown       .displayObject': 'dragStart',
			'touchmove       .displayObject': 'drag',
			'mousemove       .displayObject': 'drag',
			'touchend        .displayObject': 'dragEnd',
			'mouseup         .displayObject': 'dragEnd',
			'touchendoutside .displayObject': 'dragEnd',
			'mouseupoutside  .displayObject': 'dragEnd',
		},

		/**
		 *
		 */
		initialize: function(options) {
			this.mvt = options.mvt;

			this.movable = options.movable || false;
			this.movementConstraintBounds = options.movementConstraintBounds || defaultMovementConstraintBounds;

			this.fillColor = options.fillColor;
			this.fillAlpha = options.fillAlpha !== undefined ? options.fillAlpha : 1;
			this.lineWidth = options.lineWidth !== undefined ? options.lineWidth : 3;
			this.lineColor = options.lineColor || '#444444';
			this.lineJoin  = options.lineJoin  || 'round';
			this.textColor = options.textColor || '#000000';
			this.textFont  = options.textFont  || ElementView.TEXT_FONT;
			this.labelText = options.labelText || '';

			if (this.fillColor === undefined)
				this.fillColor = 0x000000;
			else if (_.isString(this.fillColor))
				this.fillColor =  Colors.parseHex(options.fillColor);

			// To give some feedback on the cursor
			if (this.movable)
				this.displayObject.buttonMode = true;

			this._dragBounds = new Rectangle();
		},

		calculateDragBounds: function(dx, dy) {
			var bounds = this.displayObject.getBounds();
			return this._dragBounds.set(
				bounds.x + dx,
				bounds.y + dy,
				bounds.width,
				bounds.height
			);
		},

		dragStart: function(data) {
			this.dragXOffset = data.getLocalPosition(this.displayObject).x;
			this.dragYOffset = data.getLocalPosition(this.displayObject).y;
			this.dragging = true;
			this.model.set('userControlled', true);
		},

		drag: function(data) {
			if (this.dragging) {
				var dx = data.global.x - this.displayObject.x - this.dragXOffset;
				var dy = data.global.y - this.displayObject.y - this.dragYOffset;

				var newBounds = this.calculateDragBounds(dx, dy);
				var constraintBounds = this.movementConstraintBounds;

				console.log(dx + ', ' + dy);

				if (!constraintBounds.contains(newBounds)) {
					var overflowLeft   = constraintBounds.left() - newBounds.left();
					var overflowRight  = newBounds.right() - constraintBounds.right();
					var overflowTop    = constraintBounds.bottom() - newBounds.bottom();
					var overflowBottom = newBounds.top() - constraintBounds.top();

					// Backtrack if we need to
					if (overflowLeft > 0)
						dx += overflowLeft;
					else if (overflowRight > 0)
						dx -= overflowRight;

					if (overflowTop > 0)
						dy += overflowTop;
					else if (overflowBottom > 0)
						dy -= overflowBottom;
				}

				dx = this.mvt.viewToModelDeltaX(dx);
				dy = this.mvt.viewToModelDeltaY(dy);

				this.model.translate(dx, dy);

				this.dragX = data.global.x;
				this.dragY = data.global.y;
			}
		},

		dragEnd: function(data) {
			this.dragging = false;
			this.dragData = null;
			this.model.set('userControlled', false);
		},

		update: function(time, deltaTime) {

		},

		showEnergyChunks: function() {},

		hideEnergyChunks: function() {},

		createOutlineFromPointArrays: function(pointArrays, style) {
			if (pointArrays.length === 0)
				return new PIXI.Sprite();

			if (!_.isArray(pointArrays[0]))
				pointArrays = [ pointArrays ];

			_.extend({
				lineWidth: 1,
				strokeStyle: '#000',
				lineJoin: 'miter'
			}, style || {});

			// Determine the bounds for all the points
			var curve = PiecewiseCurve.fromPointArrays(pointArrays);
			var bounds = curve.getBounds();

			// Determine if we need to shift the points to fit within the bounds
			var xShift = 0 - bounds.x;
			var yShift = 0 - bounds.y;

			xShift += style.lineWidth;
			yShift += style.lineWidth;

			// Draw the lines
			var canvas = document.createElement('canvas');
			canvas.width  = bounds.w + (2 * style.lineWidth);
			canvas.height = bounds.h + (2 * style.lineWidth);

			var ctx = canvas.getContext('2d');

			ctx.lineWidth   = style.lineWidth;
			ctx.strokeStyle = style.strokeStyle;
			ctx.lineJoin    = style.lineJoin;

			_.each(pointArrays, function(points) {
				ctx.beginPath();

				ctx.moveTo(points[0].x + xShift, points[0].y + yShift);
				for (var i = 1; i < points.length; i++)
					ctx.lineTo(points[i].x + xShift, points[i].y + yShift);

				ctx.closePath();
				ctx.stroke();
			});

			// Create the sprite and shift the anchor proportionally to the shift
			var sprite = new PIXI.Sprite(PIXI.Texture.fromCanvas(canvas));
			sprite.anchor.x = xShift / sprite.width;
			sprite.anchor.y = yShift / sprite.height;

			return sprite;
		},

		createTexturedPolygonFromPoints: function(maskingPoints, texture) {
			/*
			 * The masking points are not necessarily within the bounds of
			 *   the texture, so we need to calculate the bounding box for
			 *   the masking points, scale the texture to fit those bounds,
			 *   create a masking shape with the points, and then shift
			 *   the sprite that holds the texture to the origin of the
			 *   bounding box of the masking points to place it in its
			 *   rightful location.
			 */

			// Calculate the bounding box for the masking points
			var curve = PiecewiseCurve.fromPoints(maskingPoints);
			var bounds = curve.getBounds();

			// Ratio for scaling the texture to the size of the bounds
			var xScale = bounds.w / texture.width;
			var yScale = bounds.h / texture.height;

			// Create the mask shape
			var mask = new PIXI.Graphics();
			mask.lineStyle(0);
			mask.beginFill(0x000000, 1);
			this.displayObject.addChild(mask);

			// Draw the masking points shifted
			mask.moveTo(maskingPoints[0].x, maskingPoints[0].y);
			for (var i = 1; i < maskingPoints.length; i++)
				mask.lineTo(maskingPoints[i].x, maskingPoints[i].y);

			// Create a sprite with the texture, scaled to the size of the bounds
			var sprite = new PIXI.Sprite(texture);
			sprite.scale.x = xScale;
			sprite.scale.y = yScale;

			// Apply the mask
			sprite.mask = mask;

			// Shift the sprite back to where the masking points are supposed to be
			sprite.x = bounds.x;
			sprite.y = bounds.y;

			return sprite;
		},

		createColoredPolygonFromPoints: function(points, color, alpha) {
			var graphics = new PIXI.Graphics();
			graphics.lineStyle(0);
			graphics.beginFill(color, (alpha === undefined) ? 1 : alpha);

			graphics.moveTo(points[0].x, points[0].y);
			for (var i = 1; i < points.length; i++)
				graphics.lineTo(points[i].x, points[i].y);

			return graphics;
		}

	}, Constants.ElementView);

	return ElementView;
});<commit_msg>PIXI canvases don't listen to drag events after the pointer moves outside the canvas :(<commit_after>define(function(require) {

	'use strict';

	var _    = require('underscore');
	var PIXI = require('pixi');

	var PixiView       = require('common/pixi/view');
	var Colors         = require('common/colors/colors');
	var PiecewiseCurve = require('common/math/piecewise-curve');
	var Rectangle      = require('common/math/rectangle');

	var Constants      = require('constants');

	var defaultMovementConstraintBounds = new Rectangle(
		Number.NEGATIVE_INFINITY,
		Number.NEGATIVE_INFINITY,
		Number.POSITIVE_INFINITY,
		Number.POSITIVE_INFINITY
	);

	/**
	 * A view that represents an element model
	 */
	var ElementView = PixiView.extend({

		events: {
			'touchstart      .displayObject': 'dragStart',
			'mousedown       .displayObject': 'dragStart',
			'touchmove       .displayObject': 'drag',
			'mousemove       .displayObject': 'drag',
			'touchend        .displayObject': 'dragEnd',
			'mouseup         .displayObject': 'dragEnd',
			'touchendoutside .displayObject': 'dragEnd',
			'mouseupoutside  .displayObject': 'dragEnd',
		},

		/**
		 *
		 */
		initialize: function(options) {
			this.mvt = options.mvt;

			this.movable = options.movable || false;
			this.movementConstraintBounds = options.movementConstraintBounds || defaultMovementConstraintBounds;

			this.fillColor = options.fillColor;
			this.fillAlpha = options.fillAlpha !== undefined ? options.fillAlpha : 1;
			this.lineWidth = options.lineWidth !== undefined ? options.lineWidth : 3;
			this.lineColor = options.lineColor || '#444444';
			this.lineJoin  = options.lineJoin  || 'round';
			this.textColor = options.textColor || '#000000';
			this.textFont  = options.textFont  || ElementView.TEXT_FONT;
			this.labelText = options.labelText || '';

			if (this.fillColor === undefined)
				this.fillColor = 0x000000;
			else if (_.isString(this.fillColor))
				this.fillColor =  Colors.parseHex(options.fillColor);

			// To give some feedback on the cursor
			if (this.movable)
				this.displayObject.buttonMode = true;

			this._dragBounds = new Rectangle();
			this._dragOffset = new PIXI.Point();
		},

		calculateDragBounds: function(dx, dy) {
			var bounds = this.displayObject.getBounds();
			return this._dragBounds.set(
				bounds.x + dx,
				bounds.y + dy,
				bounds.width,
				bounds.height
			);
		},

		dragStart: function(data) {
			this.dragOffset = data.getLocalPosition(this.displayObject, this._dragOffset);
			this.dragging = true;
			this.model.set('userControlled', true);
		},

		drag: function(data) {
			if (this.dragging) {
				var dx = data.global.x - this.displayObject.x - this.dragOffset.x;
				var dy = data.global.y - this.displayObject.y - this.dragOffset.y;

				var newBounds = this.calculateDragBounds(dx, dy);
				var constraintBounds = this.movementConstraintBounds;

				if (!constraintBounds.contains(newBounds)) {
					var overflowLeft   = constraintBounds.left() - newBounds.left();
					var overflowRight  = newBounds.right() - constraintBounds.right();
					var overflowTop    = constraintBounds.bottom() - newBounds.bottom();
					var overflowBottom = newBounds.top() - constraintBounds.top();

					// Backtrack if we need to
					if (overflowLeft > 0)
						dx += overflowLeft;
					else if (overflowRight > 0)
						dx -= overflowRight;

					if (overflowTop > 0)
						dy += overflowTop;
					else if (overflowBottom > 0)
						dy -= overflowBottom;
				}

				dx = this.mvt.viewToModelDeltaX(dx);
				dy = this.mvt.viewToModelDeltaY(dy);

				this.model.translate(dx, dy);

				this.dragX = data.global.x;
				this.dragY = data.global.y;
			}
		},

		dragEnd: function(data) {
			this.dragging = false;
			this.dragData = null;
			this.model.set('userControlled', false);
		},

		update: function(time, deltaTime) {

		},

		showEnergyChunks: function() {},

		hideEnergyChunks: function() {},

		createOutlineFromPointArrays: function(pointArrays, style) {
			if (pointArrays.length === 0)
				return new PIXI.Sprite();

			if (!_.isArray(pointArrays[0]))
				pointArrays = [ pointArrays ];

			_.extend({
				lineWidth: 1,
				strokeStyle: '#000',
				lineJoin: 'miter'
			}, style || {});

			// Determine the bounds for all the points
			var curve = PiecewiseCurve.fromPointArrays(pointArrays);
			var bounds = curve.getBounds();

			// Determine if we need to shift the points to fit within the bounds
			var xShift = 0 - bounds.x;
			var yShift = 0 - bounds.y;

			xShift += style.lineWidth;
			yShift += style.lineWidth;

			// Draw the lines
			var canvas = document.createElement('canvas');
			canvas.width  = bounds.w + (2 * style.lineWidth);
			canvas.height = bounds.h + (2 * style.lineWidth);

			var ctx = canvas.getContext('2d');

			ctx.lineWidth   = style.lineWidth;
			ctx.strokeStyle = style.strokeStyle;
			ctx.lineJoin    = style.lineJoin;

			_.each(pointArrays, function(points) {
				ctx.beginPath();

				ctx.moveTo(points[0].x + xShift, points[0].y + yShift);
				for (var i = 1; i < points.length; i++)
					ctx.lineTo(points[i].x + xShift, points[i].y + yShift);

				ctx.closePath();
				ctx.stroke();
			});

			// Create the sprite and shift the anchor proportionally to the shift
			var sprite = new PIXI.Sprite(PIXI.Texture.fromCanvas(canvas));
			sprite.anchor.x = xShift / sprite.width;
			sprite.anchor.y = yShift / sprite.height;

			return sprite;
		},

		createTexturedPolygonFromPoints: function(maskingPoints, texture) {
			/*
			 * The masking points are not necessarily within the bounds of
			 *   the texture, so we need to calculate the bounding box for
			 *   the masking points, scale the texture to fit those bounds,
			 *   create a masking shape with the points, and then shift
			 *   the sprite that holds the texture to the origin of the
			 *   bounding box of the masking points to place it in its
			 *   rightful location.
			 */

			// Calculate the bounding box for the masking points
			var curve = PiecewiseCurve.fromPoints(maskingPoints);
			var bounds = curve.getBounds();

			// Ratio for scaling the texture to the size of the bounds
			var xScale = bounds.w / texture.width;
			var yScale = bounds.h / texture.height;

			// Create the mask shape
			var mask = new PIXI.Graphics();
			mask.lineStyle(0);
			mask.beginFill(0x000000, 1);
			this.displayObject.addChild(mask);

			// Draw the masking points shifted
			mask.moveTo(maskingPoints[0].x, maskingPoints[0].y);
			for (var i = 1; i < maskingPoints.length; i++)
				mask.lineTo(maskingPoints[i].x, maskingPoints[i].y);

			// Create a sprite with the texture, scaled to the size of the bounds
			var sprite = new PIXI.Sprite(texture);
			sprite.scale.x = xScale;
			sprite.scale.y = yScale;

			// Apply the mask
			sprite.mask = mask;

			// Shift the sprite back to where the masking points are supposed to be
			sprite.x = bounds.x;
			sprite.y = bounds.y;

			return sprite;
		},

		createColoredPolygonFromPoints: function(points, color, alpha) {
			var graphics = new PIXI.Graphics();
			graphics.lineStyle(0);
			graphics.beginFill(color, (alpha === undefined) ? 1 : alpha);

			graphics.moveTo(points[0].x, points[0].y);
			for (var i = 1; i < points.length; i++)
				graphics.lineTo(points[i].x, points[i].y);

			return graphics;
		}

	}, Constants.ElementView);

	return ElementView;
});<|endoftext|>


<commit_before>/**
 *  Create a sequence using a Part with callbacks that play back soundfiles.
 *  The callback includes parameters (the value at that position in the Phrase array)
 *  as well as time, which should be used to schedule playback with precision.
 *
 */

var click, beatbox ;

var looper1, looper2;

function preload() {
  soundFormats('mp3', 'ogg');
  click = loadSound('../files/drum');
  beatbox = loadSound('../files/beatbox');

}

function setup() {

  //Hemiola! 2 loops, playing sounds in a 4 over 3 pattern
  //gradually increase the tempo of both loops
  //
  //the looper's callback is passed the timeFromNow
  //this value should be used as a reference point from
  //which to schedule sounds

  looper1 = new p5.SoundLoop(function(timeFromNow){
    click.play(timeFromNow);
    looper1.bpm looper1.bpm += 0.5;
    }, "8n");

  looper2 = new p5.SoundLoop(function(timeFromNow){
  	beatbox.play(timeFromNow);
    looper2.bpm = looper1.bpm;
    }, "12n");

  //start the loops together
  looper1.syncedStart(looper2);
}

<commit_msg>patch sound loop example<commit_after>/**
 *  Create a sequence using a Part with callbacks that play back soundfiles.
 *  The callback includes parameters (the value at that position in the Phrase array)
 *  as well as time, which should be used to schedule playback with precision.
 *
 */

var click, beatbox ;

var looper1, looper2;

function preload() {
  soundFormats('mp3', 'ogg');
  click = loadSound('../files/drum');
  beatbox = loadSound('../files/beatbox');

}

function setup() {

  //Hemiola! 2 loops, playing sounds in a 4 over 3 pattern
  //gradually increase the tempo of both loops
  //
  //the looper's callback is passed the timeFromNow
  //this value should be used as a reference point from
  //which to schedule sounds

  looper1 = new p5.SoundLoop(function(timeFromNow){
    click.play(timeFromNow);
    looper1.bpm = looper1.bpm += 0.5;
    }, "8n");

  looper2 = new p5.SoundLoop(function(timeFromNow){
  	beatbox.play(timeFromNow);
    looper2.bpm = looper1.bpm;
    }, "12n");

  //start the loops together
  looper1.syncedStart(looper2);
}

<|endoftext|>


<commit_before>import { addAccessToken } from '@itslanguage/api/api/communication';

/**
 * Factory function to create a HTMLAudioElement.
 * If requested, it is capable of adding "access_token" to the audioUrl. For some audio an user
 * needs to be authenticated to be able to playback some audio.
 *
 * Keep in mind you need a (valid) token to be able to add it!
 *
 * @param {string} [audioUrl=false] - Provide URL to load.
 * @param {boolean} [secureLoad] - If true, add `access_token` to the url. But only if audioUrl was
 * also passed and you have a valid token to communicate with the backend.
 * @throws {Error} If window.Audio does not exist.
 * @returns {HTMLAudioElement}
 */
// eslint-disable-next-line import/prefer-default-export
export function createPlayer(audioUrl = null, secureLoad = false) {
  if (!Audio) {
    throw new Error('Your browser is not capable of playing audio.');
  }

  const audio = new Audio();
  audio.crossOrigin = 'use-credentials';

  if (audioUrl) {
    audio.src = secureLoad
      ? addAccessToken(audioUrl)
      : audioUrl;
  }

  return audio;
}

/**
 * Load a (new) url to an instance of a HTMLAudioElement. Main purpose of this function is to
 * support a way to add a new url with an "access_token". But it also works for url's in general.
 *
 * Note that this function does not follow functional programming guidelines: it will adjust a
 * property of a given param directly (aka param reassign). Unfortunately this is currently the
 * only way to (re)set an url on a given element.
 *
 * There are some alternatives that opt for not using this function:
 * 1. If you want to set an url on an already defined audio player, and you do not care or want to
 * set the 'access_token', it is better to set the url directly to the audioElm.src property
 * yourself.
 * 2. You can also use the @itslanguage/api method 'addAccessToken` to add an access token to any
 * url. That is in fact what this function uses.
 *
 * So, why we still provide this function? Only for convenience!
 *
 * @param {HTMLAudioElement} player - Instance of an Audio object to set a new url on.
 * @param {string} audioUrl - The url to set.
 * @param {boolean} [secureLoad] - If true, add `access_token` to the url.
 * @returns {boolean|string} - It will return false if it could not set an url or it will return the
 * url that has been set.
 */
export function loadAudioUrl(player, audioUrl, secureLoad = false) {
  if (!(player instanceof HTMLAudioElement) || !audioUrl) {
    return false; // nothing to do here!
  }

  // The HTMLAudioElement, or any element this object extends on, does
  // not have a proper setter for the src property. So we need to re-assign
  // it here.

  // eslint-disable-next-line no-param-reassign
  player.src = secureLoad
    ? addAccessToken(audioUrl)
    : audioUrl;

  return player.src;
}
<commit_msg>chore: add @module tag to player package<commit_after>/**
 * @module player
 */

import { addAccessToken } from '@itslanguage/api/api/communication';

/**
 * Factory function to create a HTMLAudioElement.
 * If requested, it is capable of adding "access_token" to the audioUrl. For some audio an user
 * needs to be authenticated to be able to playback some audio.
 *
 * Keep in mind you need a (valid) token to be able to add it!
 *
 * @param {string} [audioUrl=false] - Provide URL to load.
 * @param {boolean} [secureLoad] - If true, add `access_token` to the url. But only if audioUrl was
 * also passed and you have a valid token to communicate with the backend.
 * @throws {Error} If window.Audio does not exist.
 * @returns {HTMLAudioElement}
 */
// eslint-disable-next-line import/prefer-default-export
export function createPlayer(audioUrl = null, secureLoad = false) {
  if (!Audio) {
    throw new Error('Your browser is not capable of playing audio.');
  }

  const audio = new Audio();
  audio.crossOrigin = 'use-credentials';

  if (audioUrl) {
    audio.src = secureLoad
      ? addAccessToken(audioUrl)
      : audioUrl;
  }

  return audio;
}

/**
 * Load a (new) url to an instance of a HTMLAudioElement. Main purpose of this function is to
 * support a way to add a new url with an "access_token". But it also works for url's in general.
 *
 * Note that this function does not follow functional programming guidelines: it will adjust a
 * property of a given param directly (aka param reassign). Unfortunately this is currently the
 * only way to (re)set an url on a given element.
 *
 * There are some alternatives that opt for not using this function:
 * 1. If you want to set an url on an already defined audio player, and you do not care or want to
 * set the 'access_token', it is better to set the url directly to the audioElm.src property
 * yourself.
 * 2. You can also use the @itslanguage/api method 'addAccessToken` to add an access token to any
 * url. That is in fact what this function uses.
 *
 * So, why we still provide this function? Only for convenience!
 *
 * @param {HTMLAudioElement} player - Instance of an Audio object to set a new url on.
 * @param {string} audioUrl - The url to set.
 * @param {boolean} [secureLoad] - If true, add `access_token` to the url.
 * @returns {boolean|string} - It will return false if it could not set an url or it will return the
 * url that has been set.
 */
export function loadAudioUrl(player, audioUrl, secureLoad = false) {
  if (!(player instanceof HTMLAudioElement) || !audioUrl) {
    return false; // nothing to do here!
  }

  // The HTMLAudioElement, or any element this object extends on, does
  // not have a proper setter for the src property. So we need to re-assign
  // it here.

  // eslint-disable-next-line no-param-reassign
  player.src = secureLoad
    ? addAccessToken(audioUrl)
    : audioUrl;

  return player.src;
}
<|endoftext|>


<commit_before>import { Session } from 'meteor/session';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { BigNumber } from 'meteor/ethereum:web3';
import { web3Obj } from 'meteor/makerotc:dapple';
import { formatError } from '/imports/utils/functions';

import Tokens from '/imports/api/tokens';
import { Offers, Status } from '/imports/api/offers';

import './offermodal.html';

// TODO: DELETE THIS, TESTING PURPOSE
window.Tokens = Tokens;

Template.offermodal.viewmodel({
  share: 'newOffer',
  volume: '',
  total: '',
  autorun() {
    if (Template.currentData().offer) {
      const buyHowMuch = web3Obj.fromWei(new BigNumber(Template.currentData().offer.buyHowMuch)).toString(10);
      const sellHowMuch = web3Obj.fromWei(new BigNumber(Template.currentData().offer.sellHowMuch)).toString(10);
      const baseCurrency = Session.get('baseCurrency');
      if (baseCurrency === Template.currentData().offer.buyWhichToken) {
        this.volume(buyHowMuch);
        this.total(sellHowMuch);
      } else {
        this.volume(sellHowMuch);
        this.total(buyHowMuch);
      }
    }
  },
  precision() {
    return Dapple.getTokenSpecs(Session.get('baseCurrency')).precision;
  },
  validAmount: true,
  validNewOrderAmount: true,
  type() {
    if (Template.currentData().offer) {
      return Template.currentData().offer.type();
    }
    return '';
  },
  buyCurrency() {
    return this.type() === 'bid' ? Session.get('quoteCurrency') : Session.get('baseCurrency');
  },
  sellCurrency() {
    return this.type() === 'bid' ? Session.get('baseCurrency') : Session.get('quoteCurrency');
  },
  quoteToken() {
    return Tokens.findOne(Session.get('quoteCurrency'));
  },
  baseToken() {
    return Tokens.findOne(Session.get('baseCurrency'));
  },
  hasBalance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const balance = new BigNumber(token.balance);
      return token && balance.gte(web3Obj.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const allowance = new BigNumber(token.allowance);
      return token && allowance.gte(web3Obj.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowanceNewOrder() {
    try {
      const token = Tokens.findOne(this.offerType() === 'buy'
                                                      ? Session.get('quoteCurrency') : Session.get('baseCurrency'));
      const allowance = new BigNumber(token.allowance);

      return token && allowance.gte(web3Obj.toWei(new BigNumber(this.offerType() === 'buy'
                                                                       ? this.offerTotal() : this.offerAmount())));
    } catch (e) {
      return false;
    }
  },
  hasVolume() {
    try {
      const volume = new BigNumber(Template.currentData().offer.volume(this.buyCurrency()));
      return volume.gte(web3Obj.toWei(new BigNumber(this.type() === 'bid' ? this.total() : this.volume())));
    } catch (e) {
      return false;
    }
  },
  maxVolume() {
    let maxVolume = '0';
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(Template.currentData().offer.volume(baseCurrency));
      if (Template.currentData().offer.buyWhichToken === baseCurrency) {
        // Calculate max volume, since we want to sell MKR, we need to check how much MKR we can sell
        const token = Tokens.findOne(baseCurrency);
        if (token) {
          // Can at most sell balance, allowance, and offer's volume
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxVolume = web3Obj.fromWei(BigNumber.min(balance, allowance, volume)).toString(10);
        }
      } else {
        maxVolume = web3Obj.fromWei(volume).toString(10);
      }
    } catch (e) {
      maxVolume = '0';
    }
    return maxVolume;
  },
  maxTotal() {
    let maxTotal = '0';
    try {
      const quoteCurrency = Session.get('quoteCurrency');
      const total = new BigNumber(Template.currentData().offer.volume(quoteCurrency));
      if (Template.currentData().offer.buyWhichToken === quoteCurrency) {
        // Calculate max total, since we want to buy MKR, we need to check how much of the currency is available
        const token = Tokens.findOne(quoteCurrency);
        if (token) {
          // Can at most buy balance, allowance, and offer's total
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxTotal = web3Obj.fromWei(BigNumber.min(balance, allowance, total)).toString(10);
        }
      } else {
        maxTotal = web3Obj.fromWei(total).toString(10);
      }
    } catch (e) {
      maxTotal = '0';
    }
    return maxTotal;
  },
  calcVolume() {
    this.validAmount(true);
    if (this.precision() === 0 && this.total() % 1 !== 0) {
      this.validAmount(false);
      this.volume('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const total = new BigNumber(this.total());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.volume(buyHowMuch.div(sellHowMuch).times(total).toString(10));
      } else {
        this.volume(sellHowMuch.div(buyHowMuch).times(total).toString(10));
      }
    } catch (e) {
      this.volume('0');
    }
  },
  calcTotal() {
    this.validAmount(true);
    if (this.precision() === 0 && this.volume() % 1 !== 0) {
      this.validAmount(false);
      this.total('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(this.volume());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.total(sellHowMuch.div(buyHowMuch).times(volume).toString(10));
      } else {
        this.total(buyHowMuch.div(sellHowMuch).times(volume).toString(10));
      }
    } catch (e) {
      this.total('0');
    }
  },
  calcNewOfferTotal() {
    this.validNewOrderAmount(true);
    if (this.precision() === 0 && this.offerAmount() % 1 !== 0) {
      this.validNewOrderAmount(false);
      this.offerTotal('0');
      return;
    }
    try {
      const price = new BigNumber(this.offerPrice());
      const amount = new BigNumber(this.offerAmount());
      const total = price.times(amount);
      if (total.isNaN()) {
        this.offerTotal('0');
      } else {
        this.offerTotal(total.toString(10));
      }
    } catch (e) {
      this.offerTotal('0');
    }
  },
  calcNewOfferAmount() {
    this.validNewOrderAmount(true);
    if (this.precision() === 0 && this.offerTotal() % 1 !== 0) {
      this.validNewOrderAmount(false);
      this.offerAmount('0');
      return;
    }
    try {
      const price = new BigNumber(this.offerPrice());
      let amount = new BigNumber(this.offerAmount());
      const total = new BigNumber(this.offerTotal());
      if (total.isZero() && price.isZero() && (amount.isNaN() || amount.isNegative())) {
        this.offerAmount('0');
      } else if (!total.isZero() || !price.isZero()) {
        amount = total.div(price);
        if (amount.isNaN()) {
          this.offerAmount('0');
        } else {
          this.offerAmount(amount.toString(10));
        }
      }
    } catch (e) {
      this.offerAmount('0');
    }
  },
  alertBetterOffer() {
    let bestOffer = null;
    if (this.type() === 'bid') {
      bestOffer = Offers.findOne({
        buyWhichToken: Session.get('baseCurrency'),
        sellWhichToken: Session.get('quoteCurrency') },
        { sort: { ask_price_sort: 1 },
        });
      return (new BigNumber(bestOffer.bid_price)).gt(new BigNumber(this.templateInstance.data.offer.bid_price));
    } else if (this.type() === 'ask') {
      bestOffer = Offers.findOne({
        buyWhichToken: Session.get('quoteCurrency'),
        sellWhichToken: Session.get('baseCurrency') },
        { sort: { ask_price_sort: 1 },
        });
      return (new BigNumber(bestOffer.ask_price)).lt(new BigNumber(this.templateInstance.data.offer.ask_price));
    }
    return false;
  },
  dismiss(event) {
    $(event.target).closest('.modal').modal('hide');
  },
  canBuy() {
    try {
      if (Template.currentData().offer.status !== Status.CONFIRMED) {
        return false;
      }
      const volume = new BigNumber(this.volume());
      const total = new BigNumber(this.total());
      const marketOpen = Session.get('market_open');
      return marketOpen && !total.isNaN() && total.gt(0) && total.lte(new BigNumber(this.maxTotal()))
        && !volume.isNaN() && volume.gt(0) && volume.lte(new BigNumber(this.maxVolume()));
    } catch (e) {
      return false;
    }
  },
  buy() {
    const offerId = this.templateInstance.data.offer._id;
    const offer = Offers.findOne(offerId);

    if (this.templateInstance.data.offer.type() === 'bid') {
      Offers.buyOffer(offerId, 'sell', new BigNumber(this.total()), offer.sellWhichToken);
    } else {
      Offers.buyOffer(offerId, 'buy', new BigNumber(this.volume()), offer.sellWhichToken);
    }
  },
  maxNewOfferAmount() {
    let maxAmount = '0';
    if (this.offerType() === 'sell') {
      const token = Tokens.findOne(Session.get('baseCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxAmount = web3Obj.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxAmount = '9e999';
    }
    return maxAmount;
  },
  maxNewOfferTotal() {
    // Only allow change of total if price is well-defined
    try {
      const price = new BigNumber(this.offerPrice());
      if ((price.isNaN() || price.isZero() || price.isNegative())) {
        return '0';
      }
    } catch (e) {
      return '0';
    }
    // If price is well-defined, take minimum of balance and allowance of currency, if 'buy', otherwise Infinity
    let maxTotal = '0';
    if (this.offerType() === 'buy') {
      const token = Tokens.findOne(Session.get('quoteCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxTotal = web3Obj.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxTotal = '9e999';
    }
    return maxTotal;
  },
  canSubmit() {
    try {
      const type = this.offerType();
      const price = new BigNumber(this.offerPrice());
      const amount = new BigNumber(this.offerAmount());
      const maxAmount = new BigNumber(this.maxNewOfferAmount());
      const total = new BigNumber(this.offerTotal());
      const maxTotal = new BigNumber(this.maxNewOfferTotal());
      const marketOpen = Session.get('market_open');
      const validTokenPair = Session.get('quoteCurrency') !== Session.get('baseCurrency');
      return marketOpen && price.gt(0) && amount.gt(0) && total.gt(0) && validTokenPair &&
        (type !== 'buy' || total.lte(maxTotal)) && (type !== 'sell' || amount.lte(maxAmount));
    } catch (e) {
      return false;
    }
  },
  confirmOffer(event) {
    event.preventDefault();

    this.offerError('');
    let sellHowMuch;
    let sellWhichToken;
    let buyHowMuch;
    let buyWhichToken;
    if (this.offerType() === 'buy') {
      sellWhichToken = Session.get('quoteCurrency');
      sellHowMuch = this.offerTotal();
      buyWhichToken = Session.get('baseCurrency');
      buyHowMuch = this.offerAmount();
    } else {
      sellWhichToken = Session.get('baseCurrency');
      sellHowMuch = this.offerAmount();
      buyWhichToken = Session.get('quoteCurrency');
      buyHowMuch = this.offerTotal();
    }
    Offers.newOffer(sellHowMuch, sellWhichToken, buyHowMuch, buyWhichToken, (error) => {
      if (error != null) {
        this.offerError(formatError(error));
      }
      // Cleaning inputs
      $('.row-input-line input[type=number]').val(0);
    });
  },
});

Template.offermodal.events({
  'click button.btn-allowance-modal': (event) => {
    const refer = $(event.target).data('refer');
    const token = $(event.target).data('link');
    $(`#allowanceModal${token}`).data('refer', refer);
    $(`#allowanceModal${token}`).modal('show');
  },
});
<commit_msg>Autofocus on the input when changing allowance<commit_after>import { Session } from 'meteor/session';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { BigNumber } from 'meteor/ethereum:web3';
import { web3Obj } from 'meteor/makerotc:dapple';
import { formatError } from '/imports/utils/functions';

import Tokens from '/imports/api/tokens';
import { Offers, Status } from '/imports/api/offers';

import './offermodal.html';

// TODO: DELETE THIS, TESTING PURPOSE
window.Tokens = Tokens;

Template.offermodal.viewmodel({
  share: 'newOffer',
  volume: '',
  total: '',
  autorun() {
    if (Template.currentData().offer) {
      const buyHowMuch = web3Obj.fromWei(new BigNumber(Template.currentData().offer.buyHowMuch)).toString(10);
      const sellHowMuch = web3Obj.fromWei(new BigNumber(Template.currentData().offer.sellHowMuch)).toString(10);
      const baseCurrency = Session.get('baseCurrency');
      if (baseCurrency === Template.currentData().offer.buyWhichToken) {
        this.volume(buyHowMuch);
        this.total(sellHowMuch);
      } else {
        this.volume(sellHowMuch);
        this.total(buyHowMuch);
      }
    }
  },
  precision() {
    return Dapple.getTokenSpecs(Session.get('baseCurrency')).precision;
  },
  validAmount: true,
  validNewOrderAmount: true,
  type() {
    if (Template.currentData().offer) {
      return Template.currentData().offer.type();
    }
    return '';
  },
  buyCurrency() {
    return this.type() === 'bid' ? Session.get('quoteCurrency') : Session.get('baseCurrency');
  },
  sellCurrency() {
    return this.type() === 'bid' ? Session.get('baseCurrency') : Session.get('quoteCurrency');
  },
  quoteToken() {
    return Tokens.findOne(Session.get('quoteCurrency'));
  },
  baseToken() {
    return Tokens.findOne(Session.get('baseCurrency'));
  },
  hasBalance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const balance = new BigNumber(token.balance);
      return token && balance.gte(web3Obj.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const allowance = new BigNumber(token.allowance);
      return token && allowance.gte(web3Obj.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowanceNewOrder() {
    try {
      const token = Tokens.findOne(this.offerType() === 'buy'
        ? Session.get('quoteCurrency') : Session.get('baseCurrency'));
      const allowance = new BigNumber(token.allowance);

      return token && allowance.gte(web3Obj.toWei(new BigNumber(this.offerType() === 'buy'
                                                                       ? this.offerTotal() : this.offerAmount())));
    } catch (e) {
      return false;
    }
  },
  hasVolume() {
    try {
      const volume = new BigNumber(Template.currentData().offer.volume(this.buyCurrency()));
      return volume.gte(web3Obj.toWei(new BigNumber(this.type() === 'bid' ? this.total() : this.volume())));
    } catch (e) {
      return false;
    }
  },
  maxVolume() {
    let maxVolume = '0';
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(Template.currentData().offer.volume(baseCurrency));
      if (Template.currentData().offer.buyWhichToken === baseCurrency) {
        // Calculate max volume, since we want to sell MKR, we need to check how much MKR we can sell
        const token = Tokens.findOne(baseCurrency);
        if (token) {
          // Can at most sell balance, allowance, and offer's volume
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxVolume = web3Obj.fromWei(BigNumber.min(balance, allowance, volume)).toString(10);
        }
      } else {
        maxVolume = web3Obj.fromWei(volume).toString(10);
      }
    } catch (e) {
      maxVolume = '0';
    }
    return maxVolume;
  },
  maxTotal() {
    let maxTotal = '0';
    try {
      const quoteCurrency = Session.get('quoteCurrency');
      const total = new BigNumber(Template.currentData().offer.volume(quoteCurrency));
      if (Template.currentData().offer.buyWhichToken === quoteCurrency) {
        // Calculate max total, since we want to buy MKR, we need to check how much of the currency is available
        const token = Tokens.findOne(quoteCurrency);
        if (token) {
          // Can at most buy balance, allowance, and offer's total
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxTotal = web3Obj.fromWei(BigNumber.min(balance, allowance, total)).toString(10);
        }
      } else {
        maxTotal = web3Obj.fromWei(total).toString(10);
      }
    } catch (e) {
      maxTotal = '0';
    }
    return maxTotal;
  },
  calcVolume() {
    this.validAmount(true);
    if (this.precision() === 0 && this.total() % 1 !== 0) {
      this.validAmount(false);
      this.volume('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const total = new BigNumber(this.total());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.volume(buyHowMuch.div(sellHowMuch).times(total).toString(10));
      } else {
        this.volume(sellHowMuch.div(buyHowMuch).times(total).toString(10));
      }
    } catch (e) {
      this.volume('0');
    }
  },
  calcTotal() {
    this.validAmount(true);
    if (this.precision() === 0 && this.volume() % 1 !== 0) {
      this.validAmount(false);
      this.total('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(this.volume());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.total(sellHowMuch.div(buyHowMuch).times(volume).toString(10));
      } else {
        this.total(buyHowMuch.div(sellHowMuch).times(volume).toString(10));
      }
    } catch (e) {
      this.total('0');
    }
  },
  calcNewOfferTotal() {
    this.validNewOrderAmount(true);
    if (this.precision() === 0 && this.offerAmount() % 1 !== 0) {
      this.validNewOrderAmount(false);
      this.offerTotal('0');
      return;
    }
    try {
      const price = new BigNumber(this.offerPrice());
      const amount = new BigNumber(this.offerAmount());
      const total = price.times(amount);
      if (total.isNaN()) {
        this.offerTotal('0');
      } else {
        this.offerTotal(total.toString(10));
      }
    } catch (e) {
      this.offerTotal('0');
    }
  },
  calcNewOfferAmount() {
    this.validNewOrderAmount(true);
    if (this.precision() === 0 && this.offerTotal() % 1 !== 0) {
      this.validNewOrderAmount(false);
      this.offerAmount('0');
      return;
    }
    try {
      const price = new BigNumber(this.offerPrice());
      let amount = new BigNumber(this.offerAmount());
      const total = new BigNumber(this.offerTotal());
      if (total.isZero() && price.isZero() && (amount.isNaN() || amount.isNegative())) {
        this.offerAmount('0');
      } else if (!total.isZero() || !price.isZero()) {
        amount = total.div(price);
        if (amount.isNaN()) {
          this.offerAmount('0');
        } else {
          this.offerAmount(amount.toString(10));
        }
      }
    } catch (e) {
      this.offerAmount('0');
    }
  },
  alertBetterOffer() {
    let bestOffer = null;
    if (this.type() === 'bid') {
      bestOffer = Offers.findOne({
          buyWhichToken: Session.get('baseCurrency'),
          sellWhichToken: Session.get('quoteCurrency'),
        },
        {
          sort: { ask_price_sort: 1 },
        });
      return (new BigNumber(bestOffer.bid_price)).gt(new BigNumber(this.templateInstance.data.offer.bid_price));
    } else if (this.type() === 'ask') {
      bestOffer = Offers.findOne({
          buyWhichToken: Session.get('quoteCurrency'),
          sellWhichToken: Session.get('baseCurrency'),
        },
        {
          sort: { ask_price_sort: 1 },
        });
      return (new BigNumber(bestOffer.ask_price)).lt(new BigNumber(this.templateInstance.data.offer.ask_price));
    }
    return false;
  },
  dismiss(event) {
    $(event.target).closest('.modal').modal('hide');
  },
  canBuy() {
    try {
      if (Template.currentData().offer.status !== Status.CONFIRMED) {
        return false;
      }
      const volume = new BigNumber(this.volume());
      const total = new BigNumber(this.total());
      const marketOpen = Session.get('market_open');
      return marketOpen && !total.isNaN() && total.gt(0) && total.lte(new BigNumber(this.maxTotal()))
        && !volume.isNaN() && volume.gt(0) && volume.lte(new BigNumber(this.maxVolume()));
    } catch (e) {
      return false;
    }
  },
  buy() {
    const offerId = this.templateInstance.data.offer._id;
    const offer = Offers.findOne(offerId);

    if (this.templateInstance.data.offer.type() === 'bid') {
      Offers.buyOffer(offerId, 'sell', new BigNumber(this.total()), offer.sellWhichToken);
    } else {
      Offers.buyOffer(offerId, 'buy', new BigNumber(this.volume()), offer.sellWhichToken);
    }
  },
  maxNewOfferAmount() {
    let maxAmount = '0';
    if (this.offerType() === 'sell') {
      const token = Tokens.findOne(Session.get('baseCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxAmount = web3Obj.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxAmount = '9e999';
    }
    return maxAmount;
  },
  maxNewOfferTotal() {
    // Only allow change of total if price is well-defined
    try {
      const price = new BigNumber(this.offerPrice());
      if ((price.isNaN() || price.isZero() || price.isNegative())) {
        return '0';
      }
    } catch (e) {
      return '0';
    }
    // If price is well-defined, take minimum of balance and allowance of currency, if 'buy', otherwise Infinity
    let maxTotal = '0';
    if (this.offerType() === 'buy') {
      const token = Tokens.findOne(Session.get('quoteCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxTotal = web3Obj.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxTotal = '9e999';
    }
    return maxTotal;
  },
  canSubmit() {
    try {
      const type = this.offerType();
      const price = new BigNumber(this.offerPrice());
      const amount = new BigNumber(this.offerAmount());
      const maxAmount = new BigNumber(this.maxNewOfferAmount());
      const total = new BigNumber(this.offerTotal());
      const maxTotal = new BigNumber(this.maxNewOfferTotal());
      const marketOpen = Session.get('market_open');
      const validTokenPair = Session.get('quoteCurrency') !== Session.get('baseCurrency');
      return marketOpen && price.gt(0) && amount.gt(0) && total.gt(0) && validTokenPair &&
        (type !== 'buy' || total.lte(maxTotal)) && (type !== 'sell' || amount.lte(maxAmount));
    } catch (e) {
      return false;
    }
  },
  confirmOffer(event) {
    event.preventDefault();

    this.offerError('');
    let sellHowMuch;
    let sellWhichToken;
    let buyHowMuch;
    let buyWhichToken;
    if (this.offerType() === 'buy') {
      sellWhichToken = Session.get('quoteCurrency');
      sellHowMuch = this.offerTotal();
      buyWhichToken = Session.get('baseCurrency');
      buyHowMuch = this.offerAmount();
    } else {
      sellWhichToken = Session.get('baseCurrency');
      sellHowMuch = this.offerAmount();
      buyWhichToken = Session.get('quoteCurrency');
      buyHowMuch = this.offerTotal();
    }
    Offers.newOffer(sellHowMuch, sellWhichToken, buyHowMuch, buyWhichToken, (error) => {
      if (error != null) {
        this.offerError(formatError(error));
      }
      // Cleaning inputs
      $('.row-input-line input[type=number]').val(0);
    });
  },
});

Template.offermodal.events({
  'click button.btn-allowance-modal': (event) => {
    const refer = $(event.target).data('refer');
    const token = $(event.target).data('link');
    $(`#allowanceModal${token}`).data('refer', refer);
    $(`#allowanceModal${token}`).modal('show');
    $(`#allowanceModal${token}`).on('shown.bs.modal', () => {
      $('.set-allowance input').focus();
    });
  },
});
<|endoftext|>