<commit_before>var game = new Phaser.Game(
    800, 600,
    Phaser.AUTO,
    'gamediv',
    {
        preload: preload,
        create: create,
        update: update,
        render: render
    });

function preload() {
    // Level
    game.load.tilemap('map', 'assets/map.json', null, Phaser.Tilemap.TILED_JSON);

    // Graphics
    game.load.image('level', 'assets/level.png');
    game.load.image('background', 'assets/bg.png');
    game.load.atlasJSONHash('character', 'assets/character.png', 'assets/character.json');
    game.load.image('deathwall', 'assets/deathwall.png');

    // Sounds
    game.load.audio('backgroundMusic', ['assets/mshanty-town.OGG']);
    game.load.audio('gameoverMusic', ['assets/mgame-over.OGG']);
    game.load.audio('dieMusic', ['assets/msplash.OGG']);
    game.load.audio('jumpMusic', ['assets/mjump.OGG']);
    game.load.audio('startMusic', ['assets/mgame-start.OGG']);
}

var map;
var layer;
var player;
var deathwall;
var cursors;
var jumpButton;
var hozMove = 160; // walk
var vertMove = -180; // jump
var jumpTimer = 0;
var cameraPosX;
var score = 0;
var scoreMult = 1;
var scoreText;
var lives = 3;
var livesText;

function create() {
    //Background
    game.stage.backgroundColor = '#FFFFFF';
    game.add.tileSprite(0, 0, 2000, 600, 'background');
    backgroundMusic = game.add.audio('backgroundMusic');
    backgroundMusic.play('');
    gameoverMusic = game.add.audio('gameoverMusic');
    dieMusic = game.add.audio('dieMusic');
    jumpMusic = game.add.audio('jumpMusic');
    startMusic = game.add.audio('startMusic');

    //Physik
    game.physics.startSystem(Phaser.Physics.ARCADE);

    //Tilemap & Level
    map = game.add.tilemap('map');
    map.addTilesetImage('level');
    layer = map.createLayer('Kachelebene 1');

    // Collisions
    map.setCollisionByExclusion([1, 31]);

    // Resize World
    layer.resizeWorld();

    // Player & Animations
    player = game.add.sprite(150, 5 * 70, 'character', 'p1_walk01.png');
    player.animations.add('walk', [
        'p1_walk01.png',
        'p1_walk02.png',
        'p1_walk03.png',
        'p1_walk04.png',
        'p1_walk05.png',
        'p1_walk06.png',
        'p1_walk07.png',
        'p1_walk08.png',
        'p1_walk09.png'
    ], 30, false, false);

    // Deathwall
    deathwall = game.add.sprite(0, 250, 'deathwall');
    deathwall.fixedToCamera = true;
    deathwall.anchor.setTo(0.6, 0.5);

    // Player Physics
    game.physics.enable([player]);
    player.body.bounce.y = 0.1;
    player.body.gravity.y = 160;

    // Controls
    cursors = game.input.keyboard.createCursorKeys();
    jumpButton = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);

    // Set Camera
    cameraPosX = player.body.x - 250;
    game.camera.x = cameraPosX;
    game.camera.y = player.body.y;

    //Score Text
    scoreText = game.add.text(game.camera.width / 1.2, 40, "0 Punkte", {
        font: "25px Arial",
        fill: "#ff0044"
    });
    scoreText.anchor.setTo(0.5, 0.5);
    scoreText.fixedToCamera = true;

    //Lives Text
    livesText = game.add.text(game.camera.width / 6, 40, lives + " Leben", {
        font: "25px Arial",
        fill: "#ff0044"
    });
    livesText.anchor.setTo(0.5, 0.5);
    livesText.fixedToCamera = true;
}

function update() {
    // Check collisions & Move player forward
    game.physics.arcade.collide(player, layer);
    player.body.velocity.x = hozMove / 4;

    // Update Camera
    if (game.camera.x <= player.body.x - 600)
        cameraPosX += 2.5;
    else
        cameraPosX += 0.5;

    game.camera.y = player.body.y;
    game.camera.x = cameraPosX;

    if (!player.inCamera) {
        gameOver(game.time.now);
    }

    if (game.camera.x < 1300)
        score += 1 * scoreMult;

    // Update Score
    scoreText.setText(score + " Punkte");

    // Update Lives
    livesText.setText(lives + " Leben");

    // Controls
    if (cursors.left.isDown) {
        player.body.velocity.x = -hozMove;
        player.animations.play('walk', 30);
    }
    else if (cursors.right.isDown) {
        player.body.velocity.x = hozMove;
        player.animations.play('walk', 30);
    }
    else {
        player.animations.play('walk', 10);
    }

    if (jumpButton.isDown && player.body.onFloor() && game.time.now > jumpTimer) {
        player.body.velocity.y = vertMove;
        jumpTimer = game.time.now + 650;
        jumpMusic.play();
    }
}

function render() {

    // game.debug.body(p);
    game.debug.bodyInfo(player, 50, 480, '#ff0044');
    game.debug.cameraInfo(game.camera, 200, 100, '#ff0044');
}

function gameOver(score) {
    dieMusic.play();
    gameoverMusic.play();
    alert("Game Over!");
    if (getCookie('highscore') < score) {
        name = prompt("Neuer Highscore!\nBitte Namen eingeben:", "");
        setCookie('highscorename', name, 365);
        setCookie('highscore', score, 365);
    }

    location.reload();
}

function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
    var expires = "expires=" + d.toUTCString();
    document.cookie = cname + "=" + cvalue + "; " + expires;
}

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
    }
    return "";
}<commit_msg>score multiplier<commit_after>var game = new Phaser.Game(
    800, 600,
    Phaser.AUTO,
    'gamediv',
    {
        preload: preload,
        create: create,
        update: update,
        render: render
    });

function preload() {
    // Level
    game.load.tilemap('map', 'assets/map.json', null, Phaser.Tilemap.TILED_JSON);

    // Graphics
    game.load.image('level', 'assets/level.png');
    game.load.image('background', 'assets/bg.png');
    game.load.atlasJSONHash('character', 'assets/character.png', 'assets/character.json');
    game.load.image('deathwall', 'assets/deathwall.png');

    // Sounds
    game.load.audio('backgroundMusic', ['assets/mshanty-town.OGG']);
    game.load.audio('gameoverMusic', ['assets/mgame-over.OGG']);
    game.load.audio('dieMusic', ['assets/msplash.OGG']);
    game.load.audio('jumpMusic', ['assets/mjump.OGG']);
    game.load.audio('startMusic', ['assets/mgame-start.OGG']);
}

var map;
var layer;
var player;
var deathwall;
var cursors;
var jumpButton;
var hozMove = 160; // walk
var vertMove = -180; // jump
var jumpTimer = 0;
var cameraPosX;
var score = 0;
var scoreMult = 1;
var scoreText;
var lives = 3;
var livesText;

function create() {
    //Background
    game.stage.backgroundColor = '#FFFFFF';
    game.add.tileSprite(0, 0, 2000, 600, 'background');

    //Music
    backgroundMusic = game.add.audio('backgroundMusic');
    backgroundMusic.play('');
    gameoverMusic = game.add.audio('gameoverMusic');
    dieMusic = game.add.audio('dieMusic');
    jumpMusic = game.add.audio('jumpMusic');
    startMusic = game.add.audio('startMusic');

    //Physik
    game.physics.startSystem(Phaser.Physics.ARCADE);

    //Tilemap & Level
    map = game.add.tilemap('map');
    map.addTilesetImage('level');
    layer = map.createLayer('Kachelebene 1');

    // Collisions
    map.setCollisionByExclusion([1, 31]);

    // Resize World
    layer.resizeWorld();

    // Player & Animations
    player = game.add.sprite(150, 5 * 70, 'character', 'p1_walk01.png');
    player.animations.add('walk', [
        'p1_walk01.png',
        'p1_walk02.png',
        'p1_walk03.png',
        'p1_walk04.png',
        'p1_walk05.png',
        'p1_walk06.png',
        'p1_walk07.png',
        'p1_walk08.png',
        'p1_walk09.png'
    ], 30, false, false);

    // Deathwall
    deathwall = game.add.sprite(0, 250, 'deathwall');
    deathwall.fixedToCamera = true;
    deathwall.anchor.setTo(0.6, 0.5);

    // Player Physics
    game.physics.enable([player]);
    player.body.bounce.y = 0.1;
    player.body.gravity.y = 160;

    // Controls
    cursors = game.input.keyboard.createCursorKeys();
    jumpButton = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);

    // Set Camera
    cameraPosX = player.body.x - 250;
    game.camera.x = cameraPosX;
    game.camera.y = player.body.y;

    //Score Text
    scoreText = game.add.text(game.camera.width / 1.2, 40, "0 Punkte", {
        font: "25px Arial",
        fill: "#ff0044"
    });
    scoreText.anchor.setTo(0.5, 0.5);
    scoreText.fixedToCamera = true;

    //Lives Text
    livesText = game.add.text(game.camera.width / 6, 40, lives + " Leben", {
        font: "25px Arial",
        fill: "#ff0044"
    });
    livesText.anchor.setTo(0.5, 0.5);
    livesText.fixedToCamera = true;
}

function update() {
    // Check collisions & Move player forward
    game.physics.arcade.collide(player, layer);
    player.body.velocity.x = hozMove / 4;

    // Update Camera
    if (game.camera.x <= player.body.x - 600) {
        cameraPosX += 2.5;
        scoreMult = 3;
    }
    else {
        cameraPosX += 0.5;
        scoreMult = 1;
    }

    game.camera.y = player.body.y;
    game.camera.x = cameraPosX;

    if (!player.inCamera) {
        gameOver(game.time.now);
    }

    if (game.camera.x < 1300)
        score += 1 * scoreMult;

    // Update Score
    scoreText.setText(score + " Punkte");

    // Update Lives
    livesText.setText(lives + " Leben");

    // Controls
    if (cursors.left.isDown) {
        player.body.velocity.x = -hozMove;
        player.animations.play('walk', 30);
    }
    else if (cursors.right.isDown) {
        player.body.velocity.x = hozMove;
        player.animations.play('walk', 30);
    }
    else {
        player.animations.play('walk', 10);
    }

    if (jumpButton.isDown && player.body.onFloor() && game.time.now > jumpTimer) {
        player.body.velocity.y = vertMove;
        jumpTimer = game.time.now + 650;
        jumpMusic.play();
    }
}

