<commit_before>var Game = function(boardString){
  var board = '';
  this.board = '';
  if (arguments.length === 1) {
    this.board = this.toArray(boardString);
  } else {
    function random() {
      return Math.floor(Math.random() * 10 + 6);
    };
    var firstTwo = random(), secondTwo = random();
    for ( var i = 0; i < 16; i++ ) {
      if (i === firstTwo || i === secondTwo) {
        board += '2';
      } else {
        board += '0';
      };
    };
    this.board = this.toArray(board);
  }
};

Game.prototype = {

  toString: function() {
    this.board.forEach(function(row) {
      console.log(row.join(''));
    });
  },

  toArray: function(chars) {
    var boardArray = [];
    for( var i = 0; i < 16; i += 4) {
      var subarray = chars.slice(0 + i, 4 + i);
      boardArray.push(subarray.split(''));
    }
    return boardArray;
  }
};

<commit_msg>Add method to filter zeros and add neighbors by direction<commit_after>var Game = function(boardString){
  var board = '';
  this.board = '';
  if (arguments.length === 1) {
    this.board = this.toArray(boardString);
  } else {
    function random() {
      return Math.floor(Math.random() * 10 + 6);
    };
    var firstTwo = random(), secondTwo = random();
    for ( var i = 0; i < 16; i++ ) {
      if (i === firstTwo || i === secondTwo) {
        board += '2';
      } else {
        board += '0';
      };
    };
    this.board = this.toArray(board);
  }
};

Game.prototype = {

  toString: function() {
    this.board.forEach(function(row) {
      console.log(row.join(''));
    });
  },

  toArray: function(chars) {
    var boardArray = [];
    for( var i = 0; i < 16; i += 4) {
      var subarray = chars.slice(i, 4 + i);
      boardArray.push(subarray.split(''));
    }
    return boardArray;
  },

  filterZeros: function(matrix) {
    filtered = []
    matrix.forEach(function(row) {
      filtered.push(row.filter(function(value) {
        return value !== '0';
      }));
    });
    return filtered
  },

  leftAddNumbers: function(subarrays) {
    subarrays.forEach(function(arr) {
      if (arr.length > 1){
        for(var i = 0; i < arr.length; i++){
          if (arr[i] === arr[i+1]){
            arr[i] = (parseInt(arr[i]) + parseInt(arr[i+1])).toString();
            arr.splice(i+1, 1);
          }
        }
      }
    })
    return subarrays;
  },

  rightAddNumbers: function(subarrays) {
    subarrays.forEach(function(arr) {
      if (arr.length > 1){
        for(var i = arr.length - 1; i > 0; i--) {
          if (arr[i] === arr[i-1]){
            arr[i] = (parseInt(arr[i]) + parseInt(arr[i-1])).toString();
            console.log(arr[i]);
            arr.splice(i-1, 1);
          }
        }
      }
    })
    return subarrays;

  },

  move: function(dir) {
    switch (dir) {
      case 'left':
        this.board = this.leftAddNumbers(this.filterZeros(this.board))
        this.board.forEach(function(row) {
          for( var i = 0; row.length < 4; i++ ) {
            row.push('0');
          }
        })
        break;
      case 'right':
        this.board = this.rightAddNumbers(this.filterZeros(this.board))
        this.board.forEach(function(row) {
          for( var i = 0; row.length < 4; i++ ) {
            row.unshift('0');
          }
        })
        break;
      case 'up':
        var transposedArray = _.zip.apply(null, this.board);
        transposedArray = this.filterZeros(transposedArray)
        transposedArray.forEach(function(row) {
          for( var i = 0; row.length < 4; i++ ) {
            row.push('0');
          }
        })
        this.board = _.zip.apply(null, transposedArray);
        break;
      case 'down':
        var transposedArray = _.zip.apply(null, this.board);
        transposedArray = this.filterZeros(transposedArray)
        transposedArray.forEach(function(row) {
          for( var i = 0; row.length < 4; i++ ) {
            row.unshift('0');
          }
        })
        this.board = _.zip.apply(null, transposedArray);
        break;
    }
  }
};

<|endoftext|>


<commit_before>var scene = new THREE.Scene();

//Center hexagon object
var hexagon = new THREE.Object3D();

//Camera
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 110;
camera.position.y = -30;
camera.position.x = -30;
camera.lookAt(scene.position);

//Raycaster
var raycaster = new THREE.Raycaster();

//Controls
var controls = new THREE.OrbitControls(camera);
controls.damping = 0.2;
controls.addEventListener('change', render);

//Keyboard
var keyboard = new THREEx.KeyboardState();

//Render
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
THREEx.WindowResize(renderer, camera);

var playing = false;

//Array containing the obstacles
var arrayObstacles = [];

//Array containing the background
var arrayBackground = [];

//Degrees of the level
// /!\ 360(modulo)degrees should be equal to 0
var degrees = 60;

//Number of obstacles
var n_obstacles_max = 360 / degrees;

//Obstacles.y
var spawn_y = 600;

//Obstacle width
var spawn_width = 8;

//Initial size of the obstacle,
var spawn_size;

//Rotation function var
var current_rotation;
var rotation_needed;

//Level var
var frames;
var spawn_obstacle_delay;
var obstacle_speed;
var fastrotate_level_delay;
var rotate_level_speed;
var fastrotate_level_speed;
var pattern_duration;
var current_pattern;
var current_obstacle_position;

var r;
var g;
var b;
var rgb;

spawn_size = (spawn_y * getTanDeg(degrees / 2)) * 2;

//Central hexagon
var geometry_hexagon = new THREE.CylinderGeometry(14, 14, 5, 0);
var hexagon1 = new THREE.Mesh(geometry_hexagon, new THREE.MeshBasicMaterial({
    color: new THREE.Color("rgb(20,245,117)"),
    opacity: 1
}));
hexagon1.position.x = 0;
hexagon1.position.y = 0;
hexagon1.rotation.x = 90 * (Math.PI / 180);
hexagon.add(hexagon1);

var geometry_hexagonbis = new THREE.CylinderGeometry(13, 13, 6, 0);
var hexagonbis = new THREE.Mesh(geometry_hexagonbis, new THREE.MeshBasicMaterial({
    color: new THREE.Color("rgb(0,0,0)"),
    opacity: 1
}));
hexagonbis.position.x = 0;
hexagonbis.position.y = 0;
hexagonbis.rotation.x = 90 * (Math.PI / 180);
hexagon.add(hexagonbis);

//Player
var geometry = new THREE.BoxGeometry(4, 3, 4);
var material = new THREE.MeshBasicMaterial({
    color: new THREE.Color("rgb(20,245,117)"),
    opacity: 1
});
var player = new THREE.Mesh(geometry, material);
player.geometry.vertices[0].x = player.geometry.vertices[2].x - 2;
player.geometry.vertices[1].x = player.geometry.vertices[1].x - 2;
player.geometry.vertices[4].x = player.geometry.vertices[6].x + 2;
player.geometry.vertices[5].x = player.geometry.vertices[6].x + 2;
player.geometry.verticesNeedUpdate = true;
player.position.z = 0;
player.position.x = 0;
player.position.y = 20;

function getTanDeg(deg) {
    var rad = deg * Math.PI / 180;
    return Math.tan(rad);
}

function rotateEuler(object, x, axis) {

    var eul = new THREE.Euler(0, 0, x, "XYZ");

    if (axis === "X")
        object.rotation.x = object.rotation.x + x;
    else if (axis === "Y")
        object.rotation.y = object.rotation.y + x;
    else if (axis === "Z")
        object.rotation.z = object.rotation.z + x;

    object.position = object.position.applyEuler(eul);
}

function setupScene() {

    resetGame();

    current_rotation = 0;
    rotation_needed = 0;
    frames = 0;
    spawn_obstacle_delay = 40;
    obstacle_speed = 0.0035;
    fastrotate_level_delay = 380;
    rotate_level_speed = 2;
    fastrotate_level_speed = 6;
    pattern_duration = 450;
    current_pattern = 1;
    current_obstacle_position = 1;

    rotateEuler(player, 0.0.1, "Z");

    scene.add(player);
    scene.add(hexagon);
    generateBackground();

}

function resetGame() {

    var children = scene.children;
    for(var i = children.length-1;i>=0;i--){
        var child = children[i];
        scene.remove(child);
    };

}

function generateBackground() {

    var tan_degree = 600 * getTanDeg(degrees);

    for (i = 0; i < n_obstacles_max; i++) {

        //triangles
        var t1 = new THREE.Geometry();

        t1.vertices.push(
            new THREE.Vector3(600, tan_degree, 0),
            new THREE.Vector3(600, 0, 0),
            new THREE.Vector3(0, 0, 0)
        );

        t1.faces.push(new THREE.Face3(0, 1, 2));

        var triangleMaterial;

        if (i % 2 === 0) {

            triangleMaterial = new THREE.MeshBasicMaterial({
                color: new THREE.Color("rgb(0,0,0)"),
                side: THREE.DoubleSide, transparent:true
            });

            triangleMaterial.opacity = 0.1;
        } else {

            triangleMaterial = new THREE.MeshBasicMaterial({
                color: new THREE.Color("rgb(3,38,18)"),
                side: THREE.DoubleSide, transparent:true
            });

            triangleMaterial.opacity = 0.3;
        }

        var triangleMesh = new THREE.Mesh(t1, triangleMaterial);

        triangleMesh.position.x = 0;
        triangleMesh.position.y = 0;
        triangleMesh.position.z = -1;

        rotateEuler(triangleMesh, ((degrees * i)+(degrees/2)) * (Math.PI / 180), "Z");

        arrayBackground.push(triangleMesh);
        scene.add(triangleMesh);
    }

}

function spawnObjects(pos) {

    var y = spawn_y;

    var material = new THREE.MeshBasicMaterial({
        color: new THREE.Color("rgb(20,245,117)"),
        opacity: 1
    });

    var geometry = new THREE.BoxGeometry(spawn_size, spawn_width, 4);

    var obstacle = new THREE.Mesh(geometry, material);

    obstacle.position.y = y;
    obstacle.position.z = 0;

    rotateEuler(obstacle, ((degrees / 2) + (degrees * (pos - 1))) * (Math.PI / 180), "Z");

    arrayObstacles.push(obstacle);
    scene.add(obstacle);

}

function rotateGame(speed) {

    scene.rotation.z += speed * (Math.PI / 180);

    if (rotation_needed > 0) {
        rotateEuler(scene, fastrotate_level_speed * (Math.PI / 180), "Z");
        rotation_needed -= Math.abs(speed * 4);
    }

}

function moveWithMusic() {

    console.log(boost);
    var scale = boost / 80;

    if (scale > 1) {

        if (scale > 1.1)
            scale = 1.1;

        hexagon.scale.x = (scale < 1 ? 1 : scale);
        hexagon.scale.y = (scale < 1 ? 1 : scale);
    }

}

function changeGameColors() {

    var color = getUiColor();
    var colorThree = new THREE.Color(color);

    if (typeof arrayObstacles === 'object' && arrayObstacles.length > 0) {
        for (var i = 0; i < arrayObstacles.length; i++) {
            arrayObstacles[i].material.color.set(colorThree);
        }
    }

    if (typeof arrayBackground === 'object' && arrayBackground.length > 0) {
        for (var i = 0; i < arrayBackground.length; i++) {
            arrayBackground[i].material.color.set(colorThree);
        }
    }

    player.material.color.set(colorThree);
    hexagon1.material.color.set(colorThree);
}

function switchPattern(pattern){

    current_pattern = pattern;
    current_obstacle_position = 1;

    if (pattern == 1){

      spawn_obstacle_delay = 40;
    }

   if (pattern == 2){
       spawn_obstacle_delay = 30;
    }

    if (pattern == 3){
       spawn_obstacle_delay = 50;
    }

    if (pattern == 4){
       spawn_obstacle_delay = 25;
    }

}

