<commit_before>CLAZZ("projects.sprite.filters.Perlin", {
    seed: 0,
    contrast: 1,
    iterations: 0,

    meta:{
        seed:{int:{min:0, max:0xFFFFFFFF}},
        contrast:{int:{min:0, max:20}},
        iterations:{dynamic:true}
    },

    activate:function( layer ){
        this.iterations = Math.floor(Math.log2( layer.data.width ));
        return true;
    },

    kernel:function(d){
        var x = this.thread.x%this.constants.stride;
        var y = Math.floor(this.thread.x/this.constants.stride);
        var channel = x % 4;
        x = Math.floor(x/4);

        function prand(x, y, t){
            var max = 22381,
                a   = 2665425599,
                b   = 849233383,
                c   = 726169489,
                d   = 3300550843,
                p   = Math.pow(2, t-1),
                x1, x2, y1, y2, r1, r2, r3, r4, fx, fy;

            x = x / p;
            y = y / p;

            x1 = Math.floor( x );
            fx = 1 - (x - x1);
            x2 = x1 + 1;

            y1 = Math.floor( y );
            fy = 1 - (y - y1);
            y2 = y1 + 1;

            t = t + this.constants.seed;

            r1 = ( ( Math.abs( Math.sin( x1*a + y1*b ) * d ) + Math.abs(Math.sin(t*c)*d) ) % max) / max;
            r2 = ( ( Math.abs( Math.sin( x2*a + y1*b ) * d ) + Math.abs(Math.sin(t*c)*d) ) % max) / max;
            r3 = ( ( Math.abs( Math.sin( x1*a + y2*b ) * d ) + Math.abs(Math.sin(t*c)*d) ) % max) / max;
            r4 = ( ( Math.abs( Math.sin( x2*a + y2*b ) * d ) + Math.abs(Math.sin(t*c)*d) ) % max) / max;

            return (r1*fx+r2*(1-fx)) * fy + (r3*fx+r4*(1-fx)) * (1-fy);
        }

        var ret = 1;
        if( channel != 3 ){
            ret = 0;
            for( var i=0; i<this.constants.iterations; i++ )
                ret += prand(x, y, i+1) / Math.pow(2, this.constants.iterations - i);
        }

        if( ret > 1 ) ret = 1;
        if( ret < 0.5 ) ret = Math.pow( ret * 2, this.constants.contrast ) / 2;
        else if( ret > 0.5 ) ret = 1 - Math.pow( (1-ret) * 2, this.constants.contrast ) / 2;

        return ret*255;
    }

});
<commit_msg>adjust perlin random function so it'd work on other PCs.<commit_after>CLAZZ("projects.sprite.filters.Perlin", {
    seed: 0,
    contrast: 1,
    iterations: 0,

    meta:{
        seed:{int:{min:0, max:0xFFFFFFFF}},
        contrast:{int:{min:0, max:20}},
        iterations:{dynamic:true}
    },

    activate:function( layer ){
        this.iterations = Math.floor(Math.log2( layer.data.width ));
        return true;
    },

    kernel:function(d){
        var x = this.thread.x%this.constants.stride;
        var y = Math.floor(this.thread.x/this.constants.stride);
        var channel = x % 4;
        x = Math.floor(x/4);

        function prand(x, y, t){
            var max = 22381,
                a   = 2665425599,
                b   = 849233383,
                c   = 726169489,
                d   = 3300550843,
                p   = Math.pow(2, t-1),
                x1, x2, y1, y2, r1, r2, r3, r4, fx, fy;

            x = x / p;
            y = y / p;
            a /= c;
            b /= c;

            x1 = Math.floor( x );
            fx = 1 - (x - x1);
            x2 = x1 + 1;

            y1 = Math.floor( y );
            fy = 1 - (y - y1);
            y2 = y1 + 1;

            t = t + this.constants.seed;

            r1 = ( ( Math.abs( Math.sin( x1*a + y1*b ) ) + Math.abs(Math.sin(t*c)) ) * d % max) / max;
            r2 = ( ( Math.abs( Math.sin( x2*a + y1*b ) ) + Math.abs(Math.sin(t*c)) ) * d % max) / max;
            r3 = ( ( Math.abs( Math.sin( x1*a + y2*b ) ) + Math.abs(Math.sin(t*c)) ) * d % max) / max;
            r4 = ( ( Math.abs( Math.sin( x2*a + y2*b ) ) + Math.abs(Math.sin(t*c)) ) * d % max) / max;

            return (r1*fx+r2*(1-fx)) * fy + (r3*fx+r4*(1-fx)) * (1-fy);
        }

        var ret = 1;
        if( channel != 3 ){
            ret = 0;
            for( var i=0; i<this.constants.iterations; i++ )
                ret += prand(x, y, i+1) / Math.pow(2, this.constants.iterations - i);
                // ret = ( ( Math.abs( Math.sin( (x*2665425599 + y*849233383) / 726169489 ) ) + Math.abs(Math.sin(1*726169489)) ) * 3300550843 % 22381) / 22381;
        }

        if( ret > 1 ) ret = 1;
        if( ret < 0.5 ) ret = Math.pow( ret * 2, this.constants.contrast ) / 2;
        else if( ret > 0.5 ) ret = 1 - Math.pow( (1-ret) * 2, this.constants.contrast ) / 2;

        return ret*255;
    }

});
<|endoftext|>


<commit_before>const fs = require('fs-extra');
const path = require('path');
const execa = require('execa');
const Listr = require('listr');
const semver = require('semver');
const chalk = require('chalk');

const rootDir = path.join(__dirname, '../');

const packages = [
  'core',
  'angular'
];

function readPkg(project) {
  const packageJsonPath = packagePath(project);
  return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
}

function writePkg(project, pkg) {
  const packageJsonPath = packagePath(project);
  const text = JSON.stringify(pkg, null, 2);
  return fs.writeFileSync(packageJsonPath, text);
}

function packagePath(project) {
  return path.join(rootDir, project, 'package.json');
}

function projectPath(project) {
  return path.join(rootDir, project);
}

function checkGit(tasks) {
  tasks.push(
    {
      title: 'Check current branch',
      task: () => execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']).then(branch => {
        if (branch !== 'master') {
          throw new Error(`Not on "master" branch`);
        }
      })
    },
    {
      title: 'Check local working tree',
      task: () => execa.stdout('git', ['status', '--porcelain']).then(status => {
        if (status !== '') {
          throw new Error(`Unclean working tree. Commit or stash changes first.`);
        }
      })
    },
    {
      title: 'Check remote history',
      task: () => execa.stdout('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD']).then(result => {
        if (result !== '0') {
          throw new Error(`Remote history differs. Please pull changes.`);
        }
      })
    }
  );
}

const isValidVersion = input => Boolean(semver.valid(input));

function preparePackage(tasks, package, version) {
  const projectRoot = projectPath(package);
  const pkg = readPkg(package);

  const projectTasks = [];
  if (version) {
    projectTasks.push({
      title: `${pkg.name}: validate new version`,
      task: () => {
        if (!isVersionGreater(pkg.version, version)) {
          throw new Error(`New version \`${version}\` should be higher than current version \`${pkg.version}\``);
        }
      }
    });
  }

  projectTasks.push({
    title: `${pkg.name}: install npm dependencies`,
    task: async () => {
      await fs.remove(path.join(projectRoot, 'node_modules'))
      await execa('npm', ['ci'], { cwd: projectRoot });
    }
  });

  if (package !== 'core') {
    projectTasks.push({
      title: `${pkg.name}: npm link @ionic/core`,
      task: () => execa('npm', ['link', '@ionic/core'], { cwd: projectRoot })
    });
    if (version) {
      projectTasks.push({
        title: `${pkg.name}: update ionic/core dep to ${version}`,
        task: () => {
          updateDependency(pkg, "@ionic/core", version);
          writePkg(package, pkg);
        }
      });
    }
  }

  if (version) {
    projectTasks.push({
      title: `${pkg.name}: lint`,
      task: () => execa('npm', ['run', 'lint'], { cwd: projectRoot })
    });
  }

  projectTasks.push({
    title: `${pkg.name}: build`,
    task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
  });

  if (version) {
    projectTasks.push({
      title: `${pkg.name}: test`,
      task: () => execa('npm', ['test'], { cwd: projectRoot })
    });
  }

  if (package === 'core') {
    projectTasks.push({
      title: `${pkg.name}: npm link`,
      task: () => execa('npm', ['link'], { cwd: projectRoot })
    });
  }

  // Add project tasks
  tasks.push({
    title: `Prepare ${chalk.bold(pkg.name)}`,
    task: () => new Listr(projectTasks)
  });
}

function updateDependency(pkg, dependency, version) {
  if (pkg.dependencies && pkg.dependencies[dependency]) {
    pkg.dependencies[dependency] = version;
  }
  if (pkg.devDependencies && pkg.devDependencies[dependency]) {
    pkg.devDependencies[dependency] = version;
  }
}

function isVersionGreater(oldVersion, newVersion) {
  if (!isValidVersion(newVersion)) {
    throw new Error('Version should be a valid semver version.');
  }

  return semver.gt(newVersion, oldVersion);
}

module.exports = {
  isValidVersion,
  isVersionGreater,
  readPkg,
  writePkg,
  rootDir,
  projectPath,
  checkGit,
  packages,
  preparePackage
};
<commit_msg>chore(build): use install instead of ci for release<commit_after>const fs = require('fs-extra');
const path = require('path');
const execa = require('execa');
const Listr = require('listr');
const semver = require('semver');
const chalk = require('chalk');

const rootDir = path.join(__dirname, '../');

const packages = [
  'core',
  'angular'
];

function readPkg(project) {
  const packageJsonPath = packagePath(project);
  return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
}

function writePkg(project, pkg) {
  const packageJsonPath = packagePath(project);
  const text = JSON.stringify(pkg, null, 2);
  return fs.writeFileSync(packageJsonPath, text);
}

function packagePath(project) {
  return path.join(rootDir, project, 'package.json');
}

function projectPath(project) {
  return path.join(rootDir, project);
}

function checkGit(tasks) {
  tasks.push(
    {
      title: 'Check current branch',
      task: () => execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']).then(branch => {
        if (branch !== 'master') {
          throw new Error(`Not on "master" branch`);
        }
      })
    },
    {
      title: 'Check local working tree',
      task: () => execa.stdout('git', ['status', '--porcelain']).then(status => {
        if (status !== '') {
          throw new Error(`Unclean working tree. Commit or stash changes first.`);
        }
      })
    },
    {
      title: 'Check remote history',
      task: () => execa.stdout('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD']).then(result => {
        if (result !== '0') {
          throw new Error(`Remote history differs. Please pull changes.`);
        }
      })
    }
  );
}

const isValidVersion = input => Boolean(semver.valid(input));