function render() {

    // game.debug.body(p);
    game.debug.bodyInfo(player, 50, 480, '#ff0044');
    game.debug.cameraInfo(game.camera, 200, 100, '#ff0044');
}

function gameOver(score) {
    dieMusic.play();
    gameoverMusic.play();
    alert("Game Over!");
    if (getCookie('highscore') < score) {
        name = prompt("Neuer Highscore!\nBitte Namen eingeben:", "");
        setCookie('highscorename', name, 365);
        setCookie('highscore', score, 365);
    }

    location.reload();
}

function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
    var expires = "expires=" + d.toUTCString();
    document.cookie = cname + "=" + cvalue + "; " + expires;
}

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
    }
    return "";
}<|endoftext|>


<commit_before>//====================================================//
//==== Playlist: enter the file names here: ==========//

var myVidsH264=[
   "videos/01-16s_h264.mp4",
   "videos/02-18s_h264.mp4",
   "videos/03-13s_h264.mp4",
   "videos/04-13s_h264.mp4",
   "videos/05-22s_h264.mp4",
   "videos/magenta_test.mp4",
   "videos/magenta_test2.mp4",
]

// var myVidsH264=[
//    "videos/01-16s_h264.mov",
//    "videos/02-18s_h264.mov",
//    "videos/03-13s_h264.mov",
//    "videos/04-13s_h264.mov",
//    "videos/05-22s_h264.mov",
// ]

var myVidsWebm=[
   "videos/01-16s_h264.webm",
   "videos/02-18s_h264.webm",
   "videos/03-13s_h264.webm",
   "videos/04-13s_h264.webm",
   "videos/05-22s_h264.webm",
]

var myVidsOgg=[
   "videos/01-16s_h264.ogv",
   "videos/02-18s_h264.ogv",
   "videos/03-13s_h264.ogv",
   "videos/04-13s_h264.ogv",
   "videos/05-22s_h264.ogv",
]

var randomOrder = true; // done - set to false if playlist order is non-random

///TBD
var autoplayOn = false;  /// what is behavior of autoplay? this doesnt seem like a UI feature
var doubleplay = false; // play each video twice

//=== UI control toggles - set to false to remove from UI
var playOn = true; // done
var ffOn = true; // uhh
var rwOn = true; // wat
var skipOn = true; // done
var volumeOn =  true;
var muteOn = true;
var durationOn = true;
var fullscOn = true;

//====================================================//
//===================================================//

// html5 video elements
var vidElements = [];

console.log("modernizr video h264 support? " + Modernizr.video.h264);
console.log("modernizr video webm support? " + Modernizr.video.webm);
console.log("modernizr video ogg support? " + Modernizr.video.ogg);

// this function will randomly shuffle the list of videos upon page load
// from http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex ;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

// check the video loading progress and update the progress bar
function checkLoad(){
  var percentLoaded = 0;
  var timeoutID = setInterval(function(){
    console.log("videlements.length: "+vidElements.length);
    console.log("myVidsH264.length: "+myVidsH264.length);
    if(percentLoaded < 100){
      percentLoaded = (vidElements.length+1) / (myVidsH264.length+1) * 100;
      $('progress').val(percentLoaded);
    }
    else{
      console.log("percentLoaded: "+percentLoaded);
      clearTimeout(timeoutID);
      $('progress').val(percentLoaded);
      document.getElementById("loading").style.display="none";
      player();
    }
  }, 400);}