function followPattern(){

    if (current_pattern == 1){

        for (i = 0; i < n_obstacles_max-1; i++) {
            spawnObjects(Math.floor((Math.random() * n_obstacles_max) + 1));
        }

    }

   if (current_pattern == 2){

      var selected = Math.floor((Math.random() * n_obstacles_max) + 1);

       spawnObjects(selected);

      if (selected <= Math.floor(n_obstacles_max)/2){
        spawnObjects(selected + Math.floor(n_obstacles_max)/2);
          selected++;
      }
      else {
        spawnObjects(selected - Math.floor(n_obstacles_max)/2);
          selected--;
      }

      if (selected <= Math.floor(n_obstacles_max)/2)
        spawnObjects(selected + Math.floor(n_obstacles_max)/2);
      else
        spawnObjects(selected - Math.floor(n_obstacles_max)/2);

       spawnObjects(selected);

    }

    if (current_pattern == 3){

        var empty = Math.floor((Math.random() * n_obstacles_max) + 1);
        for (i = 1; i <= n_obstacles_max; i++) {

            if (i != empty)
                spawnObjects(i);
        }
    }

    if (current_pattern == 4){

        if (current_obstacle_position%2 != 0)
            for (i = 1; i <= n_obstacles_max; i++) {
                if (i % 2 == 0){
                    spawnObjects(i);
                    current_obstacle_position = i;
                }
            }
        else
            for (i = 1; i <= n_obstacles_max; i++) {
                if (i % 2 != 0){
                    spawnObjects(i);
                    current_obstacle_position = i;
                }
            }
    }

}

function moveBlocs(speed_percent) {

    if (typeof arrayObstacles === 'object' && arrayObstacles.length > 0) {
        for (var i = 0; i < arrayObstacles.length; i++) {

            var x = Math.abs(arrayObstacles[i].position.x);
            var y = Math.abs(arrayObstacles[i].position.y);

            //Distance of the obsctacle
            var k = arrayObstacles[i].position.distanceTo(new THREE.Vector3(0, 0, 0));
            var percent_base = spawn_y * speed_percent;
            var new_percent = ((percent_base) / k);

            //If the obstacle is still in front of the player
            if (k > 1) {

                arrayObstacles[i].position.setY(arrayObstacles[i].position.y - (arrayObstacles[i].position.y * new_percent));
                arrayObstacles[i].position.setX(arrayObstacles[i].position.x - (arrayObstacles[i].position.x * new_percent));

                k = arrayObstacles[i].position.distanceTo(new THREE.Vector3(0, 0, 0));

                var lenght_1 = ((k + (spawn_width / 2)) * getTanDeg(degrees / 2));
                var lenght_2 = ((k - (spawn_width / 2)) * getTanDeg(degrees / 2));

                arrayObstacles[i].geometry.vertices[0].x = lenght_1;
                arrayObstacles[i].geometry.vertices[1].x = lenght_1;
                arrayObstacles[i].geometry.vertices[2].x = lenght_2;
                arrayObstacles[i].geometry.vertices[3].x = lenght_2;
                arrayObstacles[i].geometry.vertices[4].x = -lenght_1;
                arrayObstacles[i].geometry.vertices[5].x = -lenght_1;
                arrayObstacles[i].geometry.vertices[6].x = -lenght_2;
                arrayObstacles[i].geometry.vertices[7].x = -lenght_2;

                //indicate that the vertices need update
                arrayObstacles[i].geometry.verticesNeedUpdate = true;

            //Else the obstacle is deleted
            } else {

                scene.remove(arrayObstacles[i]);
                arrayObstacles.splice(i, 1);
                i--;
            }

        }
    }

    var vector = new THREE.Vector3();
    vector.setFromMatrixPosition(player.matrixWorld);

    var or = new THREE.Vector3(vector.x * 0.99, vector.y * 0.99, 0);
    var dir = new THREE.Vector3().subVectors(vector, or).normalize();

    //Update the picking ray with the camera and mouse position
    raycaster.set(or, dir);

    //Calculate objects intersecting the picking ray
    var intersects = raycaster.intersectObjects(scene.children);

    if (intersects.length > 0) {
        if (intersects[0].distance < 5) {
            intersects[0].object.material.color.set(0xffffff);
            playing = false;
            gameOver();
        }

    }

}

var render = function() {

    requestAnimationFrame(render);

    changeGameColors();

    rotateGame(rotate_level_speed);

    if (playing) {

        //moveWithMusic();

        if (frames % pattern_duration == 0){
            switchPattern(Math.floor((Math.random() * 4) + 1));
        }

        moveBlocs(obstacle_speed);

        if (keyboard.pressed("left")) {
            rotateEuler(player, 0.15, "Z");
        }

        if (keyboard.pressed("right")) {
            rotateEuler(player, -0.15, "Z");
        }

        if (frames % spawn_obstacle_delay == 0) {
            followPattern();
        }

        if (frames % fastrotate_level_delay == 0) {
            rotation_needed = 180;
        }

        if (frames % 600 == 0) {
            rotate_level_speed = rotate_level_speed * -1;
        }

        frames++;

        displayTime(frames, '#current_n');
        store(frames);

    }

     renderer.render(scene, camera);
};

setupScene();
render();
<commit_msg>Fix#2<commit_after>var scene = new THREE.Scene();

//Center hexagon object
var hexagon = new THREE.Object3D();

//Camera
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 110;
camera.position.y = -30;
camera.position.x = -30;
camera.lookAt(scene.position);

//Raycaster
var raycaster = new THREE.Raycaster();

//Controls
var controls = new THREE.OrbitControls(camera);
controls.damping = 0.2;
controls.addEventListener('change', render);

//Keyboard
var keyboard = new THREEx.KeyboardState();

//Render
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
THREEx.WindowResize(renderer, camera);

var playing = false;

//Array containing the obstacles
var arrayObstacles = [];

//Array containing the background
var arrayBackground = [];

//Degrees of the level
// /!\ 360(modulo)degrees should be equal to 0
var degrees = 60;

//Number of obstacles
var n_obstacles_max = 360 / degrees;

//Obstacles.y
var spawn_y = 600;

//Obstacle width
var spawn_width = 8;

//Initial size of the obstacle,
var spawn_size;

//Rotation function var
var current_rotation;
var rotation_needed;

//Level var
var frames;
var spawn_obstacle_delay;
var obstacle_speed;
var fastrotate_level_delay;
var rotate_level_speed;
var fastrotate_level_speed;
var pattern_duration;
var current_pattern;
var current_obstacle_position;

var r;
var g;
var b;
var rgb;

spawn_size = (spawn_y * getTanDeg(degrees / 2)) * 2;

//Central hexagon
var geometry_hexagon = new THREE.CylinderGeometry(14, 14, 5, 0);
var hexagon1 = new THREE.Mesh(geometry_hexagon, new THREE.MeshBasicMaterial({
    color: new THREE.Color("rgb(20,245,117)"),
    opacity: 1
}));
hexagon1.position.x = 0;
hexagon1.position.y = 0;
hexagon1.rotation.x = 90 * (Math.PI / 180);
hexagon.add(hexagon1);

var geometry_hexagonbis = new THREE.CylinderGeometry(13, 13, 6, 0);
var hexagonbis = new THREE.Mesh(geometry_hexagonbis, new THREE.MeshBasicMaterial({
    color: new THREE.Color("rgb(0,0,0)"),
    opacity: 1
}));
hexagonbis.position.x = 0;
hexagonbis.position.y = 0;
hexagonbis.rotation.x = 90 * (Math.PI / 180);
hexagon.add(hexagonbis);

//Player
var geometry = new THREE.BoxGeometry(4, 3, 4);
var material = new THREE.MeshBasicMaterial({
    color: new THREE.Color("rgb(20,245,117)"),
    opacity: 1
});
var player = new THREE.Mesh(geometry, material);
player.geometry.vertices[0].x = player.geometry.vertices[2].x - 2;
player.geometry.vertices[1].x = player.geometry.vertices[1].x - 2;
player.geometry.vertices[4].x = player.geometry.vertices[6].x + 2;
player.geometry.vertices[5].x = player.geometry.vertices[6].x + 2;
player.geometry.verticesNeedUpdate = true;
player.position.z = 0;
player.position.x = 0;
player.position.y = 20;

function getTanDeg(deg) {
    var rad = deg * Math.PI / 180;
    return Math.tan(rad);
}

function rotateEuler(object, x, axis) {

    var eul = new THREE.Euler(0, 0, x, "XYZ");

    if (axis === "X")
        object.rotation.x = object.rotation.x + x;
    else if (axis === "Y")
        object.rotation.y = object.rotation.y + x;
    else if (axis === "Z")
        object.rotation.z = object.rotation.z + x;

    object.position = object.position.applyEuler(eul);
}

function setupScene() {

    resetGame();

    current_rotation = 0;
    rotation_needed = 0;
    frames = 0;
    spawn_obstacle_delay = 40;
    obstacle_speed = 0.0035;
    fastrotate_level_delay = 380;
    rotate_level_speed = 2;
    fastrotate_level_speed = 6;
    pattern_duration = 450;
    current_pattern = 1;
    current_obstacle_position = 1;

    scene.add(player);
    scene.add(hexagon);
    generateBackground();

}

function resetGame() {

    var children = scene.children;
    for(var i = children.length-1;i>=0;i--){
        var child = children[i];
        scene.remove(child);
    };

}

function generateBackground() {

    var tan_degree = 600 * getTanDeg(degrees);

    for (i = 0; i < n_obstacles_max; i++) {

        //triangles
        var t1 = new THREE.Geometry();

        t1.vertices.push(
            new THREE.Vector3(600, tan_degree, 0),
            new THREE.Vector3(600, 0, 0),
            new THREE.Vector3(0, 0, 0)
        );

        t1.faces.push(new THREE.Face3(0, 1, 2));

        var triangleMaterial;

        if (i % 2 === 0) {

            triangleMaterial = new THREE.MeshBasicMaterial({
                color: new THREE.Color("rgb(0,0,0)"),
                side: THREE.DoubleSide, transparent:true
            });

            triangleMaterial.opacity = 0.1;
        } else {

            triangleMaterial = new THREE.MeshBasicMaterial({
                color: new THREE.Color("rgb(3,38,18)"),
                side: THREE.DoubleSide, transparent:true
            });

            triangleMaterial.opacity = 0.3;
        }

        var triangleMesh = new THREE.Mesh(t1, triangleMaterial);

        triangleMesh.position.x = 0;
        triangleMesh.position.y = 0;
        triangleMesh.position.z = -1;

        rotateEuler(triangleMesh, ((degrees * i)+(degrees/2)) * (Math.PI / 180), "Z");

        arrayBackground.push(triangleMesh);
        scene.add(triangleMesh);
    }

}

function spawnObjects(pos) {

    var y = spawn_y;

    var material = new THREE.MeshBasicMaterial({
        color: new THREE.Color("rgb(20,245,117)"),
        opacity: 1
    });

    var geometry = new THREE.BoxGeometry(spawn_size, spawn_width, 4);

    var obstacle = new THREE.Mesh(geometry, material);

    obstacle.position.y = y;
    obstacle.position.z = 0;

    rotateEuler(obstacle, ((degrees / 2) + (degrees * (pos - 1))) * (Math.PI / 180), "Z");

    arrayObstacles.push(obstacle);
    scene.add(obstacle);

}

function rotateGame(speed) {

    scene.rotation.z += speed * (Math.PI / 180);

    if (rotation_needed > 0) {
        rotateEuler(scene, fastrotate_level_speed * (Math.PI / 180), "Z");
        rotation_needed -= Math.abs(speed * 4);
    }

}