function preparePackage(tasks, package, version) {
  const projectRoot = projectPath(package);
  const pkg = readPkg(package);

  const projectTasks = [];
  if (version) {
    projectTasks.push({
      title: `${pkg.name}: validate new version`,
      task: () => {
        if (!isVersionGreater(pkg.version, version)) {
          throw new Error(`New version \`${version}\` should be higher than current version \`${pkg.version}\``);
        }
      }
    });
  }

  projectTasks.push({
    title: `${pkg.name}: install npm dependencies`,
    task: async () => {
      await fs.remove(path.join(projectRoot, 'node_modules'))
      await execa('npm', ['i'], { cwd: projectRoot });
    }
  });

  if (package !== 'core') {
    projectTasks.push({
      title: `${pkg.name}: npm link @ionic/core`,
      task: () => execa('npm', ['link', '@ionic/core'], { cwd: projectRoot })
    });
    if (version) {
      projectTasks.push({
        title: `${pkg.name}: update ionic/core dep to ${version}`,
        task: () => {
          updateDependency(pkg, "@ionic/core", version);
          writePkg(package, pkg);
        }
      });
    }
  }

  if (version) {
    projectTasks.push({
      title: `${pkg.name}: lint`,
      task: () => execa('npm', ['run', 'lint'], { cwd: projectRoot })
    });
  }

  projectTasks.push({
    title: `${pkg.name}: build`,
    task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
  });

  if (version) {
    projectTasks.push({
      title: `${pkg.name}: test`,
      task: () => execa('npm', ['test'], { cwd: projectRoot })
    });
  }

  if (package === 'core') {
    projectTasks.push({
      title: `${pkg.name}: npm link`,
      task: () => execa('npm', ['link'], { cwd: projectRoot })
    });
  }

  // Add project tasks
  tasks.push({
    title: `Prepare ${chalk.bold(pkg.name)}`,
    task: () => new Listr(projectTasks)
  });
}

function updateDependency(pkg, dependency, version) {
  if (pkg.dependencies && pkg.dependencies[dependency]) {
    pkg.dependencies[dependency] = version;
  }
  if (pkg.devDependencies && pkg.devDependencies[dependency]) {
    pkg.devDependencies[dependency] = version;
  }
}

function isVersionGreater(oldVersion, newVersion) {
  if (!isValidVersion(newVersion)) {
    throw new Error('Version should be a valid semver version.');
  }

  return semver.gt(newVersion, oldVersion);
}

module.exports = {
  isValidVersion,
  isVersionGreater,
  readPkg,
  writePkg,
  rootDir,
  projectPath,
  checkGit,
  packages,
  preparePackage
};
<|endoftext|>


<commit_before>import {Board} from '../board.js';
import {Bombs} from '../bombs.js';
import {Events} from '../app/events.js';
import {Utilities} from '../app/utilities.js';
import {Timer} from '../timer.js';

let timeSpan = document.getElementById('timer');
let timer = new Timer();
let time;

function newGame(numberOfBombs, numberOfRows, numberOfColumns) {
    //create board
    timer.stopTimer();
    clearInterval(time);
    let events = new Events(); // created for events
    let $board = $('#table');
    $('.dropdown-menu').hide()
    $board.empty();

    if (!$('#high-score-input').hasClass('hidden')) {
        events.switchElementsVisibility('#high-score-input', "#high-scores-btn");
    }
    $('#display').on('click', ZoomIn);
    $('#zoomOut').on('click', ZoomOut);

    $board.addClass('table-styles'); // added this class here because if it's static broke visually the minefield
    let board = new Board(numberOfRows, numberOfColumns);

    $board.append(board.createBoard());

    //add bombs
    let numberBombs = numberOfBombs;
    $('#display-bomb-number').html('Number of Bombs ' + numberBombs);
    let newBombs = new Bombs();
    let arrayOfBombs = newBombs.generateBombs(board.numberElements, numberBombs);

    let timerContainer = document.getElementById('game-time').childNodes[1];
    let firstTriggered = true;
    let timerValue = null;

    //left click a square
    $('.field').on('click', squareLeftClick);
    $('#new-game').on('click', start);
    $('#chooseOption').on('click', function (ev) {
        $('.dropdown-menu').show();
    });

    function start() {
//TODO replace the if statements
        if (location.hash === '#/beginner+zoom') {

            return (function () {
                newGame(10, 8, 8);
                ZoomIn();
            }());
        } else if (location.hash === '#/intermediate+zoom') {
            return (function () {
                newGame(40, 16, 16);
                ZoomIn();
            }());
        } else if (location.hash === '#/expert+zoom') {
            return (function () {
                newGame(99, 16, 30);
                ZoomIn();
            }());
        }
        else if (location.hash === '#/beginner') {
            return newGame(10, 8, 8);
        }
        else if (location.hash === '#/intermediate') {
            return newGame(40, 16, 16);
        }
        else if (location.hash === '#/expert') {
            return newGame(99, 16, 30);
        }
        else {
            $('#options').show()
        }

    }

    function ZoomIn() {
        let currentHREf = location.hash;

        $('.field').css("width",35);

        $('.field').css("height", 35);
        if (currentHREf.indexOf('zoom') > 0) {
            return
        }
        location.hash = currentHREf + '+zoom';
    }

    function ZoomOut() {
        let currentHREf = location.hash;

        $('.field').css("width",23);

        $('.field').css("height", 23);

        if (currentHREf.indexOf('zoom') < 0) {
            return
        }
        location.hash = currentHREf.slice(0, -5);
    }

    function showBomb() {
        for (let i = 0; i < arrayOfBombs.length; i++) {
            arrayOfBombs[i].className += ' bomb';//not jquery object to use addClass

        }
    }

    function checkCorrectFlag() {
        let markedAsBombFiled = $('.field.flag');
        let isCorrect = true;
        for (var i = 0; i < markedAsBombFiled.length; i++) {
            if (!markedAsBombFiled[i].bomb) {
                markedAsBombFiled[i].style.color = 'yellow';
                markedAsBombFiled[i].value = 'X';
                isCorrect = false;
            }
        }
        return isCorrect;
    }

    function checkAllFieldAreOpen() {
        let allFields = $('.field');
        let isCorrect = true;
        for (var i = 0; i < allFields.length; i++) {
            if (allFields[i].isClicked) {

                isCorrect = true;
            }
            else {
                isCorrect = false
            }
        }
        return isCorrect;

    }

    function gameOver() {
        showBomb();
        checkCorrectFlag();
        alert("Game Over");
        $('.field').off();//stops the event handlers

        timerValue = timerContainer.innerText; // save current time to use it for score
        timer.stopTimer();
        clearInterval(time);
    }

    function winner() {

        if (checkCorrectFlag) {

            alert('winner winner chicken dinner');
            timerValue = timerContainer.innerText; // save current time to use it for score
            timer.stopTimer();
            clearInterval(time);
        }
        else {
            return
        }
    }

    function squareLeftClick(ev) {
        if (firstTriggered) {
            // this starts the timer when a click is made on the board
            // and checks if its the 1st click only
            firstTriggered = false;
             // starts the timer
            timer.startTimer();
            time = setInterval(function() {timer.startTimer()}, 1000);
        }
        ev.target.isClicked = true;//the button is clicked
        if (ev.target.classList.contains('flag')) {
            return
        }

        if (ev.target.bomb) {
            gameOver();
            timer.stopTimer();
            clearInterval(time);

        } else {
            let button = ev.target;
            let x = button.coordX;
            let y = button.coordY;

            if (ev.target.classList.contains('flag')) {
                return;
            }//can't click on a flag

            function FindByAttributeValue(coordX, coordY, value, value2) {
                let allElements = document.getElementsByClassName('field');
                for (let i = 0; i < allElements.length; i++) {
                    if (allElements[i].coordX === value && allElements[i].coordY === value2) {

                        return allElements[i];
                    }
                }
            }

            function howManyBombsArroundClickedButton(x, y) {
                let counterBomb = 0;

                let yMoving = y === 0 ? y : y - 1;

                for (; yMoving <= y + 1 && yMoving < board.cols; yMoving++) {
                    let xMoving = x === 0 ? x : x - 1;
                    for (; xMoving <= x + 1 && xMoving < board.rows; xMoving++) {
                        let selEl = FindByAttributeValue('coordX', 'coordY', xMoving, yMoving);
                        if (selEl.bomb) {
                            counterBomb++;

                        }
                    }
                }

                return counterBomb;
            }

            let number = howManyBombsArroundClickedButton(x, y);

            if (number === 0) {
                ev.target.value = 0;
                let expand = function () {
                    let yMoving = y === 0 ? y : y - 1;

                    for (; yMoving <= y + 1 && yMoving < board.cols; yMoving++) {
                        let xMoving = x === 0 ? x : x - 1;
                        for (; xMoving <= x + 1 && xMoving < board.rows; xMoving++) {
                            let selEl = FindByAttributeValue('coordX', 'coordY', xMoving, yMoving);
                            if (selEl.value) {
                                continue;
                            }
                            //if there's already a flag should stop expanding
                            if (selEl.classList.contains('flag')) {
                                continue;
                            }
                            selEl.click();
                        }
                    }

                };
                expand();

            }
            let colors = ['red', 'teal', 'brown', 'rebeccapurple', 'purple', 'darkgreen', 'green', 'navy'];
            ev.target.style.color = colors[number - 1];
            ev.target.value = number;
        }
    }

    // event for input field
    let inputHighScore = document.querySelector('#high-score-input');
    inputHighScore.addEventListener('keypress', saveScore);
    let storage = new Utilities();

    function saveScore(ev) {
        let enterTriggered = false;
        let name = inputHighScore.value;

        if (ev.keyCode === 13) { // 13 is enter
            storage.localStorageSet(name, timeSpan.innerText);

            //console.log(storage.allStorage()); // for testing

            document.removeEventListener('keypress', saveScore);
            enterTriggered = true;
        }
        if (enterTriggered) {
            events.switchElementsVisibility('#high-score-input', "#high-scores-btn");
            inputHighScore.innerHTML = '';
        }
    }

    document.removeEventListener('keypress', saveScore);

//right click a square
    $('.field').on('contextmenu', squareRightClick);

    function squareRightClick(ev) {
        ev.preventDefault();
        if (ev.target.value) {
            return
        }

        let flag = $('<img>');
        flag.attr('src', '../img/flag.png');
        flag.addClass('img');

        let $target = $(ev.target);
        //don't show context menu

        if ($target.hasClass('flag')) {

            $target.isClicked = false;//unclicked the button
            $target.removeClass('flag')
            numberBombs++;
            $('#display-bomb-number').html('Number of Bombs ' + numberBombs);
        } else {
            if (numberBombs === 0) {
                return
            }
            $target.isClicked = true;//button is clicked
            $target.addClass('flag');
            // $target.html('*');
            numberBombs--;
            $('#display-bomb-number').html('Number of Bombs ' + numberBombs);
            if (numberBombs === 0 && checkAllFieldAreOpen) {
                if (winner) {
                    alert('winer');
                    showBomb('win');
                    timerValue = timerContainer.innerText; // save current time to use it for score
                    events.stopTimer(timerContainer); // stop the timer
                    events.switchElementsVisibility("#high-scores-btn", '#high-score-input');
                }
            }
            ;
        }

        //think to simplifie,duplicate on each controller
    }

    $(window).on('hashchange', function () {
        clearInterval(time);
        document.removeEventListener('keypress', saveScore);
        inputHighScore.innerHTML = '';
    });
}