// initialize video player and its UI
var player = function(){
  // video elements
  var vindex = 0;
  var videoPlayer, theVideo;

  // buttons - so they can access each other
  var prevBtn, nextBtn, playBtn, ffBtn, rwBtn;

  // player state
  var playing, speed, ffing, rwing, rwinterval;

  videoPlayer = document.getElementById("video_player");
  theVideo = document.getElementById("video"+vindex);

  videoPlayer.style.display="table";
  theVideo.style.display="block";

  // UI controls
  if(playOn){ playUI(); }
  if(skipOn){ skipUI(); }
  if(rwOn){ rwUI(-0.1); }
  if(ffOn){ ffUI(); }
  if(volumeOn){ volUI(); }
  if( doubleplay ){ doubleplay(); }

  function skipUI(){
      $("#video_player").append('<button type="button" class="btn_skip" id="btn_prev" disabled> < < </button>');
      $("#video_player").append('<button type="button" class="btn_skip" id="btn_next" > > > </button>');

      prevBtn = document.getElementById("btn_prev");
      nextBtn = document.getElementById("btn_next");

      // iterate through video playlist backwards
      prevBtn.addEventListener("click", function(){
        if(vindex == 0){
          prevBtn.disabled = true;
        }
        else if (vindex == 1) {
          theVideo.style.display="none";
          vindex--;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          prevBtn.disabled = true;
        }
        else{
          theVideo.style.display="none";
          vindex--;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          nextBtn.disabled = false;
        }
        // also change the play button state
        normalizeUI();
      })
      // iterate through video playlist forwards
      nextBtn.addEventListener("click", function(){
        if(vindex == vidElements.length-1){
          nextBtn.disabled = true;
        }
        else if(vindex == vidElements.length-2){
          theVideo.style.display="none";
          vindex++;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          prevBtn.disabled = false;
          nextBtn.disabled = true;
        }
        else{
          theVideo.style.display="none";
          vindex++;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          prevBtn.disabled = false;
        }
        // also change the play button state
        normalizeUI();
      })
    }

  function playUI(){
    $("#video_player").append('<input type="button" class="btn_skip" id="btn_play" value=" > "></input>');
    playBtn = document.getElementById("btn_play");
    playing = false;
    playBtn.addEventListener("click", function(){
      if(!playing){
        normalizeUI();
        theVideo.play();
        playBtn.value=" || ";

      }
      else{
        theVideo.pause();
        playBtn.value=" > ";
      }
      playing = !playing;
    })
  }

  function ffUI(){
     $("#video_player").append('<input type="button" class="btn_ffrw" id="btn_ff" value=" >>| "></input>');
    ffBtn = $("#btn_ff");
    speed = 0;
    var ffing = false;
    ffBtn.click(function(){
      speed = !ffing ? 1.5 : 1;
      theVideo.playbackRate = speed;
      ffing = !ffing;
      console.log("speed: "+ speed);
      theVideo.play();
    })
  }

  function rwUI(rate){
     $("#video_player").append('<input type="button" class="btn_ffrw" id="btn_rw" value=" |<< "></input>');
    rwBtn = $("#btn_rw");
    var rwing = false;
    rwBtn.click(function(){
      rwing = !rwing;
      if(rwing){
        rwinterval = setInterval(function(){
          theVideo.playbackRate = 1.0;
          if(theVideo.currentTime <= rate){
            clearInterval(rwinterval);
            theVideo.pause();
            normalizeUI();
          }
          else{
            theVideo.currentTime += rate;
          }
          console.log("current time: "+ theVideo.currentTime);
        }, 30);
      }
      else{
        normalizeUI();
      }

      // speed = !rwing ? (rate) : 1;
      // while (theVideo.currentTime != 0){
      //   var now = theVideo.currentTime;
      //   theVideo.currentTime = now + rate;
      // }

      // console.log("speed: "+ speed);
    })
  }

  function volUI(){
    $("#video_player").append('

');
    $("#volume").slider({
      value: 60,
      orientation: "horizontal",
      range: "min",
      animate: true
    })
    volSdr = document.getElementById("volume");
    playing = false;
    volSdr.addEventListener("click", function(){
      //stuff linking volume and slider value
    })
  }

  function normalizeUI(){
    if(playOn){
      playBtn.value = " > ";
      playing = false;
    }
    if(ffOn || rwOn){
      speed = 1;
      ffing = false;
      rwing = false;
    }
  }

} // end player function

// send the appropriate videos to the video loader
var preLoader = function(){
  var vidList = [];
  var vidType ;

  // check browser compatibilty and initiate fall-backs
  if (Modernizr.video.h264){ vidList = myVidsH264; vidType = "video/mp4";}
  else if (Modernizr.video.webm){  vidList = myVidsWebm; vidType = "video/webm";}
  else if(Modernizr.video.ogg){ vidList = myVidsOgg; vidType = "video/ogg";}
  else { console.log("no html5 video support :( consider upgrading to a modern browser"); }

  // randomize the videos, if necessary
  if (randomOrder){ shuffle(vidList); }

  // start loading the videos
  for (var i = 0; i < vidList.length; i++) {
    // add form elements to track play count
    $('form[name="myForm"]').append('<input type="hidden" name="'+vidList[i]+'" value="0" />');
    // add video element for each video
    $("#videos").append('<video id="video'+i+'"  > Your browser does not support the video tag. </video>');
    // load the videos into their elements
    console.log("video " +i+ " filename: " + (vidList[i]));
    loadVid(vidList[i], vidType, i);

  }

  // progress bar
  checkLoad();
}

$(document).ready(preLoader());

// load the videos asynchronously while the user waits
// based on http://stackoverflow.com/questions/18251632/another-force-chrome-to-fully-buffer-mp4-video
function loadVid(vidFile, vidType, i){
	var elementID = "video"+i;
    var xhr = new XMLHttpRequest();
    xhr.open('GET', vidFile, true);
    xhr.responseType = 'blob';
    xhr.onload = function(e) {
    if (this.status == 200) {
    	var myBlob = this.response;
    	var vid = (window.webkitURL ? webkitURL : URL).createObjectURL(myBlob);
        // myBlob is now the blob that the object URL pointed to.
        var video = document.getElementById(elementID);
        video.style.display="none";
        console.log("Loading video "+vidFile+" into element video"+i);
        video.src = vid;
        video.type=vidType;
        video.controls=true;
        // update hidden form with play count
        $(video).on('play', function(){
          var v = parseInt($('input[name="'+vidFile+'"]').val());
          $('input[name="'+vidFile+'"]').val(++v);
        })
        vidElements.push(video);
   }
  }
  xhr.send();

}

<commit_msg>saving more changes<commit_after>//====================================================//
//==== Playlist: enter the file names here: ==========//

var myVidsH264=[
   "videos/01-16s_h264.mp4",
   "videos/02-18s_h264.mp4",
   "videos/03-13s_h264.mp4",
   "videos/04-13s_h264.mp4",
   "videos/05-22s_h264.mp4",
   "videos/magenta_test.mp4",
   "videos/magenta_test2.mp4",
]

// var myVidsH264=[
//    "videos/01-16s_h264.mov",
//    "videos/02-18s_h264.mov",
//    "videos/03-13s_h264.mov",
//    "videos/04-13s_h264.mov",
//    "videos/05-22s_h264.mov",
// ]

var myVidsWebm=[
   "videos/01-16s_h264.webm",
   "videos/02-18s_h264.webm",
   "videos/03-13s_h264.webm",
   "videos/04-13s_h264.webm",
   "videos/05-22s_h264.webm",
]

var myVidsOgg=[
   "videos/01-16s_h264.ogv",
   "videos/02-18s_h264.ogv",
   "videos/03-13s_h264.ogv",
   "videos/04-13s_h264.ogv",
   "videos/05-22s_h264.ogv",
]

var randomOrder = true; // done - set to false if playlist order is non-random

///TBD
var autoplayOn = false;  /// what is behavior of autoplay? this doesnt seem like a UI feature
var doubleplay = false; // play each video twice

//=== UI control toggles - set to false to remove from UI
var playOn = true; // done
var ffOn = true; // uhh
var rwOn = true; // wat
var skipOn = true; // done
var volumeOn =  true;
var muteOn = true;
var durationOn = true;
var fullscOn = true;

//====================================================//
//===================================================//

// html5 video elements
var vidElements = [];

console.log("modernizr video h264 support? " + Modernizr.video.h264);
console.log("modernizr video webm support? " + Modernizr.video.webm);
console.log("modernizr video ogg support? " + Modernizr.video.ogg);

// this function will randomly shuffle the list of videos upon page load
// from http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex ;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

// check the video loading progress and update the progress bar
function checkLoad(){
  var percentLoaded = 0;
  var timeoutID = setInterval(function(){
    console.log("videlements.length: "+vidElements.length);
    console.log("myVidsH264.length: "+myVidsH264.length);
    if(percentLoaded < 100){
      percentLoaded = (vidElements.length+1) / (myVidsH264.length+1) * 100;
      $('progress').val(percentLoaded);
    }
    else{
      console.log("percentLoaded: "+percentLoaded);
      clearTimeout(timeoutID);
      $('progress').val(percentLoaded);
      document.getElementById("loading").style.display="none";
      player();
    }
  }, 400);}

// initialize video player and its UI
var player = function(){
  // video elements
  var vindex = 0;
  var videoPlayer, theVideo;

  // buttons - so they can access each other
  var prevBtn, nextBtn, playBtn, ffBtn, rwBtn;

  // player state
  var playing, speed, ffing, rwing, rwinterval;

  videoPlayer = document.getElementById("video_player");
  theVideo = document.getElementById("video"+vindex);

  videoPlayer.style.display="table";
  theVideo.style.display="block";

  // UI controls
  if(playOn){ playUI(); }
  if(skipOn){ skipUI(); }
  if(rwOn){ rwUI(-0.1); }
  if(ffOn){ ffUI(); }
  if(volumeOn){ volUI(); }

  function skipUI(){
      $("#video_player").append('<button type="button" class="btn_skip" id="btn_prev" disabled> < < </button>');
      $("#video_player").append('<button type="button" class="btn_skip" id="btn_next" > > > </button>');

      prevBtn = document.getElementById("btn_prev");
      nextBtn = document.getElementById("btn_next");

      // iterate through video playlist backwards
      prevBtn.addEventListener("click", function(){
        if(vindex == 0){
          prevBtn.disabled = true;
        }
        else if (vindex == 1) {
          theVideo.style.display="none";
          vindex--;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          prevBtn.disabled = true;
        }
        else{
          theVideo.style.display="none";
          vindex--;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          nextBtn.disabled = false;
        }
        // also change the play button state
        normalizeUI();
      })
      // iterate through video playlist forwards
      nextBtn.addEventListener("click", function(){
        if(vindex == vidElements.length-1){
          nextBtn.disabled = true;
        }
        else if(vindex == vidElements.length-2){
          theVideo.style.display="none";
          vindex++;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          prevBtn.disabled = false;
          nextBtn.disabled = true;
        }
        else{
          theVideo.style.display="none";
          vindex++;
          theVideo = document.getElementById("video"+vindex);
          theVideo.currentTime=0;
          theVideo.style.display="block";
          theVideo.pause();
          prevBtn.disabled = false;
        }
        // also change the play button state
        normalizeUI();
      })
    }

  function playUI(){
    $("#video_player").append('<input type="button" class="btn_skip" id="btn_play" value=" > "></input>');
    playBtn = document.getElementById("btn_play");
    playing = false;
    playBtn.addEventListener("click", function(){
      if(!playing){
        normalizeUI();
        theVideo.play();
        playBtn.value=" || ";

      }
      else{
        theVideo.pause();
        playBtn.value=" > ";
      }
      playing = !playing;
    })
  }

  function ffUI(){
     $("#video_player").append('<input type="button" class="btn_ffrw" id="btn_ff" value=" >>| "></input>');
    ffBtn = $("#btn_ff");
    speed = 0;
    var ffing = false;
    ffBtn.click(function(){
      speed = !ffing ? 1.5 : 1;
      theVideo.playbackRate = speed;
      ffing = !ffing;
      console.log("speed: "+ speed);
      theVideo.play();
    })
  }

  function rwUI(rate){
     $("#video_player").append('<input type="button" class="btn_ffrw" id="btn_rw" value=" |<< "></input>');
    rwBtn = $("#btn_rw");
    var rwing = false;
    rwBtn.click(function(){
      rwing = !rwing;
      if(rwing){
        rwinterval = setInterval(function(){
          theVideo.playbackRate = 1.0;
          if(theVideo.currentTime <= rate){
            clearInterval(rwinterval);
            theVideo.pause();
            normalizeUI();
          }
          else{
            theVideo.currentTime += rate;
          }
          console.log("current time: "+ theVideo.currentTime);
        }, 30);
      }
      else{
        normalizeUI();
      }

      // speed = !rwing ? (rate) : 1;
      // while (theVideo.currentTime != 0){
      //   var now = theVideo.currentTime;
      //   theVideo.currentTime = now + rate;
      // }

      // console.log("speed: "+ speed);
    })
  }

  function volUI(){
    $("#video_player").append('

');
    $("#volume").slider({
      value: 60,
      orientation: "horizontal",
      range: "min",
      animate: true
    })
    volSdr = document.getElementById("volume");
    playing = false;
    volSdr.addEventListener("click", function(){
      //stuff linking volume and slider value
    })
  }

  function normalizeUI(){
    if(playOn){
      playBtn.value = " > ";
      playing = false;
    }
    if(ffOn || rwOn){
      speed = 1;
      ffing = false;
      rwing = false;
    }
  }

} // end player function

// send the appropriate videos to the video loader
var preLoader = function(){
  var vidList = [];
  var vidType ;

  // check browser compatibilty and initiate fall-backs
  if (Modernizr.video.h264){ vidList = myVidsH264; vidType = "video/mp4";}
  else if (Modernizr.video.webm){  vidList = myVidsWebm; vidType = "video/webm";}
  else if(Modernizr.video.ogg){ vidList = myVidsOgg; vidType = "video/ogg";}
  else { console.log("no html5 video support :( consider upgrading to a modern browser"); }

  // randomize the videos, if necessary
  if (randomOrder){ shuffle(vidList); }

  // start loading the videos
  for (var i = 0; i < vidList.length; i++) {
    // add form elements to track play count
    $('form[name="myForm"]').append('<input type="hidden" name="'+vidList[i]+'" value="0" />');
    // add video element for each video
    $("#videos").append('<video id="video'+i+'"  > Your browser does not support the video tag. </video>');
    // load the videos into their elements
    console.log("video " +i+ " filename: " + (vidList[i]));
    loadVid(vidList[i], vidType, i);

  }

  // progress bar
  checkLoad();
}

$(document).ready(preLoader());

// load the videos asynchronously while the user waits
// based on http://stackoverflow.com/questions/18251632/another-force-chrome-to-fully-buffer-mp4-video
function loadVid(vidFile, vidType, i){
	var elementID = "video"+i;
    var xhr = new XMLHttpRequest();
    xhr.open('GET', vidFile, true);
    xhr.responseType = 'blob';
    xhr.onload = function(e) {
    if (this.status == 200) {
    	var myBlob = this.response;
    	var vid = (window.webkitURL ? webkitURL : URL).createObjectURL(myBlob);
        // myBlob is now the blob that the object URL pointed to.
        var video = document.getElementById(elementID);
        video.style.display="none";
        console.log("Loading video "+vidFile+" into element video"+i);
        video.src = vid;
        video.type=vidType;
        video.controls=true;
        // update hidden form with play count
        $(video).on('play', function(){
          var v = parseInt($('input[name="'+vidFile+'"]').val());
          $('input[name="'+vidFile+'"]').val(++v);
        })
        vidElements.push(video);
   }
  }
  xhr.send();

}

<|endoftext|>


<commit_before>"use strict";

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

const Exchange = require ('./base/Exchange')
const { ExchangeError, InsufficientFunds, OrderNotFound, DDoSProtection } = require ('./base/errors')

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

module.exports = class gdax extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'gdax',
            'name': 'GDAX',
            'countries': 'US',
            'rateLimit': 1000,
            'hasCORS': true,
            'hasFetchOHLCV': true,
            'hasWithdraw': true,
            'hasFetchOrder': true,
            'hasFetchOrders': true,
            'hasFetchOpenOrders': true,
            'hasFetchClosedOrders': true,
            'timeframes': {
                '1m': 60,
                '5m': 300,
                '15m': 900,
                '30m': 1800,
                '1h': 3600,
                '2h': 7200,
                '4h': 14400,
                '12h': 43200,
                '1d': 86400,
                '1w': 604800,
                '1M': 2592000,
                '1y': 31536000,
            },
            'urls': {
                'test': 'https://api-public.sandbox.gdax.com',
                'logo': 'https://user-images.githubusercontent.com/1294454/27766527-b1be41c6-5edb-11e7-95f6-5b496c469e2c.jpg',
                'api': 'https://api.gdax.com',
                'www': 'https://www.gdax.com',
                'doc': 'https://docs.gdax.com',
            },
            'api': {
                'public': {
                    'get': [
                        'currencies',
                        'products',
                        'products/{id}/book',
                        'products/{id}/candles',
                        'products/{id}/stats',
                        'products/{id}/ticker',
                        'products/{id}/trades',
                        'time',
                    ],
                },
                'private': {
                    'get': [
                        'accounts',
                        'accounts/{id}',
                        'accounts/{id}/holds',
                        'accounts/{id}/ledger',
                        'coinbase-accounts',
                        'fills',
                        'funding',
                        'orders',
                        'orders/{id}',
                        'payment-methods',
                        'position',
                        'reports/{id}',
                        'users/self/trailing-volume',
                    ],
                    'post': [
                        'deposits/coinbase-account',
                        'deposits/payment-method',
                        'funding/repay',
                        'orders',
                        'position/close',
                        'profiles/margin-transfer',
                        'reports',
                        'withdrawals/coinbase',
                        'withdrawals/crypto',
                        'withdrawals/payment-method',
                    ],
                    'delete': [
                        'orders',
                        'orders/{id}',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.0,
                    'taker': 0.25 / 100,
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetProducts ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'];
            let base = market['base_currency'];
            let quote = market['quote_currency'];
            let symbol = base + '/' + quote;
            let amountLimits = {
                'min': market['base_min_size'],
                'max': market['base_max_size'],
            };
            let priceLimits = {
                'min': market['quote_increment'],
                'max': undefined,
            };
            let costLimits = {
                'min': priceLimits['min'],
                'max': undefined,
            };
            let limits = {
                'amount': amountLimits,
                'price': priceLimits,
                'cost': costLimits,
            };
            let precision = {
                'amount': -Math.log10 (parseFloat (amountLimits['min'])),
                'price': -Math.log10 (parseFloat (priceLimits['min'])),
            };
            let taker = this.fees['trading']['taker'];
            if ((base == 'ETH') || (base == 'LTC')) {
                taker = 0.3;
            }
            result.push (this.extend (this.fees['trading'], {
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'info': market,
                'precision': precision,
                'limits': limits,
                'taker': taker,
            }));
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetAccounts ();
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['currency'];
            let account = {
                'free': parseFloat (balance['available']),
                'used': parseFloat (balance['hold']),
                'total': parseFloat (balance['balance']),
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetProductsIdBook (this.extend ({
            'id': this.marketId (symbol),
            'level': 2, // 1 best bidask, 2 aggregated, 3 full
        }, params));
        return this.parseOrderBook (orderbook);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = this.extend ({
            'id': market['id'],
        }, params);
        let ticker = await this.publicGetProductsIdTicker (request);
        let quote = await this.publicGetProductsIdStats (request);
        let timestamp = this.parse8601 (ticker['time']);
        let bid = undefined;
        let ask = undefined;
        if ('bid' in ticker)
            bid = parseFloat (ticker['bid']);
        if ('ask' in ticker)
            ask = parseFloat (ticker['ask']);
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': parseFloat (quote['high']),
            'low': parseFloat (quote['low']),
            'bid': bid,
            'ask': ask,
            'vwap': undefined,
            'open': parseFloat (quote['open']),
            'close': undefined,
            'first': undefined,
            'last': parseFloat (quote['last']),
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': parseFloat (ticker['volume']),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

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

    async fetchTrades (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetProductsIdTrades (this.extend ({
            'id': market['id'], // fixes issue #2
        }, params));
        return this.parseTrades (response, market);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
        return [
            ohlcv[0] * 1000,
            ohlcv[3],
            ohlcv[2],
            ohlcv[1],
            ohlcv[4],
            ohlcv[5],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let granularity = this.timeframes[timeframe];
        let request = {
            'id': market['id'],
            'granularity': granularity,
        };
        if (since) {
            request['start'] = this.iso8601 (since);
            if (!limit)
                limit = 200; // max = 200
            request['end'] = this.iso8601 (limit * granularity * 1000 + since);
        }
        let response = await this.publicGetProductsIdCandles (this.extend (request, params));
        return this.parseOHLCVs (response, market, timeframe, since, limit);
    }

    async fetchTime () {
        let response = this.publicGetTime ();
        return this.parse8601 (response['iso']);
    }

    getOrderStatus (status) {
        let statuses = {
            'pending': 'open',
            'active': 'open',
            'open': 'open',
            'done': 'closed',
            'canceled': 'canceled',
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        let timestamp = this.parse8601 (order['created_at']);
        let symbol = undefined;
        if (!market) {
            if (order['product_id'] in this.markets_by_id)
                market = this.markets_by_id[order['product_id']];
        }
        let status = this.getOrderStatus (order['status']);
        let price = this.safeFloat (order, 'price');
        let amount = this.safeFloat (order, 'size');
        let filled = this.safeFloat (order, 'filled_size');
        let remaining = amount - filled;
        let cost = this.safeFloat (order, 'executed_value');
        if (market)
            symbol = market['symbol'];
        return {
            'id': order['id'],
            'info': order,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'status': status,
            'symbol': symbol,
            'type': order['type'],
            'side': order['side'],
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'fee': undefined,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (response);
    }

    async fetchOrders (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'status': 'all',
        };
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let response = await this.privateGetOrders (this.extend (request, params));
        return this.parseOrders (response, market);
    }

    async fetchOpenOrders (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let response = await this.privateGetOrders (this.extend (request, params));
        return this.parseOrders (response, market);
    }

    async fetchClosedOrders (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'status': 'done',
        };
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let response = await this.privateGetOrders (this.extend (request, params));
        return this.parseOrders (response, market);
    }

    async createOrder (market, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        // let oid = this.nonce ().toString ();
        let order = {
            'product_id': this.marketId (market),
            'side': side,
            'size': amount,
            'type': type,
        };
        if (type == 'limit')
            order['price'] = price;
        let response = await this.privatePostOrders (this.extend (order, params));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privateDeleteOrdersId ({ 'id': id });
    }

    async getPaymentMethods () {
        let response = await this.privateGetPaymentMethods ();
        return response;
    }

    async withdraw (currency, amount, address, params = {}) {
        await this.loadMarkets ();
        let response = undefined;
        if ('payment_method_id' in params) {
            response = await this.privatePostWithdrawalsPaymentMethod (this.extend ({
                'currency': currency,
                'amount': amount,
            }, params));
        } else {
            response = await this.privatePostWithdrawalsCrypto (this.extend ({
                'currency': currency,
                'amount': amount,
                'crypto_address': address,
            }, params));
        }
        if (!response)
            throw ExchangeError (this.id + ' withdraw() error: ' + this.json (response));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (method == 'GET') {
            if (Object.keys (query).length)
                request += '?' + this.urlencode (query);
        }
        let url = this.urls['api'] + request;
        if (api == 'private') {
            if (!this.apiKey)
                throw new AuthenticationError (this.id + ' requires apiKey property for authentication and trading');
            if (!this.secret)
                throw new AuthenticationError (this.id + ' requires secret property for authentication and trading');
            if (!this.password)
                throw new AuthenticationError (this.id + ' requires password property for authentication and trading');
            let nonce = this.nonce ().toString ();
            let payload = '';
            if (method == 'POST') {
                if (Object.keys (query).length)
                    body = this.json (query);
                    payload = body;
            }
            // let payload = (body) ? body : '';
            let what = nonce + method + request + payload;
            let secret = this.base64ToBinary (this.secret);
            let signature = this.hmac (this.encode (what), secret, 'sha256', 'base64');
            headers = {
                'CB-ACCESS-KEY': this.apiKey,
                'CB-ACCESS-SIGN': this.decode (signature),
                'CB-ACCESS-TIMESTAMP': nonce,
                'CB-ACCESS-PASSPHRASE': this.password,
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let response = await this.fetch2 (path, api, method, params, headers, body);
        if ('message' in response) {
            if (response['message'].indexOf ('price too precise') >= 0) {
                throw new InvalidOrder (this.id + ' ' + this.json (response));
            }
            throw new ExchangeError (this.id + ' ' + this.json (response));
        }
        return response;
    }
}<commit_msg>GDAX minor fix #427<commit_after>"use strict";

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

const Exchange = require ('./base/Exchange')
const { ExchangeError, InsufficientFunds, OrderNotFound, DDoSProtection } = require ('./base/errors')

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

module.exports = class gdax extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'gdax',
            'name': 'GDAX',
            'countries': 'US',
            'rateLimit': 1000,
            'hasCORS': true,
            'hasFetchOHLCV': true,
            'hasWithdraw': true,
            'hasFetchOrder': true,
            'hasFetchOrders': true,
            'hasFetchOpenOrders': true,
            'hasFetchClosedOrders': true,
            'timeframes': {
                '1m': 60,
                '5m': 300,
                '15m': 900,
                '30m': 1800,
                '1h': 3600,
                '2h': 7200,
                '4h': 14400,
                '12h': 43200,
                '1d': 86400,
                '1w': 604800,
                '1M': 2592000,
                '1y': 31536000,
            },
            'urls': {
                'test': 'https://api-public.sandbox.gdax.com',
                'logo': 'https://user-images.githubusercontent.com/1294454/27766527-b1be41c6-5edb-11e7-95f6-5b496c469e2c.jpg',
                'api': 'https://api.gdax.com',
                'www': 'https://www.gdax.com',
                'doc': 'https://docs.gdax.com',
            },
            'api': {
                'public': {
                    'get': [
                        'currencies',
                        'products',
                        'products/{id}/book',
                        'products/{id}/candles',
                        'products/{id}/stats',
                        'products/{id}/ticker',
                        'products/{id}/trades',
                        'time',
                    ],
                },
                'private': {
                    'get': [
                        'accounts',
                        'accounts/{id}',
                        'accounts/{id}/holds',
                        'accounts/{id}/ledger',
                        'coinbase-accounts',
                        'fills',
                        'funding',
                        'orders',
                        'orders/{id}',
                        'payment-methods',
                        'position',
                        'reports/{id}',
                        'users/self/trailing-volume',
                    ],
                    'post': [
                        'deposits/coinbase-account',
                        'deposits/payment-method',
                        'funding/repay',
                        'orders',
                        'position/close',
                        'profiles/margin-transfer',
                        'reports',
                        'withdrawals/coinbase',
                        'withdrawals/crypto',
                        'withdrawals/payment-method',
                    ],
                    'delete': [
                        'orders',
                        'orders/{id}',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.0,
                    'taker': 0.25 / 100,
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetProducts ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'];
            let base = market['base_currency'];
            let quote = market['quote_currency'];
            let symbol = base + '/' + quote;
            let amountLimits = {
                'min': market['base_min_size'],
                'max': market['base_max_size'],
            };
            let priceLimits = {
                'min': market['quote_increment'],
                'max': undefined,
            };
            let costLimits = {
                'min': priceLimits['min'],
                'max': undefined,
            };
            let limits = {
                'amount': amountLimits,
                'price': priceLimits,
                'cost': costLimits,
            };
            let precision = {
                'amount': -Math.log10 (parseFloat (amountLimits['min'])),
                'price': -Math.log10 (parseFloat (priceLimits['min'])),
            };
            let taker = this.fees['trading']['taker'];
            if ((base == 'ETH') || (base == 'LTC')) {
                taker = 0.3;
            }
            result.push (this.extend (this.fees['trading'], {
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'info': market,
                'precision': precision,
                'limits': limits,
                'taker': taker,
            }));
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetAccounts ();
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['currency'];
            let account = {
                'free': parseFloat (balance['available']),
                'used': parseFloat (balance['hold']),
                'total': parseFloat (balance['balance']),
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetProductsIdBook (this.extend ({
            'id': this.marketId (symbol),
            'level': 2, // 1 best bidask, 2 aggregated, 3 full
        }, params));
        return this.parseOrderBook (orderbook);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = this.extend ({
            'id': market['id'],
        }, params);
        let ticker = await this.publicGetProductsIdTicker (request);
        let quote = await this.publicGetProductsIdStats (request);
        let timestamp = this.parse8601 (ticker['time']);
        let bid = undefined;
        let ask = undefined;
        if ('bid' in ticker)
            bid = parseFloat (ticker['bid']);
        if ('ask' in ticker)
            ask = parseFloat (ticker['ask']);
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': parseFloat (quote['high']),
            'low': parseFloat (quote['low']),
            'bid': bid,
            'ask': ask,
            'vwap': undefined,
            'open': parseFloat (quote['open']),
            'close': undefined,
            'first': undefined,
            'last': parseFloat (quote['last']),
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': parseFloat (ticker['volume']),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

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

    async fetchTrades (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetProductsIdTrades (this.extend ({
            'id': market['id'], // fixes issue #2
        }, params));
        return this.parseTrades (response, market);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
        return [
            ohlcv[0] * 1000,
            ohlcv[3],
            ohlcv[2],
            ohlcv[1],
            ohlcv[4],
            ohlcv[5],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let granularity = this.timeframes[timeframe];
        let request = {
            'id': market['id'],
            'granularity': granularity,
        };
        if (since) {
            request['start'] = this.iso8601 (since);
            if (!limit)
                limit = 200; // max = 200
            request['end'] = this.iso8601 (limit * granularity * 1000 + since);
        }
        let response = await this.publicGetProductsIdCandles (this.extend (request, params));
        return this.parseOHLCVs (response, market, timeframe, since, limit);
    }

    async fetchTime () {
        let response = this.publicGetTime ();
        return this.parse8601 (response['iso']);
    }

    getOrderStatus (status) {
        let statuses = {
            'pending': 'open',
            'active': 'open',
            'open': 'open',
            'done': 'closed',
            'canceled': 'canceled',
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        let timestamp = this.parse8601 (order['created_at']);
        let symbol = undefined;
        if (!market) {
            if (order['product_id'] in this.markets_by_id)
                market = this.markets_by_id[order['product_id']];
        }
        let status = this.getOrderStatus (order['status']);
        let price = this.safeFloat (order, 'price');
        let amount = this.safeFloat (order, 'size');
        let filled = this.safeFloat (order, 'filled_size');
        let remaining = amount - filled;
        let cost = this.safeFloat (order, 'executed_value');
        if (market)
            symbol = market['symbol'];
        return {
            'id': order['id'],
            'info': order,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'status': status,
            'symbol': symbol,
            'type': order['type'],
            'side': order['side'],
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'fee': undefined,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (response);
    }

    async fetchOrders (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'status': 'all',
        };
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let response = await this.privateGetOrders (this.extend (request, params));
        return this.parseOrders (response, market);
    }

    async fetchOpenOrders (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let response = await this.privateGetOrders (this.extend (request, params));
        return this.parseOrders (response, market);
    }

    async fetchClosedOrders (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'status': 'done',
        };
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let response = await this.privateGetOrders (this.extend (request, params));
        return this.parseOrders (response, market);
    }

    async createOrder (market, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        // let oid = this.nonce ().toString ();
        let order = {
            'product_id': this.marketId (market),
            'side': side,
            'size': amount,
            'type': type,
        };
        if (type == 'limit')
            order['price'] = price;
        let response = await this.privatePostOrders (this.extend (order, params));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privateDeleteOrdersId ({ 'id': id });
    }

    async getPaymentMethods () {
        let response = await this.privateGetPaymentMethods ();
        return response;
    }

    async withdraw (currency, amount, address, params = {}) {
        await this.loadMarkets ();
        let response = undefined;
        if ('payment_method_id' in params) {
            response = await this.privatePostWithdrawalsPaymentMethod (this.extend ({
                'currency': currency,
                'amount': amount,
            }, params));
        } else {
            response = await this.privatePostWithdrawalsCrypto (this.extend ({
                'currency': currency,
                'amount': amount,
                'crypto_address': address,
            }, params));
        }
        if (!response)
            throw ExchangeError (this.id + ' withdraw() error: ' + this.json (response));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (method == 'GET') {
            if (Object.keys (query).length)
                request += '?' + this.urlencode (query);
        }
        let url = this.urls['api'] + request;
        if (api == 'private') {
            if (!this.apiKey)
                throw new AuthenticationError (this.id + ' requires apiKey property for authentication and trading');
            if (!this.secret)
                throw new AuthenticationError (this.id + ' requires secret property for authentication and trading');
            if (!this.password)
                throw new AuthenticationError (this.id + ' requires password property for authentication and trading');
            let nonce = this.nonce ().toString ();
            let payload = '';
            if (method == 'POST') {
                if (Object.keys (query).length)
                    body = this.json (query);
                    payload = body;
            }
            // let payload = (body) ? body : '';
            let what = nonce + method + request + payload;
            let secret = this.base64ToBinary (this.secret);
            let signature = this.hmac (this.encode (what), secret, 'sha256', 'base64');
            headers = {
                'CB-ACCESS-KEY': this.apiKey,
                'CB-ACCESS-SIGN': this.decode (signature),
                'CB-ACCESS-TIMESTAMP': nonce,
                'CB-ACCESS-PASSPHRASE': this.password,
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (code == 400) {
            let response = JSON.parse (body);
            let message = response['message'];
            if (message.includes ('price too precise')) {
                throw new InvalidOrder (this.id + ' ' + this.json (response));
            }
        }
    }

    async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let response = await this.fetch2 (path, api, method, params, headers, body);
        if ('message' in response) {
            throw new ExchangeError (this.id + ' ' + this.json (response));
        }
        return response;
    }
}<|endoftext|>


<commit_before>module.exports = (function(){

	return function unixToDate(unixTime) {
		var date = new Date(Number(unixTime));
		var year = date.getFullYear();
		var month;
		var day;

		if (date.getMonth().toString().length === 1) {
			month = "0" + date.getMonth().toString();
		} else {
			month = date.getMonth().toString();
		}

		if (date.getDate().toString().length === 1) {
			day = "0" + date.getDay().toString();
		} else {
			day = date.getDate().toString();
		}

		return year + '-' + month + '-' + day;
	}
})();<commit_msg>Fix previous month bug due to 0-11 months scale.<commit_after>module.exports = (function(){

	return function unixToDate(unixTime) {
		console.log(unixTime)
		var date = new Date(Number(unixTime));
		var year = date.getFullYear();
		var month;
		var day;

		if (date.getMonth().toString().length === 1) {
			month = "0" + (date.getMonth() + 1).toString();
		} else {
			month = (date.getMonth() + 1).toString();
		}

		if (date.getDate().toString().length === 1) {
			day = "0" + date.getDay().toString();
		} else {
			day = date.getDate().toString();
		}

		return year + '-' + month + '-' + day;
	}
})();<|endoftext|>


<commit_before>'use strict';

var utilsLib = require('../tasks/utils');

function getData(source) {
  var attr = 'group_name';
  var answer = [];
  var groups = [];

  source.forEach(function(file) {
    var data = require('.' + file);

    data.events.forEach(function(ev) {
      var attribute = ev[ attr ];

      if (groups.indexOf(attribute) < 0) {
        if (attribute) {
          groups.push(attribute)
          answer.push({
            group: attribute,
            n: 1,
            url: ev.group_url
          })
        }
      } else {
        answer.forEach(function(a) {
          if (a.group === ev[ attr ]) {
            a.n += 1;
          }
        })
      }
    })
  })

  answer = getMoreThan(answer, 9);
  answer = removeLocationString(answer);
  answer = utilsLib.sortByAlphabet(answer, 'group');

  utilsLib.publishData('events-per-group', answer);
}

function getMoreThan(array, number) {
  var answer = [];

  array.forEach(function(eachItem) {
    if (eachItem.n > number) {
      answer.push(eachItem)
    }
  })

  return answer;
}

function removeLocationString(array) {
  array.forEach(function(eachItem) {
    var group = eachItem.group.replace('Singapore ', '');
    eachItem.group = group;

    group = eachItem.group.replace('(Singapore)', '');
    eachItem.group = group;

    group = eachItem.group.replace('(SG)', '');
    eachItem.group = group;

    group = eachItem.group.replace(' SG', '');
    eachItem.group = group;

    // remove "/groups" from facebook group url for Facebook Pages/Groups
    var url = eachItem.url;
    if (url.indexOf('www.facebook.com/groups') > -1) {
      eachItem.url = url.replace('/groups', '')
    }
  })

  return array;
}

exports.getData = getData;
<commit_msg>refactor: publish graph from a main file<commit_after>'use strict';

var utilsLib = require('../tasks/utils');

function getData(source) {
  var attr = 'group_name';
  var answer = [];
  var groups = [];

  source.forEach(function(file) {
    var data = require('.' + file);

    data.events.forEach(function(ev) {
      var attribute = ev[ attr ];

      if (groups.indexOf(attribute) < 0) {
        if (attribute) {
          groups.push(attribute)
          answer.push({
            group: attribute,
            n: 1,
            url: ev.group_url
          })
        }
      } else {
        answer.forEach(function(a) {
          if (a.group === ev[ attr ]) {
            a.n += 1;
          }
        })
      }
    })
  })

  answer = getMoreThan(answer, 9);
  answer = removeLocationString(answer);
  answer = utilsLib.sortByAlphabet(answer, 'group');

  return answer;
}

function getMoreThan(array, number) {
  var answer = [];

  array.forEach(function(eachItem) {
    if (eachItem.n > number) {
      answer.push(eachItem)
    }
  })

  return answer;
}

function removeLocationString(array) {
  array.forEach(function(eachItem) {
    var group = eachItem.group.replace('Singapore ', '');
    eachItem.group = group;

    group = eachItem.group.replace('(Singapore)', '');
    eachItem.group = group;

    group = eachItem.group.replace('(SG)', '');
    eachItem.group = group;

    group = eachItem.group.replace(' SG', '');
    eachItem.group = group;

    // remove "/groups" from facebook group url for Facebook Pages/Groups
    var url = eachItem.url;
    if (url.indexOf('www.facebook.com/groups') > -1) {
      eachItem.url = url.replace('/groups', '')
    }
  })

  return array;
}

exports.getData = getData;
<|endoftext|>


<commit_before>var _ = require('underscore');
var FieldType = require('../Type');
var util = require('util');
var utils = require('keystone-utils');
var displayName = require('display-name');

/**
 * Name FieldType Constructor
 * @extends Field
 * @api public
 */
function name (list, path, options) {
	this._fixedSize = 'full';
	options.default = { first: '', last: '' };
	options.nofilter = true; // TODO: remove this when 0.4 is merged
	name.super_.call(this, list, path, options);
}
util.inherits(name, FieldType);

/**
 * Registers the field on the List's Mongoose Schema.
 *
 * Adds String properties for .first and .last name, and a virtual
 * with get() and set() methods for .full
 *
 * @api public
 */

name.prototype.addToSchema = function () {
	var schema = this.list.schema;
	var paths = this.paths = {
		first: this._path.append('.first'),
		last: this._path.append('.last'),
		full: this._path.append('.full'),
	};

	schema.nested[this.path] = true;
	schema.add({
		first: String,
		last: String,
	}, this.path + '.');

	schema.virtual(paths.full).get(function () {
		return displayName(this.get(paths.first), this.get(paths.last));
	});

	schema.virtual(paths.full).set(function (value) {
		if (typeof value !== 'string') {
			this.set(paths.first, undefined);
			this.set(paths.last, undefined);
			return;
		}
		var split = value.split(' ');
		this.set(paths.first, split.shift());
		this.set(paths.last, split.join(' ') || undefined);
	});

	this.bindUnderscoreMethods();
};

/**
 * Gets the string to use for sorting by this field
 */

name.prototype.getSortString = function (options) {
	if (options.invert) {
		return '-' + this.paths.first + ' -' + this.paths.last;
	}
	return this.paths.first + ' ' + this.paths.last;
};

/**
 * Add filters to a query
 *
 * TODO: this filter will conflict with any other $or filter, including filters
 * on other "name" type fields; need to work out a better way to implement.
 */
name.prototype.addFilterToQuery = function (filter, query) {
	query = query || {};
	if (filter.mode === 'exactly' && !filter.value) {
		query[this.paths.first] = query[this.paths.last] = filter.inverted ? { $nin: ['', null] } : { $in: ['', null] };
		return;
	}
	var value = utils.escapeRegExp(filter.value);
	if (filter.mode === 'startsWith') {
		value = '^' + value;
	} else if (filter.mode === 'endsWith') {
		value = value + '$';
	} else if (filter.mode === 'exactly') {
		value = '^' + value + '$';
	}
	value = new RegExp(value, filter.caseSensitive ? '' : 'i');
	if (filter.inverted) {
		query[this.paths.first] = query[this.paths.last] = { $not: value };
	} else {
		var first = {}; first[this.paths.first] = value;
		var last = {}; last[this.paths.last] = value;
		var $or = [first, last];
		if (query.$and) {
			query.$and.push({ $or: $or });
		} else if (query.$or) {
			query.$and = [{ $or: query.$or }, { $or: $or }];
			delete query.$or;
		} else {
			query.$or = $or;
		}
	}
	return query;
};

/**
 * Formats the field value
 */

name.prototype.format = function (item) {
	return item.get(this.paths.full);
};

/**
 * Validates that a value for this field has been provided in a data object
 *
 * Deprecated
 */
name.prototype.inputIsValid = function (data, required, item) {
	// Input is valid if none was provided, but the item has data
	if (!(this.path in data || this.paths.first in data || this.paths.last in data || this.paths.full in data) && item && item.get(this.paths.full)) return true;
	// Input is valid if the field is not required
	if (!required) return true;
	// Otherwise check for valid strings in the provided data,
	// which may be nested or use flattened paths.
	if (_.isObject(data[this.path])) {
		return (data[this.path].full || data[this.path].first || data[this.path].last) ? true : false;
	} else {
		return (data[this.paths.full] || data[this.paths.first] || data[this.paths.last]) ? true : false;
	}
};

/**
 * Detects whether the field has been modified
 *
 * @api public
 */
name.prototype.isModified = function (item) {
	return item.isModified(this.paths.first) || item.isModified(this.paths.last);
};

/**
 * Updates the value for this field in the item from a data object
 *
 * @api public
 */
name.prototype.updateItem = function (item, data, callback) {
	if (!_.isObject(data)) return process.nextTick(callback);
	var paths = this.paths;
	var setValue;
	if (this.path in data && _.isString(data[this.path])) {
		// Allow the root path as an alias to {path}.full
		item.set(paths.full, data[this.path]);
	} else if (this.path in data && _.isObject(data[this.path])) {
		// Allow a nested object like { path: { first: 'Jed' } }
		var valueObj = data[this.path];
		setValue = function (key) {
			if (key in valueObj && valueObj[key] !== item.get(paths[key])) {
				item.set(paths[key], valueObj[key]);
			}
		};
	} else {
		// Default to flattened paths like { 'path.first': 'Jed' }
		setValue = function (key) {
			if (paths[key] in data && data[paths[key]] !== item.get(paths[key])) {
				item.set(paths[key], data[paths[key]]);
			}
		};
	}
	if (setValue) {
		_.each(['full', 'first', 'last'], setValue);
	}
	process.nextTick(callback);
};

/* Export Field Type */
module.exports = name;
<commit_msg>Adding getInputFromData method for name fields<commit_after>var _ = require('underscore');
var FieldType = require('../Type');
var util = require('util');
var utils = require('keystone-utils');
var displayName = require('display-name');

/**
 * Name FieldType Constructor
 * @extends Field
 * @api public
 */
function name (list, path, options) {
	this._fixedSize = 'full';
	options.default = { first: '', last: '' };
	options.nofilter = true; // TODO: remove this when 0.4 is merged
	name.super_.call(this, list, path, options);
}
util.inherits(name, FieldType);

/**
 * Registers the field on the List's Mongoose Schema.
 *
 * Adds String properties for .first and .last name, and a virtual
 * with get() and set() methods for .full
 *
 * @api public
 */

name.prototype.addToSchema = function () {
	var schema = this.list.schema;
	var paths = this.paths = {
		first: this._path.append('.first'),
		last: this._path.append('.last'),
		full: this._path.append('.full'),
	};

	schema.nested[this.path] = true;
	schema.add({
		first: String,
		last: String,
	}, this.path + '.');

	schema.virtual(paths.full).get(function () {
		return displayName(this.get(paths.first), this.get(paths.last));
	});

	schema.virtual(paths.full).set(function (value) {
		if (typeof value !== 'string') {
			this.set(paths.first, undefined);
			this.set(paths.last, undefined);
			return;
		}
		var split = value.split(' ');
		this.set(paths.first, split.shift());
		this.set(paths.last, split.join(' ') || undefined);
	});

	this.bindUnderscoreMethods();
};

/**
 * Gets the string to use for sorting by this field
 */

name.prototype.getSortString = function (options) {
	if (options.invert) {
		return '-' + this.paths.first + ' -' + this.paths.last;
	}
	return this.paths.first + ' ' + this.paths.last;
};

/**
 * Add filters to a query
 *
 * TODO: this filter will conflict with any other $or filter, including filters
 * on other "name" type fields; need to work out a better way to implement.
 */
name.prototype.addFilterToQuery = function (filter, query) {
	query = query || {};
	if (filter.mode === 'exactly' && !filter.value) {
		query[this.paths.first] = query[this.paths.last] = filter.inverted ? { $nin: ['', null] } : { $in: ['', null] };
		return;
	}
	var value = utils.escapeRegExp(filter.value);
	if (filter.mode === 'startsWith') {
		value = '^' + value;
	} else if (filter.mode === 'endsWith') {
		value = value + '$';
	} else if (filter.mode === 'exactly') {
		value = '^' + value + '$';
	}
	value = new RegExp(value, filter.caseSensitive ? '' : 'i');
	if (filter.inverted) {
		query[this.paths.first] = query[this.paths.last] = { $not: value };
	} else {
		var first = {}; first[this.paths.first] = value;
		var last = {}; last[this.paths.last] = value;
		var $or = [first, last];
		if (query.$and) {
			query.$and.push({ $or: $or });
		} else if (query.$or) {
			query.$and = [{ $or: query.$or }, { $or: $or }];
			delete query.$or;
		} else {
			query.$or = $or;
		}
	}
	return query;
};

/**
 * Formats the field value
 */

name.prototype.format = function (item) {
	return item.get(this.paths.full);
};

/**
 * Get the value from a data object; may be simple or a pair of fields
 */
name.prototype.getInputFromData = function (data) {
	var first = this.getValueFromData(data, '_first');
	var last = this.getValueFromData(data, '_last');
	if (typeof first === 'string' || typeof last === 'string') {
		return {
			first: first,
			last: last,
		};
	}
	return this.getValueFromData(data);
};

/**
 * Validates that a value for this field has been provided in a data object
 *
 * Deprecated
 */
name.prototype.inputIsValid = function (data, required, item) {
	// Input is valid if none was provided, but the item has data
	if (!(this.path in data || this.paths.first in data || this.paths.last in data || this.paths.full in data) && item && item.get(this.paths.full)) return true;
	// Input is valid if the field is not required
	if (!required) return true;
	// Otherwise check for valid strings in the provided data,
	// which may be nested or use flattened paths.
	if (_.isObject(data[this.path])) {
		return (data[this.path].full || data[this.path].first || data[this.path].last) ? true : false;
	} else {
		return (data[this.paths.full] || data[this.paths.first] || data[this.paths.last]) ? true : false;
	}
};

/**
 * Detects whether the field has been modified
 *
 * @api public
 */
name.prototype.isModified = function (item) {
	return item.isModified(this.paths.first) || item.isModified(this.paths.last);
};

/**
 * Updates the value for this field in the item from a data object
 *
 * @api public
 */
name.prototype.updateItem = function (item, data, callback) {
	if (!_.isObject(data)) return process.nextTick(callback);
	var paths = this.paths;
	var setValue;
	if (this.path in data && _.isString(data[this.path])) {
		// Allow the root path as an alias to {path}.full
		item.set(paths.full, data[this.path]);
	} else if (this.path in data && _.isObject(data[this.path])) {
		// Allow a nested object like { path: { first: 'Jed' } }
		var valueObj = data[this.path];
		setValue = function (key) {
			if (key in valueObj && valueObj[key] !== item.get(paths[key])) {
				item.set(paths[key], valueObj[key]);
			}
		};
	} else {
		// Default to flattened paths like { 'path.first': 'Jed' }
		setValue = function (key) {
			if (paths[key] in data && data[paths[key]] !== item.get(paths[key])) {
				item.set(paths[key], data[paths[key]]);
			}
		};
	}
	if (setValue) {
		_.each(['full', 'first', 'last'], setValue);
	}
	process.nextTick(callback);
};

/* Export Field Type */
module.exports = name;
<|endoftext|>


<commit_before>google.charts.load('current', {packages: ['corechart', 'line']});

var key = '';

function formatter(hour, minute) {
    var str = '';
    if (hour < 10) {
        str += '0';
    }
    str += String(hour);
    str += ':';
    if (minute < 10) {
        str += '0';
    }
    str += String(minute);
    return str;
}

function parse_detail(detail, first_blood) {
    var html = '';
    var first_solve = false;
    if (detail[1] !== -1) {
        var time = formatter(Math.floor(detail[1] / 60), detail[1] % 60);
        html += '';
        if (detail[1] === first_blood) {
            first_solve = true;
        }
        if (detail[2] === 0) {
            html += '+
' + time;
        } else {
            html += '+' + String(detail[2]) + '
' + time;
        }
    } else if (detail[2] > 0) {
        html += '';
        html += String(-detail[2]) + '';
    }
    if (first_solve) {
        html = '' + html + '	';
    } else {
        html = '' + html + '	'
    }
    return html;
}

function parse_board() {
    var contest = data[key];
    console.log(contest.title);
    $('.title').text(contest.title);
    $('.date').text(contest.date);
    $('.table').empty();
    var problem_num = contest.num;
    var header = '
Standings

#	Who	=	Penalty	';
    for (var i = 0 ; i < problem_num ; ++ i) {
        header += '';
        header += String.fromCharCode('A'.charCodeAt(0) + i);
        header += '	';
    }
    header += '
';
    $('.table').append(header);

    var ranklist = contest.ranklist;

    var first_blood = new Array(problem_num);
    for (var i = 0 ; i < problem_num ; ++ i) {
        first_blood[i] = 1 << 30;
    }
    for (var i = 0 ; i < ranklist.length ; ++ i) {
        var team = ranklist[i];
        var status = contest.statuses[team];
        for (var j = 0 ; j < problem_num ; ++ j) {
            if (status[j][1] !== -1) {
                first_blood[j] = Math.min(first_blood[j], status[j][1]);
            }
        }
    }

    for (var i = 0 ; i < ranklist.length ; ++ i) {
        var team = ranklist[i];
        var status = contest.statuses[team];
        var row = '
' + String(i + 1) + '	' + team + '	';

        var solved = 0, penalty = 0;
        for (var j = 0 ; j < problem_num ; ++ j) {
            if (status[j][1] !== -1) {
                solved ++;
                penalty += status[j][1] + status[j][2] * 20;
            }
        }
        row += '' + String(solved) + '	';
        row += '' + String(penalty) + '	';
        for (var j = 0 ; j < problem_num ; ++ j) {
            row += parse_detail(status[j] , first_blood[j]);
        }
        row += '
';
        $('.table').append(row);
    }
}

function drawChart() {
    var contest = data[key];
    var ranklist = contest.ranklist;
    var problem_num = contest.num;
    var chart_data = new google.visualization.DataTable();
    var pass_time = [0, contest.time ? contest.time : 300];

    chart_data.addColumn('number', 'X');
    for (var i = 0 ; i < ranklist.length ; ++ i) {
        chart_data.addColumn('number',  ranklist[i]);
        chart_data.addColumn({type:'string', role:'annotation'});
        for (var j = 0 ; j < problem_num ; ++ j) {
            var t = contest.statuses[ranklist[i]][j][1];
            if (t >= 0) {
                pass_time.push(t);
            }
        }
    }
    pass_time = pass_time.sort(function (a , b) {
        return a - b;
    });
    for (var k = 0 ; k < pass_time.length ; ++ k) {
        if (k > 0 && pass_time[k] === pass_time[k - 1]) {
            continue;
        }
        var row = [pass_time[k]];
        var scores = [];
        for (var i = 0 ; i < ranklist.length ; ++ i) {
            var team = ranklist[i], solved = 0, penalty = 0;
            for (var j = 0 ; j < problem_num ; ++ j) {
                var t = contest.statuses[team][j][1];
                if (t >= 0 && t <= pass_time[k]) {
                    ++ solved;
                    penalty += contest.statuses[team][j][1] + contest.statuses[team][j][2] * 20;
                }
            }
            scores.push([solved, penalty]);
        }

        for (var i = 0 ; i < ranklist.length ; ++ i) {
            var team = ranklist[i], rank = 1;
            for (var j = 0 ; j < ranklist.length ; ++ j) {
                if (scores[j][0] > scores[i][0]) {
                    ++ rank;
                } else if (scores[j][0] === scores[i][0] && scores[j][1] < scores[i][1]) {
                    ++ rank;
                }
            }
            row.push(-rank);

            var solved = '';
            for (var j = 0 ; j < problem_num ; ++ j) {
                var t = contest.statuses[team][j][1];
                if (t === pass_time[k]) {
                    solved += String.fromCharCode('A'.charCodeAt(0) + j);
                }
            }
            if (solved.length > 0) {
                row.push(solved);
            } else {
                row.push(null);
            }
        }
        chart_data.addRow(row);
    }

    var options = {
        hAxis: {
            title: 'Time'
        },
        vAxis: {
            title: 'Rank'
        },
        width: 1366,
        height: 720
    };

    var chart = new google.visualization.LineChart(document.getElementById('chart'));
    chart.draw(chart_data, options);
}

$(document).ready(function () {
    $('#contest_list').empty();
    contest_list = [];
    for (var p in data) {
        if (p === 'end') continue;
        contest_list.append(p);
    }
    for (var i in contest_list.sort()) {
        var p = contest_list[i];
        var link = '' + data[p].date + '';
        $('#contest_list').append(link);
    }
    var arg_list = window.location.href.split('#');
    key = arg_list.length < 2 ? '01' : arg_list[1];
    parse(key);
});

function parse(str) {
    key = str;
    parse_board();
    google.charts.setOnLoadCallback(drawChart);
}
<commit_msg>Update renderers.js<commit_after>google.charts.load('current', {packages: ['corechart', 'line']});

var key = '';

function formatter(hour, minute) {
    var str = '';
    if (hour < 10) {
        str += '0';
    }
    str += String(hour);
    str += ':';
    if (minute < 10) {
        str += '0';
    }
    str += String(minute);
    return str;
}

function parse_detail(detail, first_blood) {
    var html = '';
    var first_solve = false;
    if (detail[1] !== -1) {
        var time = formatter(Math.floor(detail[1] / 60), detail[1] % 60);
        html += '';
        if (detail[1] === first_blood) {
            first_solve = true;
        }
        if (detail[2] === 0) {
            html += '+
' + time;
        } else {
            html += '+' + String(detail[2]) + '
' + time;
        }
    } else if (detail[2] > 0) {
        html += '';
        html += String(-detail[2]) + '';
    }
    if (first_solve) {
        html = '' + html + '	';
    } else {
        html = '' + html + '	'
    }
    return html;
}

function parse_board() {
    var contest = data[key];
    console.log(contest.title);
    $('.title').text(contest.title);
    $('.date').text(contest.date);
    $('.table').empty();
    var problem_num = contest.num;
    var header = '
Standings

#	Who	=	Penalty	';
    for (var i = 0 ; i < problem_num ; ++ i) {
        header += '';
        header += String.fromCharCode('A'.charCodeAt(0) + i);
        header += '	';
    }
    header += '
';
    $('.table').append(header);

    var ranklist = contest.ranklist;

    var first_blood = new Array(problem_num);
    for (var i = 0 ; i < problem_num ; ++ i) {
        first_blood[i] = 1 << 30;
    }
    for (var i = 0 ; i < ranklist.length ; ++ i) {
        var team = ranklist[i];
        var status = contest.statuses[team];
        for (var j = 0 ; j < problem_num ; ++ j) {
            if (status[j][1] !== -1) {
                first_blood[j] = Math.min(first_blood[j], status[j][1]);
            }
        }
    }

    for (var i = 0 ; i < ranklist.length ; ++ i) {
        var team = ranklist[i];
        var status = contest.statuses[team];
        var row = '
' + String(i + 1) + '	' + team + '	';

        var solved = 0, penalty = 0;
        for (var j = 0 ; j < problem_num ; ++ j) {
            if (status[j][1] !== -1) {
                solved ++;
                penalty += status[j][1] + status[j][2] * 20;
            }
        }
        row += '' + String(solved) + '	';
        row += '' + String(penalty) + '	';
        for (var j = 0 ; j < problem_num ; ++ j) {
            row += parse_detail(status[j] , first_blood[j]);
        }
        row += '
';
        $('.table').append(row);
    }
}

function drawChart() {
    var contest = data[key];
    var ranklist = contest.ranklist;
    var problem_num = contest.num;
    var chart_data = new google.visualization.DataTable();
    var pass_time = [0, contest.time ? contest.time : 300];

    chart_data.addColumn('number', 'X');
    for (var i = 0 ; i < ranklist.length ; ++ i) {
        chart_data.addColumn('number',  ranklist[i]);
        chart_data.addColumn({type:'string', role:'annotation'});
        for (var j = 0 ; j < problem_num ; ++ j) {
            var t = contest.statuses[ranklist[i]][j][1];
            if (t >= 0) {
                pass_time.push(t);
            }
        }
    }
    pass_time = pass_time.sort(function (a , b) {
        return a - b;
    });
    for (var k = 0 ; k < pass_time.length ; ++ k) {
        if (k > 0 && pass_time[k] === pass_time[k - 1]) {
            continue;
        }
        var row = [pass_time[k]];
        var scores = [];
        for (var i = 0 ; i < ranklist.length ; ++ i) {
            var team = ranklist[i], solved = 0, penalty = 0;
            for (var j = 0 ; j < problem_num ; ++ j) {
                var t = contest.statuses[team][j][1];
                if (t >= 0 && t <= pass_time[k]) {
                    ++ solved;
                    penalty += contest.statuses[team][j][1] + contest.statuses[team][j][2] * 20;
                }
            }
            scores.push([solved, penalty]);
        }

        for (var i = 0 ; i < ranklist.length ; ++ i) {
            var team = ranklist[i], rank = 1;
            for (var j = 0 ; j < ranklist.length ; ++ j) {
                if (scores[j][0] > scores[i][0]) {
                    ++ rank;
                } else if (scores[j][0] === scores[i][0] && scores[j][1] < scores[i][1]) {
                    ++ rank;
                }
            }
            row.push(-rank);

            var solved = '';
            for (var j = 0 ; j < problem_num ; ++ j) {
                var t = contest.statuses[team][j][1];
                if (t === pass_time[k]) {
                    solved += String.fromCharCode('A'.charCodeAt(0) + j);
                }
            }
            if (solved.length > 0) {
                row.push(solved);
            } else {
                row.push(null);
            }
        }
        chart_data.addRow(row);
    }

    var options = {
        hAxis: {
            title: 'Time'
        },
        vAxis: {
            title: 'Rank'
        },
        width: 1366,
        height: 720
    };

    var chart = new google.visualization.LineChart(document.getElementById('chart'));
    chart.draw(chart_data, options);
}

$(document).ready(function () {
    $('#contest_list').empty();
    contest_list = [];
    for (var p in data) {
        if (p === 'end') continue;
        contest_list.push(p);
    }
    for (var i in contest_list.sort()) {
        var p = contest_list[i];
        var link = '' + data[p].date + '';
        $('#contest_list').append(link);
    }
    var arg_list = window.location.href.split('#');
    key = arg_list.length < 2 ? '01' : arg_list[1];
    parse(key);
});

function parse(str) {
    key = str;
    parse_board();
    google.charts.setOnLoadCallback(drawChart);
}
<|endoftext|>


<commit_before>var City = function(deathRate, sliderId, dataset) {
  this.deathRate = deathRate;
  this.dataset = dataset;
  this.getDeathCountList();
  this.sliderSelector = "#" + sliderId;

  var city = this;

  $(this.sliderSelector).slider({
    values: [ deathRate ],
    change: function(event, ui){
      console.log(ui);
      // simulation.drawChart();
    }
  });
};

City.prototype.getDeathCountList = function(){

  this.deathrate = $(this.sliderSelector).slider("option", "value");

  var population = 100000;
  var deaths = 1;
  var generations = 0;

  var deaths_list = [];
  deaths_list.push(deaths);

  while(population > 0){
    deaths = Math.ceil(this.deathrate * deaths);
    population = population - deaths;

    generations++;
    deaths_list.push(deaths);
  }

  this.duration = deaths_list.length;
  return deaths_list;
}

City.prototype.getChartDataset = function(){
  this.dataset.data = this.getDeathCountList();
  return this.dataset;
}

var Simulation = function(cities){
  this.cities = cities;
  this.updateChartWidth();
}

Simulation.prototype.updateChartWidth = function(){
  var chartWidth = 0;

  for (var i = 0; i < this.cities.length; i++){
    var cityOutbreakLength = cities[i].duration;
    if (cityOutbreakLength > chartWidth){
      chartWidth = cityOutbreakLength;
    }
  }

  this.chartWidth = chartWidth;
}

Simulation.prototype.drawChart = function(){
  var context = $("#sim_chart").get(0).getContext("2d");
  var labels = [];

  for (var i = 0; i < this.chartWidth; i++){
    labels.push(i);
  }

  var datasets = [];

  for (var i = 0; i < this.cities.length; i++){
    datasets.push(cities[i].getChartDataset(data));
  }

  var data = {
    labels: labels,
    datasets: datasets
  };

  var chart = new Chart(context).Line(data);
  return chart;
}

var pistoriaDataset = {
  label: "Pistoia: prevention and coping",
  fillColor: "rgba(220,220,220,0.2)",
  strokeColor: "rgba(220,220,220,1)",
  pointColor: "rgba(220,220,220,1)",
  pointStrokeColor: "#fff",
  pointHighlightFill: "#fff",
  pointHighlightStroke: "rgba(220,220,220,1)"
}

var milanDataset = {
  label: "Milan: Quarantine",
  fillColor: "rgba(151,187,205,0.2)",
  strokeColor: "rgba(151,187,205,1)",
  pointColor: "rgba(151,187,205,1)",
  pointStrokeColor: "#fff",
  pointHighlightFill: "#fff",
  pointHighlightStroke: "rgba(151,187,205,1)"
}

var pistoria = new City(35 * 0.1 * 5, "pistoria-slider", pistoriaDataset);
var milan = new City(35 * 0.1 * 1, "milan-slider", milanDataset);

var cities = [pistoria, milan];

var simulation = new Simulation(cities);

var chart = simulation.drawChart();

<commit_msg>more debugging<commit_after>var City = function(deathRate, sliderId, dataset) {
  this.deathRate = deathRate;
  this.dataset = dataset;
  this.getDeathCountList();
  this.sliderSelector = "#" + sliderId;

  var city = this;

  $(this.sliderSelector).slider({
    values: [ deathRate ],
    change: function(event, ui){
      console.log(ui);
      city.deathrate = ui.value;
      simulation.drawChart();
    }
  });
};

City.prototype.getDeathCountList = function(){

  var population = 100000;
  var deaths = 1;
  var generations = 0;

  var deaths_list = [];
  deaths_list.push(deaths);

  while(population > 0){
    deaths = Math.ceil(this.deathrate * deaths);
    population = population - deaths;

    generations++;
    deaths_list.push(deaths);
  }

  this.duration = deaths_list.length;
  return deaths_list;
}

City.prototype.getChartDataset = function(){
  this.dataset.data = this.getDeathCountList();
  return this.dataset;
}

var Simulation = function(cities){
  this.cities = cities;
  this.updateChartWidth();
}

Simulation.prototype.updateChartWidth = function(){
  var chartWidth = 0;

  for (var i = 0; i < this.cities.length; i++){
    var cityOutbreakLength = cities[i].duration;
    if (cityOutbreakLength > chartWidth){
      chartWidth = cityOutbreakLength;
    }
  }

  this.chartWidth = chartWidth;
}

Simulation.prototype.drawChart = function(){
  var context = $("#sim_chart").get(0).getContext("2d");
  var labels = [];

  for (var i = 0; i < this.chartWidth; i++){
    labels.push(i);
  }

  var datasets = [];

  for (var i = 0; i < this.cities.length; i++){
    datasets.push(cities[i].getChartDataset(data));
  }

  var data = {
    labels: labels,
    datasets: datasets
  };

  var chart = new Chart(context).Line(data);
  return chart;
}

var pistoriaDataset = {
  label: "Pistoia: prevention and coping",
  fillColor: "rgba(220,220,220,0.2)",
  strokeColor: "rgba(220,220,220,1)",
  pointColor: "rgba(220,220,220,1)",
  pointStrokeColor: "#fff",
  pointHighlightFill: "#fff",
  pointHighlightStroke: "rgba(220,220,220,1)"
}

var milanDataset = {
  label: "Milan: Quarantine",
  fillColor: "rgba(151,187,205,0.2)",
  strokeColor: "rgba(151,187,205,1)",
  pointColor: "rgba(151,187,205,1)",
  pointStrokeColor: "#fff",
  pointHighlightFill: "#fff",
  pointHighlightStroke: "rgba(151,187,205,1)"
}

var pistoria = new City(35 * 0.1 * 5, "pistoria-slider", pistoriaDataset);
var milan = new City(35 * 0.1 * 1, "milan-slider", milanDataset);

var cities = [pistoria, milan];

var simulation = new Simulation(cities);

var chart = simulation.drawChart();

<|endoftext|>