<commit_before>function draw(){
    if(game_running){
        frames += 1;

        /* if new obstacle should be added this frame, add one */
        if(frames % frames_per_obstacle === 0){
            i = random_number(30) + 40;
            obstacles.splice(
                0,
                0,
                [
                    x + i,
                    random_number(500) - 250,
                    i,
                    random_number(30) + 40
                ]
            );
        }

        /* if obstacle frequency increase should happen this frame, do it */
        if(settings[4] > 0 && frames_per_obstacle > 1 && frames % settings[4] === 0){
            /* obstacle frequency increase */
            frames_per_obstacle -= 1;
        }

        /* if the player has activated jetpack, increase y speed and add smoke */
        if(key_jetpack){
            player_speed += settings[2];/* jetpack power */
            smoke.splice(
                0,
                0,
                [
                    -20,
                    player_y - 10
                ]
            );

        /* else apply gravity */
        }else{
            player_speed -= settings[1];/* gravity */
        }

        player_y += player_speed;
    }

    if(settings[8]){/* clear? */
        buffer.clearRect(
            0,
            0,
            width,
            height
        );
    }

    /* draw corridor over grey background */
    buffer.fillStyle = '#000';
    buffer.fillRect(
        0,
        y - 250,
        width,
        500
    );

    /* draw player body */
    buffer.fillStyle = '#090';
    buffer.fillRect(
        x,
        y - player_y - 25,
        25,
        50
    );

    /* draw jetpack */
    buffer.fillStyle = '#aaa';
    buffer.fillRect(
        x - 25,
        y - player_y - 15,
        25,
        20
    );

    /* draw activated jetpack fire */
    if(game_running && key_jetpack){
        buffer.fillStyle = '#f00';
        buffer.fillRect(
            x - 22,
            y - player_y + 5,
            18,
            10
        );
    }

    /* check if player is outside of game boundaries */
    if(player_y + 25 > 250 || player_y - 25 < -250){
        game_running = 0;
        update_best();
    }

    i = obstacles.length - 1;
    if(i >= 0){
        if(game_running){
            do{
                /* delete obstacles that are past left side of screen */
                if(obstacles[i][0] < -x){
                    obstacles.splice(i, 1);

                }else{
                    /* move obstacles left */
                    obstacles[i][0] -= 10;

                    /* check for player collision with obstacle */
                    if(obstacles[i][0] >= -25 - obstacles[i][2] / 2
                     && obstacles[i][0] <=  25 + obstacles[i][2] / 2
                     && obstacles[i][1] >= -player_y - 25 - obstacles[i][3] / 2
                     && obstacles[i][1] <= -player_y + 25 + obstacles[i][3] / 2){
                        game_running = 0;
                        update_best();
                    }
                }
            }while(i--);

            /* get new amount of obstacles, some may have been spliced */
            i = obstacles.length - 1;
        }

        /* draw obstacles */
        if(i >= 0){
            buffer.fillStyle = '#555';
            do{
                buffer.fillRect(
                    x + obstacles[i][0] - obstacles[i][2] / 2,
                    y + obstacles[i][1] - obstacles[i][3] / 2,
                    obstacles[i][2],
                    obstacles[i][3]
                );
            }while(i--);
        }
    }

    i = smoke.length-1;
    if(i >= 0){
        if(game_running){
            /* delete smoke trails past left side of screen, else move left */
            do{
                if(smoke[i][0] < -x){
                    smoke.splice(i, 1);

                }else if(game_running){
                    smoke[i][0] -= 10;
                }
            }while(i--);

            /* get new amount of smoke, some may have been spliced */
            i = smoke.length - 1;
        }

        /* draw smoke trails behind the player */
        if(i >= 0){
            buffer.fillStyle = '#777';
            do{
                buffer.fillRect(
                    x + smoke[i][0],
                    y - smoke[i][1],
                    10,
                    10
                );
            }while(i--);
        }
    }

    /* setup text display */
    buffer.font = '23pt sans-serif';
    buffer.textAlign = 'center';
    buffer.textBaseline = 'top';
    buffer.fillStyle = '#fff';

    /* if game is over, display game over messages */
    if(!game_running){
        if(!played_explosion_sound){
            if(settings[5] > 0){/* audio volume */
                /* play explode sound */
            }
            played_explosion_sound = 1;
        }

        i = y / 2;
        if(frames > best_display){
            buffer.fillText(
                'NEW BEST SCORE!',
                x,
                i - 60
            );
        }
        buffer.fillText(
            'You crashed... ☹',
            x,
            i
        );
        buffer.fillText(
            settings[7] + ' = Restart',/* restart key */
            x,
            i + 60
        );
        buffer.fillText(
            'ESC = Main Menu',
            x,
            i+120
        );
    }

    /* top left text displays */
    buffer.textAlign = 'left';
    buffer.fillText(
        frames,
        5,
        0
    );
    buffer.fillText(
        best_display,
        5,
        32
    );

    if(settings[8]){/* clear? */
        canvas.clearRect(
            0,
            0,
            width,
            height
        );
    }
    canvas.drawImage(
        get('buffer'),
        0,
        0
    );
}

function get(i){
    return document.getElementById(i);
}

function random_number(i){
    return Math.floor(Math.random() * i);
}

function resize(){
    if(mode > 0){
        width = window.innerWidth;
        get('buffer').width = width;
        get('canvas').width = width;

        height = window.innerHeight;
        get('buffer').height = height;
        get('canvas').height = height;

        x = width / 2;
        y = height / 2;
    }
}

function save(){
    i = 3;
    do{
        if(isNaN(get(['ms-per-frame', 'obstacle-frequency', 'obstacle-increase', 'audio-volume'][i]).value)
              || get(['ms-per-frame', 'obstacle-frequency', 'obstacle-increase', 'audio-volume'][i]).value < [1, 1, 0, 0][i]){
            get('si').value = [
                30,
                23,
                115,
                1
            ][i];
        }
    }while(i--);

    i = 5;
    do{
        j = [
            'ms-per-frame',
            'gravity',
            'jetpack-power',
            'obstacle-frequency',
            'obstacle-increase',
            'audio-volume'
        ][i];

        if(isNaN(get(j).value) || get(j).value === [30, 1, 2, 23, 115, 1][i]){
            ls.removeItem('jetpack-' + i);
            settings[i] = [
                30,
                1,
                2,
                23,
                115,
                1
            ][i];
            get(j).value = settings[i];

        }else{
            settings[i] = parseFloat(get(j).value);
            ls.setItem(
                'jetpack-' + i,
                settings[i]
            );
        }
    }while(i--);

    if(get('jetpack-key').value === 'W'){
        ls.removeItem('jetpack-6');
        settings[6] = 'W';

    }else{
        settings[6] = get('jetpack-key').value;
        ls.setItem(
            'jetpack-6',
            settings[6]
        );
    }

    if(get('restart-key').value === 'H'){
        ls.removeItem('jetpack-7');
        settings[7] = 'H';

    }else{
        settings[7] = get('restart-key').value;
        ls.setItem(
            'jetpack-7',
            settings[7]
        );
    }

    settings[8] = get('clear').checked;
    if(settings[8]){
        ls.removeItem('jetpack-8');

    }else{
        ls.setItem(
            'jetpack-8',
            0
        );
    }
}