export {newGame};

<commit_msg>stop the timer in highscores<commit_after>import {Board} from '../board.js';
import {Bombs} from '../bombs.js';
import {Events} from '../app/events.js';
import {Utilities} from '../app/utilities.js';
import {Timer} from '../timer.js';

let timeSpan = document.getElementById('timer');
let timer = new Timer();
let time;

function newGame(numberOfBombs, numberOfRows, numberOfColumns) {
    //create board
    timer.stopTimer();
    clearInterval(time);
    let events = new Events(); // created for events
    let $board = $('#table');
    $('.dropdown-menu').hide()
    $board.empty();

    if (!$('#high-score-input').hasClass('hidden')) {
        events.switchElementsVisibility('#high-score-input', "#high-scores-btn");
    }
    $('#display').on('click', ZoomIn);
    $('#zoomOut').on('click', ZoomOut);

    $board.addClass('table-styles'); // added this class here because if it's static broke visually the minefield
    let board = new Board(numberOfRows, numberOfColumns);

    $board.append(board.createBoard());

    //add bombs
    let numberBombs = numberOfBombs;
    $('#display-bomb-number').html('Number of Bombs ' + numberBombs);
    let newBombs = new Bombs();
    let arrayOfBombs = newBombs.generateBombs(board.numberElements, numberBombs);

    let timerContainer = document.getElementById('game-time').childNodes[1];
    let firstTriggered = true;
    let timerValue = null;

    //left click a square
    $('.field').on('click', squareLeftClick);
    $('#new-game').on('click', start);
    $('#chooseOption').on('click', function (ev) {
        $('.dropdown-menu').show();
    });

    function start() {
//TODO replace the if statements
        if (location.hash === '#/beginner+zoom') {

            return (function () {
                newGame(10, 8, 8);
                ZoomIn();
            }());
        } else if (location.hash === '#/intermediate+zoom') {
            return (function () {
                newGame(40, 16, 16);
                ZoomIn();
            }());
        } else if (location.hash === '#/expert+zoom') {
            return (function () {
                newGame(99, 16, 30);
                ZoomIn();
            }());
        }
        else if (location.hash === '#/beginner') {
            return newGame(10, 8, 8);
        }
        else if (location.hash === '#/intermediate') {
            return newGame(40, 16, 16);
        }
        else if (location.hash === '#/expert') {
            return newGame(99, 16, 30);
        }
        else {
            $('#options').show()
        }

    }

    function ZoomIn() {
        let currentHREf = location.hash;

        $('.field').css("width",35);

        $('.field').css("height", 35);
        if (currentHREf.indexOf('zoom') > 0) {
            return
        }
        location.hash = currentHREf + '+zoom';
    }

    function ZoomOut() {
        let currentHREf = location.hash;

        $('.field').css("width",23);

        $('.field').css("height", 23);

        if (currentHREf.indexOf('zoom') < 0) {
            return
        }
        location.hash = currentHREf.slice(0, -5);
    }

    function showBomb() {
        for (let i = 0; i < arrayOfBombs.length; i++) {
            arrayOfBombs[i].className += ' bomb';//not jquery object to use addClass

        }
    }

    function checkCorrectFlag() {
        let markedAsBombFiled = $('.field.flag');
        let isCorrect = true;
        for (var i = 0; i < markedAsBombFiled.length; i++) {
            if (!markedAsBombFiled[i].bomb) {
                markedAsBombFiled[i].style.color = 'yellow';
                markedAsBombFiled[i].value = 'X';
                isCorrect = false;
            }
        }
        return isCorrect;
    }

    function checkAllFieldAreOpen() {
        let allFields = $('.field');
        let isCorrect = true;
        for (var i = 0; i < allFields.length; i++) {
            if (allFields[i].isClicked) {

                isCorrect = true;
            }
            else {
                isCorrect = false
            }
        }
        return isCorrect;

    }

    function gameOver() {
        showBomb();
        checkCorrectFlag();
        alert("Game Over");
        $('.field').off();//stops the event handlers

        timerValue = timerContainer.innerText; // save current time to use it for score
        timer.stopTimer();
        clearInterval(time);
    }

    function winner() {

        if (checkCorrectFlag) {

            alert('winner winner chicken dinner');
            timerValue = timerContainer.innerText; // save current time to use it for score
            clearInterval(time);
        }
        else {
            return;
        }
    }

    function squareLeftClick(ev) {
        if (firstTriggered) {
            // this starts the timer when a click is made on the board
            // and checks if its the 1st click only
            firstTriggered = false;
             // starts the timer
            timer.startTimer();
            time = setInterval(function() {timer.startTimer()}, 1000);
        }
        ev.target.isClicked = true;//the button is clicked
        if (ev.target.classList.contains('flag')) {
            return
        }

        if (ev.target.bomb) {
            gameOver();
            timer.stopTimer();
            clearInterval(time);

        } else {
            let button = ev.target;
            let x = button.coordX;
            let y = button.coordY;

            if (ev.target.classList.contains('flag')) {
                return;
            }//can't click on a flag

            function FindByAttributeValue(coordX, coordY, value, value2) {
                let allElements = document.getElementsByClassName('field');
                for (let i = 0; i < allElements.length; i++) {
                    if (allElements[i].coordX === value && allElements[i].coordY === value2) {

                        return allElements[i];
                    }
                }
            }

            function howManyBombsArroundClickedButton(x, y) {
                let counterBomb = 0;

                let yMoving = y === 0 ? y : y - 1;

                for (; yMoving <= y + 1 && yMoving < board.cols; yMoving++) {
                    let xMoving = x === 0 ? x : x - 1;
                    for (; xMoving <= x + 1 && xMoving < board.rows; xMoving++) {
                        let selEl = FindByAttributeValue('coordX', 'coordY', xMoving, yMoving);
                        if (selEl.bomb) {
                            counterBomb++;

                        }
                    }
                }

                return counterBomb;
            }

            let number = howManyBombsArroundClickedButton(x, y);

            if (number === 0) {
                ev.target.value = 0;
                let expand = function () {
                    let yMoving = y === 0 ? y : y - 1;

                    for (; yMoving <= y + 1 && yMoving < board.cols; yMoving++) {
                        let xMoving = x === 0 ? x : x - 1;
                        for (; xMoving <= x + 1 && xMoving < board.rows; xMoving++) {
                            let selEl = FindByAttributeValue('coordX', 'coordY', xMoving, yMoving);
                            if (selEl.value) {
                                continue;
                            }
                            //if there's already a flag should stop expanding
                            if (selEl.classList.contains('flag')) {
                                continue;
                            }
                            selEl.click();
                        }
                    }

                };
                expand();

            }
            let colors = ['red', 'teal', 'brown', 'rebeccapurple', 'purple', 'darkgreen', 'green', 'navy'];
            ev.target.style.color = colors[number - 1];
            ev.target.value = number;
        }
    }

    // event for input field
    let inputHighScore = document.querySelector('#high-score-input');
    inputHighScore.addEventListener('keypress', saveScore);
    let storage = new Utilities();

    function saveScore(ev) {
        let enterTriggered = false;
        let name = inputHighScore.value;
        clearInterval(time);
        if (ev.keyCode === 13) { // 13 is enter
            storage.localStorageSet(name, timeSpan.innerText);

            //console.log(storage.allStorage()); // for testing

            document.removeEventListener('keypress', saveScore);
            enterTriggered = true;
        }
        if (enterTriggered) {
            events.switchElementsVisibility('#high-score-input', "#high-scores-btn");
            inputHighScore.innerHTML = '';
        }
    }

    document.removeEventListener('keypress', saveScore);

//right click a square
    $('.field').on('contextmenu', squareRightClick);

    function squareRightClick(ev) {
        ev.preventDefault();
        if (ev.target.value) {
            return
        }

        let flag = $('<img>');
        flag.attr('src', '../img/flag.png');
        flag.addClass('img');

        let $target = $(ev.target);
        //don't show context menu

        if ($target.hasClass('flag')) {

            $target.isClicked = false;//unclicked the button
            $target.removeClass('flag')
            numberBombs++;
            $('#display-bomb-number').html('Number of Bombs ' + numberBombs);
        } else {
            if (numberBombs === 0) {
                return
            }
            $target.isClicked = true;//button is clicked
            $target.addClass('flag');
            // $target.html('*');
            numberBombs--;
            $('#display-bomb-number').html('Number of Bombs ' + numberBombs);
            if (numberBombs === 0 && checkAllFieldAreOpen) {
                if (winner) {
                    alert('winer');
                    showBomb('win');
                    timerValue = timerContainer.innerText; // save current time to use it for score
                    clearInterval(time);
                    events.switchElementsVisibility("#high-scores-btn", '#high-score-input');
                }
            }
            ;
        }

        //think to simplifie,duplicate on each controller
    }

    $(window).on('hashchange', function () {
        clearInterval(time);
        //events.stopTimer(timerContainer); // stop the timer when page is changed
        document.removeEventListener('keypress', saveScore);
        inputHighScore.innerHTML = '';
    });
}

export {newGame};

<|endoftext|>