function moveWithMusic() {

    console.log(boost);
    var scale = boost / 80;

    if (scale > 1) {

        if (scale > 1.1)
            scale = 1.1;

        hexagon.scale.x = (scale < 1 ? 1 : scale);
        hexagon.scale.y = (scale < 1 ? 1 : scale);
    }

}

function changeGameColors() {

    var color = getUiColor();
    var colorThree = new THREE.Color(color);

    if (typeof arrayObstacles === 'object' && arrayObstacles.length > 0) {
        for (var i = 0; i < arrayObstacles.length; i++) {
            arrayObstacles[i].material.color.set(colorThree);
        }
    }

    if (typeof arrayBackground === 'object' && arrayBackground.length > 0) {
        for (var i = 0; i < arrayBackground.length; i++) {
            arrayBackground[i].material.color.set(colorThree);
        }
    }

    player.material.color.set(colorThree);
    hexagon1.material.color.set(colorThree);
}

function switchPattern(pattern){

    current_pattern = pattern;
    current_obstacle_position = 1;

    if (pattern == 1){

      spawn_obstacle_delay = 40;
    }

   if (pattern == 2){
       spawn_obstacle_delay = 30;
    }

    if (pattern == 3){
       spawn_obstacle_delay = 50;
    }

    if (pattern == 4){
       spawn_obstacle_delay = 25;
    }

}

function followPattern(){

    if (current_pattern == 1){

        for (i = 0; i < n_obstacles_max-1; i++) {
            spawnObjects(Math.floor((Math.random() * n_obstacles_max) + 1));
        }

    }

   if (current_pattern == 2){

      var selected = Math.floor((Math.random() * n_obstacles_max) + 1);

       spawnObjects(selected);

      if (selected <= Math.floor(n_obstacles_max)/2){
        spawnObjects(selected + Math.floor(n_obstacles_max)/2);
          selected++;
      }
      else {
        spawnObjects(selected - Math.floor(n_obstacles_max)/2);
          selected--;
      }

      if (selected <= Math.floor(n_obstacles_max)/2)
        spawnObjects(selected + Math.floor(n_obstacles_max)/2);
      else
        spawnObjects(selected - Math.floor(n_obstacles_max)/2);

       spawnObjects(selected);

    }

    if (current_pattern == 3){

        var empty = Math.floor((Math.random() * n_obstacles_max) + 1);
        for (i = 1; i <= n_obstacles_max; i++) {

            if (i != empty)
                spawnObjects(i);
        }
    }

    if (current_pattern == 4){

        if (current_obstacle_position%2 != 0)
            for (i = 1; i <= n_obstacles_max; i++) {
                if (i % 2 == 0){
                    spawnObjects(i);
                    current_obstacle_position = i;
                }
            }
        else
            for (i = 1; i <= n_obstacles_max; i++) {
                if (i % 2 != 0){
                    spawnObjects(i);
                    current_obstacle_position = i;
                }
            }
    }

}

function moveBlocs(speed_percent) {

    if (typeof arrayObstacles === 'object' && arrayObstacles.length > 0) {
        for (var i = 0; i < arrayObstacles.length; i++) {

            var x = Math.abs(arrayObstacles[i].position.x);
            var y = Math.abs(arrayObstacles[i].position.y);

            //Distance of the obsctacle
            var k = arrayObstacles[i].position.distanceTo(new THREE.Vector3(0, 0, 0));
            var percent_base = spawn_y * speed_percent;
            var new_percent = ((percent_base) / k);

            //If the obstacle is still in front of the player
            if (k > 1) {

                arrayObstacles[i].position.setY(arrayObstacles[i].position.y - (arrayObstacles[i].position.y * new_percent));
                arrayObstacles[i].position.setX(arrayObstacles[i].position.x - (arrayObstacles[i].position.x * new_percent));

                k = arrayObstacles[i].position.distanceTo(new THREE.Vector3(0, 0, 0));

                var lenght_1 = ((k + (spawn_width / 2)) * getTanDeg(degrees / 2));
                var lenght_2 = ((k - (spawn_width / 2)) * getTanDeg(degrees / 2));

                arrayObstacles[i].geometry.vertices[0].x = lenght_1;
                arrayObstacles[i].geometry.vertices[1].x = lenght_1;
                arrayObstacles[i].geometry.vertices[2].x = lenght_2;
                arrayObstacles[i].geometry.vertices[3].x = lenght_2;
                arrayObstacles[i].geometry.vertices[4].x = -lenght_1;
                arrayObstacles[i].geometry.vertices[5].x = -lenght_1;
                arrayObstacles[i].geometry.vertices[6].x = -lenght_2;
                arrayObstacles[i].geometry.vertices[7].x = -lenght_2;

                //indicate that the vertices need update
                arrayObstacles[i].geometry.verticesNeedUpdate = true;

            //Else the obstacle is deleted
            } else {

                scene.remove(arrayObstacles[i]);
                arrayObstacles.splice(i, 1);
                i--;
            }

        }
    }

    var vector = new THREE.Vector3();
    vector.setFromMatrixPosition(player.matrixWorld);

    var or = new THREE.Vector3(vector.x * 0.99, vector.y * 0.99, 0);
    var dir = new THREE.Vector3().subVectors(vector, or).normalize();

    //Update the picking ray
    raycaster.set(or, dir);

    //Calculate objects intersecting the picking ray
    var intersects = raycaster.intersectObjects(scene.children);

    if (intersects.length > 0) {
        if (intersects[0].distance < 5) {
            intersects[0].object.material.color.set(0xffffff);
            playing = false;
            gameOver();
        }

    }

}

var render = function() {

    requestAnimationFrame(render);

    changeGameColors();

    rotateGame(rotate_level_speed);

    if (playing) {

        //moveWithMusic();

        if (frames % pattern_duration == 0){
            switchPattern(Math.floor((Math.random() * 4) + 1));
        }

        moveBlocs(obstacle_speed);

        if (keyboard.pressed("left")) {
            rotateEuler(player, 0.15, "Z");
        }

        if (keyboard.pressed("right")) {
            rotateEuler(player, -0.15, "Z");
        }

        if (frames % spawn_obstacle_delay == 0) {
            followPattern();
        }

        if (frames % fastrotate_level_delay == 0) {
            rotation_needed = 180;
        }

        if (frames % 600 == 0) {
            rotate_level_speed = rotate_level_speed * -1;
        }

        frames++;

        displayTime(frames, '#current_n');
        store(frames);

    }
    else
        rotateEuler(player, -0.05, "Z");

     renderer.render(scene, camera);
};

setupScene();
render();
<|endoftext|>


<commit_before>(function($){
  $(function(){

    $('.button-collapse').sideNav();
    $('.parallax').parallax();

  }); // end of document ready
})(jQuery); // end of jQuery name space<commit_msg>modal initialization with jquery<commit_after>(function($){
  $(function(){

    $('.button-collapse').sideNav();
    $('.parallax').parallax();

  }); // end of document ready
})(jQuery); // end of jQuery name space

$(document).ready(function () {
  // the "href" attribute of the modal trigger must specify the modal ID that wants to be triggered
  $('.modal').modal();
});<|endoftext|>


<commit_before>'use strict';

// ---------------------------------------------------------------------------

const acx = require ('./acx.js');
const { ExchangeError, InsufficientFunds, OrderNotFound } = require ('./base/errors');

// ---------------------------------------------------------------------------