function setmode(newmode){
    clearInterval(interval);

    obstacles = [];
    smoke = [];
    best_display = best;
    mode = newmode;

    /* play game mode */
    if(mode > 0){
        save();

        frames = 0;
        frames_per_obstacle = settings[3];/* obstacle frequency */
        game_running = 1;
        played_explosion_sound = 0;
        player_speed = 0;
        player_y = 0;

        get('page').innerHTML='<canvas id=canvas></canvas>';
        buffer = get('buffer').getContext('2d');
        canvas = get('canvas').getContext('2d');

        resize();

        interval = setInterval('draw()', settings[0]);/* ms/frame */

    /* main menu mode */
    }else{
        buffer = 0;
        canvas = 0;

        get('page').innerHTML='

Jetpack

Cave Corridor (Best: '
            + best + ')

Reset Best

<input disabled size=9 style=border:0 type=text value="Mouse Click">Activate Jetpack
<input id=jetpack-key maxlength=1 size=9 type=text value='
            + settings[6] + '>Activate Jetpack
<input disabled size=9 style=border:0 type=text value=ESC>Main Menu
<input id=restart-key maxlength=1 size=9 type=text value='
            + settings[7] + '>Restart

<input id=audio-volume max=1 min=0 step=.01 type=range value='
            + settings[5] + '>Audio
<input '
            + (settings[8] ? 'checked ' : '')+'id=clear type=checkbox>Clear
Reset Settings
Hack

<input id=gravity size=1 type=text value='
            + settings[1] + '>Gravity
<input id=jetpack-power size=1 type=text value='
            + settings[2] + '>Jetpack Power
<input id=ms-per-frame size=1 type=text value='
            + settings[0] + '>ms/Frame
<input id=obstacle-frequency size=1 type=text value='
            + settings[3] + '>Obstacle Frequency
<input id=obstacle-increase size=1 type=text value='
            + settings[4] + '>Obstacle Increase

';
    }
}

function update_best(){
    if(frames > best){
        best = frames;
    }

    if(best > 0){
        ls.setItem(
            'jetpack-best',
            best
        );

    }else{
        ls.removeItem('jetpack-best');
    }
}

var ls = window.localStorage;

var best = ls.getItem('jetpack-best') === null ? 0 : parseInt(ls.getItem('jetpack-best'));
var best_display = 0;
var buffer = 0;
var canvas = 0;
var frames = 0;
var game_running = 0;
var height = 0;
var i = 0;
var interval = 0;
var j = 0;
var key_jetpack = 0;
var mode = 0;
var obstacles = [];
var played_explosion_sound = 0;
var player_speed = 0;
var player_y = 0;
var frames_per_obstacle = 0;
var settings = [
    ls.getItem('jetpack-0') === null ?  30 : parseInt(ls.getItem('jetpack-0')),/* ms/frame */
    ls.getItem('jetpack-1') === null ?   1 : parseFloat(ls.getItem('jetpack-1')),/* gravity */
    ls.getItem('jetpack-2') === null ?   2 : parseFloat(ls.getItem('jetpack-2')),/* jetpack power */
    ls.getItem('jetpack-3') === null ?  23 : parseInt(ls.getItem('jetpack-3')),/* obstacle frequency */
    ls.getItem('jetpack-4') === null ? 115 : parseInt(ls.getItem('jetpack-4')),/* obstacle increase */
    ls.getItem('jetpack-5') === null ?   1 : parseFloat(ls.getItem('jetpack-5')),/* audio volume */
    ls.getItem('jetpack-6') === null ? 'W' : ls.getItem('jetpack-6'),/* activate jetpack key */
    ls.getItem('jetpack-7') === null ? 'H' : ls.getItem('jetpack-7'),/* restart key */
    ls.getItem('jetpack-8') === null/* clear? */
];
var smoke = [];
var width = 0;
var x = 0;
var y = 0;

setmode(0);

window.onkeydown = function(e){
    if(mode > 0){
        i = window.event ? event : e;
        i = i.charCode ? i.charCode : i.keyCode;

        if(String.fromCharCode(i) === settings[6]){/* activate jetpack key */
            key_jetpack = 1;

        }else if(String.fromCharCode(i) === settings[7]){/* restart key */
            update_best();

            best_display = best;
            frames = 0;
            frames_per_obstacle = settings[3];/* obstacle frequency */
            game_running = 1;
            obstacles = [];
            played_explosion_sound = 0;
            player_speed = 0;
            player_y = 0;
            smoke = [];

        }else if(i === 27){/* ESC */
            update_best();
            setmode(0);
        }
    }
};

window.onkeyup = function(e){
    i = window.event ? event : e;
    i = i.charCode ? i.charCode : i.keyCode;

    if(String.fromCharCode(i) === settings[6]){/* activate jetpack key */
        key_jetpack = 0;
    }
};

window.onmousedown = function(e){
    if(mode > 0){
        e.preventDefault();
        key_jetpack = 1;
    }
};

window.onmouseup = function(e){
    key_jetpack = 0;
};

window.onresize = resize;
<commit_msg>improved formatting<commit_after>function draw(){
    if(game_running){
        frames += 1;

        // if new obstacle should be added this frame, add one
        if(frames % frames_per_obstacle === 0){
            i = random_number(30) + 40;
            obstacles.splice(
                0,
                0,
                [
                    x + i,
                    random_number(500) - 250,
                    i,
                    random_number(30) + 40
                ]
            );
        }

        // if obstacle frequency increase should happen this frame, do it
        if(settings[4] > 0 && frames_per_obstacle > 1 && frames % settings[4] === 0){
            // obstacle frequency increase
            frames_per_obstacle -= 1;
        }

        // if the player has activated jetpack, increase y speed and add smoke
        if(key_jetpack){
            player_speed += settings[2];// jetpack power
            smoke.splice(
                0,
                0,
                [
                    -20,
                    player_y - 10
                ]
            );

        // else apply gravity
        }else{
            player_speed -= settings[1];// gravity
        }

        player_y += player_speed;
    }

    if(settings[8]){// clear?
        buffer.clearRect(
            0,
            0,
            width,
            height
        );
    }

    // draw corridor over grey background
    buffer.fillStyle = '#000';
    buffer.fillRect(
        0,
        y - 250,
        width,
        500
    );

    // draw player body
    buffer.fillStyle = '#090';
    buffer.fillRect(
        x,
        y - player_y - 25,
        25,
        50
    );

    // draw jetpack
    buffer.fillStyle = '#aaa';
    buffer.fillRect(
        x - 25,
        y - player_y - 15,
        25,
        20
    );

    // draw activated jetpack fire
    if(game_running && key_jetpack){
        buffer.fillStyle = '#f00';
        buffer.fillRect(
            x - 22,
            y - player_y + 5,
            18,
            10
        );
    }

    // check if player is outside of game boundaries
    if(player_y + 25 > 250 || player_y - 25 < -250){
        game_running = 0;
        update_best();
    }

    i = obstacles.length - 1;
    if(i >= 0){
        if(game_running){
            do{
                // delete obstacles that are past left side of screen
                if(obstacles[i][0] < -x){
                    obstacles.splice(i, 1);

                }else{
                    // move obstacles left
                    obstacles[i][0] -= 10;

                    // check for player collision with obstacle
                    if(obstacles[i][0] >= -25 - obstacles[i][2] / 2
                     && obstacles[i][0] <=  25 + obstacles[i][2] / 2
                     && obstacles[i][1] >= -player_y - 25 - obstacles[i][3] / 2
                     && obstacles[i][1] <= -player_y + 25 + obstacles[i][3] / 2){
                        game_running = 0;
                        update_best();
                    }
                }
            }while(i--);

            // get new amount of obstacles, some may have been spliced
            i = obstacles.length - 1;
        }

        // draw obstacles
        if(i >= 0){
            buffer.fillStyle = '#555';
            do{
                buffer.fillRect(
                    x + obstacles[i][0] - obstacles[i][2] / 2,
                    y + obstacles[i][1] - obstacles[i][3] / 2,
                    obstacles[i][2],
                    obstacles[i][3]
                );
            }while(i--);
        }
    }

    i = smoke.length-1;
    if(i >= 0){
        if(game_running){
            // delete smoke trails past left side of screen, else move left
            do{
                if(smoke[i][0] < -x){
                    smoke.splice(i, 1);

                }else if(game_running){
                    smoke[i][0] -= 10;
                }
            }while(i--);

            // get new amount of smoke, some may have been spliced
            i = smoke.length - 1;
        }

        // draw smoke trails behind the player
        if(i >= 0){
            buffer.fillStyle = '#777';
            do{
                buffer.fillRect(
                    x + smoke[i][0],
                    y - smoke[i][1],
                    10,
                    10
                );
            }while(i--);
        }
    }

    // setup text display
    buffer.font = '23pt sans-serif';
    buffer.textAlign = 'center';
    buffer.textBaseline = 'top';
    buffer.fillStyle = '#fff';

    // if game is over, display game over messages
    if(!game_running){
        if(!played_explosion_sound){
            if(settings[5] > 0){// audio volume
                // play explode sound
            }
            played_explosion_sound = 1;
        }

        i = y / 2;
        if(frames > best_display){
            buffer.fillText(
                'NEW BEST SCORE!',
                x,
                i - 60
            );
        }
        buffer.fillText(
            'You crashed... ☹',
            x,
            i
        );
        buffer.fillText(
            settings[7] + ' = Restart',// restart key
            x,
            i + 60
        );
        buffer.fillText(
            'ESC = Main Menu',
            x,
            i+120
        );
    }

    // top left text displays
    buffer.textAlign = 'left';
    buffer.fillText(
        frames,
        5,
        0
    );
    buffer.fillText(
        best_display,
        5,
        32
    );

    if(settings[8]){// clear?
        canvas.clearRect(
            0,
            0,
            width,
            height
        );
    }
    canvas.drawImage(
        get('buffer'),
        0,
        0
    );
}

function get(i){
    return document.getElementById(i);
}

function random_number(i){
    return Math.floor(Math.random() * i);
}

function resize(){
    if(mode > 0){
        width = window.innerWidth;
        get('buffer').width = width;
        get('canvas').width = width;

        height = window.innerHeight;
        get('buffer').height = height;
        get('canvas').height = height;

        x = width / 2;
        y = height / 2;
    }
}

function save(){
    i = 3;
    do{
        if(isNaN(get(['ms-per-frame', 'obstacle-frequency', 'obstacle-increase', 'audio-volume'][i]).value)
              || get(['ms-per-frame', 'obstacle-frequency', 'obstacle-increase', 'audio-volume'][i]).value < [1, 1, 0, 0][i]){
            get('si').value = [
                30,
                23,
                115,
                1
            ][i];
        }
    }while(i--);

    i = 5;
    do{
        j = [
            'ms-per-frame',
            'gravity',
            'jetpack-power',
            'obstacle-frequency',
            'obstacle-increase',
            'audio-volume'
        ][i];

        if(isNaN(get(j).value) || get(j).value === [30, 1, 2, 23, 115, 1][i]){
            ls.removeItem('jetpack-' + i);
            settings[i] = [
                30,
                1,
                2,
                23,
                115,
                1
            ][i];
            get(j).value = settings[i];

        }else{
            settings[i] = parseFloat(get(j).value);
            ls.setItem(
                'jetpack-' + i,
                settings[i]
            );
        }
    }while(i--);

    if(get('jetpack-key').value === 'W'){
        ls.removeItem('jetpack-6');
        settings[6] = 'W';

    }else{
        settings[6] = get('jetpack-key').value;
        ls.setItem(
            'jetpack-6',
            settings[6]
        );
    }

    if(get('restart-key').value === 'H'){
        ls.removeItem('jetpack-7');
        settings[7] = 'H';

    }else{
        settings[7] = get('restart-key').value;
        ls.setItem(
            'jetpack-7',
            settings[7]
        );
    }

    settings[8] = get('clear').checked;
    if(settings[8]){
        ls.removeItem('jetpack-8');

    }else{
        ls.setItem(
            'jetpack-8',
            0
        );
    }
}

function setmode(newmode){
    clearInterval(interval);

    obstacles = [];
    smoke = [];
    best_display = best;
    mode = newmode;

    // play game mode
    if(mode > 0){
        save();

        frames = 0;
        frames_per_obstacle = settings[3];// obstacle frequency
        game_running = 1;
        played_explosion_sound = 0;
        player_speed = 0;
        player_y = 0;

        get('page').innerHTML='<canvas id=canvas></canvas>';
        buffer = get('buffer').getContext('2d');
        canvas = get('canvas').getContext('2d');

        resize();

        interval = setInterval('draw()', settings[0]);// ms/frame

    // main menu mode
    }else{
        buffer = 0;
        canvas = 0;

        get('page').innerHTML='

Jetpack

Cave Corridor (Best: '
            + best + ')

Reset Best

<input disabled size=9 style=border:0 value="Mouse Click">Activate Jetpack
<input id=jetpack-key maxlength=1 size=9 value='
            + settings[6] + '>Activate Jetpack
<input disabled size=9 style=border:0 value=ESC>Main Menu
<input id=restart-key maxlength=1 size=9 value='
            + settings[7] + '>Restart

<input id=audio-volume max=1 min=0 step=.01 type=range value='
            + settings[5] + '>Audio
<input '
            + (settings[8] ? 'checked ' : '')+'id=clear type=checkbox>Clear
Reset Settings
Hack

<input id=gravity size=1 value='
            + settings[1] + '>Gravity
<input id=jetpack-power size=1 value='
            + settings[2] + '>Jetpack Power
<input id=ms-per-frame size=1 value='
            + settings[0] + '>ms/Frame
<input id=obstacle-frequency size=1 value='
            + settings[3] + '>Obstacle Frequency
<input id=obstacle-increase size=1 value='
            + settings[4] + '>Obstacle Increase

';
    }
}

function update_best(){
    if(frames > best){
        best = frames;
    }

    if(best > 0){
        ls.setItem(
            'jetpack-best',
            best
        );

    }else{
        ls.removeItem('jetpack-best');
    }
}

var ls = window.localStorage;

var best = ls.getItem('jetpack-best') === null ? 0 : parseInt(ls.getItem('jetpack-best'));
var best_display = 0;
var buffer = 0;
var canvas = 0;
var frames = 0;
var game_running = 0;
var height = 0;
var i = 0;
var interval = 0;
var j = 0;
var key_jetpack = 0;
var mode = 0;
var obstacles = [];
var played_explosion_sound = 0;
var player_speed = 0;
var player_y = 0;
var frames_per_obstacle = 0;
var settings = [
    ls.getItem('jetpack-0') === null ?  30 : parseInt(ls.getItem('jetpack-0')),// ms/frame
    ls.getItem('jetpack-1') === null ?   1 : parseFloat(ls.getItem('jetpack-1')),// gravity
    ls.getItem('jetpack-2') === null ?   2 : parseFloat(ls.getItem('jetpack-2')),// jetpack power
    ls.getItem('jetpack-3') === null ?  23 : parseInt(ls.getItem('jetpack-3')),// obstacle frequency
    ls.getItem('jetpack-4') === null ? 115 : parseInt(ls.getItem('jetpack-4')),// obstacle increase
    ls.getItem('jetpack-5') === null ?   1 : parseFloat(ls.getItem('jetpack-5')),// audio volume
    ls.getItem('jetpack-6') === null ? 'W' : ls.getItem('jetpack-6'),// activate jetpack key
    ls.getItem('jetpack-7') === null ? 'H' : ls.getItem('jetpack-7'),// restart key
    ls.getItem('jetpack-8') === null// clear?
];
var smoke = [];
var width = 0;
var x = 0;
var y = 0;

setmode(0);

window.onkeydown = function(e){
    if(mode > 0){
        i = window.event ? event : e;
        i = i.charCode ? i.charCode : i.keyCode;

        if(String.fromCharCode(i) === settings[6]){// activate jetpack key
            key_jetpack = 1;

        }else if(String.fromCharCode(i) === settings[7]){// restart key
            update_best();

            best_display = best;
            frames = 0;
            frames_per_obstacle = settings[3];// obstacle frequency
            game_running = 1;
            obstacles = [];
            played_explosion_sound = 0;
            player_speed = 0;
            player_y = 0;
            smoke = [];

        }else if(i === 27){// ESC
            update_best();
            setmode(0);
        }
    }
};

window.onkeyup = function(e){
    i = window.event ? event : e;
    i = i.charCode ? i.charCode : i.keyCode;

    if(String.fromCharCode(i) === settings[6]){// activate jetpack key
        key_jetpack = 0;
    }
};

window.onmousedown = function(e){
    if(mode > 0){
        e.preventDefault();
        key_jetpack = 1;
    }
};

window.onmouseup = function(e){
    key_jetpack = 0;
};

window.onresize = resize;
<|endoftext|>


<commit_before>(function(global) {
  // lock in the angular package version; do not let it float to current!
  var ngVer = '@2.0.0-rc.4';

  //map tells the System loader where to look for things
  var  map = {
    'app':                        'app',

    '@angular':                   'https://npmcdn.com/@angular', // sufficient if we didn't pin the version
    'rxjs':                       'https://npmcdn.com/rxjs@5.0.0-beta.6',
    'ts':                         'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
    'typescript':                 'https://npmcdn.com/typescript@1.8.10/lib/typescript.js',
    'ng2-recaptcha':              'https://npmcdn.com/ng2-recaptcha', // always fetch the latest npm version
 };

  //packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.ts',  defaultExtension: 'ts' },
    'ng2-recaptcha':              { main: 'ng2-recaptcha.ts', defaultExtension: 'ts' },
  };

  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'platform-browser',
    'platform-browser-dynamic',
  ];

  // Add map entries for each angular package
  // only because we're pinning the version with `ngVer`.
  ngPackageNames.forEach(function(pkgName) {
    map['@angular/'+pkgName] = 'https://npmcdn.com/@angular/' + pkgName + ngVer;
  });

  // Add package entries for angular packages
  ngPackageNames.forEach(function(pkgName) {
    packages['@angular/'+pkgName] = { main: 'bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  });

  var config = {
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    typescriptOptions: {
      "target": "es5",
      "module": "system",
      "moduleResolution": "node",
      "sourceMap": false,
      "declaration": true,
      "removeComments": false,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "noImplicitAny": true,
      "listFiles": false,
      "noLib": false
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    map: map,
    packages: packages
  }

  System.config(config);

})(this);
<commit_msg>Fixed a file reference in sample pages<commit_after>(function(global) {
  // lock in the angular package version; do not let it float to current!
  var ngVer = '@2.0.0-rc.4';

  //map tells the System loader where to look for things
  var  map = {
    'app':                        'app',

    '@angular':                   'https://npmcdn.com/@angular', // sufficient if we didn't pin the version
    'rxjs':                       'https://npmcdn.com/rxjs@5.0.0-beta.6',
    'ts':                         'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
    'typescript':                 'https://npmcdn.com/typescript@1.8.10/lib/typescript.js',
    'ng2-recaptcha':              'https://npmcdn.com/ng2-recaptcha', // always fetch the latest npm version
 };

  //packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.ts',  defaultExtension: 'ts' },
    'ng2-recaptcha':              { main: 'ng2-recaptcha.js', defaultExtension: 'js' },
  };

  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'platform-browser',
    'platform-browser-dynamic',
  ];

  // Add map entries for each angular package
  // only because we're pinning the version with `ngVer`.
  ngPackageNames.forEach(function(pkgName) {
    map['@angular/'+pkgName] = 'https://npmcdn.com/@angular/' + pkgName + ngVer;
  });

  // Add package entries for angular packages
  ngPackageNames.forEach(function(pkgName) {
    packages['@angular/'+pkgName] = { main: 'bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  });

  var config = {
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    typescriptOptions: {
      "target": "es5",
      "module": "system",
      "moduleResolution": "node",
      "sourceMap": false,
      "declaration": true,
      "removeComments": false,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "noImplicitAny": true,
      "listFiles": false,
      "noLib": false
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    map: map,
    packages: packages
  }

  System.config(config);

})(this);
<|endoftext|>


<commit_before>(function (Modules) {
  "use strict";

  Modules.DeselectTaxonClick = function () {
    var helper = window.GOVUK.taxonomyTreeHelper;
    this.start = function (container) {
      var deselectTaxonClick = function () {
        var taxon_name = $(container).closest('.taxon-breadcrumb').find('li:last').text() ;
        $("input[data-taxon-name=\"" + taxon_name + "\"]").each(function(idx, el){
          $(el).prop('checked', false);
          if (!helper.hasCheckedSiblings(el)){
            helper.uncheckAncestors(el);
          }
        });
        $('.topic-tree').trigger('change');
        return false;
      };

      container.on("click", deselectTaxonClick);
    };
  };

})(window.GOVUKAdmin.Modules);
<commit_msg>Rename helper to taxonomyTreeHelper<commit_after>(function (Modules) {
  "use strict";

  Modules.DeselectTaxonClick = function () {
    var taxonomyTreeHelper = window.GOVUK.taxonomyTreeHelper;
    this.start = function (container) {
      var deselectTaxonClick = function () {
        var taxon_name = $(container).closest('.taxon-breadcrumb').find('li:last').text() ;
        $("input[data-taxon-name=\"" + taxon_name + "\"]").each(function(idx, el){
          $(el).prop('checked', false);
          if (!taxonomyTreeHelper.hasCheckedSiblings(el)){
            taxonomyTreeHelper.uncheckAncestors(el);
          }
        });
        $('.topic-tree').trigger('change');
        return false;
      };

      container.on("click", deselectTaxonClick);
    };
  };

})(window.GOVUKAdmin.Modules);
<|endoftext|>


<commit_before>App.addChild('DashboardUserSettings', {
  el: '#dashboard-user_settings-tab',

  events:{
    "change .account_type": "changeType",
    "change .project_account_attributes_agency": "padZeros"
  },

  activate: function() {
    var mode = ($(this.el).data('mode') === 'flex' ? 'flexible_' : '');
    this.$inscription = this.$("."+mode+"project_account_state_inscription");
    this.changeType();
  },

  padZeros: function(field) {
    field = this.$('.project_account_attributes_agency');
    field.val(("0000" + field.val()).substr(-4,4));

    return true;
  },

  changeType: function () {
    var mode = ($(this.el).data('mode') === 'flex' ? 'flexible_' : '');
    var type = $( ".account_type option:selected" ).text();
    var label_text;

    if (type == 'Pessoa Física') {
      label_text = this.$("#"+mode+"project_account_attributes_owner_name").data('natural');
      document_label_text = this.$("#"+mode+"project_account_attributes_owner_document").data('natural');
      this.$inscription.hide();
      this.$(".user-document").prop('maxlength', 11);
      this.$(".user-document").fixedMask('999.999.999-99');
    }
    else if (type == 'Pessoa Jurídica') {
      label_text = this.$("#"+mode+"project_account_attributes_owner_name").data('juridical');
      document_label_text = this.$("#"+mode+"project_account_attributes_owner_document").data('juridical');
      this.$inscription.show();
      this.$(".user-document").prop('maxlength', 14);
      this.$(".user-document").fixedMask('99.999.999/9999-99');
    }

    this.$("."+mode+"project_account_owner_name > label:first-child").html(label_text);
    this.$("."+mode+"project_account_owner_document > label:first-child").html(document_label_text);
  }

});

App.addChild('DashboardUserSettingsForm', _.extend({
  el: '#project_account_form',

  events: {
    'blur input' : 'checkInput',
    'click input[type="submit"]' : 'validate',
    "keydown #project_account_attributes_account": "allowOnlyNumbers"
  },

  activate: function(){
    this.setupForm();
  },

  allowOnlyNumbers: function (e) {
    // Allow: backspace, delete, tab, escape and enter
    if ($.inArray(e.keyCode, [ 8, 9, 27, 13, 110]) !== -1 ||
       // Allow: Ctrl+A
      (e.keyCode == 65 && e.ctrlKey === true) ||
       // Allow: Ctrl+C
      (e.keyCode == 67 && e.ctrlKey === true) ||
       // Allow: Ctrl+X
      (e.keyCode == 88 && e.ctrlKey === true) ||
       // Allow: home, end, left, right
      (e.keyCode >= 35 && e.keyCode <= 39)) {
           // let it happen, don't do anything
           return;
    }
    // Ensure that it is a number and stop the keypress
    if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
      e.preventDefault();
    }
  }

}, Skull.Form));
<commit_msg>Fixes on document mask<commit_after>App.addChild('DashboardUserSettings', {
  el: '#dashboard-user_settings-tab',

  events:{
    "change .account_type": "changeType",
    "change .project_account_attributes_agency": "padZeros"
  },

  activate: function() {
    var mode = ($(this.el).data('mode') === 'flex' ? 'flexible_' : '');
    this.$inscription = this.$("."+mode+"project_account_state_inscription");
    this.changeType();
  },

  padZeros: function(field) {
    field = this.$('.project_account_attributes_agency');
    field.val(("0000" + field.val()).substr(-4,4));

    return true;
  },

  changeType: function () {
    var mode = ($(this.el).data('mode') === 'flex' ? 'flexible_' : '');
    var type = $( ".account_type option:selected" ).text();
    var label_text;

    this.$(".user-document").fixedMask('off');
    if (type == 'Pessoa Física') {
      label_text = this.$("#"+mode+"project_account_attributes_owner_name").data('natural');
      document_label_text = this.$("#"+mode+"project_account_attributes_owner_document").data('natural');
      this.$inscription.hide();
      this.$(".user-document").prop('maxlength', 14);
      this.$(".user-document").fixedMask('999.999.999-99');
    }
    else if (type == 'Pessoa Jurídica') {
      label_text = this.$("#"+mode+"project_account_attributes_owner_name").data('juridical');
      document_label_text = this.$("#"+mode+"project_account_attributes_owner_document").data('juridical');
      this.$inscription.show();
      this.$(".user-document").prop('maxlength', 18);
      this.$(".user-document").fixedMask('99.999.999/9999-99');
    }

    this.$("."+mode+"project_account_owner_name > label:first-child").html(label_text);
    this.$("."+mode+"project_account_owner_document > label:first-child").html(document_label_text);
  }

});

App.addChild('DashboardUserSettingsForm', _.extend({
  el: '#project_account_form',

  events: {
    'blur input' : 'checkInput',
    'click input[type="submit"]' : 'validate',
    "keydown #project_account_attributes_account": "allowOnlyNumbers"
  },

  activate: function(){
    this.setupForm();
  },

  allowOnlyNumbers: function (e) {
    // Allow: backspace, delete, tab, escape and enter
    if ($.inArray(e.keyCode, [ 8, 9, 27, 13, 110]) !== -1 ||
       // Allow: Ctrl+A
      (e.keyCode == 65 && e.ctrlKey === true) ||
       // Allow: Ctrl+C
      (e.keyCode == 67 && e.ctrlKey === true) ||
       // Allow: Ctrl+X
      (e.keyCode == 88 && e.ctrlKey === true) ||
       // Allow: home, end, left, right
      (e.keyCode >= 35 && e.keyCode <= 39)) {
           // let it happen, don't do anything
           return;
    }
    // Ensure that it is a number and stop the keypress
    if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
      e.preventDefault();
    }
  }

}, Skull.Form));
<|endoftext|>


<commit_before>var React = require('react');
var classNames = require('classnames');

var Icon = require('./Icon');
var Container = require('./Container');
var STYLES = require('./STYLES');

var Alert = React.createClass({
    propTypes: {
        onClose:  React.PropTypes.func,
        closable: React.PropTypes.bool,
        style:    React.PropTypes.oneOf(STYLES)
    },

    getInitialState: function() {
        return {
            opened: true
        };
    },

    getDefaultProps: function() {
        return {
            style: STYLES[0]
        };
    },

    onClose: function(e) {
        e.preventDefault();
        var onClose = this.props.onClose;

        this.setState({
            opened: false
        }, function() {
            if (onClose) onClose();
        });
    },

    render: function() {
        var style     = this.props.style;
        var className = classNames('alert', 'alert-' + style, this.props.className);
        var onClose   = this.props.onClose;
        var closable  = this.props.closable;
        var style     = this.props.style;
        var inner;

        if (!this.state.opened) {
            return
;
        }

        if (onClose || closable) {
            inner = <Icon id="x" />;
        }

        return (

                <Container>
                {inner}
                {this.props.children}
                </Container>

        );
    }
});

/**
 * Create a style of alert
 * @param {String} style
 * @return {React.Component}
 */
function createAlertStyle(style) {
    return React.createClass({
        displayName: Alert.displayName + style,
        render: function() {
            return <Alert {...this.props} style={style.toLowerCase()} />;
        }
    });
}

module.exports         = Alert;
module.exports.Info    = createAlertStyle('Info');
module.exports.Danger  = createAlertStyle('Danger');
module.exports.Success = createAlertStyle('Success');
module.exports.Warning = createAlertStyle('Warning');

<commit_msg>Fix option "style"<commit_after>var React = require('react');
var classNames = require('classnames');

var Icon = require('./Icon');
var Container = require('./Container');
var STYLES = require('./STYLES');

var Alert = React.createClass({
    propTypes: {
        onClose:  React.PropTypes.func,
        closable: React.PropTypes.bool,
        style:    React.PropTypes.oneOf(STYLES)
    },

    getInitialState: function() {
        return {
            opened: true
        };
    },

    getDefaultProps: function() {
        return {
            style: STYLES[0]
        };
    },

    onClose: function(e) {
        e.preventDefault();
        var onClose = this.props.onClose;

        this.setState({
            opened: false
        }, function() {
            if (onClose) onClose();
        });
    },

    render: function() {
        var style     = this.props.style;
        var className = classNames('alert', 'alert-' + style, this.props.className);
        var onClose   = this.props.onClose;
        var closable  = this.props.closable;
        var inner;

        if (!this.state.opened) {
            return
;
        }

        if (onClose || closable) {
            inner = <Icon id="x" />;
        }

        return (

                <Container>
                {inner}
                {this.props.children}
                </Container>

        );
    }
});

/**
 * Create a style of alert
 * @param {String} style
 * @return {React.Component}
 */
function createAlertStyle(style) {
    return React.createClass({
        displayName: Alert.displayName + style,
        render: function() {
            return <Alert {...this.props} style={style.toLowerCase()} />;
        }
    });
}

module.exports         = Alert;
module.exports.Info    = createAlertStyle('Info');
module.exports.Danger  = createAlertStyle('Danger');
module.exports.Success = createAlertStyle('Success');
module.exports.Warning = createAlertStyle('Warning');

<|endoftext|>


<commit_before>$(document).ready(function() {
  submitForm();
  clickToEdit();
});

function submitForm() {
  $("#new_element").on("submit", function(event) {
    event.preventDefault();
    var folioId = $("#id").val();
    console.log(folioId);
    var data = $(this).serialize();
    console.log(this);
    elm_id = "#" + id;
    console.log(elm_id);
    console.log($(elm_id).hasClass("editing"));
    if ($(elm_id).hasClass("editing")) {
      console.log("true");
      update(id);
    } else {
      post(id, data);
    }
    // ^this code doesn't work yet.  Why?
  });
}

function post(id, data) {

  $.ajax({
    dataType: "json",
    method: "POST",
    url: "/folios/" + id + "/elements",
    data: data
  }).done(function(responseData) {
    var element = new Element(responseData);
    var elementView = new ElementView();
    var html = elementView.compile(element);
    elementView.render(html);
    folioView.toggleSidebar();
  });
}
<commit_msg>Update submit js<commit_after>$(document).ready(function() {
  submitForm();
  clickToEdit();
});

function submitForm() {
  $("#new_element").on("submit", function(event) {
    event.preventDefault();
    var folioId = $("#id").val();

    var data = $(this).serialize();

    // elm_id = "#" + ;

    // if ($(elm_id).hasClass("editing")) {
    //   console.log("true");
    //   update(id);
    // } else {
     post(folioId, data);
    // }
    // ^this code doesn't work yet.  Why?
  });
}

function post(folioId, data) {

  $.ajax({
    dataType: "json",
    method: "POST",
    url: "/folios/" + folioId + "/elements",
    data: data
  }).done(function(responseData) {
    var element = new Element(responseData);
    var elementView = new ElementView();
    var html = elementView.compile(element);
    elementView.render(html);
    folioView.toggleSidebar();
  });
}
<|endoftext|>


<commit_before>

var BroDB = (function(){
    "use strict";
    var expose = ExposeClient();
    var db = {};

    var changeListeners = {};

    function notifyListeners(key) {
        if (changeListeners[key]){
            changeListeners.forEach(function(cb){
               cb(key);
            })
        }
    }

    expose.exports.brodb_create = function(key, value) {
        db[key] = db[key] || value;
        notifyListeners(key);
    }

    expose.exports.brodb_clear = function(key) {
        db[key] = [];
        notifyListeners(key);
    }

    expose.exports.brodb_popfront = function(key) {
        db[key].shift();
        notifyListeners(key);
    }

    expose.exports.brodb_pushfront = function(key, value) {
        db[key].unshift(value);
        notifyListeners(key);
    }

    expose.exports.brodb_pop = function(key) {
        db[key].pop();
        notifyListeners(key);
    }

    expose.exports.brodb_push = function(key, value) {
        db[key].push(value);
        notifyListeners(key);
    }

    expose.exports.brodb_put = function(key, idx, value) {
        db[key][idx] = value;
        notifyListeners(key);
    }

    var retval = function(key) {

        return {
            get: function(idx){
                return db[key][idx || 0];
            },
            getAll: function(){
              return db[key];
            },
            put: function(value, idx){
                expose.withServerApi(function(api){
                    api.brodb_put(key, idx || 0, value);
                });
                db[key][idx || 0] = value;
            },
            push: function(value){
                expose.withServerApi(function(api){
                    api.brodb_push(key, value);
                });
                db[key].push(value);
            },
            pop: function(){
                expose.withServerApi(function(api){
                    api.brodb_pop(key);
                });
                return db[key].pop();
            },
            pushFront: function(value){
                expose.withServerApi(function(api){
                    api.brodb_pushFront(key, value);
                });
                db[key].unshift(value);
            },
            popFront: function(){
                expose.withServerApi(function(api){
                    api.brodb_popFront(key);
                });
                return db[key].shift();
            },
            clear: function(){
                expose.withServerApi(function(api){
                    api.brodb_clear(key);
                });
                db[key] = [];
            },
            onChange: function(cb){
                changeListeners[key] = changeListeners[key] || [];
                changeListeners[key].push(cb);
            }
        }
    }

    retval.subscribe = function(keys, sync, cb){
        keys.forEach(function(key){
           db[key] = db[key] || [];
        });
        expose.withServerApi(function(api){
            api.brodb_subscribe(keys, sync).onSuccess(function(serverDB){
                if (sync) {
                    keys.forEach(function(key){
                       db[key] = serverDB[key];
                    });
                    if (cb) cb();
                }
            });
        });
    };

    retval.keys = function(){
        var res = [];
        for (var k in db) {
            res.push(k);
        }
        return res;
    }

    expose.start();

    return retval;

})();

<commit_msg>fixing typo in example<commit_after>

var BroDB = (function(){
    "use strict";
    var expose = ExposeClient();
    var db = {};

    var changeListeners = {};

    function notifyListeners(key) {
        if (changeListeners[key]){
            changeListeners.forEach(function(cb){
               cb(key);
            })
        }
    }

    expose.exports.brodb_create = function(key, value) {
        db[key] = db[key] || value;
        notifyListeners(key);
    }

    expose.exports.brodb_clear = function(key) {
        db[key] = [];
        notifyListeners(key);
    }

    expose.exports.brodb_popFront = function(key) {
        db[key].shift();
        notifyListeners(key);
    }

    expose.exports.brodb_pushFront = function(key, value) {
        db[key].unshift(value);
        notifyListeners(key);
    }

    expose.exports.brodb_pop = function(key) {
        db[key].pop();
        notifyListeners(key);
    }

    expose.exports.brodb_push = function(key, value) {
        db[key].push(value);
        notifyListeners(key);
    }

    expose.exports.brodb_put = function(key, idx, value) {
        db[key][idx] = value;
        notifyListeners(key);
    }

    var retval = function(key) {

        return {
            get: function(idx){
                return db[key][idx || 0];
            },
            getAll: function(){
              return db[key];
            },
            put: function(value, idx){
                expose.withServerApi(function(api){
                    api.brodb_put(key, idx || 0, value);
                });
                db[key][idx || 0] = value;
            },
            push: function(value){
                expose.withServerApi(function(api){
                    api.brodb_push(key, value);
                });
                db[key].push(value);
            },
            pop: function(){
                expose.withServerApi(function(api){
                    api.brodb_pop(key);
                });
                return db[key].pop();
            },
            pushFront: function(value){
                expose.withServerApi(function(api){
                    api.brodb_pushFront(key, value);
                });
                db[key].unshift(value);
            },
            popFront: function(){
                expose.withServerApi(function(api){
                    api.brodb_popFront(key);
                });
                return db[key].shift();
            },
            clear: function(){
                expose.withServerApi(function(api){
                    api.brodb_clear(key);
                });
                db[key] = [];
            },
            onChange: function(cb){
                changeListeners[key] = changeListeners[key] || [];
                changeListeners[key].push(cb);
            }
        }
    }

    retval.subscribe = function(keys, sync, cb){
        keys.forEach(function(key){
           db[key] = db[key] || [];
        });
        expose.withServerApi(function(api){
            api.brodb_subscribe(keys, sync).onSuccess(function(serverDB){
                if (sync) {
                    keys.forEach(function(key){
                       db[key] = serverDB[key];
                    });
                    if (cb) cb();
                }
            });
        });
    };

    retval.keys = function(){
        var res = [];
        for (var k in db) {
            res.push(k);
        }
        return res;
    }

    expose.start();

    return retval;

})();

<|endoftext|>


<commit_before>import SpotSet from './SpotSet';

const BLACK = -1;
const EMPTY = 0;
const WHITE = 1;

class Board {
  constructor(size) {
    this.size = size;
    this.board = [];
    this.toMove = BLACK;

    // Hashes of every position there has been (after the first one)
    this.hashes = new Set();

    for (var i = 0; i < size; i++) {
      let row = [];
      for (var j = 0; j < size; j++) {
        row.push(EMPTY);
      }
      this.board.push(row);
    }
  }

  log() {
    for (var row of this.board) {
      console.log(row);
    }
  }

  // Returns a list of stuff adjacent to i, j
  adjacent(i, j) {
    let answer = [];
    if (i > 0) {
      answer.push([i - 1, j]);
    }
    if (j > 0) {
      answer.push([i, j - 1]);
    }
    if (i + 1 < this.size) {
      answer.push([i + i, j]);
    }
    if (j + 1 < this.size) {
      answer.push([i, j + 1]);
    }
    return answer;
  }

  // Returns a spotset of liberties for the group with the stone at i, j.
  liberties(i, j) {
    if (this.board[i][j] === EMPTY) {
      return -1;
    }
    let seen = new SpotSet();
    let libs = new SpotSet();
    let frontier = [[i, j]];
    while (frontier.length > 0) {
      let [x1, y1] = frontier.pop();
      if (seen.has(x1, y1)) {
        continue;
      }
      let adj = this.adjacent(x1, y1);
      for (let [x2, y2] of adj) {
        // TODO
      }
    }
    // TODO
  }

  // Returns whether the move was valid.
  makeMove(i, j) {
    let initialBoard = JSON.stringify(this.board);

    if (!this.isValidSpot(i, j)) {
      throw new Error(`invalid move because of invalid spot: ${i}, ${j}`);
    }
    if (this.board[i][j] !== EMPTY) {
      return false;
    }

    let color = this.toMove;
    this.toMove = -this.toMove;
    this.board[i][j] = color;

    // Check for captures
    let captures = false;
    for (let [a, b] of this.neighbors(i, j)) {
      if (this.board[a][b] === -color) {
        let {spots, alive} = this.findGroup(a, b);
        if (!alive) {
          captures = true;
          for (let [c, d] of spots) {
            this.board[c][d] = EMPTY;
          }
        }
      }
    }

    // Prevent suicide
    if (!captures) {
      let {alive} = this.findGroup(i, j);
      if (!alive) {
        this.board[i][j] = EMPTY;
        return false;
      }
    }

    // Check for ko
    let h = this.hash();
    if (this.hashes.has(h)) {
      // Reset the board state
      this.toMove = -this.toMove;
      this.board = JSON.parse(initialBoard);

      throw new Error('ko');
    }
    this.hashes.add(h);

    return true;
  }

  // Returns a value for the overall board
  // Based on the Java hash function
  hash() {
    let answer = 0;
    for (let i = 0; i < this.size; i++) {
      for (let j = 0; j < this.size; j++) {
        answer = ((answer << 5) - answer) + this.board[i][j];
        answer |= 0; // convert to 32 bit int
      }
    }
    return answer;
  }

  // Returns whether [i, j] is a valid spot on the board.
  isValidSpot(i, j) {
    return (i >= 0 &&
            i < this.size &&
            j >= 0 &&
            j < this.size);
  }

  // Returns a list of [i, j] pairs for all valid neighbors to the
  // provided spot.
  neighbors(i, j) {
    let answer = [];
    for (let [a, b] of [[i + 1, j],
                        [i - 1, j],
                        [i, j + 1],
                        [i, j - 1]]) {
      if (this.isValidSpot(a, b)) {
        answer.push([a, b]);
      }
    }
    return answer;
  }

  // Finds the group of stones that contains the current spot.
  // A group has two parameters:
  //   spots: a list of the [i, j] spots involved
  //   alive: a boolean
  findGroup(i, j) {
    let color = this.board[i][j];
    if (color === EMPTY) {
      throw new Error('no group for empty color');
    }

    // Contains strings of the form "i,j"
    let seen = new Set();
    let spots = [];
    let alive = false;
    let pending = [[i, j]];
    while (pending.length > 0) {
      let [a, b] = pending.pop();
      let key = a + "," + b;
      if (seen.has(key)) {
        continue;
      }
      seen.add(key);
      spots.push([a, b]);

      for (let [c, d] of this.neighbors(a, b)) {
        let neighborColor = this.board[c][d];
        if (neighborColor === EMPTY) {
          alive = true;
        } else if (neighborColor === color) {
          pending.push([c, d]);
        }
      }
    }

    return {spots, alive};
  }
}

Board.BLACK = BLACK;
Board.WHITE = WHITE;
Board.EMPTY = EMPTY;

export default Board;
<commit_msg>libs fn<commit_after>import SpotSet from './SpotSet';

const BLACK = -1;
const EMPTY = 0;
const WHITE = 1;

class Board {
  constructor(size) {
    this.size = size;
    this.board = [];
    this.toMove = BLACK;

    // Hashes of every position there has been (after the first one)
    this.hashes = new Set();

    for (var i = 0; i < size; i++) {
      let row = [];
      for (var j = 0; j < size; j++) {
        row.push(EMPTY);
      }
      this.board.push(row);
    }
  }

  log() {
    for (var row of this.board) {
      console.log(row);
    }
  }

  // Returns a list of stuff adjacent to i, j
  adjacent(i, j) {
    let answer = [];
    if (i > 0) {
      answer.push([i - 1, j]);
    }
    if (j > 0) {
      answer.push([i, j - 1]);
    }
    if (i + 1 < this.size) {
      answer.push([i + i, j]);
    }
    if (j + 1 < this.size) {
      answer.push([i, j + 1]);
    }
    return answer;
  }

  // Returns a spotset of liberties for the group with the stone at i, j.
  // TODO: test
  liberties(i, j) {
    if (this.board[i][j] === EMPTY) {
      return -1;
    }
    let seen = new SpotSet();
    let libs = new SpotSet();
    let frontier = [[i, j]];
    while (frontier.length > 0) {
      let [x1, y1] = frontier.pop();
      if (seen.has(x1, y1)) {
        continue;
      }
      seen.add(x1, y1);
      let adj = this.adjacent(x1, y1);
      for (let [x2, y2] of adj) {
        if (this.board[x2][y2] === EMPTY) {
          libs.add(x2, y2);
        }
        if (this.board[x2][y2] === this.board[i][j]) {
          frontier.push([x2, y2])
        }
      }
    }
    return libs;
  }

  // Returns whether the move was valid.
  makeMove(i, j) {
    let initialBoard = JSON.stringify(this.board);

    if (!this.isValidSpot(i, j)) {
      throw new Error(`invalid move because of invalid spot: ${i}, ${j}`);
    }
    if (this.board[i][j] !== EMPTY) {
      return false;
    }

    let color = this.toMove;
    this.toMove = -this.toMove;
    this.board[i][j] = color;

    // Check for captures
    let captures = false;
    for (let [a, b] of this.neighbors(i, j)) {
      if (this.board[a][b] === -color) {
        let {spots, alive} = this.findGroup(a, b);
        if (!alive) {
          captures = true;
          for (let [c, d] of spots) {
            this.board[c][d] = EMPTY;
          }
        }
      }
    }

    // Prevent suicide
    if (!captures) {
      let {alive} = this.findGroup(i, j);
      if (!alive) {
        this.board[i][j] = EMPTY;
        return false;
      }
    }

    // Check for ko
    let h = this.hash();
    if (this.hashes.has(h)) {
      // Reset the board state
      this.toMove = -this.toMove;
      this.board = JSON.parse(initialBoard);

      throw new Error('ko');
    }
    this.hashes.add(h);

    return true;
  }

  // Returns a value for the overall board
  // Based on the Java hash function
  hash() {
    let answer = 0;
    for (let i = 0; i < this.size; i++) {
      for (let j = 0; j < this.size; j++) {
        answer = ((answer << 5) - answer) + this.board[i][j];
        answer |= 0; // convert to 32 bit int
      }
    }
    return answer;
  }

  // Returns whether [i, j] is a valid spot on the board.
  isValidSpot(i, j) {
    return (i >= 0 &&
            i < this.size &&
            j >= 0 &&
            j < this.size);
  }

  // Returns a list of [i, j] pairs for all valid neighbors to the
  // provided spot.
  neighbors(i, j) {
    let answer = [];
    for (let [a, b] of [[i + 1, j],
                        [i - 1, j],
                        [i, j + 1],
                        [i, j - 1]]) {
      if (this.isValidSpot(a, b)) {
        answer.push([a, b]);
      }
    }
    return answer;
  }

  // Finds the group of stones that contains the current spot.
  // A group has two parameters:
  //   spots: a list of the [i, j] spots involved
  //   alive: a boolean
  findGroup(i, j) {
    let color = this.board[i][j];
    if (color === EMPTY) {
      throw new Error('no group for empty color');
    }

    // Contains strings of the form "i,j"
    let seen = new Set();
    let spots = [];
    let alive = false;
    let pending = [[i, j]];
    while (pending.length > 0) {
      let [a, b] = pending.pop();
      let key = a + "," + b;
      if (seen.has(key)) {
        continue;
      }
      seen.add(key);
      spots.push([a, b]);

      for (let [c, d] of this.neighbors(a, b)) {
        let neighborColor = this.board[c][d];
        if (neighborColor === EMPTY) {
          alive = true;
        } else if (neighborColor === color) {
          pending.push([c, d]);
        }
      }
    }

    return {spots, alive};
  }
}

Board.BLACK = BLACK;
Board.WHITE = WHITE;
Board.EMPTY = EMPTY;

export default Board;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Limerun Project Contributors
 * Portions Copyright (c) 2015 Internet of Protocols Assocation (IOPA)
 *
 * 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.
 */

var Promise = require('bluebird');
var LRU = require('lru-cache');
var iopaStream = require('iopa-common-stream');

// GLOBALS

/**
 * LRU exposed as context["server.Capabilities"]["iopaCache.Support"]["iopaCache.cache"].lru
 *
 * LRU cache for responses to avoid DDOS etc.
 * max packet size is 1280
 * 32 MB / 1280 = 26214
 * The max lifetime is roughly 200s per packet.
 * Which equates to ~131 packets/second
 *
 * @private
 */
var _db = LRU({
    max: (32768 * 1024),
    length: function(n) {
        return n.length
    },
    dispose: function(key, value) {
        for (var prop in value) {
            if (value.hasOwnProperty(prop)) {
                delete value[prop];
            }
        };
    }
});

function cacheKeyId(context) {

    var result = "cache://";
       result += context["server.RemoteAddress"];
       result += ":"+ context["server.RemotePort"];
                //  result += "/" + (context["server.IsRequest"]) ? 'request' : 'response' ;
      result += "/&id=" + context["iopa.MessageId"] ;

      return result;
}

function cacheKeyToken(context) {

    var result = "cache://";
       result += context["server.RemoteAddress"];
       result += ":"+ context["server.RemotePort"];
                //  result += "/" + (context["server.IsRequest"]) ? 'request' : 'response' ;
      result += "/&token=" + context["iopa.Token"] ;

      return result;
}

/**
 * IOPA Middleware for Cache of Outgoing Messages on Servers/Clients
 *
 * @class Cache
 * @constructor
 * @public
 */
function Cache(app) {
      if (!app.properties["server.Capabilities"]["cache.Version"])
        throw ("Missing Dependency:  cache Server/Middleware in Pipeline");

    this._db = app.properties["server.Capabilities"]["cache.Support"]["cache.db"]();
}

/**
 * @method invoke
 * @param context IOPA context dictionary
 * @param next   IOPA application delegate for the remainder of the pipeline
 */
Cache.prototype.invoke = function Cache_invoke(context, next) {

  if (context["server.IsLocalOrigin"])
     // client
      context["server.RawStream"] = new iopaStream.OutgoingStreamTransform(this._write.bind(this, context, context["server.RawStream"]));
  else
    // server
     context.response["server.RawStream"] = new iopaStream.OutgoingStreamTransform(this._write.bind(this, context.response, context.response["server.RawStream"]));

  return next();

};

/**
 * @method _write
 * @this context IOPA context dictionary
 * @param nextStream  Raw Stream to send transformed data to
 * @param chunk     String | Buffer The data to write
 * @param encoding String The encoding, if chunk is a String
 * @param callback Function Callback for when this chunk of data is flushed
 * @private
*/
Cache.prototype._write = function Cache_write(context, nextStream, chunk, encoding, callback) {

     if (!context["cache.DoNotCache"])
     {
            var cacheData = {
                "server.InProcess": context["server.InProcess"],
                "server.IsLocalOrigin": context["server.IsLocalOrigin"],
                "iopa.CallCancelledSource": context["iopa.CallCancelledSource"],
                "iopa.Events": context["iopa.Events"],
                "server.RawStream": context["server.RawStream"],
                "iopa.Seq": context["iopa.Seq"],
                  "iopa.MessageId": context["iopa.MessageId"]
                };

            var key = cacheKeyId(context);
            this._db.set(key, cacheData);
              console.log(key);

            if (context["iopa.Token"])
            {
               key = cacheKeyToken(context);
               this._db.set(key, cacheData);
               console.log(key);
            }
     } else
     console.log("DO NOT CACHE " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"]);

   //  context["cache.DoNotCache"] = true;
     context["iopa.Events"].on('close', this._closeContext.bind(this, context));
     nextStream.write(chunk, encoding, callback);
};

/**
 * @method _closeContext
 * @this context IOPA context dictionary
 * @private
*/
Cache.prototype._closeContext = function Cache_close(context, key) {
       this._db.del(key);
};

module.exports.Cache = Cache;

/* *********************************************************
 * IOPA MIDDLEWARE: CACHE MIDDLEWARE SERVER EXTENSIONS
 * ********************************************************* */

/**
 * IOPA Middleware for Cache Matching on Incoming Responses
 *
 * @class CacheMatch
 * @constructor
 * @public
 */
function CacheMatch(app) {

    app.properties["server.Capabilities"]["cache.Version"] = "1.0";
    app.properties["server.Capabilities"]["cache.Support"] = {
        "cache.db": this.db
    };
}

CacheMatch.prototype.db = function() {
    return _db;
};

/**
 * @method invoke
 * @this channelContext IOPA context dictionary
 * @param next   IOPA application delegate for the remainder of the pipeline
 */
CacheMatch.prototype.invoke = function CacheMatch_invoke(channelContext, next) {
    channelContext["iopa.Events"].on("response", this._client_invokeOnParentResponse.bind(this, channelContext));
    return next();
};

/**
 * @method _client_invokeOnParentResponse
 * @this CacheMatch
 * @param channelContext IOPA parent context dictionary
 * @param context IOPA childResponse context dictionary
 * @param next   IOPA application delegate for the remainder of the pipeline
 */
CacheMatch.prototype._client_invokeOnParentResponse = function CacheMatch_client_invokeOnParentResponse(channelContext, context) {
    // SERVER REQUESTS ONLY;  IGNORE CLIENT RESPONSES
    //  if (!context["server.IsRequest"])
    //    return next();

    //CHECK CACHE
    var key = cacheKeyId(context);

    var cachedOriginal = _db.peek(key);

    if (context["iopa.Token"])
    {
        if (!cachedOriginal) {
            if (context["iopa.Token"])
            {
            key = cacheKeyToken(context);
            cachedOriginal = _db.peek(key);
            }
        } else {
            if (context["iopa.Token"] && cachedOriginal["iopa.Token"] &&
             (context["iopa.Token"] !== cachedOriginal["iopa.Token"]))
             {
                cachedOriginal = undefined;
                context.log.info("[IOPA_MATCH] TOKENS DONT MATCH " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"]);
             }
        }
    }

    if (cachedOriginal) {
              if (cachedOriginal["server.InProcess"]) {
             // TRANSFER ONTO EVENTS PIPELINE
              context.log.info("[IOPA_MATCH] MATCHED " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"] + " to " + cachedOriginal["iopa.MessageId"] +":" + cachedOriginal["iopa.Seq"] );

              cachedOriginal["iopa.Events"].emit("response", context);
        } else
         {
           context.log.info("[IOPA_MATCH] TOO LATE FOR PIPELINE " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"]);

             // silently ignore  TODO: Transfer to a different pipeline
         }
    } else
         {
                context.log.info("[IOPA_MATCH] UNKNOWN RESPONSE REFERENCE " + cacheKeyId(context) + "    " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"]);

             // silently ignore    TODO: Transfer to a different pipeline
         }
};

module.exports.Match = CacheMatch;
<commit_msg>logging<commit_after>/*
 * Copyright (c) 2015 Limerun Project Contributors
 * Portions Copyright (c) 2015 Internet of Protocols Assocation (IOPA)
 *
 * 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.
 */

var Promise = require('bluebird');
var LRU = require('lru-cache');
var iopaStream = require('iopa-common-stream');

// GLOBALS

/**
 * LRU exposed as context["server.Capabilities"]["iopaCache.Support"]["iopaCache.cache"].lru
 *
 * LRU cache for responses to avoid DDOS etc.
 * max packet size is 1280
 * 32 MB / 1280 = 26214
 * The max lifetime is roughly 200s per packet.
 * Which equates to ~131 packets/second
 *
 * @private
 */
var _db = LRU({
    max: (32768 * 1024),
    length: function(n) {
        return n.length
    },
    dispose: function(key, value) {
        for (var prop in value) {
            if (value.hasOwnProperty(prop)) {
                delete value[prop];
            }
        };
    }
});

function cacheKeyId(context) {

    var result = "cache://";
       result += context["server.RemoteAddress"];
       result += ":"+ context["server.RemotePort"];
                //  result += "/" + (context["server.IsRequest"]) ? 'request' : 'response' ;
      result += "/&id=" + context["iopa.MessageId"] ;

      return result;
}

function cacheKeyToken(context) {

    var result = "cache://";
       result += context["server.RemoteAddress"];
       result += ":"+ context["server.RemotePort"];
                //  result += "/" + (context["server.IsRequest"]) ? 'request' : 'response' ;
      result += "/&token=" + context["iopa.Token"] ;

      return result;
}

/**
 * IOPA Middleware for Cache of Outgoing Messages on Servers/Clients
 *
 * @class Cache
 * @constructor
 * @public
 */
function Cache(app) {
      if (!app.properties["server.Capabilities"]["cache.Version"])
        throw ("Missing Dependency:  cache Server/Middleware in Pipeline");

    this._db = app.properties["server.Capabilities"]["cache.Support"]["cache.db"]();
}

/**
 * @method invoke
 * @param context IOPA context dictionary
 * @param next   IOPA application delegate for the remainder of the pipeline
 */
Cache.prototype.invoke = function Cache_invoke(context, next) {

  if (context["server.IsLocalOrigin"])
     // client
      context["server.RawStream"] = new iopaStream.OutgoingStreamTransform(this._write.bind(this, context, context["server.RawStream"]));
  else
    // server
     context.response["server.RawStream"] = new iopaStream.OutgoingStreamTransform(this._write.bind(this, context.response, context.response["server.RawStream"]));

  return next();

};

/**
 * @method _write
 * @this context IOPA context dictionary
 * @param nextStream  Raw Stream to send transformed data to
 * @param chunk     String | Buffer The data to write
 * @param encoding String The encoding, if chunk is a String
 * @param callback Function Callback for when this chunk of data is flushed
 * @private
*/
Cache.prototype._write = function Cache_write(context, nextStream, chunk, encoding, callback) {

     if (!context["cache.DoNotCache"])
     {
            var cacheData = {
                "server.InProcess": context["server.InProcess"],
                "server.IsLocalOrigin": context["server.IsLocalOrigin"],
                "iopa.CallCancelledSource": context["iopa.CallCancelledSource"],
                "iopa.Events": context["iopa.Events"],
                "server.RawStream": context["server.RawStream"],
                "iopa.Seq": context["iopa.Seq"],
                  "iopa.MessageId": context["iopa.MessageId"]
                };

            var key = cacheKeyId(context);
            this._db.set(key, cacheData);
              console.log(key);

            if (context["iopa.Token"])
            {
               key = cacheKeyToken(context);
               this._db.set(key, cacheData);
               console.log(key);
            }
     } else
     console.log("DO NOT CACHE " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"]);

   //  context["cache.DoNotCache"] = true;
     context["iopa.Events"].on('close', this._closeContext.bind(this, context));
     nextStream.write(chunk, encoding, callback);
};

/**
 * @method _closeContext
 * @this context IOPA context dictionary
 * @private
*/
Cache.prototype._closeContext = function Cache_close(context, key) {
       this._db.del(key);
};

module.exports.Cache = Cache;

/* *********************************************************
 * IOPA MIDDLEWARE: CACHE MIDDLEWARE SERVER EXTENSIONS
 * ********************************************************* */

/**
 * IOPA Middleware for Cache Matching on Incoming Responses
 *
 * @class CacheMatch
 * @constructor
 * @public
 */
function CacheMatch(app) {

    app.properties["server.Capabilities"]["cache.Version"] = "1.0";
    app.properties["server.Capabilities"]["cache.Support"] = {
        "cache.db": this.db
    };
}

CacheMatch.prototype.db = function() {
    return _db;
};

/**
 * @method invoke
 * @this channelContext IOPA context dictionary
 * @param next   IOPA application delegate for the remainder of the pipeline
 */
CacheMatch.prototype.invoke = function CacheMatch_invoke(channelContext, next) {
    channelContext["iopa.Events"].on("response", this._client_invokeOnParentResponse.bind(this, channelContext));
    return next();
};

/**
 * @method _client_invokeOnParentResponse
 * @this CacheMatch
 * @param channelContext IOPA parent context dictionary
 * @param context IOPA childResponse context dictionary
 * @param next   IOPA application delegate for the remainder of the pipeline
 */
CacheMatch.prototype._client_invokeOnParentResponse = function CacheMatch_client_invokeOnParentResponse(channelContext, context) {
    // SERVER REQUESTS ONLY;  IGNORE CLIENT RESPONSES
    //  if (!context["server.IsRequest"])
    //    return next();

    //CHECK CACHE
    var key = cacheKeyId(context);

    var cachedOriginal = _db.peek(key);

    if (context["iopa.Token"])
    {
        if (!cachedOriginal) {
            if (context["iopa.Token"])
            {
            key = cacheKeyToken(context);
            cachedOriginal = _db.peek(key);
            }
        } else {
            if (context["iopa.Token"] && cachedOriginal["iopa.Token"] &&
             (context["iopa.Token"] !== cachedOriginal["iopa.Token"]))
             {
                cachedOriginal = undefined;
              }
        }
    }

    if (cachedOriginal) {
              if (cachedOriginal["server.InProcess"]) {
             // TRANSFER ONTO EVENTS PIPELINE
              cachedOriginal["iopa.Events"].emit("response", context);
        } else
         {
           context.log.info("[IOPA_MATCH] TOO LATE FOR PIPELINE " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"]);
               // silently ignore  TODO: Transfer to a different pipeline
         }
    } else
         {
                context.log.info("[IOPA_MATCH] UNKNOWN RESPONSE REFERENCE " + cacheKeyId(context) + "    " + context["iopa.Method"] +" "+ context["iopa.MessageId"] +":" + context["iopa.Seq"]);
               // silently ignore    TODO: Transfer to a different pipeline
         }
};

module.exports.Match = CacheMatch;
<|endoftext|>