<commit_before>(function() {
  'use strict';
  angular.module('docs')
  .config(config);

  // app.config.js
  function config($locationProvider, $stateProvider, API_DATA, GUIDE_DATA, $urlRouterProvider) {

      // Set HTML5 Mode
      $locationProvider.html5Mode(true);

      // Configure URL Router to redirect to /api
      // if state doesn't exist
      $urlRouterProvider.otherwise('/api');

      // Defining our template for the sidebar
      // Could've been in a partial, but it's simple
      // enough that it can be a string template
      var sidebarTemplate = '
Contents
' +
          '
' +
          '
' +
          '' +
          '
' +
          '
' +
          '' +
          '
' +
          '
' +
          '
' +
          '
';

      // Assign our root state for API pages to var
      // Assigning the basepage as the partials
      // Setup the sidebar to use our ApiController and template
      var apiState = {
          name: 'api',
          url: '/api',
          views: {
              'main': {
                  templateUrl: 'partials/api.html',
              },
              'sidebar': {
                  template: sidebarTemplate,
                  controller: 'ApiController as ctrl',
              }
          }
      };

      // Same thing for our guide page
      var guideState = {
          name: 'guide',
          url: '/guide',
          views: {
              'main': {
                  templateUrl: 'partials/guide.html'
              },
              'sidebar': {
                  template: sidebarTemplate,
                  controller: 'GuideController as ctrl',
              }
          }
      };

      // Using the $stateProvider from UI-Router
      // to create the states in the application
      $stateProvider.state(apiState);
      $stateProvider.state(guideState);

      // Looping through all of our API pages
      // and dynamically creating new states based
      // on the data generated by Dgeni
      angular.forEach(API_DATA, function(parent) {

          var newState = {
              name: parent.name,
              url: '/' + parent.url,
              views: {
                  'main': {
                      templateUrl: parent.outputPath
                  },
                  'sidebar': {
                      template: sidebarTemplate,
                      controller: 'ApiController as ctrl'
                  }
              }
          };

          // Creating the states using $stateProvider
          $stateProvider.state(newState);

          // In the case of API, we have multiple modules and each
          // of them have children, so we are doing the same thing
          // here but for the child states
          angular.forEach(parent.docs, function(doc) {

              var newState = {
                  name: doc.name,
                  url: '/' + doc.url,
                  views: {
                      'main': {
                          templateUrl: doc.outputPath
                      },
                      'sidebar': {
                          template: sidebarTemplate,
                          controller: 'ApiController as ctrl'
                      }
                  }
              };

              // Creating the states using $stateProvider
              $stateProvider.state(newState);
          });
      });

      // Same thing for Guide, except in this case we only
      // have 'root' pages, so no need to loop twice
      angular.forEach(GUIDE_DATA, function(parent) {

          var newState = {
              name: parent.name,
              url: '/' + parent.url,
              views: {
                  'main': {
                      templateUrl: parent.outputPath
                  },
                  'sidebar': {
                      template: sidebarTemplate,
                      controller: 'GuideController as ctrl'
                  }
              }
          };

          // Creating the states using $stateProvider
          $stateProvider.state(newState);

      });

  }
  config.$inject = ["$locationProvider", "$stateProvider", "API_DATA", "GUIDE_DATA", "$urlRouterProvider"];

}());
<commit_msg>copied templates over from reference site, seems to work now<commit_after>'use strict';

angular
  .module('docs')
  .config(config);

function config($locationProvider, $stateProvider, API_DATA, GUIDE_DATA, $urlRouterProvider) {

  $locationProvider.html5Mode(true);

  $urlRouterProvider.otherwise('/api');

  var sidebarTemplate = '
Contents
' +
    '
' +
    '
' +
    '{{page.name}}' +
    '
' +
    '
' +
    '{{child.name}}' +
    '
' +
    '
' +
    '
' +
    '
';

  var apiState = {
    name: 'api',
    url: '/api',
    views: {
      'main': {
        templateUrl: 'partials/api.html',
      },
      'sidebar': {
        template: sidebarTemplate,
        controller: 'ApiController as ctrl',
      }
    }
  }

  var guideState = {
    name: 'guide',
    url: '/guide',
    views: {
      'main': {
        templateUrl: 'partials/guide.html'
      },
      'sidebar': {
        template: sidebarTemplate,
        controller: 'GuideController as ctrl',
      }
    }
  }

  $stateProvider.state(apiState);
  $stateProvider.state(guideState);

  angular.forEach(API_DATA, function(parent) {

    var newState = {
      name: parent.stateName,
      url: '/' + parent.url,
      views: {
        'main': {
          templateUrl: parent.outputPath
        },
        'sidebar': {
          template: sidebarTemplate,
          controller: 'ApiController as ctrl'
        }
      }
    };

    $stateProvider.state(newState);

    angular.forEach(parent.docs, function(doc) {

      var newState = {
        name: doc.stateName,
        url: '/' + doc.url,
        views: {
          'main': {
            templateUrl: doc.outputPath
          },
          'sidebar': {
            template: sidebarTemplate,
            controller: 'ApiController as ctrl'
          }
        }
      };

      $stateProvider.state(newState);
    });
  });

  angular.forEach(GUIDE_DATA, function(parent) {

    var newState = {
      name: parent.name,
      url: '/' + parent.url,
      views: {
        'main': {
          templateUrl: parent.outputPath
        },
        'sidebar': {
          template: sidebarTemplate,
          controller: 'GuideController as ctrl'
        }
      }
    };

    $stateProvider.state(newState);

  });

}
config.$inject = ["$locationProvider", "$stateProvider", "API_DATA", "GUIDE_DATA", "$urlRouterProvider"];
<|endoftext|>


<commit_before>angular.module('search', [])

.controller('DocsSearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
  function clearResults() {
    $scope.results = [];
    $scope.colClassName = null;
    $scope.hasResults = false;
  }

  $scope.search = function(q) {
    var MIN_SEARCH_LENGTH = 3;
    if(q.length >= MIN_SEARCH_LENGTH) {
      var results = docsSearch(q);
      var totalAreas = 0;
      for(var i in results) {
        ++totalAreas;
      }
      if(totalAreas > 0) {
        $scope.colClassName = 'cols-' + totalAreas;
      }
      $scope.hasResults = totalAreas > 0;
      $scope.results = results;
    }
    else {
      clearResults();
    }
    if(!$scope.$$phase) $scope.$apply();
  };
  $scope.submit = function() {
    var result;
    for(var i in $scope.results) {
      result = $scope.results[i][0];
      if(result) {
        break;
      }
    }
    if(result) {
      $location.path(result.url);
      $scope.hideResults();
    }
  };
  $scope.hideResults = function() {
    clearResults();
    $scope.q = '';
  };
}])

.controller('Error404SearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
  $scope.results = docsSearch($location.path().split(/[\/\.:]/).pop());
}])

.factory('lunrSearch', function() {
  return function(properties) {
    if (window.RUNNING_IN_NG_TEST_RUNNER) return null;

    var engine = lunr(properties);
    return {
      store : function(values) {
        engine.add(values);
      },
      search : function(q) {
        return engine.search(q);
      }
    };
  };
})

.factory('docsSearch', ['$rootScope','lunrSearch', 'NG_PAGES',
    function($rootScope, lunrSearch, NG_PAGES) {
  if (window.RUNNING_IN_NG_TEST_RUNNER) {
    return null;
  }

  var index = lunrSearch(function() {
    this.ref('id');
    this.field('title', {boost: 50});
    this.field('keywords', { boost : 20 });
  });

  angular.forEach(NG_PAGES, function(page, key) {
    if(page.searchTerms) {
      index.store({
        id : key,
        title : page.searchTerms.titleWords,
        keywords : page.searchTerms.keywords
      });
    };
  });

  return function(q) {
    var results = {
      api : [],
      tutorial : [],
      guide : [],
      error : [],
      misc : []
    };
    angular.forEach(index.search(q), function(result) {
      var key = result.ref;
      var item = NG_PAGES[key];
      var area = item.area;
      item.path = key;

      var limit = area == 'api' ? 40 : 14;
      if(results[area].length < limit) {
        results[area].push(item);
      }
    });
    return results;
  };
}])

.directive('focused', function($timeout) {
  return function(scope, element, attrs) {
    element[0].focus();
    element.on('focus', function() {
      scope.$apply(attrs.focused + '=true');
    });
    element.on('blur', function() {
      // have to use $timeout, so that we close the drop-down after the user clicks,
      // otherwise when the user clicks we process the closing before we process the click.
      $timeout(function() {
        scope.$eval(attrs.focused + '=false');
      });
    });
    scope.$eval(attrs.focused + '=true');
  };
})

.directive('docsSearchInput', ['$document',function($document) {
  return function(scope, element, attrs) {
    var ESCAPE_KEY_KEYCODE = 27,
        FORWARD_SLASH_KEYCODE = 191;
    angular.element($document[0].body).bind('keydown', function(event) {
      var input = element[0];
      if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) {
        event.stopPropagation();
        event.preventDefault();
        input.focus();
      }
    });

    element.bind('keydown', function(event) {
      if(event.keyCode == ESCAPE_KEY_KEYCODE) {
        event.stopPropagation();
        event.preventDefault();
        scope.$apply(function() {
          scope.hideResults();
        });
      }
    });
  };
}]);
<commit_msg>docs(search): set minimum length to 2<commit_after>angular.module('search', [])

.controller('DocsSearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
  function clearResults() {
    $scope.results = [];
    $scope.colClassName = null;
    $scope.hasResults = false;
  }

  $scope.search = function(q) {
    var MIN_SEARCH_LENGTH = 2;
    if(q.length >= MIN_SEARCH_LENGTH) {
      var results = docsSearch(q);
      var totalAreas = 0;
      for(var i in results) {
        ++totalAreas;
      }
      if(totalAreas > 0) {
        $scope.colClassName = 'cols-' + totalAreas;
      }
      $scope.hasResults = totalAreas > 0;
      $scope.results = results;
    }
    else {
      clearResults();
    }
    if(!$scope.$$phase) $scope.$apply();
  };
  $scope.submit = function() {
    var result;
    for(var i in $scope.results) {
      result = $scope.results[i][0];
      if(result) {
        break;
      }
    }
    if(result) {
      $location.path(result.url);
      $scope.hideResults();
    }
  };
  $scope.hideResults = function() {
    clearResults();
    $scope.q = '';
  };
}])

.controller('Error404SearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
  $scope.results = docsSearch($location.path().split(/[\/\.:]/).pop());
}])

.factory('lunrSearch', function() {
  return function(properties) {
    if (window.RUNNING_IN_NG_TEST_RUNNER) return null;

    var engine = lunr(properties);
    return {
      store : function(values) {
        engine.add(values);
      },
      search : function(q) {
        return engine.search(q);
      }
    };
  };
})

.factory('docsSearch', ['$rootScope','lunrSearch', 'NG_PAGES',
    function($rootScope, lunrSearch, NG_PAGES) {
  if (window.RUNNING_IN_NG_TEST_RUNNER) {
    return null;
  }

  var index = lunrSearch(function() {
    this.ref('id');
    this.field('title', {boost: 50});
    this.field('keywords', { boost : 20 });
  });

  angular.forEach(NG_PAGES, function(page, key) {
    if(page.searchTerms) {
      index.store({
        id : key,
        title : page.searchTerms.titleWords,
        keywords : page.searchTerms.keywords
      });
    };
  });

  return function(q) {
    var results = {
      api : [],
      tutorial : [],
      guide : [],
      error : [],
      misc : []
    };
    angular.forEach(index.search(q), function(result) {
      var key = result.ref;
      var item = NG_PAGES[key];
      var area = item.area;
      item.path = key;

      var limit = area == 'api' ? 40 : 14;
      if(results[area].length < limit) {
        results[area].push(item);
      }
    });
    return results;
  };
}])