module.exports = class kuna extends acx {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'kuna',
            'name': 'Kuna',
            'countries': 'UA',
            'rateLimit': 1000,
            'version': 'v2',
            'has': {
                'CORS': false,
                'fetchTickers': false,
                'fetchOHLCV': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/31697638-912824fa-b3c1-11e7-8c36-cf9606eb94ac.jpg',
                'api': 'https://kuna.io',
                'www': 'https://kuna.io',
                'doc': 'https://kuna.io/documents/api',
                'fees': 'https://kuna.io/documents/api',
            },
            'api': {
                'public': {
                    'get': [
                        'tickers/{market}',
                        'order_book',
                        'order_book/{market}',
                        'trades',
                        'trades/{market}',
                        'timestamp',
                    ],
                },
                'private': {
                    'get': [
                        'members/me',
                        'orders',
                        'trades/my',
                    ],
                    'post': [
                        'orders',
                        'order/delete',
                    ],
                },
            },
            'markets': {
                'BTC/UAH': { 'id': 'btcuah', 'symbol': 'BTC/UAH', 'base': 'BTC', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'ETH/UAH': { 'id': 'ethuah', 'symbol': 'ETH/UAH', 'base': 'ETH', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'GBG/UAH': { 'id': 'gbguah', 'symbol': 'GBG/UAH', 'base': 'GBG', 'quote': 'UAH', 'precision': { 'amount': 3, 'price': 2 }, 'lot': 0.001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 0.01, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}}, // Golos Gold (GBG != GOLOS)
                'KUN/BTC': { 'id': 'kunbtc', 'symbol': 'KUN/BTC', 'base': 'KUN', 'quote': 'BTC', 'precision': { 'amount': 6, 'price': 6 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 0.000001, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'BCH/BTC': { 'id': 'bchbtc', 'symbol': 'BCH/BTC', 'base': 'BCH', 'quote': 'BTC', 'precision': { 'amount': 6, 'price': 6 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 0.000001, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'BCH/UAH': { 'id': 'bchuah', 'symbol': 'BCH/UAH', 'base': 'BCH', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'WAVES/UAH': { 'id': 'wavesuah', 'symbol': 'WAVES/UAH', 'base': 'WAVES', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'ARN/BTC': { 'id': 'arnbtc', 'symbol': 'ARN/BTC', 'base': 'ARN', 'quote': 'BTC' },
                'B2B/BTC': { 'id': 'b2bbtc', 'symbol': 'B2B/BTC', 'base': 'B2B', 'quote': 'BTC' },
                'EVR/BTC': { 'id': 'evrbtc', 'symbol': 'EVR/BTC', 'base': 'EVR', 'quote': 'BTC' },
                'GOL/GBG': { 'id': 'golgbg', 'symbol': 'GOL/GBG', 'base': 'GOL', 'quote': 'GBG' },
                'R/BTC': { 'id': 'rbtc', 'symbol': 'R/BTC', 'base': 'R', 'quote': 'BTC' },
                'RMC/BTC': { 'id': 'rmcbtc', 'symbol': 'RMC/BTC', 'base': 'RMC', 'quote': 'BTC' },
            },
            'fees': {
                'trading': {
                    'taker': 0.25 / 100,
                    'maker': 0.25 / 100,
                },
                'funding': {
                    'withdraw': {
                        'UAH': '1%',
                        'BTC': 0.001,
                        'BCH': 0.001,
                        'ETH': 0.01,
                        'WAVES': 0.01,
                        'GOL': 0.0,
                        'GBG': 0.0,
                        // 'RMC': 0.001 BTC
                        // 'ARN': 0.01 ETH
                        // 'R': 0.01 ETH
                        // 'EVR': 0.01 ETH
                    },
                    'deposit': {
                        // 'UAH': (amount) => amount * 0.001 + 5
                    },
                },
            },
        });
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (code === 400) {
            let response = JSON.parse (body);
            let error = this.safeValue (response, 'error');
            let errorCode = this.safeInteger (error, 'code');
            if (errorCode === 2002) {
                throw new InsufficientFunds ([ this.id, method, url, code, reason, body ].join (' '));
            } else if (errorCode === 2003) {
                throw new OrderNotFound ([ this.id, method, url, code, reason, body ].join (' '));
            }
        }
    }

    async fetchOrderBook (symbol, params = {}) {
        let market = this.market (symbol);
        let orderBook = await this.publicGetOrderBook (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseOrderBook (orderBook, undefined, 'bids', 'asks', 'price', 'remaining_volume');
    }

    async fetchL3OrderBook (symbol, params) {
        return this.fetchOrderBook (symbol, params);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (!symbol)
            throw new ExchangeError (this.id + ' fetchOpenOrders requires a symbol argument');
        let market = this.market (symbol);
        let orders = await this.privateGetOrders (this.extend ({
            'market': market['id'],
        }, params));
        // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder
        // with order cache + fetchOpenOrders
        // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX
        return this.parseOrders (orders, market, since, limit);
    }

    parseTrade (trade, market = undefined) {
        let timestamp = this.parse8601 (trade['created_at']);
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'id': trade['id'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': undefined,
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['volume']),
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        let market = this.market (symbol);
        let response = await this.publicGetTrades (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    parseMyTrade (trade, market) {
        let timestamp = this.parse8601 (trade['created_at']);
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'id': trade['id'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'price': trade['price'],
            'amount': trade['volume'],
            'cost': trade['funds'],
            'symbol': symbol,
            'side': trade['side'],
            'order': trade['order_id'],
        };
    }

    parseMyTrades (trades, market = undefined) {
        let parsedTrades = [];
        for (let i = 0; i < trades.length; i++) {
            let trade = trades[i];
            let parsedTrade = this.parseMyTrade (trade, market);
            parsedTrades.push (parsedTrade);
        }
        return parsedTrades;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (!symbol)
            throw new ExchangeError (this.id + ' fetchOpenOrders requires a symbol argument');
        let market = this.market (symbol);
        let response = await this.privateGetTradesMy ({ 'market': market['id'] });
        return this.parseMyTrades (response, market);
    }
};
<commit_msg>kuna now passes the tests<commit_after>'use strict';

// ---------------------------------------------------------------------------

const acx = require ('./acx.js');
const { ExchangeError, InsufficientFunds, OrderNotFound } = require ('./base/errors');

// ---------------------------------------------------------------------------

module.exports = class kuna extends acx {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'kuna',
            'name': 'Kuna',
            'countries': 'UA',
            'rateLimit': 1000,
            'version': 'v2',
            'has': {
                'CORS': false,
                'fetchTickers': false,
                'fetchOHLCV': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/31697638-912824fa-b3c1-11e7-8c36-cf9606eb94ac.jpg',
                'api': 'https://kuna.io',
                'www': 'https://kuna.io',
                'doc': 'https://kuna.io/documents/api',
                'fees': 'https://kuna.io/documents/api',
            },
            'api': {
                'public': {
                    'get': [
                        'tickers/{market}',
                        'order_book',
                        'order_book/{market}',
                        'trades',
                        'trades/{market}',
                        'timestamp',
                    ],
                },
                'private': {
                    'get': [
                        'members/me',
                        'orders',
                        'trades/my',
                    ],
                    'post': [
                        'orders',
                        'order/delete',
                    ],
                },
            },
            'markets': {
                'BTC/UAH': { 'id': 'btcuah', 'symbol': 'BTC/UAH', 'base': 'BTC', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'ETH/UAH': { 'id': 'ethuah', 'symbol': 'ETH/UAH', 'base': 'ETH', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'GBG/UAH': { 'id': 'gbguah', 'symbol': 'GBG/UAH', 'base': 'GBG', 'quote': 'UAH', 'precision': { 'amount': 3, 'price': 2 }, 'lot': 0.001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 0.01, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}}, // Golos Gold (GBG != GOLOS)
                'KUN/BTC': { 'id': 'kunbtc', 'symbol': 'KUN/BTC', 'base': 'KUN', 'quote': 'BTC', 'precision': { 'amount': 6, 'price': 6 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 0.000001, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'BCH/BTC': { 'id': 'bchbtc', 'symbol': 'BCH/BTC', 'base': 'BCH', 'quote': 'BTC', 'precision': { 'amount': 6, 'price': 6 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 0.000001, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'BCH/UAH': { 'id': 'bchuah', 'symbol': 'BCH/UAH', 'base': 'BCH', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'WAVES/UAH': { 'id': 'wavesuah', 'symbol': 'WAVES/UAH', 'base': 'WAVES', 'quote': 'UAH', 'precision': { 'amount': 6, 'price': 0 }, 'lot': 0.000001, 'limits': { 'amount': { 'min': 0.000001, 'max': undefined }, 'price': { 'min': 1, 'max': undefined }, 'cost': { 'min': 0.000001, 'max': undefined }}},
                'ARN/BTC': { 'id': 'arnbtc', 'symbol': 'ARN/BTC', 'base': 'ARN', 'quote': 'BTC' },
                'B2B/BTC': { 'id': 'b2bbtc', 'symbol': 'B2B/BTC', 'base': 'B2B', 'quote': 'BTC' },
                'EVR/BTC': { 'id': 'evrbtc', 'symbol': 'EVR/BTC', 'base': 'EVR', 'quote': 'BTC' },
                'GOL/GBG': { 'id': 'golgbg', 'symbol': 'GOL/GBG', 'base': 'GOL', 'quote': 'GBG' },
                'R/BTC': { 'id': 'rbtc', 'symbol': 'R/BTC', 'base': 'R', 'quote': 'BTC' },
                'RMC/BTC': { 'id': 'rmcbtc', 'symbol': 'RMC/BTC', 'base': 'RMC', 'quote': 'BTC' },
            },
            'fees': {
                'trading': {
                    'taker': 0.25 / 100,
                    'maker': 0.25 / 100,
                },
                'funding': {
                    'withdraw': {
                        'UAH': '1%',
                        'BTC': 0.001,
                        'BCH': 0.001,
                        'ETH': 0.01,
                        'WAVES': 0.01,
                        'GOL': 0.0,
                        'GBG': 0.0,
                        // 'RMC': 0.001 BTC
                        // 'ARN': 0.01 ETH
                        // 'R': 0.01 ETH
                        // 'EVR': 0.01 ETH
                    },
                    'deposit': {
                        // 'UAH': (amount) => amount * 0.001 + 5
                    },
                },
            },
        });
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (code === 400) {
            let response = JSON.parse (body);
            let error = this.safeValue (response, 'error');
            let errorCode = this.safeInteger (error, 'code');
            if (errorCode === 2002) {
                throw new InsufficientFunds ([ this.id, method, url, code, reason, body ].join (' '));
            } else if (errorCode === 2003) {
                throw new OrderNotFound ([ this.id, method, url, code, reason, body ].join (' '));
            }
        }
    }

    async fetchOrderBook (symbol, params = {}) {
        let market = this.market (symbol);
        let orderBook = await this.publicGetOrderBook (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseOrderBook (orderBook, undefined, 'bids', 'asks', 'price', 'remaining_volume');
    }

    async fetchL3OrderBook (symbol, params) {
        return this.fetchOrderBook (symbol, params);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (!symbol)
            throw new ExchangeError (this.id + ' fetchOpenOrders requires a symbol argument');
        let market = this.market (symbol);
        let orders = await this.privateGetOrders (this.extend ({
            'market': market['id'],
        }, params));
        // todo emulation of fetchClosedOrders, fetchOrders, fetchOrder
        // with order cache + fetchOpenOrders
        // as in BTC-e, Liqui, Yobit, DSX, Tidex, WEX
        return this.parseOrders (orders, market, since, limit);
    }

    parseTrade (trade, market = undefined) {
        let timestamp = this.parse8601 (trade['created_at']);
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'id': trade['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': undefined,
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['volume']),
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        let market = this.market (symbol);
        let response = await this.publicGetTrades (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    parseMyTrade (trade, market) {
        let timestamp = this.parse8601 (trade['created_at']);
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'id': trade['id'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'price': trade['price'],
            'amount': trade['volume'],
            'cost': trade['funds'],
            'symbol': symbol,
            'side': trade['side'],
            'order': trade['order_id'],
        };
    }

    parseMyTrades (trades, market = undefined) {
        let parsedTrades = [];
        for (let i = 0; i < trades.length; i++) {
            let trade = trades[i];
            let parsedTrade = this.parseMyTrade (trade, market);
            parsedTrades.push (parsedTrade);
        }
        return parsedTrades;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (!symbol)
            throw new ExchangeError (this.id + ' fetchOpenOrders requires a symbol argument');
        let market = this.market (symbol);
        let response = await this.privateGetTradesMy ({ 'market': market['id'] });
        return this.parseMyTrades (response, market);
    }
};
<|endoftext|>


<commit_before>function register() {
  window.location = 'https://api.twitch.tv/kraken/oauth2/authorize?response_type=token&client_id=cx94gjhz4ful945h0a3b4hbntiscia&redirect_uri=http://nico.kuro.ml&scope=chat_login';
}

function check() {
  var parser = document.createElement('a');
  parser.href = window.location.href;

  if (parser.hash.indexOf('#access_token=') > -1 && parser.hash.indexOf('&scope=chat_login') > -1) {
    //document.getElementById('url').style.visibility = 'visible';
    generate();
  } else {
    //document.getElementById('url').style.visibility = 'hidden';
  }
}

function generate() {
  //var chanName = document.getElementById('chanID');
  //var chanName = 'creditsToKuromachii'
  var parser = document.createElement('a');
  parser.href = window.location.href;
  var hash = parser.hash.replace('#access_token=','')
  hash = hash.replace('&scope=chat_login','')

  window.location = 'http://nico.kuro.ml/chat?token='+hash;//+'&chan_name='+chanName;
}

function load() {
  var parser = document.createElement('a');
  parser.href = window.location.href;
  var token = parser.search.split("token=")[1];
  //var token = parser.search.split("&chan_name=")[0].split("token=")[1];
  //var channelName = parser.search.split('&chan_name=').pop();

  //console.log(token);
  chat(token);
}

function chat(token) {
    var oauth = token;

    // You have to run .setup() before anything besides .listen()
    TAPIC.setup(oauth, function (username) {

      // By default, TAPIC refreshes API information every 5 seconds, which is the minimum.
      // Setting the refresh rate is optional.
      //TAPIC.setRefreshRate(10);

      // This is also required for a lot of things to work
       TAPIC.joinChannel(username, function () {
             tests();
         });
    });

    TAPIC.listen('message', function (e) {
      var output = '' +
        e.from +
        '' +
        (e.action ? '' : ':  ') +
        e.text +
        (e.action ? '' : '' );
        // e.emotes is the emotes, e.g. '25:0-4,12-16/1902:6-10'
        // https://github.com/justintv/Twitch-API/blob/master/IRC.md#privmsg
        // e.badges is an array of badges: https://discuss.dev.twitch.tv/t/beta-badge-api/6388
      writeChat( output );
    });
    // TAPIC.listen('echoChat', function (e) {
    //   var output = '' + TAPIC.getDisplayName() +
    //     ' : ' + e;
    //   writeChat( output );
    // });
}

// This is for the webpage's chat, it doesn't have anything directly to do with TAPIC.js
function writeChat(msg) {
  document.getElementById('chat').innerHTML += msg + '
';
  document.getElementById('chat').scrollTop = Number.MAX_SAFE_INTEGER;
}
<commit_msg>Little update<commit_after>function register() {
  window.location = 'https://api.twitch.tv/kraken/oauth2/authorize?response_type=token&client_id=cx94gjhz4ful945h0a3b4hbntiscia&redirect_uri=http://nico.kuro.ml&scope=chat_login';
}

function check() {
  var parser = document.createElement('a');
  parser.href = window.location.href;

  if (parser.hash.indexOf('#access_token=') > -1 && parser.hash.indexOf('&scope=chat_login') > -1) {
    //document.getElementById('url').style.visibility = 'visible';
    generate();
  } else {
    //document.getElementById('url').style.visibility = 'hidden';
  }
}

function generate() {
  //var chanName = document.getElementById('chanID');
  //var chanName = 'creditsToKuromachii'
  var parser = document.createElement('a');
  parser.href = window.location.href;
  var hash = parser.hash.replace('#access_token=','')
  hash = hash.replace('&scope=chat_login','')

  window.location = 'http://nico.kuro.ml/chat?token='+hash;//+'&chan_name='+chanName;
}

function load() {
  var parser = document.createElement('a');
  parser.href = window.location.href;
  var token = parser.search.split("token=")[1];
  //var token = parser.search.split("&chan_name=")[0].split("token=")[1];
  //var channelName = parser.search.split('&chan_name=').pop();

  //console.log(token);
  chat(token);
}

function chat(token) {
    var oauth = token;

    // You have to run .setup() before anything besides .listen()
    TAPIC.setup(oauth, function (username) {

      // By default, TAPIC refreshes API information every 5 seconds, which is the minimum.
      // Setting the refresh rate is optional.
      //TAPIC.setRefreshRate(10);

      // This is also required for a lot of things to work
       TAPIC.joinChannel(username, function () {
             tests();
         });
    });

    TAPIC.listen('message', function (e) {
      var output = '
' '' +
        e.from + ': ' + e.text + '
';
        // e.emotes is the emotes, e.g. '25:0-4,12-16/1902:6-10'
        // https://github.com/justintv/Twitch-API/blob/master/IRC.md#privmsg
        // e.badges is an array of badges: https://discuss.dev.twitch.tv/t/beta-badge-api/6388
      writeChat( output );
    });
    // TAPIC.listen('echoChat', function (e) {
    //   var output = '' + TAPIC.getDisplayName() +
    //     ' : ' + e;
    //   writeChat( output );
    // });
}

// This is for the webpage's chat, it doesn't have anything directly to do with TAPIC.js
function writeChat(msg) {
  document.getElementById('chat').innerHTML += msg + '
';
  document.getElementById('chat').scrollTop = Number.MAX_SAFE_INTEGER;
}
<|endoftext|>


<commit_before>/**
 * Legacy admin bar widgets.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { useEffect, useState } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { STORE_NAME as CORE_MODULES } from '../../googlesitekit/modules/datastore/constants';
import AnalyticsAdminbarWidgetOverview from '../../modules/analytics/components/adminbar/AnalyticsAdminbarWidgetOverview';
import SearchConsoleAdminbarWidgetOverview from '../../modules/search-console/components/adminbar/SearchConsoleAdminbarWidgetOverview';
import { Row } from '../../material-components';
import AdminBarZeroData from './AdminBarZeroData';
const { useSelect } = Data;

export default function LegacyAdminBarWidgets() {
	const analyticsModuleActive = useSelect( ( select ) => select( CORE_MODULES ).isModuleActive( 'analytics' ) );
	const [ zeroDataSearchConsole, setZeroDataSearchConsole ] = useState( false );
	const [ zeroDataAnalytics, setZeroDataAnalytics ] = useState( false );
	const [ zeroData, setZeroData ] = useState( false );

	useEffect( () => {
		if ( zeroDataSearchConsole && zeroDataAnalytics ) {
			setZeroData( true );
		}
	}, [ zeroDataSearchConsole, zeroDataAnalytics ] );

	if ( zeroData ) {
		return <AdminBarZeroData />;
	}

	const handleSearchConsoleDataError = ( error, data ) => {
		global.console.log( 'handleSearchConsoleDataError', error, data );
		if ( ! error ) {
			setZeroDataSearchConsole( true );
		}
	};

	const handleAnalyticsDataError = ( error, data ) => {
		global.console.log( 'handleAnalyticsDataError', error, data );
		if ( ! error ) {
			setZeroDataAnalytics( true );
		}
	};

	return (
		<Row>
			{ /* Legacy widgets include their own grid classes */ }
			<SearchConsoleAdminbarWidgetOverview
				handleDataError={ handleSearchConsoleDataError }
			/>

			{ /* Due to limitations of withData, the component must always render unconditionally */ }
			<AnalyticsAdminbarWidgetOverview
				handleDataError={ handleAnalyticsDataError }
				analyticsActive={ analyticsModuleActive }
			/>
		</Row>
	);
}
<commit_msg>Remove log statements and document data error handlers.<commit_after>/**
 * Legacy admin bar widgets.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { useEffect, useState } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { STORE_NAME as CORE_MODULES } from '../../googlesitekit/modules/datastore/constants';
import AnalyticsAdminbarWidgetOverview from '../../modules/analytics/components/adminbar/AnalyticsAdminbarWidgetOverview';
import SearchConsoleAdminbarWidgetOverview from '../../modules/search-console/components/adminbar/SearchConsoleAdminbarWidgetOverview';
import { Row } from '../../material-components';
import AdminBarZeroData from './AdminBarZeroData';
const { useSelect } = Data;

export default function LegacyAdminBarWidgets() {
	const analyticsModuleActive = useSelect( ( select ) => select( CORE_MODULES ).isModuleActive( 'analytics' ) );
	const [ zeroDataSearchConsole, setZeroDataSearchConsole ] = useState( false );
	const [ zeroDataAnalytics, setZeroDataAnalytics ] = useState( false );
	const [ zeroData, setZeroData ] = useState( false );

	useEffect( () => {
		if ( zeroDataSearchConsole && zeroDataAnalytics ) {
			setZeroData( true );
		}
	}, [ zeroDataSearchConsole, zeroDataAnalytics ] );

	if ( zeroData ) {
		return <AdminBarZeroData />;
	}

	// withData uses handleDataError function props for handling both errors and zero-data.
	// If called without an error, it means zero data.
	const handleSearchConsoleDataError = ( error ) => {
		if ( ! error ) {
			setZeroDataSearchConsole( true );
		}
	};

	const handleAnalyticsDataError = ( error ) => {
		if ( ! error ) {
			setZeroDataAnalytics( true );
		}
	};

	return (
		<Row>
			{ /* Legacy widgets include their own grid classes */ }
			<SearchConsoleAdminbarWidgetOverview
				handleDataError={ handleSearchConsoleDataError }
			/>

			{ /* Due to limitations of withData, the component must always render unconditionally */ }
			<AnalyticsAdminbarWidgetOverview
				handleDataError={ handleAnalyticsDataError }
				analyticsActive={ analyticsModuleActive }
			/>
		</Row>
	);
}
<|endoftext|>


<commit_before>var canvas = document.getElementsByTagName('canvas')[0];
var ctx = null;
var body = document.getElementsByTagName('body')[0];
var keysDown = new Array();
var SCREENWIDTH  = 640;
var SCREENHEIGHT = 480;
var MODE_TITLE = 0;
var MODE_PLAY  = 1;
var MODE_WIN   = 2;

function getImage(name)
{
    image = new Image();
    image.src = 'graphics/'+name+'.png';
    return image;
}

function drawChar(context, c, x, y)
{
    c = c.charCodeAt(0);
    if(c > 0) {
        context.drawImage(bitfont, c*6, 0, 6,8, x, y, 12, 16);
    }
}

function drawString(context, string, x, y) {
    string = string.toUpperCase();
    for(i = 0; i < string.length; i++) {
	drawChar(context, string[i], x, y);
	x += 12;
    }
}

function paintTitleBitmaps()
{
    drawString(titlectx, 'This is a demo of the JavaScript/HTML5 game loop',32,32);
    drawString(winctx, 'Your game should always have an ending',32,32);
}

function makeTitleBitmaps()
{
    titleBitmap = document.createElement('canvas');
    titleBitmap.width = SCREENWIDTH;
    titleBitmap.height = SCREENHEIGHT;
    titlectx = titleBitmap.getContext('2d');
    winBitmap = document.createElement('canvas');
    winBitmap.width = SCREENWIDTH;
    winBitmap.height = SCREENHEIGHT;
    winctx = winBitmap.getContext('2d');
    bitfont = new Image();
    bitfont.src = "graphics/bitfont.png";
    bitfont.onload = paintTitleBitmaps;
}

function resetGame()
{
    batx = 128;
    x = 320;
    y = 128;
    dx = -4;
    dy = 4;

    fragments = [
	[[316.000000,468.000000],[302.000000,514.000000],[235.000000,514.000000],[218.000000,488.000000],[243.000000,433.000000],[295.000000,433.000000]],
	[[243.000000,433.000000],[218.000000,488.000000],[164.000000,487.000000],[159.000000,456.000000],[176.000000,415.000000],[227.000000,414.000000]],
	[[204.000000,362.000000],[213.000000,384.000000],[205.000000,404.000000],[167.000000,403.000000],[201.000000,433.000000],[97.000000,368.000000],[145.000000,360.000000]]
    ];

}

function init()
{
    mode = MODE_TITLE;
    playerImage = getImage("player");
    springSound = new Audio("audio/boing.wav");
    makeTitleBitmaps();
    return true;
}

function TaggedPoint(coords, polygon, pointid)
{
    this.x1 = coords[0];
    this.y1 = coords[1];
    this.ident = "p%dv%d"%(polygon.ident,pointid)
    this.polygon = polygon
}

function TaggedLine(x1, y1, x2, y2, polygon, lineid){
    this.x1 = x1;
    this.x2 = x2;
    this.y1 = y1;
    this.y2 = y2;
    this.polygon = polygon;
    this.ident = "p"+polygon.ident+lineid;
}

function TaggedPoly(ident, pointarray, region) {
    this.poly = pointarray;
    this.region = region;
    this.ident = ident;

}

function Collision(ix,iy,dist,outAngle,obj)
{
    this.ix = ix;
    this.iy = iy;
    this.dist = dist;
    this.outAngle = outAngle;
    this.obj = obj;
}
function getTaggedPolyLines(taggedPolygon)
{
    lines = new Array();
    poly = taggedPolygon.poly;
    for(p=0;p<poly.length-1;p++) {
        lines.push(new TaggedLine(poly[p][0],poly[p][1],poly[p+1][0],poly[p+1][1],taggedPolygon,p));
    }
    return lines;
}

function degrees(r) {
    return r*(180/Math.PI);
}

function lineIntersection(ballx, bally, ballxv, ballyv,
			  lstartx, lstarty, lxv, lyv)
{
    j = (lstarty/ballyv - bally/ballyv + ballx/ballxv -lstartx/ballxv)/(lxv/ballxv -lyv/ballyv);
    i = (lstartx+j*lxv-ballx)/ballxv;
    return [i,j];
}

function lineLen(x,y)
{
    return Math.sqrt(x*x+y*y);
}

function intersectPoly(poly, collisions, ball, considerRadius, lastCollisionObjectID)
{
    lines = getTaggedPolyLines(poly);
    hitline = null;
    lowi = 1.1;

    for(ln=0;ln<lines.length;ln++) {
	l = lines[ln]
        if(l.ident == lastCollisionObjectID) continue;
        lxv = l.x2-l.x1;
	lyv = l.y2-l.y1;
	lnormx = -lyv;
        lnormy = lxv;
        normScale = lineLen(lnormx,lnormy);
        lnormx = lnormx / normScale;
        lnormy = lnormy / normScale;
        dotproduct = lnormx*ball.dx+lnormy*ball.dy;
        if(dotproduct>0) {
            lnormx = -lnormx;
            lnormy = -lnormy;
	}
        if(considerRadius) {
            // Make a parallel line
            lstartx = l.x1+lnormx*ball.radius;
            lstarty = l.y1+lnormy*ball.radius;
	}
        else {
            lstartx = l.x1;
            lstarty = l.y1;
	}

        res = lineIntersection(ball.x,ball.y,ball.dx,ball.dy,
                               lstartx,lstarty,lxv,lyv);
        i = res[0];
	j = res[1];
        if(i>=0 && i<=1 && j>=0 && j<=1) {
            if(i<lowi) {
                lowi = i;
                hitline = l;
	    }
	}

        }
    if(hitline != null) {
	// Ok, now we can figure out the angle wrt the surface normal...
        lxv = hitline.x2 - hitline.x1;
        lyv = hitline.y2 - hitline.y1;

        lnormx = -lyv;
        lnormy = lxv;
        normScale = Math.sqrt(lnormx*lnormx+lnormy*lnormy);
        lnormx = lnormx / normScale;
        lnormy = lnormy / normScale;
        dotproduct = lnormx*ball.dx+lnormy*ball.dy;
	// This time, we make the normal in the same direction as the ball vector
        if(dotproduct<0) {
	    lnormx = -lnormx;
	    lnormy = -lnormy;
	}
        lenNormal = 1.0;
        ballToIntersectX = lowi*ball.dx;
        ballToIntersectY = lowi*ball.dy;
        distToIntersect = Math.sqrt(ballToIntersectX*ballToIntersectX
                                    +ballToIntersectY*ballToIntersectY);
        ballToIntersectX /= distToIntersect;
        ballToIntersectY /= distToIntersect;
        angle = Math.acos(ballToIntersectX*lnormx+ballToIntersectY*lnormy);
        console.log("Collision is at %f degrees to surface normal"+degrees(angle));
        normAngle = Math.atan2(lnormy,lnormx)+Math.PI;
        incident = Math.atan2(ball.dy,ball.dx)+Math.PI;
        angle =  incident - normAngle;

        outangle = normAngle - angle;

        //if(poly.region.collide == False) {
        //    outangle = incident - Math.PI;
	//}
        collisions.push(new Collision(ball.x + lowi*ball.dx, ball.y+lowi*ball.dy, lowi, outangle,hitline));
	console.log("Intersection with polygon "+poly.ident);
    }
    return collisions;
}

function checkClosestApproach(point, startx, starty, dx, dy)
{
    normx = -dy;
    normy = dx;
    res = lineIntersection(startx,starty,dx,dy,
                             point.x1,point.y1,normx,normy);
    i = res[0]; j = res[1];
    dist = Math.abs(j*lineLen(normx,normy));
    return [dist,i];
}
function intersectVertices(points, collisions, ballx,bally,ballxv,ballyv, ballRadius,lastCollisionObjectID)
{
    for(pointindex=0;pointindex<points.length;pointindex++) {
	p = points[pointindex];
        if(p.ident == lastCollisionObjectID) continue;
        res = checkClosestApproach(p,ballx,bally,ballxv,ballyv);
	d = res[0]; i = res[1];
        if(d<ballRadius) {
            diff = ballRadius - d;
            dist = Math.sqrt(ballRadius*ballRadius-d*d);
            iPoint = (lineLen(ballxv,ballyv)*i-dist)/lineLen(ballxv,ballyv) // Distance to intersect
            if(iPoint >=0 && iPoint <=1) {
                ix = ballx+ballxv*iPoint;
                iy = bally+ballyv*iPoint;
                radiusAng = Math.atan2(iy-p.y1,ix-p.x1);
                incident = Math.atan2(ballyv,ballxv)+Math.PI;
                angle =  incident - radiusAng;
                console.log("Incident angle = "+degrees(incident));
                console.log("Surface normal angle = "+degrees(radiusAng));
                outangle = radiusAng - angle;
                //if(p.polygon.region.collide == False):
                //outangle = incident-Math.PI
                collisions.push(Collision(ix,iy, iPoint, outangle, p))
	    }
	}
    }
}

function animate()
{
    x += dx;
    y += dy;
    if(x > SCREENWIDTH || x<0)  dx = -dx;
    if(y > SCREENHEIGHT || y<0)  dy = -dy;
    var ball = { 'x': x, 'y': y, 'dx': dx, 'dy': dy, 'radius': 64 };
    collisions = new Array();
    for(f=0;f<fragments.length;f++) {
	poly = new TaggedPoly("poly"+f, fragments[f], null);
	lastCollisionObjectID = "";
	collisions = intersectPoly(poly, collisions, ball, 1, lastCollisionObjectID);
    }

    points = new Array();
    for(f=0;f<fragments.length;f++) {
	poly = new TaggedPoly("poly"+f, fragments[f], null);
	for(p=0;p<poly.poly.length;p++) {
	    points.push(new TaggedPoint(poly.poly[p], poly, p));
	}
    }

    intersectVertices(points, collisions, ball.x,ball.y,ball.dx,ball.dy, ball.radius,lastCollisionObjectID)
    closestDist = 1.1;
    closest = null;
    console.log("X", "Y", "i", "Ang");

    for(c=0;c<collisions.length;c++) {
        console.log(c.ix, c.iy, c.dist, c.outAngle);
        if(c.dist < closestDist) {
            closest = c;
            closestDist = c.dist;
	}
    }

}

function draw() {
    ctx.fillStyle = "#0000ff";
    ctx.fillRect(0, 0, SCREENWIDTH, SCREENHEIGHT);

    if(mode == MODE_TITLE) {
	ctx.drawImage(titleBitmap, 0, 0);
	return;
    }

    ctx.drawImage(playerImage, batx, 400);
    ctx.beginPath();
    ctx.arc(x, y, 8, 0, 2 * Math.PI, false);
    ctx.fillStyle = 'white';
    ctx.fill();

    ctx.fillStyle = 'red';

    for(f=0;f<fragments.length;f++) {
	poly = fragments[f];
	ctx.beginPath();
	ctx.moveTo(poly[0][0], poly[0][1]-100);
	for(p=1;p<poly.length;p++) {
	    point = poly[p];
	    ctx.lineTo(point[0], point[1]-100);
	    }
	ctx.fill()
	}

    if(mode == MODE_WIN) {
	ctx.drawImage(winBitmap, 0, 0);
    }
}

function processKeys() {
    if(keysDown[37] || keysDown[65]) batx -= 8;
    if(keysDown[39] || keysDown[68]) batx += 8;
    if(batx < 0) batx = 0;
    if(batx > SCREENWIDTH - playerImage.width)  batx = SCREENWIDTH - playerImage.width;
}

function drawRepeat() {
    if(mode != MODE_TITLE) {
	processKeys();
	animate();
    }
    draw();
    if(!stopRunloop) setTimeout('drawRepeat()',20);
}

if (canvas.getContext('2d')) {
    stopRunloop = false;
    ctx = canvas.getContext('2d');
    body.onkeydown = function (event) {
	var c = event.keyCode;
        keysDown[c] = 1;
	if(c == 81) {
	    stopRunloop=true;
	}
	if(c == 32) {
	    if(mode == MODE_TITLE) {
		resetGame();
		mode = MODE_PLAY;
	    }
	}
	if(c == 82) {
	    if(mode == MODE_WIN) {
		mode = MODE_TITLE;
	    }
	}
    };

    body.onkeyup = function (event) {
	var c = event.keyCode;
        keysDown[c] = 0;
    };

    if(init()) {
      drawRepeat();
    }
}
<commit_msg>Collisions almost working<commit_after>var canvas = document.getElementsByTagName('canvas')[0];
var ctx = null;
var body = document.getElementsByTagName('body')[0];
var keysDown = new Array();
var SCREENWIDTH  = 640;
var SCREENHEIGHT = 480;
var MODE_TITLE = 0;
var MODE_PLAY  = 1;
var MODE_WIN   = 2;

function getImage(name)
{
    image = new Image();
    image.src = 'graphics/'+name+'.png';
    return image;
}

function drawChar(context, c, x, y)
{
    c = c.charCodeAt(0);
    if(c > 0) {
        context.drawImage(bitfont, c*6, 0, 6,8, x, y, 12, 16);
    }
}

function drawString(context, string, x, y) {
    string = string.toUpperCase();
    for(i = 0; i < string.length; i++) {
	drawChar(context, string[i], x, y);
	x += 12;
    }
}

function paintTitleBitmaps()
{
    drawString(titlectx, 'This is a demo of the JavaScript/HTML5 game loop',32,32);
    drawString(winctx, 'Your game should always have an ending',32,32);
}

function makeTitleBitmaps()
{
    titleBitmap = document.createElement('canvas');
    titleBitmap.width = SCREENWIDTH;
    titleBitmap.height = SCREENHEIGHT;
    titlectx = titleBitmap.getContext('2d');
    winBitmap = document.createElement('canvas');
    winBitmap.width = SCREENWIDTH;
    winBitmap.height = SCREENHEIGHT;
    winctx = winBitmap.getContext('2d');
    bitfont = new Image();
    bitfont.src = "graphics/bitfont.png";
    bitfont.onload = paintTitleBitmaps;
}

function resetGame()
{
    batx = 128;
    x = 320;
    y = 128;
    dx = -4;
    dy = 4;

    fragments = [
	[[500.000000,368.000000],[302.000000,414.000000],[235.000000,414.000000],[218.000000,388.000000],[243.000000,333.000000],[295.000000,333.000000]],
	[[243.000000,433.000000],[218.000000,488.000000],[164.000000,487.000000],[159.000000,456.000000],[176.000000,415.000000],[227.000000,414.000000]],
	[[204.000000,362.000000],[213.000000,384.000000],[205.000000,404.000000],[167.000000,403.000000],[201.000000,433.000000],[97.000000,368.000000],[145.000000,360.000000]]
    ];

}

function init()
{
    mode = MODE_TITLE;
    playerImage = getImage("player");
    springSound = new Audio("audio/boing.wav");
    makeTitleBitmaps();
    return true;
}

function TaggedPoint(coords, polygon, pointid)
{
    this.x1 = coords[0];
    this.y1 = coords[1];
    this.ident = polygon.ident+"-"+pointid;
    this.polygon = polygon
}

function TaggedLine(x1, y1, x2, y2, polygon, lineid){
    this.x1 = x1;
    this.x2 = x2;
    this.y1 = y1;
    this.y2 = y2;
    this.polygon = polygon;
    this.ident = polygon.ident+"-l"+lineid;
}

function TaggedPoly(ident, pointarray, region) {
    this.poly = pointarray;
    this.region = region;
    this.ident = ident;

}

function Collision(ix,iy,dist,outAngle,obj)
{
    this.ix = ix;
    this.iy = iy;
    this.dist = dist;
    this.outAngle = outAngle;
    this.obj = obj;
}
function getTaggedPolyLines(taggedPolygon)
{
    lines = new Array();
    poly = taggedPolygon.poly;
    for(p=0;p<poly.length-1;p++) {
        lines.push(new TaggedLine(poly[p][0],poly[p][1],poly[p+1][0],poly[p+1][1],taggedPolygon,p));
    }
    return lines;
}

function degrees(r) {
    return r*(180/Math.PI);
}

function lineIntersection(ballx, bally, ballxv, ballyv,
			  lstartx, lstarty, lxv, lyv)
{
    j = (lstarty/ballyv - bally/ballyv + ballx/ballxv -lstartx/ballxv)/(lxv/ballxv -lyv/ballyv);
    i = (lstartx+j*lxv-ballx)/ballxv;
    return [i,j];
}

function lineLen(x,y)
{
    return Math.sqrt(x*x+y*y);
}

function intersectPoly(poly, collisions, ball, considerRadius, lastCollisionObjectID)
{
    lines = getTaggedPolyLines(poly);
    hitline = null;
    lowi = 1.1;

    for(ln=0;ln<lines.length;ln++) {
	l = lines[ln]
        if(l.ident == lastCollisionObjectID) continue;
        lxv = l.x2-l.x1;
	lyv = l.y2-l.y1;
	lnormx = -lyv;
        lnormy = lxv;
        normScale = lineLen(lnormx,lnormy);
        lnormx = lnormx / normScale;
        lnormy = lnormy / normScale;
        dotproduct = lnormx*ball.dx+lnormy*ball.dy;
        if(dotproduct>0) {
            lnormx = -lnormx;
            lnormy = -lnormy;
	}
        if(considerRadius) {
            // Make a parallel line
            lstartx = l.x1+lnormx*ball.radius;
            lstarty = l.y1+lnormy*ball.radius;
	}
        else {
            lstartx = l.x1;
            lstarty = l.y1;
	}

        res = lineIntersection(ball.x,ball.y,ball.dx,ball.dy,
                               lstartx,lstarty,lxv,lyv);
        i = res[0];
	j = res[1];
        if(i>=0 && i<=1 && j>=0 && j<=1) {
            if(i<lowi) {
                lowi = i;
                hitline = l;
	    }
	}

        }
    if(hitline != null) {
	// Ok, now we can figure out the angle wrt the surface normal...
        lxv = hitline.x2 - hitline.x1;
        lyv = hitline.y2 - hitline.y1;

        lnormx = -lyv;
        lnormy = lxv;
        normScale = Math.sqrt(lnormx*lnormx+lnormy*lnormy);
        lnormx = lnormx / normScale;
        lnormy = lnormy / normScale;
        dotproduct = lnormx*ball.dx+lnormy*ball.dy;
	// This time, we make the normal in the same direction as the ball vector
        if(dotproduct<0) {
	    lnormx = -lnormx;
	    lnormy = -lnormy;
	}
        lenNormal = 1.0;
        ballToIntersectX = lowi*ball.dx;
        ballToIntersectY = lowi*ball.dy;
        distToIntersect = Math.sqrt(ballToIntersectX*ballToIntersectX
                                    +ballToIntersectY*ballToIntersectY);
        ballToIntersectX /= distToIntersect;
        ballToIntersectY /= distToIntersect;
        angle = Math.acos(ballToIntersectX*lnormx+ballToIntersectY*lnormy);
        console.log("Collision is at "+degrees(angle)+" degrees to surface normal");
        normAngle = Math.atan2(lnormy,lnormx)+Math.PI;
        incident = Math.atan2(ball.dy,ball.dx)+Math.PI;
        angle =  incident - normAngle;

        outangle = normAngle - angle;

        //if(poly.region.collide == False) {
        //    outangle = incident - Math.PI;
	//}
        collisions.push(new Collision(ball.x + lowi*ball.dx, ball.y+lowi*ball.dy, lowi, outangle,hitline));
	console.log("Intersection with polygon "+poly.ident+" line "+hitline.ident);
    }
    return collisions;
}

function checkClosestApproach(point, startx, starty, dx, dy)
{
    normx = -dy;
    normy = dx;
    res = lineIntersection(startx,starty,dx,dy,
                             point.x1,point.y1,normx,normy);
    i = res[0]; j = res[1];
    dist = Math.abs(j*lineLen(normx,normy));
    return [dist,i];
}
function intersectVertices(points, collisions, ballx,bally,ballxv,ballyv, ballRadius,lastCollisionObjectID)
{
    for(pointindex=0;pointindex<points.length;pointindex++) {
	p = points[pointindex];
        if(p.ident == lastCollisionObjectID) continue;
        res = checkClosestApproach(p,ballx,bally,ballxv,ballyv);

	d = res[0]; i = res[1];
        console.log("Closest approach to "+p.ident+" is "+d);
        if(d<ballRadius) {
            diff = ballRadius - d;
            dist = Math.sqrt(ballRadius*ballRadius-d*d);
            iPoint = (lineLen(ballxv,ballyv)*i-dist)/lineLen(ballxv,ballyv); // Distance to intersect
            if(iPoint >=0 && iPoint <=1) {
                ix = ballx+ballxv*iPoint;
                iy = bally+ballyv*iPoint;
                radiusAng = Math.atan2(iy-p.y1,ix-p.x1);
                incident = Math.atan2(ballyv,ballxv)+Math.PI;
                angle =  incident - radiusAng;
                console.log("Collides with ident "+p.ident+" Incident angle = "+degrees(incident));
                console.log("Surface normal angle = "+degrees(radiusAng));
                outangle = radiusAng - angle;
                //if(p.polygon.region.collide == False):
                //outangle = incident-Math.PI
                collisions.push(new Collision(ix,iy, iPoint, outangle, p))
	    }
	}
    }
}

function animate()
{
    if(x > SCREENWIDTH || x<0)  dx = -dx;
    if(y > SCREENHEIGHT || y<0)  dy = -dy;
    var ball = { 'x': x, 'y': y, 'dx': dx, 'dy': dy, 'radius': 8 };
    collisions = new Array();
    for(f=0;f<fragments.length;f++) {
	poly = new TaggedPoly("poly"+f, fragments[f], null);
	lastCollisionObjectID = "";
	collisions = intersectPoly(poly, collisions, ball, 1, lastCollisionObjectID);
    }

    points = new Array();
    for(f=0;f<fragments.length;f++) {
	poly = new TaggedPoly("poly"+f, fragments[f], null);
	for(p=0;p<poly.poly.length;p++) {
	    points.push(new TaggedPoint(poly.poly[p], poly, p));
	}
    }

    intersectVertices(points, collisions, ball.x,ball.y,ball.dx,ball.dy, ball.radius,lastCollisionObjectID)
    closestDist = 1.1;
    closest = null;

    for(c=0;c<collisions.length;c++) {
	col = collisions[c];
        console.log(col.ix, col.iy, col.dist, col.outAngle);
        if(col.dist < closestDist) {
            closest = col;
            closestDist = col.dist;
	}
    }
    if(closest != null) {
        console.log("Identified collision as one at dist "+closestDist);
	ctx.beginPath();
	ctx.moveTo(x,y);
	x = closest.ix;
        y = closest.iy;
        dist = lineLen(dx,dy);
        //distRemain = dist*(1.0-closest.dist);
        dx = dist*Math.cos(closest.outAngle);
        dy = dist*Math.sin(closest.outAngle);
	console.log("Moving to "+x+","+y+" with vel "+dx+","+dy);
//	stopRunloop=true;
	ctx.lineTo(x,y);
	ctx.stroke();

    } else {
	x += dx;
	y += dy;
    }

}

function draw() {
    ctx.fillStyle = "#0000ff";
    //ctx.fillRect(0, 0, SCREENWIDTH, SCREENHEIGHT);

    if(mode == MODE_TITLE) {
	ctx.drawImage(titleBitmap, 0, 0);
	return;
    }

    ctx.drawImage(playerImage, batx, 400);
    ctx.beginPath();
    ctx.arc(x, y, 8, 0, 2 * Math.PI, false);
    ctx.strokeStyle = 'white';
    ctx.stroke();

    ctx.fillStyle = 'red';

    for(f=0;f<fragments.length;f++) {
	poly = fragments[f];
	ctx.beginPath();
	ctx.moveTo(poly[0][0], poly[0][1]);
	for(p=1;p<poly.length;p++) {
	    point = poly[p];
	    ctx.lineTo(point[0], point[1]);
	    }
	ctx.closePath();
	ctx.stroke()
	}

    if(mode == MODE_WIN) {
	ctx.drawImage(winBitmap, 0, 0);
    }
}

function processKeys() {
    if(keysDown[37] || keysDown[65]) batx -= 8;
    if(keysDown[39] || keysDown[68]) batx += 8;
    if(batx < 0) batx = 0;
    if(batx > SCREENWIDTH - playerImage.width)  batx = SCREENWIDTH - playerImage.width;
}

function drawRepeat() {
    if(mode != MODE_TITLE) {
	processKeys();
	animate();
    }
    draw();
    if(!stopRunloop) setTimeout('drawRepeat()',20);
}

if (canvas.getContext('2d')) {
    stopRunloop = false;
    ctx = canvas.getContext('2d');
    ctx.fillStyle = "#0000ff";
    ctx.fillRect(0, 0, SCREENWIDTH, SCREENHEIGHT);
    body.onkeydown = function (event) {
	var c = event.keyCode;
        keysDown[c] = 1;
	if(c == 81) {
	    stopRunloop=true;
	}
	if(c == 32) {
	    if(mode == MODE_TITLE) {
		resetGame();
		mode = MODE_PLAY;
	    }
	}
	if(c == 82) {
	    if(mode == MODE_WIN) {
		mode = MODE_TITLE;
	    }
	}
    };

    body.onkeyup = function (event) {
	var c = event.keyCode;
        keysDown[c] = 0;
    };

    if(init()) {
      drawRepeat();
    }
}
<|endoftext|>


<commit_before>/**
 * Provides API functions to create a datastore for a module.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import {
	createNotificationsStore,
} from '../data/create-notifications-store';

export const createModuleStore = ( slug ) => {
	const notifications = createNotificationsStore( 'modules', slug, 'notifications' );

	const INITIAL_STATE = Data.collectState( notifications.INITIAL_STATE );
	const actions = Data.collectActions( notifications.actions );
	const controls = Data.collectControls( notifications.controls );
	const reducer = Data.collectReducers( INITIAL_STATE, [ notifications.reducer ] );
	const resolvers = Data.collectResolvers( notifications.resolvers );
	const selectors = Data.collectSelectors( notifications.resolvers );

	return {
		INITIAL_STATE,
		actions,
		controls,
		reducer,
		resolvers,
		selectors,
	};
};
<commit_msg>Simplify createModuleStore function.<commit_after>/**
 * Provides API functions to create a datastore for a module.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import {
	createNotificationsStore,
} from '../data/create-notifications-store';

export const createModuleStore = ( slug ) => {
	// For now, a base module store only consists of the notifications functionality.
	return createNotificationsStore( 'modules', slug, 'notifications' );
};
<|endoftext|>


<commit_before>$(document).ready(function(){
  $('.dropdown').hover(function() {
    $(this).addClass('open');
  }, function() {
    $(this).removeClass('open');
  });
});
<commit_msg>SVG javascript from The New Group<commit_after>$(document).ready(function(){
  // SVG CSS color adjusting
  $('img.svg').each(function(){
    var $img = $(this);
    var imgID = $img.attr('id');
    var imgClass = $img.attr('class');
    var imgURL = $img.attr('src');

    $.get(imgURL, function(data) {
      // Get the SVG tag, ignore the rest
      var $svg = $(data).find('svg');

      // Add replaced image's ID to the new SVG
      if(typeof imgID !== 'undefined') {
        $svg = $svg.attr('id', imgID);
      }
      // Add replaced image's classes to the new SVG
      if(typeof imgClass !== 'undefined') {
        $svg = $svg.attr('class', imgClass+' replaced-svg');
      }

      // Remove any invalid XML tags as per http://validator.w3.org
      $svg = $svg.removeAttr('xmlns:a');

      // Replace image with new SVG
      $img.replaceWith($svg);
    }, 'xml');
  });

  $('.dropdown').hover(function() {
    $(this).addClass('open');
  }, function() {
    $(this).removeClass('open');
  });
});
<|endoftext|>


<commit_before>window.onload = function() {
	var toggleSound = $('<button id="toggleSound"></svg></button>');
	var tempoDisplay = $('
120
');
	var tempoText;
	var toggleSoundButton;
	var iconOfToggleSound;
	var slider = $('#slider');

	var defaultFontSize = parseFloat(getComputedStyle(document.body).fontSize);

	var intervalId;
	var tempo = 500;

	var marimba_1 = new Howl({
		src: ['sounds/marimba_1.mp3']
	});

	function playSound(sound) {
		sound.stop();
		sound.play();
	}

	var editElements = {
		centerInside: function(insideElement) {
			var outsideElement = insideElement.closest("div");
			insideElement.css("top", ((outsideElement.outerHeight() - insideElement.outerHeight()) / 2) + "px");
			insideElement.css("left", ((outsideElement.outerWidth() - insideElement.outerWidth()) / 2) + "px");
		},
		growText: function(element) {
			element.css("font-size", "20em");
		},
		shrinkText: function (element) {
			element.css("font-size", "2em");
		},
		bringDown: function (element) {
			element.css("top", "500px");
		},
		standby: function(element) {
			this.shrinkText(element);
			this.centerInside(element);
			this.bringDown(element);
		},
		bringToMain: function(element) {
			this.growText(element);
			this.centerInside(element);
		}
	}

	slider.roundSlider({
		max: 360,
		min: 20,
		value: 120,
		radius: 360,
		width: 35,
		handleShape: "square",
		handleSize: "20, 35",
		showTooltip: false,
		sliderType: "min-range",
		create: function () {
			var that = this;
		  	this.innerBlock.append(toggleSound);
		  	toggleSoundButton = $('#toggleSound');
		  	editElements.bringToMain(toggleSoundButton);
		  	iconOfToggleSound =  $('#toggleSound > i');
		  	this.innerBlock.append(tempoDisplay);
		  	tempoText = $('#tempo');
		  	editElements.standby(tempoText);
	  		toggleSound.on('click', function() {
	  			editElements.shrinkText(toggleSoundButton);
	  	  		if(iconOfToggleSound.hasClass("icon-play")) {
	  					intervalId = setInterval(playSound, tempo, marimba_1);
	  	  		} else {
	  	  			clearInterval(intervalId);
	  	  		}
	  	  		iconOfToggleSound.toggleClass("icon-play icon-stop");
	  	  	});
		},
		start: function() {
			editElements.standby(toggleSoundButton);
			editElements.bringToMain(tempoText);
		},
		drag: function() {
			tempoText.text(("0" + this.getValue()).slice(-3));
		},
		change: function() {
			tempoText.text(("0" + this.getValue()).slice(-3));
			tempo = 1000 / (this.getValue() / 60);
			if(iconOfToggleSound.hasClass("icon-stop")) {
				clearInterval(intervalId);
				intervalId = setInterval(playSound, tempo, marimba_1);
			}
		},
		stop: function() {
			tempo = 1000 / (this.getValue() / 60);
			editElements.bringToMain(toggleSoundButton);
			editElements.standby(tempoText);
			editElements.centerInside(tempoText);
			editElements.bringDown(tempoText);
			if(iconOfToggleSound.hasClass("icon-stop")) {
				clearInterval(intervalId);
				intervalId = setInterval(playSound, tempo, marimba_1);
			}
		}
	});

}<commit_msg>Accidentally left testing function<commit_after>window.onload = function() {
	var toggleSound = $('<button id="toggleSound"></svg></button>');
	var tempoDisplay = $('
120
');
	var tempoText;
	var toggleSoundButton;
	var iconOfToggleSound;
	var slider = $('#slider');

	var defaultFontSize = parseFloat(getComputedStyle(document.body).fontSize);

	var intervalId;
	var tempo = 500;

	var marimba_1 = new Howl({
		src: ['sounds/marimba_1.mp3']
	});

	function playSound(sound) {
		sound.stop();
		sound.play();
	}

	var editElements = {
		centerInside: function(insideElement) {
			var outsideElement = insideElement.closest("div");
			insideElement.css("top", ((outsideElement.outerHeight() - insideElement.outerHeight()) / 2) + "px");
			insideElement.css("left", ((outsideElement.outerWidth() - insideElement.outerWidth()) / 2) + "px");
		},
		growText: function(element) {
			element.css("font-size", "20em");
		},
		shrinkText: function (element) {
			element.css("font-size", "2em");
		},
		bringDown: function (element) {
			element.css("top", "500px");
		},
		standby: function(element) {
			this.shrinkText(element);
			this.centerInside(element);
			this.bringDown(element);
		},
		bringToMain: function(element) {
			this.growText(element);
			this.centerInside(element);
		}
	}

	slider.roundSlider({
		max: 360,
		min: 20,
		value: 120,
		radius: 360,
		width: 35,
		handleShape: "square",
		handleSize: "20, 35",
		showTooltip: false,
		sliderType: "min-range",
		create: function () {
			var that = this;
		  	this.innerBlock.append(toggleSound);
		  	toggleSoundButton = $('#toggleSound');
		  	editElements.bringToMain(toggleSoundButton);
		  	iconOfToggleSound =  $('#toggleSound > i');
		  	this.innerBlock.append(tempoDisplay);
		  	tempoText = $('#tempo');
		  	editElements.standby(tempoText);
	  		toggleSound.on('click', function() {
	  	  		if(iconOfToggleSound.hasClass("icon-play")) {
	  					intervalId = setInterval(playSound, tempo, marimba_1);
	  	  		} else {
	  	  			clearInterval(intervalId);
	  	  		}
	  	  		iconOfToggleSound.toggleClass("icon-play icon-stop");
	  	  	});
		},
		start: function() {
			editElements.standby(toggleSoundButton);
			editElements.bringToMain(tempoText);
		},
		drag: function() {
			tempoText.text(("0" + this.getValue()).slice(-3));
		},
		change: function() {
			tempoText.text(("0" + this.getValue()).slice(-3));
			tempo = 1000 / (this.getValue() / 60);
			if(iconOfToggleSound.hasClass("icon-stop")) {
				clearInterval(intervalId);
				intervalId = setInterval(playSound, tempo, marimba_1);
			}
		},
		stop: function() {
			tempo = 1000 / (this.getValue() / 60);
			editElements.bringToMain(toggleSoundButton);
			editElements.standby(tempoText);
			editElements.centerInside(tempoText);
			editElements.bringDown(tempoText);
			if(iconOfToggleSound.hasClass("icon-stop")) {
				clearInterval(intervalId);
				intervalId = setInterval(playSound, tempo, marimba_1);
			}
		}
	});

}<|endoftext|>


<commit_before>$(document).ready(function() {
  $gavel = $("#gavel");
  $service = $('.service');
  $(window).scroll(function(){
    scrtop = $(window).scrollTop();
    serviceBox = $(".service-box")
    $service.each (function(){
      if (($(window).height() + scrtop) > $(this).offset().top)
        $(this).find($('.service-box')).velocity({opacity: 1}, {duration:1700}).end().find($('.font-icon')).addClass("animated fadeInLeft");;
    });
  });

  $('#team-link').click(function(){
    $('#team').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('#services-link').click(function(){
    $('#services').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('#location-link').click(function(){
    $('#map-canvas').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('#contact-link').click(function(){
    $('#contact').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('.navbar-brand').click(function(){
    $('#hero').velocity('scroll', {duration: 1500, easing: "easeOutQuint", offset: -100})
  })

})
<commit_msg>fixed javascript file<commit_after>$(document).ready(function() {
  $service = $('.service');
  $(window).scroll(function(){
    scrtop = $(window).scrollTop();
    serviceBox = $(".service-box")
    $service.each (function(){
      if (($(window).height() + scrtop) > $(this).offset().top){
        $(this).find($('.service-box')).velocity({opacity: 1}, {duration:1700}).end().find($('.font-icon')).addClass("animated fadeInLeft");;
      }
    });
  });

  $('#team-link').click(function(){
    $('#team').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('#services-link').click(function(){
    $('#services').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('#location-link').click(function(){
    $('#map-canvas').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('#contact-link').click(function(){
    $('#contact').velocity("scroll", {duration: 1500, easing: "easeOutQuint", offset: -100})
  });

  $('.navbar-brand').click(function(){
    $('#hero').velocity('scroll', {duration: 1500, easing: "easeOutQuint", offset: -100})
  })

})
<|endoftext|>


<commit_before>var async = require('async');
var _ = require('lodash');
var siteInfoService = require('../services/site-info.service');
var categoriesService = require('../services/categories.service');
var contentsService = require('../services/contents.service');
var listsService = require('../services/lists.service');

/**
 * 内容
 * @param {Object} req
 * @param {Object} res
 * @param {Function} next
 */
module.exports = function (req, res, next) {
  if (!req.params[0]) return next();

  contentsService.one({
    alias: _(req.params[0]).split('/').last()
  }, function (err, content) {
    if (err) return res.status(500).end();

    if (!content) return next();

    var categoryPath = '/' + req.params.content + _(req.params[0]).split('/').initial().join('/');

    async.auto({
      siteInfo: siteInfoService.get,
      navigation: function (callback) {
        categoriesService.navigation({ current: categoryPath }, callback);
      },
      category: function (callback) {
        categoriesService.one({
          path: categoryPath,
          type: 'column'
        }, callback);
      },
      localReadingTotal: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id }, callback);
      }],
      localReadingDay: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id, sort: '-reading.day' }, callback);
      }],
      localReadingWeek: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id, sort: '-reading.week' }, callback);
      }],
      localReadingMonth: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id, sort: '-reading.month' }, callback);
      }]
    }, function (err, results) {
      res.render(_.get(results.category, 'views.content'), {
        layout: _.get(results.category, 'views.layout'),
        siteInfo: results.siteInfo,
        navigation: results.navigation,
        category: results.category,
        readingList: {
          total: results.localReadingTotal,
          day: results.localReadingDay,
          week: results.localReadingWeek,
          month: results.localReadingMonth
        },
        title: content.title,
        href: content.href,
        user: content.user,
        date: content.date,
        reading: content.reading,
        thumbnail: content.thumbnail,
        media: content.media,
        abstract: content.abstract,
        content: content.content,
        tags: content.tags,
        extensions: content.extensions
      });
    });
  });
};<commit_msg>fix bug<commit_after>var async = require('async');
var _ = require('lodash');
var siteInfoService = require('../services/site-info.service');
var categoriesService = require('../services/categories.service');
var contentsService = require('../services/contents.service');
var listsService = require('../services/lists.service');