.directive('focused', function($timeout) {
  return function(scope, element, attrs) {
    element[0].focus();
    element.on('focus', function() {
      scope.$apply(attrs.focused + '=true');
    });
    element.on('blur', function() {
      // have to use $timeout, so that we close the drop-down after the user clicks,
      // otherwise when the user clicks we process the closing before we process the click.
      $timeout(function() {
        scope.$eval(attrs.focused + '=false');
      });
    });
    scope.$eval(attrs.focused + '=true');
  };
})

.directive('docsSearchInput', ['$document',function($document) {
  return function(scope, element, attrs) {
    var ESCAPE_KEY_KEYCODE = 27,
        FORWARD_SLASH_KEYCODE = 191;
    angular.element($document[0].body).bind('keydown', function(event) {
      var input = element[0];
      if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) {
        event.stopPropagation();
        event.preventDefault();
        input.focus();
      }
    });

    element.bind('keydown', function(event) {
      if(event.keyCode == ESCAPE_KEY_KEYCODE) {
        event.stopPropagation();
        event.preventDefault();
        scope.$apply(function() {
          scope.hideResults();
        });
      }
    });
  };
}]);
<|endoftext|>


<commit_before>var _           = require('lodash');
var assert      = require('assert');
var taskcluster = require('taskcluster-client');
var events      = require('events');
var base        = require('taskcluster-base');
var debug       = require('debug')('auth:ScopeResolver');
var Promise     = require('promise');
var dfa         = require('./dfa');

class ScopeResolver extends events.EventEmitter {
  /** Create ScopeResolver */
  constructor(options = {}) {
    super();

    // Provide default options
    options = _.defaults({}, options, {
      // Maximum time that lastUsed must be behind, must always be negative
      maxLastUsedDelay: '-6h',
    });
    this._maxLastUsedDelay = options.maxLastUsedDelay;
    assert(/^ *-/.test(options.maxLastUsedDelay),
           'maxLastUsedDelay must be negative');

    // List of client objects on the form:
    // {
    //    clientId, accessToken,
    //    scopes: [...],                // Scopes (as set in the table)
    //    disabled: true | false,       // If true, client is disabled
    //    expandedScopes: [...],        // Scopes (including indirect scopes)
    //    updateLastUsed: true | false  // true, if lastUsed should be updated
    // }
    this._clients = [];
    // List of role objects on the form:
    // {roleId: '...', scopes: [...], expandedScopes: [...]}
    this._roles = [];

    // Mapping from clientId to client objects from _clients,
    // _clientCache[clientId] === this._clients[i] === {     // for some i
    //   clientId, accessToken, expandedScopes: [...], updateLastUsed
    // };
    this._clientCache = {};

    // Promise that we're done reloading, used to serialize reload operations
    this._reloadDone = Promise.resolve();
  }

  /**
   * Load cache, setup interval for reloading cache, start listening
   *
   * options:
   * {
   *   Client:              // data.Client object
   *   Role:                // data.Role object
   *   connection:          // PulseConnection object
   *   exchangeReference:   // reference for exchanges declared
   *   cacheExpiry:         // Time before clearing cache
   * }
   */
  async setup(options) {
    options = _.defaults({}, options || {}, {
      cacheExpiry:    20 * 60 * 1000,   // default to 20 min
    });
    assert(options.Client, "Expected options.Client");
    assert(options.Role, "Expected options.Role");
    assert(options.exchangeReference, "Expected options.exchangeReference");
    assert(options.connection instanceof taskcluster.PulseConnection,
           "Expected options.connection to be a PulseConnection object");
    this._Client        = options.Client;
    this._Role          = options.Role;
    this._options       = options;

    // Create authEvents client
    var AuthEvents = taskcluster.createClient(this._options.exchangeReference);
    var authEvents = new AuthEvents();

    // Create PulseListeners
    this._clientListener = new taskcluster.PulseListener({
      connection:   options.connection,
      reconnect:    true
    });
    this._roleListener = new taskcluster.PulseListener({
      connection:   options.connection,
      reconnect:    true
    });

    // listen for client events
    await this._clientListener.bind(authEvents.clientCreated());
    await this._clientListener.bind(authEvents.clientUpdated());
    await this._clientListener.bind(authEvents.clientDeleted());
    // listen for role events
    await this._roleListener.bind(authEvents.roleCreated());
    await this._roleListener.bind(authEvents.roleUpdated());
    await this._roleListener.bind(authEvents.roleDeleted());

    // Reload when we get message
    this._clientListener.on('message', m => {
      return this.reloadClient(m.payload.clientId);
    });
    this._roleListener.on('message', m => {
      return this.reloadRole(m.payload.roleId);
    });

    // Load initially
    await this.reload();

    // Set this.reload() to run repeatedly
    this._reloadIntervalHandle = setInterval(() => {
      this.reload().catch(err => this.emit('error', err));
    }, this._options.cacheExpiry);

    // Start listening
    await this._clientListener.resume();
    await this._roleListener.resume();
  }

  /**
   * Execute async `reloader` function, after any earlier async `reloader`
   * function given this function has completed. Ensuring that the `reloader`
   * functions are executed in serial.
   */
  _syncReload(reloader) {
    return this._reloadDone = this._reloadDone.catch(() => {}).then(reloader);
  }

  reloadClient(clientId) {
    return this._syncReload(async () => {
      let client = await this._Client.load({clientId}, true);
      // Always remove it
      this._clients = this._clients.filter(c => c.clientId !== clientId);
      // If a client was loaded, add it back
      if (client) {
        // For reasoning on structure, see reload()
        let lastUsedDate = new Date(client.details.lastDateUsed);
        let minLastUsed = taskcluster.fromNow(this._maxLastUsedDelay);
        this._clients.push({
          clientId:       client.clientId,
          accessToken:    client.accessToken,
          expires:        client.expires,
          updateLastUsed: lastUsedDate < minLastUsed,
          scopes:         client.scopes,
          disabled:       client.disabled
        });
      }
      this._computeFixedPoint();
    });
  }

  reloadRole(roleId) {
    return this._syncReload(async () => {
      let role = await this._Role.load({roleId}, true);
      // Always remove it
      this._roles = this._roles.filter(r => r.roleId !== roleId);
      // If a role was loaded add it back
      if (role) {
        let scopes = role.scopes;
        if (!role.roleId.endsWith('*')) {
          // For reasoning on structure, see reload()
          scopes = _.union(scopes, ['assume:' + role.roleId]);
        }
        this._roles.push({roleId: role.roleId, scopes});
      }
      this._computeFixedPoint();
    });
  }

  reload() {
    return this._syncReload(async () => {
      debug("Loading clients and roles");

      // Load clients and roles in parallel
      let clients = [];
      let roles   = [];
      await Promise.all([
        // Load all clients on a simplified form:
        // {clientId, accessToken, updateLastUsed}
        // _computeFixedPoint() will construct the `_clientCache` object
        this._Client.scan({}, {
          handler: client => {
            let lastUsedDate = new Date(client.details.lastDateUsed);
            let minLastUsed = taskcluster.fromNow(this._maxLastUsedDelay);
            clients.push({
              clientId:       client.clientId,
              accessToken:    client.accessToken,
              expires:        client.expires,
              // Note that lastUsedDate should be updated, if it's out-dated by
              // more than 6 hours.
              // (cheap way to know if it's been used recently)
              updateLastUsed: lastUsedDate < minLastUsed,
              scopes:         client.scopes,
              disabled:       client.disabled
            });
          }
        }),
        // Load all roles on a simplified form: {roleId, scopes}
        // _computeFixedPoint() will later add the `expandedScopes` property
        this._Role.scan({}, {
          handler(role) {
            let scopes = role.scopes;
            if (!role.roleId.endsWith('*')) {
              // Ensure identity, if role isn't a prefix pattern. Obviously,
              // 'assume:ab' which matches 'assume:a*' doesn't have 'assume:a*'
              // by the identity relation. But for non-prefix patterns, the
              // identify relation implies that you have 'assume:<roleId>'.
              // This speeds up fixed-point computation, and means that if you
              // have a match without any *, then you can look up the role, and
              // not have to worry about any prefix patterns that may also match
              // as they are already saturated.
              scopes = _.union(scopes, ['assume:' + role.roleId]);
            }
            roles.push({roleId: role.roleId, scopes});
          }
        })
      ]);

      // Set _roles and _clients at the same time and immediately call
      // _computeFixedPoint, so anyone using the cache is using a consistent one
      this._roles = roles;
      this._clients = clients;
      this._computeFixedPoint();
    });
  }

  /** Compute fixed point over this._roles, and construct _clientCache */
  _computeFixedPoint() {
    //console.time("_computeFixedPoint");
    this._resolver = dfa.computeFixedPoint(this._roles);
    //console.timeEnd("_computeFixedPoint");

    // Construct client cache
    this._clientCache = {};
    for (let client of this._clients) {
      var scopes = this.resolve([
        'assume:client-id:' + client.clientId
      ].concat(client._scopes || []));
      client.scopes = scopes; // for createSignatureValidator compatibility
      client.expandedScopes = scopes;
      this._clientCache[client.clientId] = client;
    }
  }

  /** Update lastDateUsed for a clientId */
  async _updateLastUsed(clientId) {
    let client = await this._Client.load({clientId});
    await client.modify(client => {
      let lastUsedDate = new Date(client.details.lastDateUsed);
      let minLastUsed = taskcluster.fromNow(this._maxLastUsedDelay);
      if (lastUsedDate < minLastUsed) {
        client.details.lastDateUsed = new Date().toJSON();
      }
    });
  }

  /**
   * Return set of scopes that `scopes` can be expanded to when assuming all
   * authorized roles.
   */
  resolve(scopes) {
    let granted = dfa.sortScopesForMerge(_.clone(scopes));
    for (let scope of scopes) {
      let found = this._resolver(scope);
      if (found.length > 0) {
        granted = dfa.mergeScopeSets(granted, found);
      }
    }
    return granted;
  }

  createSignatureValidator(options = {}) {
    return base.API.createSignatureValidator({
      expandScopes: (scopes) => this.resolve(scopes),
      clientLoader: async (clientId) => {
        let client = this._clientCache[clientId];
        if (!client) {
          throw new Error("Client with clientId '" + clientId + "' not found");
        }
        if (client.disabled) {
          throw new Error("Client with clientId '" + clientId + "' is disabled");
        }
        if (client.expires < new Date()) {
          throw new Error("Client with clientId: '" + clientId + "' has expired");
        }

        if (client.updateLastUsed) {
          client.updateLastUsed = false;
          this._updateLastUsed(clientId).catch(err => this.emit('error', err));
        }
        return client;
      }
    });
  }

  /**
   * Remove scopes that aren't needed, e.g. if you have ["q:1", "q:*"], then
   * the scope-set ["q:*"] is the formal-form. Basically shorter, but same
   * level of authority.
   */
  static normalizeScopes(scopes) {
    //return scopes;
    // Filter out any duplicate scopes (so we only have unique strings)
    scopes = _.uniq(scopes);
    // Filter out scopes that are covered by some other scope
    return scopes.filter(scope => {
      return scopes.every(other => {
        // If `scope` is `other`, then we can't filter it! It has to be
        // strictly greater than (otherwise scopes would filter themselves)
        if (other === scope) {
          return true;
        }
        // But if the other one ends with '*' and `scope` starts with its
        // prefix then `other` is strictly greater than `scope` and we filter
        // out `scope`.
        return !(other.endsWith('*') && scope.startsWith(other.slice(0, -1)));
      });
    });
  }

  /**
   * Determine if scope grants a roleId, and allows owner to assume the role.
   * This is equivalent to: `scopeMatch([["assume:" + roleId]], scopes)`
   */
  static grantsRole(scope, roleId) {
    // We have 3 rules (A), (B) and (C) by which a scope may match a role.
    // This implementation focuses on being reasonably fast by avoiding
    // allocations whenever possible.

    // Rule (A) and (B) both requires the scope to start with "assume:"
    if (scope.startsWith('assume:')) {
      // A) We have scope = 'assume:<roleId>', so we can assume the role
      if (scope.length === roleId.length + 7 && scope.endsWith(roleId)) {
        return true;
      }

      // B) role is on the form 'assume:<prefix>*' and we have a scope on the
      //    form 'assume:<prefix>...'. This is special rule, assigning
      //    special meaning to '*' when used at the end of a roleId.
      if (roleId.endsWith('*') && scope.slice(7).startsWith(roleId.slice(0, -1))) {
        return true;
      }

      // C) We have scope as 'assume:<prefix>*' and '<prefix>' is a prefix of
      // roleId, this is similar to rule (A) relying on the normal scope
      // satisfiability. Note, this is only half of role (C).
      if (scope.endsWith('*') && roleId.startsWith(scope.slice(7, -1))) {
        return true;
      }
    }

    // C) We have scope as '<prefix>*' and '<prefix>' is a prefix of 'assume',
    // then similar to rule (A) relying on the normal scope satisfiability we
    // have that any role is granted.
    if (scope.endsWith('*') && 'assume'.startsWith(scope.slice(0, -1))) {
      return true;
    }

    return false;
  }
}

// Export ScopeResolver
module.exports = ScopeResolver;
<commit_msg>Fixed _scopes<commit_after>var _           = require('lodash');
var assert      = require('assert');
var taskcluster = require('taskcluster-client');
var events      = require('events');
var base        = require('taskcluster-base');
var debug       = require('debug')('auth:ScopeResolver');
var Promise     = require('promise');
var dfa         = require('./dfa');

class ScopeResolver extends events.EventEmitter {
  /** Create ScopeResolver */
  constructor(options = {}) {
    super();

    // Provide default options
    options = _.defaults({}, options, {
      // Maximum time that lastUsed must be behind, must always be negative
      maxLastUsedDelay: '-6h',
    });
    this._maxLastUsedDelay = options.maxLastUsedDelay;
    assert(/^ *-/.test(options.maxLastUsedDelay),
           'maxLastUsedDelay must be negative');

    // List of client objects on the form:
    // {
    //    clientId, accessToken,
    //    unexpandedScopes:             // Scopes (as set in the table)
    //    disabled: true | false,       // If true, client is disabled
    //    scopes: [...],                // Scopes (including indirect scopes)
    //    expandedScopes: [...],        // Scopes (including indirect scopes)
    //    updateLastUsed: true | false  // true, if lastUsed should be updated
    // }
    this._clients = [];
    // List of role objects on the form:
    // {roleId: '...', scopes: [...], expandedScopes: [...]}
    this._roles = [];

    // Mapping from clientId to client objects from _clients,
    // _clientCache[clientId] === this._clients[i] === {     // for some i
    //   clientId, accessToken, expandedScopes: [...], updateLastUsed
    // };
    this._clientCache = {};

    // Promise that we're done reloading, used to serialize reload operations
    this._reloadDone = Promise.resolve();
  }

  /**
   * Load cache, setup interval for reloading cache, start listening
   *
   * options:
   * {
   *   Client:              // data.Client object
   *   Role:                // data.Role object
   *   connection:          // PulseConnection object
   *   exchangeReference:   // reference for exchanges declared
   *   cacheExpiry:         // Time before clearing cache
   * }
   */
  async setup(options) {
    options = _.defaults({}, options || {}, {
      cacheExpiry:    20 * 60 * 1000,   // default to 20 min
    });
    assert(options.Client, "Expected options.Client");
    assert(options.Role, "Expected options.Role");
    assert(options.exchangeReference, "Expected options.exchangeReference");
    assert(options.connection instanceof taskcluster.PulseConnection,
           "Expected options.connection to be a PulseConnection object");
    this._Client        = options.Client;
    this._Role          = options.Role;
    this._options       = options;

    // Create authEvents client
    var AuthEvents = taskcluster.createClient(this._options.exchangeReference);
    var authEvents = new AuthEvents();

    // Create PulseListeners
    this._clientListener = new taskcluster.PulseListener({
      connection:   options.connection,
      reconnect:    true
    });
    this._roleListener = new taskcluster.PulseListener({
      connection:   options.connection,
      reconnect:    true
    });

    // listen for client events
    await this._clientListener.bind(authEvents.clientCreated());
    await this._clientListener.bind(authEvents.clientUpdated());
    await this._clientListener.bind(authEvents.clientDeleted());
    // listen for role events
    await this._roleListener.bind(authEvents.roleCreated());
    await this._roleListener.bind(authEvents.roleUpdated());
    await this._roleListener.bind(authEvents.roleDeleted());

    // Reload when we get message
    this._clientListener.on('message', m => {
      return this.reloadClient(m.payload.clientId);
    });
    this._roleListener.on('message', m => {
      return this.reloadRole(m.payload.roleId);
    });

    // Load initially
    await this.reload();

    // Set this.reload() to run repeatedly
    this._reloadIntervalHandle = setInterval(() => {
      this.reload().catch(err => this.emit('error', err));
    }, this._options.cacheExpiry);

    // Start listening
    await this._clientListener.resume();
    await this._roleListener.resume();
  }

  /**
   * Execute async `reloader` function, after any earlier async `reloader`
   * function given this function has completed. Ensuring that the `reloader`
   * functions are executed in serial.
   */
  _syncReload(reloader) {
    return this._reloadDone = this._reloadDone.catch(() => {}).then(reloader);
  }

  reloadClient(clientId) {
    return this._syncReload(async () => {
      let client = await this._Client.load({clientId}, true);
      // Always remove it
      this._clients = this._clients.filter(c => c.clientId !== clientId);
      // If a client was loaded, add it back
      if (client) {
        // For reasoning on structure, see reload()
        let lastUsedDate = new Date(client.details.lastDateUsed);
        let minLastUsed = taskcluster.fromNow(this._maxLastUsedDelay);
        this._clients.push({
          clientId:         client.clientId,
          accessToken:      client.accessToken,
          expires:          client.expires,
          updateLastUsed:   lastUsedDate < minLastUsed,
          unexpandedScopes: client.scopes,
          disabled:         client.disabled
        });
      }
      this._computeFixedPoint();
    });
  }

  reloadRole(roleId) {
    return this._syncReload(async () => {
      let role = await this._Role.load({roleId}, true);
      // Always remove it
      this._roles = this._roles.filter(r => r.roleId !== roleId);
      // If a role was loaded add it back
      if (role) {
        let scopes = role.scopes;
        if (!role.roleId.endsWith('*')) {
          // For reasoning on structure, see reload()
          scopes = _.union(scopes, ['assume:' + role.roleId]);
        }
        this._roles.push({roleId: role.roleId, scopes});
      }
      this._computeFixedPoint();
    });
  }

  reload() {
    return this._syncReload(async () => {
      debug("Loading clients and roles");

      // Load clients and roles in parallel
      let clients = [];
      let roles   = [];
      await Promise.all([
        // Load all clients on a simplified form:
        // {clientId, accessToken, updateLastUsed}
        // _computeFixedPoint() will construct the `_clientCache` object
        this._Client.scan({}, {
          handler: client => {
            let lastUsedDate = new Date(client.details.lastDateUsed);
            let minLastUsed = taskcluster.fromNow(this._maxLastUsedDelay);
            clients.push({
              clientId:         client.clientId,
              accessToken:      client.accessToken,
              expires:          client.expires,
              // Note that lastUsedDate should be updated, if it's out-dated by
              // more than 6 hours.
              // (cheap way to know if it's been used recently)
              updateLastUsed:   lastUsedDate < minLastUsed,
              unexpandedScopes: client.scopes,
              disabled:         client.disabled
            });
          }
        }),
        // Load all roles on a simplified form: {roleId, scopes}
        // _computeFixedPoint() will later add the `expandedScopes` property
        this._Role.scan({}, {
          handler(role) {
            let scopes = role.scopes;
            if (!role.roleId.endsWith('*')) {
              // Ensure identity, if role isn't a prefix pattern. Obviously,
              // 'assume:ab' which matches 'assume:a*' doesn't have 'assume:a*'
              // by the identity relation. But for non-prefix patterns, the
              // identify relation implies that you have 'assume:<roleId>'.
              // This speeds up fixed-point computation, and means that if you
              // have a match without any *, then you can look up the role, and
              // not have to worry about any prefix patterns that may also match
              // as they are already saturated.
              scopes = _.union(scopes, ['assume:' + role.roleId]);
            }
            roles.push({roleId: role.roleId, scopes});
          }
        })
      ]);

      // Set _roles and _clients at the same time and immediately call
      // _computeFixedPoint, so anyone using the cache is using a consistent one
      this._roles = roles;
      this._clients = clients;
      this._computeFixedPoint();
    });
  }

  /** Compute fixed point over this._roles, and construct _clientCache */
  _computeFixedPoint() {
    //console.time("_computeFixedPoint");
    this._resolver = dfa.computeFixedPoint(this._roles);
    //console.timeEnd("_computeFixedPoint");

    // Construct client cache
    this._clientCache = {};
    for (let client of this._clients) {
      var scopes = this.resolve([
        'assume:client-id:' + client.clientId
      ].concat(client.unexpandedScopes));
      client.scopes = scopes; // for createSignatureValidator compatibility
      client.expandedScopes = scopes;
      this._clientCache[client.clientId] = client;
    }
  }

  /** Update lastDateUsed for a clientId */
  async _updateLastUsed(clientId) {
    let client = await this._Client.load({clientId});
    await client.modify(client => {
      let lastUsedDate = new Date(client.details.lastDateUsed);
      let minLastUsed = taskcluster.fromNow(this._maxLastUsedDelay);
      if (lastUsedDate < minLastUsed) {
        client.details.lastDateUsed = new Date().toJSON();
      }
    });
  }