/**
 * 内容
 * @param {Object} req
 * @param {Object} res
 * @param {Function} next
 */
module.exports = function (req, res, next) {
  if (!req.params[0]) return next();

  contentsService.one({
    alias: _(req.params[0]).split('/').last()
  }, function (err, content) {
    if (err) return res.status(500).end();

    if (!content) return next();

    var categoryPath = '/' + req.params.content + _(req.params[0]).split('/').initial().join('/');

    async.auto({
      siteInfo: siteInfoService.get,
      navigation: function (callback) {
        categoriesService.navigation({ current: categoryPath }, callback);
      },
      category: function (callback) {
        categoriesService.one({
          path: categoryPath,
          type: 'column'
        }, function (err, category) {
          if (err) return callback(err);
          if (!category) return callback('没有找到 Category');

          callback(null, category);
        });
      },
      localReadingTotal: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id }, callback);
      }],
      localReadingDay: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id, sort: '-reading.day' }, callback);
      }],
      localReadingWeek: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id, sort: '-reading.week' }, callback);
      }],
      localReadingMonth: ['category', function (callback, results) {
        listsService.reading({ _id: results.category._id, sort: '-reading.month' }, callback);
      }]
    }, function (err, results) {
      if (err && !results.category) return next();
      if (err) return res.status(500).end();

      res.render(_.get(results.category, 'views.content'), {
        layout: _.get(results.category, 'views.layout'),
        siteInfo: results.siteInfo,
        navigation: results.navigation,
        category: results.category,
        readingList: {
          total: results.localReadingTotal,
          day: results.localReadingDay,
          week: results.localReadingWeek,
          month: results.localReadingMonth
        },
        title: content.title,
        href: content.href,
        user: content.user,
        date: content.date,
        reading: content.reading,
        thumbnail: content.thumbnail,
        media: content.media,
        abstract: content.abstract,
        content: content.content,
        tags: content.tags,
        extensions: content.extensions
      });
    });
  });
};<|endoftext|>