  /**
   * Return set of scopes that `scopes` can be expanded to when assuming all
   * authorized roles.
   */
  resolve(scopes) {
    let granted = dfa.sortScopesForMerge(_.clone(scopes));
    for (let scope of scopes) {
      let found = this._resolver(scope);
      if (found.length > 0) {
        granted = dfa.mergeScopeSets(granted, found);
      }
    }
    return granted;
  }

  createSignatureValidator(options = {}) {
    return base.API.createSignatureValidator({
      expandScopes: (scopes) => this.resolve(scopes),
      clientLoader: async (clientId) => {
        let client = this._clientCache[clientId];
        if (!client) {
          throw new Error("Client with clientId '" + clientId + "' not found");
        }
        if (client.disabled) {
          throw new Error("Client with clientId '" + clientId + "' is disabled");
        }
        if (client.expires < new Date()) {
          throw new Error("Client with clientId: '" + clientId + "' has expired");
        }

        if (client.updateLastUsed) {
          client.updateLastUsed = false;
          this._updateLastUsed(clientId).catch(err => this.emit('error', err));
        }
        return client;
      }
    });
  }

  /**
   * Remove scopes that aren't needed, e.g. if you have ["q:1", "q:*"], then
   * the scope-set ["q:*"] is the formal-form. Basically shorter, but same
   * level of authority.
   */
  static normalizeScopes(scopes) {
    //return scopes;
    // Filter out any duplicate scopes (so we only have unique strings)
    scopes = _.uniq(scopes);
    // Filter out scopes that are covered by some other scope
    return scopes.filter(scope => {
      return scopes.every(other => {
        // If `scope` is `other`, then we can't filter it! It has to be
        // strictly greater than (otherwise scopes would filter themselves)
        if (other === scope) {
          return true;
        }
        // But if the other one ends with '*' and `scope` starts with its
        // prefix then `other` is strictly greater than `scope` and we filter
        // out `scope`.
        return !(other.endsWith('*') && scope.startsWith(other.slice(0, -1)));
      });
    });
  }

  /**
   * Determine if scope grants a roleId, and allows owner to assume the role.
   * This is equivalent to: `scopeMatch([["assume:" + roleId]], scopes)`
   */
  static grantsRole(scope, roleId) {
    // We have 3 rules (A), (B) and (C) by which a scope may match a role.
    // This implementation focuses on being reasonably fast by avoiding
    // allocations whenever possible.

    // Rule (A) and (B) both requires the scope to start with "assume:"
    if (scope.startsWith('assume:')) {
      // A) We have scope = 'assume:<roleId>', so we can assume the role
      if (scope.length === roleId.length + 7 && scope.endsWith(roleId)) {
        return true;
      }

      // B) role is on the form 'assume:<prefix>*' and we have a scope on the
      //    form 'assume:<prefix>...'. This is special rule, assigning
      //    special meaning to '*' when used at the end of a roleId.
      if (roleId.endsWith('*') && scope.slice(7).startsWith(roleId.slice(0, -1))) {
        return true;
      }

      // C) We have scope as 'assume:<prefix>*' and '<prefix>' is a prefix of
      // roleId, this is similar to rule (A) relying on the normal scope
      // satisfiability. Note, this is only half of role (C).
      if (scope.endsWith('*') && roleId.startsWith(scope.slice(7, -1))) {
        return true;
      }
    }

    // C) We have scope as '<prefix>*' and '<prefix>' is a prefix of 'assume',
    // then similar to rule (A) relying on the normal scope satisfiability we
    // have that any role is granted.
    if (scope.endsWith('*') && 'assume'.startsWith(scope.slice(0, -1))) {
      return true;
    }

    return false;
  }
}

// Export ScopeResolver
module.exports = ScopeResolver;
<|endoftext|>


<commit_before>/* eslint-disable global-require, import/no-unresolved */
export default rootPath => ({
  title: 'Examples',
  props: {
    style: {
      borderTop: '2px solid #ddd'
    }
  },
  pages: [
    {
      path: `${rootPath}/all-features`,
      title: 'All Features',
      component: require('./all-features.md')
    },
    {
      path: `${rootPath}/adjusting-colspan`,
      title: 'Adjusting Colspan',
      component: require('./adjusting-colspan.md')
    },
    {
      path: `${rootPath}/crud`,
      title: 'CRUD',
      component: require('./crud.md')
    },
    {
      path: `${rootPath}/crud-redux`,
      title: 'CRUD with Redux',
      component: require('./crud-redux.md')
    },
    {
      path: `${rootPath}/excel`,
      title: 'Excel',
      component: require('./excel.md')
    },
    {
      path: `${rootPath}/expand-column-to-fit`,
      title: 'Expand Column to Fit',
      component: require('./expand-column-to-fit.md')
    },
    {
      path: `${rootPath}/fixed-width-columns`,
      title: 'Fixed Width Columns',
      component: require('./fixed-width-columns.md')
    },
    {
      path: `${rootPath}/infinite-scrolling`,
      title: 'Infinite Scrolling',
      component: require('./infinite-scrolling.md')
    },
    {
      path: `${rootPath}/multiple-async-instances`,
      title: 'Multiple Async Instances',
      component: require('./multiple-async-instances.md')
    },
    {
      imports: { styled: require('styled-components') },
      path: `${rootPath}/styled-components`,
      title: 'Styled Components',
      component: require('./styled-components.md')
    },
    {
      path: `${rootPath}/header-body-aligned`,
      title: 'Align sticky header and body',
      component: require('./header-body-aligned.md')
    }
  ]
});
<commit_msg>docs: Make a header consistent with the others<commit_after>/* eslint-disable global-require, import/no-unresolved */
export default rootPath => ({
  title: 'Examples',
  props: {
    style: {
      borderTop: '2px solid #ddd'
    }
  },
  pages: [
    {
      path: `${rootPath}/all-features`,
      title: 'All Features',
      component: require('./all-features.md')
    },
    {
      path: `${rootPath}/adjusting-colspan`,
      title: 'Adjusting Colspan',
      component: require('./adjusting-colspan.md')
    },
    {
      path: `${rootPath}/crud`,
      title: 'CRUD',
      component: require('./crud.md')
    },
    {
      path: `${rootPath}/crud-redux`,
      title: 'CRUD with Redux',
      component: require('./crud-redux.md')
    },
    {
      path: `${rootPath}/excel`,
      title: 'Excel',
      component: require('./excel.md')
    },
    {
      path: `${rootPath}/expand-column-to-fit`,
      title: 'Expand Column to Fit',
      component: require('./expand-column-to-fit.md')
    },
    {
      path: `${rootPath}/fixed-width-columns`,
      title: 'Fixed Width Columns',
      component: require('./fixed-width-columns.md')
    },
    {
      path: `${rootPath}/infinite-scrolling`,
      title: 'Infinite Scrolling',
      component: require('./infinite-scrolling.md')
    },
    {
      path: `${rootPath}/multiple-async-instances`,
      title: 'Multiple Async Instances',
      component: require('./multiple-async-instances.md')
    },
    {
      imports: { styled: require('styled-components') },
      path: `${rootPath}/styled-components`,
      title: 'Styled Components',
      component: require('./styled-components.md')
    },
    {
      path: `${rootPath}/header-body-aligned`,
      title: 'Align Sticky Header and Body',
      component: require('./header-body-aligned.md')
    }
  ]
});
<|endoftext|>


<commit_before>/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */
//

// A token has properties: text, type, line, character position in the line
// (so we can ignore tabs), token channel, index, and source from which
// we obtained this token.

function Token() {
	this.source = null;
	this.type = null; // token type of the token
	this.channel = null; // The parser ignores everything not on DEFAULT_CHANNEL
	this.start = null; // optional; return -1 if not implemented.
	this.stop = null; // optional; return -1 if not implemented.
	this.tokenIndex = null; // from 0..n-1 of the token object in the input stream
	this.line = null; // line=1..n of the 1st character
	this.column = null; // beginning of the line at which it occurs, 0..n-1
	this._text = null; // text of the token.
	return this;
}

Token.INVALID_TYPE = 0;

// During lookahead operations, this "token" signifies we hit rule end ATN state
// and did not follow it despite needing to.
Token.EPSILON = -2;

Token.MIN_USER_TOKEN_TYPE = 1;

Token.EOF = -1;

// All tokens go to the parser (unless skip() is called in that rule)
// on a particular "channel". The parser tunes to a particular channel
// so that whitespace etc... can go to the parser on a "hidden" channel.

Token.DEFAULT_CHANNEL = 0;

// Anything on different channel than DEFAULT_CHANNEL is not parsed
// by parser.

Token.HIDDEN_CHANNEL = 1;

// Explicitly set the text for this token. If {code text} is not
// {@code null}, then {@link //getText} will return this value rather than
// extracting the text from the input.
//
// @param text The explicit text of the token, or {@code null} if the text
// should be obtained from the input along with the start and stop indexes
// of the token.

Object.defineProperty(Token.prototype, "text", {
	get : function() {
		return this._text;
	},
	set : function(text) {
		this._text = text;
	}
});

Token.prototype.getTokenSource = function() {
	return this.source[0];
};

Token.prototype.getInputStream = function() {
	return this.source[1];
};

function CommonToken(source, type, channel, start, stop) {
	Token.call(this);
	this.source = source !== undefined ? source : CommonToken.EMPTY_SOURCE;
	this.type = type !== undefined ? type : null;
	this.channel = channel !== undefined ? channel : Token.DEFAULT_CHANNEL;
	this.start = start !== undefined ? start : -1;
	this.stop = stop !== undefined ? stop : -1;
	this.tokenIndex = -1;
	if (this.source[0] !== null) {
		this.line = source[0].line;
		this.column = source[0].column;
	} else {
		this.column = -1;
	}
	return this;
}

CommonToken.prototype = Object.create(Token.prototype);
CommonToken.prototype.constructor = CommonToken;

// An empty {@link Pair} which is used as the default value of
// {@link //source} for tokens that do not have a source.
CommonToken.EMPTY_SOURCE = [ null, null ];

// Constructs a new {@link CommonToken} as a copy of another {@link Token}.
//
//

// If {@code oldToken} is also a {@link CommonToken} instance, the newly
// constructed token will share a reference to the {@link //text} field and
// the {@link Pair} stored in {@link //source}. Otherwise, {@link //text} will
// be assigned the result of calling {@link //getText}, and {@link //source}
// will be constructed from the result of {@link Token//getTokenSource} and
// {@link Token//getInputStream}.

//
// @param oldToken The token to copy.
//
CommonToken.prototype.clone = function() {
	var t = new CommonToken(this.source, this.type, this.channel, this.start,
			this.stop);
	t.tokenIndex = this.tokenIndex;
	t.line = this.line;
	t.column = this.column;
	t.text = this.text;
	return t;
};

Object.defineProperty(CommonToken.prototype, "text", {
	get : function() {
		if (this._text !== null) {
			return this._text;
		}
		var input = this.getInputStream();
		if (input === null) {
			return null;
		}
		var n = input.size;
		if (this.start < n && this.stop < n) {
			return input.getText(this.start, this.stop);
		} else {
			return "<EOF>";
		}
	},
	set : function(text) {
		this._text = text;
	}
});

CommonToken.prototype.toString = function() {
	var txt = this.text;
	if (txt !== null) {
		txt = txt.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
	} else {
		txt = "<no text>";
	}
	return "[@" + this.tokenIndex + "," + this.start + ":" + this.stop + "='" +
			txt + "',<" + this.type + ">" +
			(this.channel > 0 ? ",channel=" + this.channel : "") + "," +
			this.line + ":" + this.column + "]";
};

exports.Token = Token;
exports.CommonToken = CommonToken;
<commit_msg>refactored Token.js to use es6 classes use const/let for better scoping use jsdoc<commit_after>/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

/**
 * A token has properties: text, type, line, character position in the line
 * (so we can ignore tabs), token channel, index, and source from which
 * we obtained this token.
 */
class Token {
	constructor() {
		this.source = null;
		this.type = null; // token type of the token
		this.channel = null; // The parser ignores everything not on DEFAULT_CHANNEL
		this.start = null; // optional; return -1 if not implemented.
		this.stop = null; // optional; return -1 if not implemented.
		this.tokenIndex = null; // from 0..n-1 of the token object in the input stream
		this.line = null; // line=1..n of the 1st character
		this.column = null; // beginning of the line at which it occurs, 0..n-1
		this._text = null; // text of the token.
	}

	getTokenSource() {
		return this.source[0];
	}

	getInputStream() {
		return this.source[1];
	}

	get text(){
		return this._text;
	}

	set text(text) {
		this._text = text;
	}
}

Token.INVALID_TYPE = 0;

/**
 * During lookahead operations, this "token" signifies we hit rule end ATN state
 * and did not follow it despite needing to.
 */
Token.EPSILON = -2;

Token.MIN_USER_TOKEN_TYPE = 1;

Token.EOF = -1;

/**
 * All tokens go to the parser (unless skip() is called in that rule)
 * on a particular "channel". The parser tunes to a particular channel
 * so that whitespace etc... can go to the parser on a "hidden" channel.
 */
Token.DEFAULT_CHANNEL = 0;

/**
 * Anything on different channel than DEFAULT_CHANNEL is not parsed
 * by parser.
 */
Token.HIDDEN_CHANNEL = 1;

class CommonToken extends Token {
	constructor(source, type, channel, start, stop) {
		super();
		this.source = source !== undefined ? source : CommonToken.EMPTY_SOURCE;
		this.type = type !== undefined ? type : null;
		this.channel = channel !== undefined ? channel : Token.DEFAULT_CHANNEL;
		this.start = start !== undefined ? start : -1;
		this.stop = stop !== undefined ? stop : -1;
		this.tokenIndex = -1;
		if (this.source[0] !== null) {
			this.line = source[0].line;
			this.column = source[0].column;
		} else {
			this.column = -1;
		}
	}

	/**
	 * Constructs a new {@link CommonToken} as a copy of another {@link Token}.
	 *
	 *

	 * If {@code oldToken} is also a {@link CommonToken} instance, the newly
	 * constructed token will share a reference to the {@link //text} field and
	 * the {@link Pair} stored in {@link //source}. Otherwise, {@link //text} will
	 * be assigned the result of calling {@link //getText}, and {@link //source}
	 * will be constructed from the result of {@link Token//getTokenSource} and
	 * {@link Token//getInputStream}.

	 *
	 * @param oldToken The token to copy.
	 */
	clone() {
		const t = new CommonToken(this.source, this.type, this.channel, this.start, this.stop);
		t.tokenIndex = this.tokenIndex;
		t.line = this.line;
		t.column = this.column;
		t.text = this.text;
		return t;
	}

	toString() {
		let txt = this.text;
		if (txt !== null) {
			txt = txt.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
		} else {
			txt = "<no text>";
		}
		return "[@" + this.tokenIndex + "," + this.start + ":" + this.stop + "='" +
				txt + "',<" + this.type + ">" +
				(this.channel > 0 ? ",channel=" + this.channel : "") + "," +
				this.line + ":" + this.column + "]";
	}

	get text(){
		if (this._text !== null) {
			return this._text;
		}
		const input = this.getInputStream();
		if (input === null) {
			return null;
		}
		const n = input.size;
		if (this.start < n && this.stop < n) {
			return input.getText(this.start, this.stop);
		} else {
			return "<EOF>";
		}
	}

	set text(text) {
		this._text = text;
	}
}

/**
 * An empty {@link Pair} which is used as the default value of
 * {@link //source} for tokens that do not have a source.
 */
CommonToken.EMPTY_SOURCE = [ null, null ];

module.exports = {
	Token,
	CommonToken
}
<|endoftext|>


<commit_before>function (doc) {
    //!code util/emit_array.js
    //!code util/repeats.js

    if (doc.doc_type === 'XFormInstance' && (doc.domain === 'psi' || doc.domain === 'psi-unicef')) {
        var form = doc.form;

        if (form["@name"] !== 'Training Session') {
            return;
        }

        var opened_on = form.meta.timeEnd;

        var trainee_categories = ['private', 'public', 'depot_holder', 'flw_training'];
        var category_key_slugs = {
            private: 'priv',
            public: 'pub',
            depot_training: 'dep',
            flw_training: 'flw'
        };

        var num_trained = function(doctor_type) {
            return get_repeats(form.trainee_information, function(data) {
                return data.doctor_type == doctor_type;
            }).length;
        };

        var tc = form.trainee_category;
        var slug = false;
        for (var i = 0; i < trainee_categories.length; i++) {
            if (tc === trainee_categories[i]) {
                slug = category_key_slugs[tc];
                break;
            }
        }

        if (slug) {
            var data = {};
            data[slug+"_trained"] = 1;

            if (tc === 'private' || tc === 'public') {
                data[slug+"_allo_trained"] = num_trained('allopathic');
                data[slug+"_ayush_trained"] = num_trained('ayush');
            }

            //scores
            var trainees = get_repeats(form.trainee_information, function(t) { return t; });
            var num_gt80 = 0;
            for (var i = 0; i < trainees.length; i++) {
                if (trainees[i].post_test_score >= 80) num_gt80++;

                // emit the score_diff for each repeat. We do this because we want an average and each form may
                // not have the same number of repeats and the reduce views' average wouldn't be correct,
                var score_diff = (trainees[i].post_test_score || 0) - (trainees[i].pre_test_score || 0);
                emit([form.training_state, form.training_district, slug+'_avg_diff', opened_on, i], score_diff);
            }
            data[slug+"_gt80"] = num_gt80;
            emit_array([form.training_state, form.training_district], [opened_on], data);
        }
    }
}
<commit_msg>remove unnecessary index when emitting<commit_after>function (doc) {
    //!code util/emit_array.js
    //!code util/repeats.js

    if (doc.doc_type === 'XFormInstance' && (doc.domain === 'psi' || doc.domain === 'psi-unicef')) {
        var form = doc.form;

        if (form["@name"] !== 'Training Session') {
            return;
        }

        var opened_on = form.meta.timeEnd;

        var trainee_categories = ['private', 'public', 'depot_holder', 'flw_training'];
        var category_key_slugs = {
            private: 'priv',
            public: 'pub',
            depot_training: 'dep',
            flw_training: 'flw'
        };

        var num_trained = function(doctor_type) {
            return get_repeats(form.trainee_information, function(data) {
                return data.doctor_type == doctor_type;
            }).length;
        };

        var tc = form.trainee_category;
        var slug = false;
        for (var i = 0; i < trainee_categories.length; i++) {
            if (tc === trainee_categories[i]) {
                slug = category_key_slugs[tc];
                break;
            }
        }

        if (slug) {
            var data = {};
            data[slug+"_trained"] = 1;

            if (tc === 'private' || tc === 'public') {
                data[slug+"_allo_trained"] = num_trained('allopathic');
                data[slug+"_ayush_trained"] = num_trained('ayush');
            }

            //scores
            var trainees = get_repeats(form.trainee_information, function(t) { return t; });
            var num_gt80 = 0;
            for (var i = 0; i < trainees.length; i++) {
                if (trainees[i].post_test_score >= 80) num_gt80++;

                // emit the score_diff for each repeat. We do this because we want an average and each form may
                // not have the same number of repeats and the reduce views' average wouldn't be correct,
                var score_diff = (trainees[i].post_test_score || 0) - (trainees[i].pre_test_score || 0);
                emit([form.training_state, form.training_district, slug+'_avg_diff', opened_on], score_diff);
            }
            data[slug+"_gt80"] = num_gt80;
            emit_array([form.training_state, form.training_district], [opened_on], data);
        }
    }
}
<|endoftext|>


<commit_before>
function BaseCntl($scope, $location, HTTPService) {
	$scope.domain = window.location.origin;

	$scope.chapters;

	var getChapters = function() {
		HTTPService.getChapters().then(function(data) {
			console.log('data', data);
			$scope.chapters = data;
		});
	}

	var init = function() {
		getChapters();
	}
	init();
}

function ChapterCntl($scope, $routeParams, HTTPService) {
	$scope.chapterName = $routeParams.chapterName;
	$scope.subdirectories = {};

	var init = function() {

		HTTPService.getChapter($scope.chapterName).then(function(chapter) {
			for (subdirIndex in chapter) {
				var subdirectory = chapter[subdirIndex];

				HTTPService.getChapterSubdirectory($scope.chapterName, subdirectory).then(function(data) {
					$scope.subdirectories[data.subdirectory] = data.data;
				});
			}
		});

	}
	init();
}

<commit_msg>Using new data format<commit_after>
function BaseCntl($scope, $location, HTTPService) {
	$scope.domain = window.location.origin;

	$scope.chapters;

	var getChapters = function() {
		HTTPService.getChapters().then(function(data) {
			console.log('data', data);
			$scope.chapters = data;
		});
	}

	var init = function() {
		getChapters();
	}
	init();
}

function ChapterCntl($scope, $routeParams, HTTPService) {
	$scope.chapterName = $routeParams.chapterName;
	$scope.subdirectories = {};

	var init = function() {

		HTTPService.getChapter($scope.chapterName).then(function(chapter) {
			for (subdirIndex in chapter.submodules) {
				var subdirectory = chapter.submodules[subdirIndex];

				HTTPService.getChapterSubdirectory($scope.chapterName, subdirectory).then(function(data) {
					$scope.subdirectories[data.subdirectory] = data.data;
				});
			}
		});

	}
	init();
}

<|endoftext|>