<commit_before>#!/usr/bin/env node
//
//  runner.js
//  ---------
//
//  Automated testing of Knockout-Secure-Binding
//
//
//  Some handy webdriver docs
//  https://code.google.com/p/selenium/wiki/WebDriverJs
//
'use strict'
require('colors')

var webdriverjs = require('webdriverjs'),
    server = require("./server"),

    // our webdriver desired capabilities
    capabilities,

    // what our webdriver may provide
    client,

    // we use this for ensuring the document is loaded, below
    expect_title = "Knockout Secure Binding - Local unit tests"

capabilities = {
  browserName: "chrome"
}

if (process.env['SAUCE_USERNAME']) {
  // use sauce; see
  // eg http://about.travis-ci.org/docs/user/gui-and-headless-browsers/
  console.log("\nTesting with Sauce Labs".bold)

  capabilities["build"] = process.env.TRAVIS_BUILD_NUMBER
  capabilities["javascriptEnabled"] = true
  capabilities["tunnel-identifier"] = process.env.TRAVIS_JOB_NUMBER,
  capabilities["tags"] = ["CI"]
  capabilities["name"] = "Knockout Secure Binding/Travis"

  client = webdriverjs.remote({
    host: "localhost",
    port: 4445,
    user: process.env.SAUCE_USERNAME,
    key: process.env.SAUCE_ACCESS_KEY,
    desiredCapabilities: capabilities
  })

} else {
  // don't forget to start chromedriver with:
  //  $ chromedriver --url-base=/wd/hub
  // see https://github.com/camme/webdriverjs/issues/113

  console.log("\nTesting with local chromedriver".bold)
  console.log("\nDon't forget to start chromedriver with" +
              " $ chromedriver --url-base=/wd/hub".blue)

  client = webdriverjs.remote({
    host: "localhost",
    port: 9515,
    logLevel: 'data',
    desiredCapabilities: capabilities
  })
}

function run_browser_tests() {
  var uri = 'http://' + server.host + ":" + server.port,
    remote_script = "return window.tests",
    results = false,
    WAIT = 1000,
    fails = 0;

  client.init()
    .url(uri)
    .pause(WAIT)
    .getTitle(function (err, title) {
      // just make sure we're at the right place
      if (err) {
        throw new Error(err)
      }
      if (title !== expect_title) {
        throw new Error("Expected title " + expect_title + " but got "
          + title)
      }
    })
    .execute(remote_script, null, function (err, res) {
      // print output of the tests
      if (err) {
        throw new Error(err)
      }
      results = res.value;
      console.log("\n\tBrowser test results\n".yellow)
      results.results.forEach(function (result) {
        var state = result.state;
        if (state !== 'passed') {
          fails++
          state = state.red.bold
        } else {
          state = state.blue
        }

        console.log(state + "  " + result.title)
      });

      console.log("\n\tTotal: ", results.results.length, " fails: ", fails, "\n")

      // quit the client and exit with appropriate code
      client.end(function () {
        process.exit(fails)
      })
    })
}

// when the server is listening we run our tests
server.instance.on("listening", run_browser_tests)
<commit_msg>Re-arrange end of client communication to avert halt on Travis<commit_after>#!/usr/bin/env node
//
//  runner.js
//  ---------
//
//  Automated testing of Knockout-Secure-Binding
//
//
//  Some handy webdriver docs
//  https://code.google.com/p/selenium/wiki/WebDriverJs
//
'use strict'
require('colors')

var webdriverjs = require('webdriverjs'),
    server = require("./server"),

    // our webdriver desired capabilities
    capabilities,

    // what our webdriver may provide
    client,

    // we use this for ensuring the document is loaded, below
    expect_title = "Knockout Secure Binding - Local unit tests"

capabilities = {
  browserName: "chrome"
}

if (process.env['SAUCE_USERNAME']) {
  // use sauce; see
  // eg http://about.travis-ci.org/docs/user/gui-and-headless-browsers/
  console.log("\nTesting with Sauce Labs".bold)

  capabilities["build"] = process.env.TRAVIS_BUILD_NUMBER
  capabilities["javascriptEnabled"] = true
  capabilities["tunnel-identifier"] = process.env.TRAVIS_JOB_NUMBER,
  capabilities["tags"] = ["CI"]
  capabilities["name"] = "Knockout Secure Binding/Travis"

  client = webdriverjs.remote({
    host: "localhost",
    port: 4445,
    user: process.env.SAUCE_USERNAME,
    key: process.env.SAUCE_ACCESS_KEY,
    desiredCapabilities: capabilities
  })

} else {
  // don't forget to start chromedriver with:
  //  $ chromedriver --url-base=/wd/hub
  // see https://github.com/camme/webdriverjs/issues/113

  console.log("\nTesting with local chromedriver".bold)
  console.log("\nDon't forget to start chromedriver with" +
              " $ chromedriver --url-base=/wd/hub".blue)

  client = webdriverjs.remote({
    host: "localhost",
    port: 9515,
    logLevel: 'data',
    desiredCapabilities: capabilities
  })
}

function run_browser_tests() {
  var uri = 'http://' + server.host + ":" + server.port,
    remote_script = "return window.tests",
    results = false,
    WAIT = 2500,
    fails = 0;

  client.init()
    .url(uri)
    .pause(WAIT)
    .getTitle(function (err, title) {
      // just make sure we're at the right place
      if (err) {
        throw new Error(err)
      }
      if (title !== expect_title) {
        throw new Error("Expected title " + expect_title + " but got "
          + title)
      }
    })
    .execute(remote_script, null, function (err, res) {
      // print output of the tests
      if (err) {
        throw new Error(err)
      }
      results = res.value;
      console.log("\n\tBrowser test results\n".yellow)
      results.results.forEach(function (result) {
        var state = result.state;
        if (state !== 'passed') {
          fails++
          state = state.red.bold
        } else {
          state = state.blue
        }

        console.log(state + "  " + result.title)
      })
      console.log("\n\tTotal: ", results.results.length, " fails: ", fails, "\n")
    })
    .end(function () {
      // quit the client and exit with appropriate code
      process.exit(fails)
    })
  return
}

// when the server is listening we run our tests
server.instance.on("listening", run_browser_tests)
<|endoftext|>


<commit_before>'use strict';

// Set some default values
THREE.XHRLoader.prototype.crossOrigin = 'anonymous';
THREE.ImageUtils.crossOrigin = 'anonymous';

// Set up the renderer
var renderer = null;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.setClearColor( 0x888888, 1 );
renderer.autoClear = false;

// Load any needed extensions
var minMaxGlExt = renderer.getContext().getExtension('EXT_blend_minmax');
if (!minMaxGlExt) {
  console.warn('Could not load blend_minmax extension!');
}

// Create a global scene to work with
var scene = new THREE.Scene();
var skyScene = new THREE.Scene();
var skyObject = null;

// Set up some basic initial lighting
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.1 );
directionalLight.position.set( 100, 100, 100 );
scene.add( directionalLight );

var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.3 );
hemiLight.color.setHSL( 0.6, 1, 0.75 );
hemiLight.groundColor.setHSL( 0.1, 0.8, 0.7 );
hemiLight.position.z = 500;
scene.add( hemiLight );

// Set a global camera to work with
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.up.copy(new THREE.Vector3(0, 0, 1));
camera.position.copy(new THREE.Vector3(-15, 15, 15));
camera.lookAt(new THREE.Vector3(0, 0, 0));

camera.position.add(new THREE.Vector3(5200, 5200, 0));

// Auto resize canvas
window.addEventListener('resize', onWindowResize, false);

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}

// Default material for testing with
var defaultMat = new THREE.MeshPhongMaterial({ambient: 0x030303, color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.FlatShading});

// Create a debug GUI manager.
var debugGui = new dat.GUI();
DebugHelper.init();

// Set up the debugging camera
var debugCamera = null;
var debugInput = new EventEmitter();
var debugControls = null;
var debugCamFrust = new THREE.CameraHelper(camera);

function initDebugCamera() {
  debugCamera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
  debugCamera.position.setFromMatrixPosition(camera.matrixWorld);
  debugCamera.quaternion.setFromRotationMatrix(camera.matrixWorld);
  debugControls = new THREE.FreeFlyControls(debugCamera, debugInput);
  debugControls.movementSpeed = 100;
  debugCamFrust.camera = camera;
  scene.add(debugCamFrust);
}

function destroyDebugCamera() {
  debugCamera = null;
  debugControls = null;
  scene.remove(debugCamFrust);
}

var inputMgrEventHandler = InputManager._handleEvent;
InputManager._handleEvent = function(name, e) {
  if (name === 'keydown' && e.keyCode === 192) {
    if (!debugCamera) {
      initDebugCamera();
    } else {
      destroyDebugCamera();
    }
    e.preventDefault();
    return;
  }

  if (debugControls) {
    debugInput.emit(name, e);
  } else {
    // Use the default handler
    inputMgrEventHandler.call(this, name, e);
  }
};

var activeGameState = null;

// FPS / MS indicator
var stats = new Stats();
stats.setMode(1); // 0: FPS, 1: MS
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );

var clock = new THREE.Clock();
var renderFrame = function () {
  requestAnimationFrame(renderFrame, renderer.domElement);
  stats.begin();

  var delta = clock.getDelta();
  THREE.AnimationHandler.update( delta );

  if (activeGameState) {
    activeGameState.update(delta);
  }

  var renderCamera = camera;
  if (debugCamera) {
    debugCamFrust.update(delta);
    debugControls.update(delta);
    renderCamera = debugCamera;
  }

  // TODO: I don't think this works how I think it works.
  //  Everything appears to draw perfectly correctly no matter what
  //  clearing flags I set, or what clearing I do on my own...
  if (skyObject) {
    skyObject.position.copy(renderCamera.position);
    renderer.render(skyScene, renderCamera);
    renderer.clear(false, true, false);
  } else {
    renderer.clear(true, true, false);
  }
  renderer.render(scene, renderCamera);

  stats.end();
};
renderFrame();

var launchStateName = clientParams.length > 0 ? clientParams[0] : 'test';
console.log('Launching game with state `' + launchStateName + '`');

var launchGameState = null;
if (launchStateName === 'test') {
  launchGameState = gsTest;
} else if (launchStateName === 'nettest') {
  launchGameState = gsNetTest;
} else if (launchStateName === 'login') {
  launchGameState = gsLogin;
} else if (launchStateName === 'gametest') {
  launchGameState = gsGameTest;
} else if (launchStateName === 'particle') {
  launchGameState = gsParticleTest;
} else {
  console.log('Invalid launch state specified.');
}

if (clientParams.indexOf('lmonly') !== -1) {
  config.lmonly = true;
}

ShaderManager.register('skydome', 'skydome.vert', 'skydome.frag', {
  depthWrite: false,
  depthTest: false
});
ShaderManager.register('terrain', 'terrain.vert', 'terrain.frag', {
  attributes: {uv3:{}}
});
ShaderManager.register('terrain_lmonly', 'terrain.vert', 'terrain_lmonly.frag', {
  attributes: {uv3:{}}
});
ShaderManager.register('staticobj', 'staticobj.vert', 'staticobj.frag');
ShaderManager.register('staticobj_lmonly', 'staticobj.vert', 'staticobj_lmonly.frag');
ShaderManager.register('water', 'water.vert', 'water.frag');
ShaderManager.register('particle', 'particle.vert', 'particle.frag', {
  attributes: {
    alpha: { type: 'f', value: [] },
    psize: { type: 'f', value: [] }
  }
});

if (launchGameState) {
  // Shaders before anything else
  ShaderManager.init(function() {
    // Needed for game states that alter UI.
    $(function() {
      launchGameState.prepare(function() {
        launchGameState.enter();
        activeGameState = launchGameState;
      });
    });
  });
}

GDM.register('list_event', DataTable, '3DDATA/STB/LIST_EVENT.STB');

GDM.register('list_zone', DataTable, '3DDATA/STB/LIST_ZONE.STB');
GDM.register('zone_names', StringTable, '3DDATA/STB/LIST_ZONE_S.STL');

GDM.register('char_motiontypes', DataTable, '3DDATA/STB/TYPE_MOTION.STB');
GDM.register('char_motions', DataTable, '3DDATA/STB/FILE_MOTION.STB');

GDM.register('npc_chars', CharacterList, '3DDATA/NPC/LIST_NPC.CHR');
GDM.register('npc_models', ModelListManager, '3DDATA/NPC/PART_NPC.ZSC');

GDM.register('male_skel', Skeleton, '3DDATA/AVATAR/MALE.ZMD');
GDM.register('female_skel', Skeleton, '3DDATA/AVATAR/FEMALE.ZMD');

GDM.register('itm_mface', ModelListManager, '3DDATA/AVATAR/LIST_MFACE.ZSC');
GDM.register('itm_mhair', ModelListManager, '3DDATA/AVATAR/LIST_MHAIR.ZSC');
GDM.register('itm_mcap', ModelListManager, '3DDATA/AVATAR/LIST_MCAP.ZSC');
GDM.register('itm_mbody', ModelListManager, '3DDATA/AVATAR/LIST_MBODY.ZSC');
GDM.register('itm_marms', ModelListManager, '3DDATA/AVATAR/LIST_MARMS.ZSC');
GDM.register('itm_mfoot', ModelListManager, '3DDATA/AVATAR/LIST_MFOOT.ZSC');

GDM.register('itm_fface', ModelListManager, '3DDATA/AVATAR/LIST_WFACE.ZSC');
GDM.register('itm_fhair', ModelListManager, '3DDATA/AVATAR/LIST_WHAIR.ZSC');
GDM.register('itm_fcap', ModelListManager, '3DDATA/AVATAR/LIST_WCAP.ZSC');
GDM.register('itm_fbody', ModelListManager, '3DDATA/AVATAR/LIST_WBODY.ZSC');
GDM.register('itm_farms', ModelListManager, '3DDATA/AVATAR/LIST_WARMS.ZSC');
GDM.register('itm_ffoot', ModelListManager, '3DDATA/AVATAR/LIST_WFOOT.ZSC');

if (config.isEvoData) {
  GDM.register('itm_mfaceitem', ModelListManager, '3DDATA/AVATAR/LIST_MFACEITEM.ZSC');
  GDM.register('itm_ffaceitem', ModelListManager, '3DDATA/AVATAR/LIST_WFACEITEM.ZSC');
} else {
  GDM.register('itm_mfaceitem', ModelListManager, '3DDATA/AVATAR/LIST_FACEITEM.ZSC');
  GDM.register('itm_ffaceitem', ModelListManager, '3DDATA/AVATAR/LIST_FACEITEM.ZSC');
}

GDM.register('itm_back', ModelListManager, '3DDATA/AVATAR/LIST_BACK.ZSC');
GDM.register('itm_weapon', ModelListManager, '3DDATA/WEAPON/LIST_WEAPON.ZSC');
GDM.register('itm_subwpn', ModelListManager, '3DDATA/WEAPON/LIST_SUBWPN.ZSC');
<commit_msg>Added EU tilde keycode for triggering debug camera.<commit_after>'use strict';

// Set some default values
THREE.XHRLoader.prototype.crossOrigin = 'anonymous';
THREE.ImageUtils.crossOrigin = 'anonymous';

// Set up the renderer
var renderer = null;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.setClearColor( 0x888888, 1 );
renderer.autoClear = false;

// Load any needed extensions
var minMaxGlExt = renderer.getContext().getExtension('EXT_blend_minmax');
if (!minMaxGlExt) {
  console.warn('Could not load blend_minmax extension!');
}

// Create a global scene to work with
var scene = new THREE.Scene();
var skyScene = new THREE.Scene();
var skyObject = null;

// Set up some basic initial lighting
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.1 );
directionalLight.position.set( 100, 100, 100 );
scene.add( directionalLight );

var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.3 );
hemiLight.color.setHSL( 0.6, 1, 0.75 );
hemiLight.groundColor.setHSL( 0.1, 0.8, 0.7 );
hemiLight.position.z = 500;
scene.add( hemiLight );

// Set a global camera to work with
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.up.copy(new THREE.Vector3(0, 0, 1));
camera.position.copy(new THREE.Vector3(-15, 15, 15));
camera.lookAt(new THREE.Vector3(0, 0, 0));

camera.position.add(new THREE.Vector3(5200, 5200, 0));

// Auto resize canvas
window.addEventListener('resize', onWindowResize, false);

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}

// Default material for testing with
var defaultMat = new THREE.MeshPhongMaterial({ambient: 0x030303, color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.FlatShading});

// Create a debug GUI manager.
var debugGui = new dat.GUI();
DebugHelper.init();

// Set up the debugging camera
var debugCamera = null;
var debugInput = new EventEmitter();
var debugControls = null;
var debugCamFrust = new THREE.CameraHelper(camera);

function initDebugCamera() {
  debugCamera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
  debugCamera.position.setFromMatrixPosition(camera.matrixWorld);
  debugCamera.quaternion.setFromRotationMatrix(camera.matrixWorld);
  debugControls = new THREE.FreeFlyControls(debugCamera, debugInput);
  debugControls.movementSpeed = 100;
  debugCamFrust.camera = camera;
  scene.add(debugCamFrust);
}

function destroyDebugCamera() {
  debugCamera = null;
  debugControls = null;
  scene.remove(debugCamFrust);
}

var debugTriggerKeyCodes = [ 192, 223 ];
var inputMgrEventHandler = InputManager._handleEvent;
InputManager._handleEvent = function(name, e) {
  if (name === 'keydown' && debugTriggerKeyCodes.indexOf(e.keyCode) !== -1) {
    if (!debugCamera) {
      initDebugCamera();
    } else {
      destroyDebugCamera();
    }
    e.preventDefault();
    return;
  }

  if (debugControls) {
    debugInput.emit(name, e);
  } else {
    // Use the default handler
    inputMgrEventHandler.call(this, name, e);
  }
};

var activeGameState = null;

// FPS / MS indicator
var stats = new Stats();
stats.setMode(1); // 0: FPS, 1: MS
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );

var clock = new THREE.Clock();
var renderFrame = function () {
  requestAnimationFrame(renderFrame, renderer.domElement);
  stats.begin();

  var delta = clock.getDelta();
  THREE.AnimationHandler.update( delta );

  if (activeGameState) {
    activeGameState.update(delta);
  }

  var renderCamera = camera;
  if (debugCamera) {
    debugCamFrust.update(delta);
    debugControls.update(delta);
    renderCamera = debugCamera;
  }

  // TODO: I don't think this works how I think it works.
  //  Everything appears to draw perfectly correctly no matter what
  //  clearing flags I set, or what clearing I do on my own...
  if (skyObject) {
    skyObject.position.copy(renderCamera.position);
    renderer.render(skyScene, renderCamera);
    renderer.clear(false, true, false);
  } else {
    renderer.clear(true, true, false);
  }
  renderer.render(scene, renderCamera);

  stats.end();
};
renderFrame();

var launchStateName = clientParams.length > 0 ? clientParams[0] : 'test';
console.log('Launching game with state `' + launchStateName + '`');

var launchGameState = null;
if (launchStateName === 'test') {
  launchGameState = gsTest;
} else if (launchStateName === 'nettest') {
  launchGameState = gsNetTest;
} else if (launchStateName === 'login') {
  launchGameState = gsLogin;
} else if (launchStateName === 'gametest') {
  launchGameState = gsGameTest;
} else if (launchStateName === 'particle') {
  launchGameState = gsParticleTest;
} else {
  console.log('Invalid launch state specified.');
}

if (clientParams.indexOf('lmonly') !== -1) {
  config.lmonly = true;
}

ShaderManager.register('skydome', 'skydome.vert', 'skydome.frag', {
  depthWrite: false,
  depthTest: false
});
ShaderManager.register('terrain', 'terrain.vert', 'terrain.frag', {
  attributes: {uv3:{}}
});
ShaderManager.register('terrain_lmonly', 'terrain.vert', 'terrain_lmonly.frag', {
  attributes: {uv3:{}}
});
ShaderManager.register('staticobj', 'staticobj.vert', 'staticobj.frag');
ShaderManager.register('staticobj_lmonly', 'staticobj.vert', 'staticobj_lmonly.frag');
ShaderManager.register('water', 'water.vert', 'water.frag');
ShaderManager.register('particle', 'particle.vert', 'particle.frag', {
  attributes: {
    alpha: { type: 'f', value: [] },
    psize: { type: 'f', value: [] }
  }
});

if (launchGameState) {
  // Shaders before anything else
  ShaderManager.init(function() {
    // Needed for game states that alter UI.
    $(function() {
      launchGameState.prepare(function() {
        launchGameState.enter();
        activeGameState = launchGameState;
      });
    });
  });
}

GDM.register('list_event', DataTable, '3DDATA/STB/LIST_EVENT.STB');

GDM.register('list_zone', DataTable, '3DDATA/STB/LIST_ZONE.STB');
GDM.register('zone_names', StringTable, '3DDATA/STB/LIST_ZONE_S.STL');

GDM.register('char_motiontypes', DataTable, '3DDATA/STB/TYPE_MOTION.STB');
GDM.register('char_motions', DataTable, '3DDATA/STB/FILE_MOTION.STB');

GDM.register('npc_chars', CharacterList, '3DDATA/NPC/LIST_NPC.CHR');
GDM.register('npc_models', ModelListManager, '3DDATA/NPC/PART_NPC.ZSC');

GDM.register('male_skel', Skeleton, '3DDATA/AVATAR/MALE.ZMD');
GDM.register('female_skel', Skeleton, '3DDATA/AVATAR/FEMALE.ZMD');

GDM.register('itm_mface', ModelListManager, '3DDATA/AVATAR/LIST_MFACE.ZSC');
GDM.register('itm_mhair', ModelListManager, '3DDATA/AVATAR/LIST_MHAIR.ZSC');
GDM.register('itm_mcap', ModelListManager, '3DDATA/AVATAR/LIST_MCAP.ZSC');
GDM.register('itm_mbody', ModelListManager, '3DDATA/AVATAR/LIST_MBODY.ZSC');
GDM.register('itm_marms', ModelListManager, '3DDATA/AVATAR/LIST_MARMS.ZSC');
GDM.register('itm_mfoot', ModelListManager, '3DDATA/AVATAR/LIST_MFOOT.ZSC');

GDM.register('itm_fface', ModelListManager, '3DDATA/AVATAR/LIST_WFACE.ZSC');
GDM.register('itm_fhair', ModelListManager, '3DDATA/AVATAR/LIST_WHAIR.ZSC');
GDM.register('itm_fcap', ModelListManager, '3DDATA/AVATAR/LIST_WCAP.ZSC');
GDM.register('itm_fbody', ModelListManager, '3DDATA/AVATAR/LIST_WBODY.ZSC');
GDM.register('itm_farms', ModelListManager, '3DDATA/AVATAR/LIST_WARMS.ZSC');
GDM.register('itm_ffoot', ModelListManager, '3DDATA/AVATAR/LIST_WFOOT.ZSC');

if (config.isEvoData) {
  GDM.register('itm_mfaceitem', ModelListManager, '3DDATA/AVATAR/LIST_MFACEITEM.ZSC');
  GDM.register('itm_ffaceitem', ModelListManager, '3DDATA/AVATAR/LIST_WFACEITEM.ZSC');
} else {
  GDM.register('itm_mfaceitem', ModelListManager, '3DDATA/AVATAR/LIST_FACEITEM.ZSC');
  GDM.register('itm_ffaceitem', ModelListManager, '3DDATA/AVATAR/LIST_FACEITEM.ZSC');
}

GDM.register('itm_back', ModelListManager, '3DDATA/AVATAR/LIST_BACK.ZSC');
GDM.register('itm_weapon', ModelListManager, '3DDATA/WEAPON/LIST_WEAPON.ZSC');
GDM.register('itm_subwpn', ModelListManager, '3DDATA/WEAPON/LIST_SUBWPN.ZSC');
<|endoftext|>


<commit_before>const Share = require('ftc-share');
// const oToggle = require('./toggle');
import Toggle from './toggle';
// const Sticky = require('./sticky');
import Sticky from './sticky';
// const PageCounter = require('./pager');
import PageCounter from './pager';
Share.init();
Toggle.init();

// Only enable sticky effect when HTML tag has `enabel-scrollmation` class.
if (document.documentElement.classList.contains('enable-scrollmation')) {
	new Sticky();
}

new PageCounter('.section__container');
<commit_msg>delete node style require<commit_after>const Share = require('ftc-share');
import Toggle from './toggle';
import Sticky from './sticky';
import PageCounter from './pager';
Share.init();
Toggle.init();

// Only enable sticky effect when HTML tag has `enabel-scrollmation` class.
if (document.documentElement.classList.contains('enable-scrollmation')) {
	new Sticky();
}

new PageCounter('.section__container');
<|endoftext|>


<commit_before>/**
* @author: Flightmare (http://elderscrolls.wikia.com/wiki/User:Flightmare)
* @version: 1.0.3
* @license: CC-BY-SA 3.0
* @description: Creates a flat feed for discussions module on Special:DiscussionsFeed. Includes moderation tools.
*/

function strPad(n) {
    return String("00" + n).slice(-2);
}

function updateFeed(content, isMod, canBlock) {
    var rcLimit = 50;
    var request = new XMLHttpRequest();
    request.timeout = 30000; // 30 seconds
    request.ontimeout = function() {
        content.innerHTML = "Unable to load discussions: The service is down or is not enabled for this domain.";
    };
    request.onreadystatechange = function() {
        if(request.readyState == 4) {
            switch(request.status) {
                case 200:
                    var arr = JSON.parse(request.responseText);
                    content.innerHTML = '';
                    for (var i = 0; i < rcLimit; i++) {
                        var text = arr["_embedded"]["doc:posts"][i].rawContent;
                        var user = arr["_embedded"]["doc:posts"][i]["createdBy"].name;
                        var userId = arr["_embedded"]["doc:posts"][i]["createdBy"].id;
                        var epoch = arr["_embedded"]["doc:posts"][i]["creationDate"].epochSecond;
                        var postID = arr["_embedded"]["doc:posts"][i].id;
                        var threadID = arr["_embedded"]["doc:posts"][i].threadId;
                        var isReported = Boolean(arr["_embedded"]["doc:posts"][i].isReported);
                        var forumName = arr["_embedded"]["doc:posts"][i].forumName;
                        var dt = new Date(epoch * 1000);
                        var formattedDate = strPad(dt.getHours()) + ":" + strPad(dt.getMinutes()) + ":" + strPad(dt.getSeconds());

                        //Create HTML for date:
                        var spanDate = document.createElement("span");
                        spanDate.className = "df-date";
                        var spanDateText = document.createTextNode(formattedDate + " — ");
                        spanDate.appendChild(spanDateText);

                        //Create HTML for message body:
                        var aMessage = document.createElement("a");
                        aMessage.className = "df-content";
                        aMessage.href = "/d/p/" + threadID;
                        aMessage.target = "_blank";
                        var aMessageText = document.createTextNode(text);
                        aMessage.appendChild(aMessageText);

                        //Create HTML for user:
                        var aUser = document.createElement("a");
                        aUser.className = "df-user";
                        aUser.href = "/d/u/" + userId;
                        aUser.target = "_blank";
                        var aUserText = document.createTextNode(" — " + user);
                        aUser.appendChild(aUserText);

                        //Create HTML for category:
                        var spanCategory = document.createElement("span");
                        spanCategory.className = "df-category";
                        var spanCategoryText = document.createTextNode(" in " + forumName);
                        spanCategory.appendChild(spanCategoryText);

                        //Create block button
                        if (canBlock) {
                            var aBlock = document.createElement("a");
                            aBlock.className = "df-block";
                            aBlock.href = "/wiki/Special:Block/" + user;
                            aBlock.target = "_blank";
                            var aBlockText = document.createTextNode(" (block)");
                            aBlock.appendChild(aBlockText);
                        }

                        //Put everything together
                        var par = document.createElement("p");
                        par.className = "df-entry";
                        if (isReported) {
                            par.className += " df-reported";
                        }
                        par.appendChild(spanDate);
                        par.appendChild(aMessage);
                        par.appendChild(aUser);
                        par.appendChild(spanCategory);
                        if (canBlock) {
                            par.appendChild(aBlock);
                        }
                        content.appendChild(par);
                    }
                    break;
                case 404:
                    content.innerHTML = 'There are no posts.';
                    break;
                default:
                    content.innerHTML = "Unable to load discussions: The service is down or is not enabled for this domain.";
            }
        }
    };
    request.open("GET", "https://services.wikia.com/discussion/" + wgCityId + "/posts?limit=" + rcLimit + "&page=0&responseGroup=small&reported=false&viewableOnly=" + (!isMod).toString(), true);
    request.setRequestHeader('Accept', 'application/hal+json');
    request.send();
}

function createDiscussionsFeed() {
    if(wgNamespaceNumber == -1 && wgTitle == "DiscussionsFeed") { //TODO: i18n make dictionary
        document.title = 'Discussions Feed - ' + wgSiteName;
        var canBlock = Boolean(wgUserGroups.indexOf('sysop') > -1 || wgUserGroups.indexOf('staff') > -1 || wgUserGroups.indexOf('helper') > -1 || wgUserGroups.indexOf('vstf') > -1);
        var isMod = Boolean(canBlock || wgUserGroups.indexOf('threadmoderator') > -1);
        if (window.skin == "oasis") {
            document.getElementById("WikiaPageHeader").getElementsByTagName("h1")[0].innerHTML = "
Discussions Feed
"; //Oasis skin title
        } else if (window.skin == "monobook") {
            document.getElementById("firstHeading").innerHTML = '
Discussions Feed
'; //Monobook skin title
        }
        var content = document.getElementById("mw-content-text");
        content.innerHTML = 'Loading feed...
';
        updateFeed(content, isMod, canBlock);
    }
}

addOnloadHook(createDiscussionsFeed);
<commit_msg>auto refreshing<commit_after>/**
* @author: Flightmare (http://elderscrolls.wikia.com/wiki/User:Flightmare)
* @version: 1.1
* @license: CC-BY-SA 3.0
* @description: Creates a flat feed for discussions module on Special:DiscussionsFeed. Includes moderation tools.
*/

function strPad(n) {
    return String("00" + n).slice(-2);
}

function updateContent(content, isMod, canBlock, arr) {
    for (var i = arr["_embedded"]["doc:posts"].length - 1; i > -1; i--) {
        var text = arr["_embedded"]["doc:posts"][i].rawContent;
        var user = arr["_embedded"]["doc:posts"][i]["createdBy"].name;
        var userId = arr["_embedded"]["doc:posts"][i]["createdBy"].id;
        var epoch = arr["_embedded"]["doc:posts"][i]["creationDate"].epochSecond;
        var postID = arr["_embedded"]["doc:posts"][i].id;
        var threadID = arr["_embedded"]["doc:posts"][i].threadId;
        var isReported = Boolean(arr["_embedded"]["doc:posts"][i].isReported);
        var forumName = arr["_embedded"]["doc:posts"][i].forumName;
        var dt = new Date(epoch * 1000);
        var formattedDate = strPad(dt.getHours()) + ":" + strPad(dt.getMinutes()) + ":" + strPad(dt.getSeconds());

        //Create HTML for date:
        var spanDate = document.createElement("span");
        spanDate.className = "df-date";
        var spanDateText = document.createTextNode(formattedDate + " — ");
        spanDate.appendChild(spanDateText);

        //Create HTML for message body:
        var aMessage = document.createElement("a");
        aMessage.className = "df-content";
        aMessage.href = "/d/p/" + threadID;
        aMessage.target = "_blank";
        var aMessageText = document.createTextNode(text);
        aMessage.appendChild(aMessageText);

        //Create HTML for user:
        var aUser = document.createElement("a");
        aUser.className = "df-user";
        aUser.href = "/d/u/" + userId;
        aUser.target = "_blank";
        var aUserText = document.createTextNode(" — " + user);
        aUser.appendChild(aUserText);

        //Create HTML for category:
        var spanCategory = document.createElement("span");
        spanCategory.className = "df-category";
        var spanCategoryText = document.createTextNode(" in " + forumName);
        spanCategory.appendChild(spanCategoryText);

        //Create block button
        if (canBlock) {
            var aBlock = document.createElement("a");
            aBlock.className = "df-block";
            aBlock.href = "/wiki/Special:Block/" + user;
            aBlock.target = "_blank";
            var aBlockText = document.createTextNode(" (block)");
            aBlock.appendChild(aBlockText);
        }

        //Put everything together
        var par = document.createElement("p");
        par.className = "df-entry";
        if (isReported) {
            par.className += " df-reported";
        }
        par.appendChild(spanDate);
        par.appendChild(aMessage);
        par.appendChild(aUser);
        par.appendChild(spanCategory);
        if (canBlock) {
            par.appendChild(aBlock);
        }
        content.insertBefore(par, content.firstChild);
    }
}

//TODO: enable end user to disable auto refresh
function updateFeed(content, isMod, canBlock, epoch) {
    var rcLimit = 50;
    var dt = new Date(epoch * 1000 + 1); //since epochs are rounded down to the nearest second, add 1 ms to prevent requesting the last post a second time
    var request = new XMLHttpRequest();
    request.onreadystatechange = function() {
        if(request.readyState == 4) {
            switch(request.status) {
                case 200:
                    var arr = JSON.parse(request.responseText);
                    updateContent(content, isMod, canBlock, arr);
                    //fetch timestamp of newest post, required for next request
                    if (arr["_embedded"]["doc:posts"].length > 0) {
                        epoch = arr["_embedded"]["doc:posts"][0]["creationDate"].epochSecond;
                    }
                default:
                    setTimeout(updateFeed, 120000, content, isMod, canBlock, epoch); //set new timer (2m)
            }
        }
    };
    request.open("GET", "https://services.wikia.com/discussion/" + wgCityId + "/posts?limit=" + rcLimit + "&since=" + dt.toISOString() + "&page=0&responseGroup=small&reported=false&viewableOnly=" + (!isMod).toString(), true);
    request.setRequestHeader('Accept', 'application/hal+json');
    request.send();
}

function initFeed(content, isMod, canBlock) {
    var rcLimit = 50;
    var request = new XMLHttpRequest();
    request.timeout = 30000; // 30 seconds
    request.ontimeout = function() {
        content.innerHTML = "Unable to load discussions: The service is down or is not enabled for this domain.";
    };
    request.onreadystatechange = function() {
        if(request.readyState == 4) {
            switch(request.status) {
                case 200:
                    var arr = JSON.parse(request.responseText);
                    content.innerHTML = '';
                    updateContent(content, isMod, canBlock, arr);
                    //fetch timestamp of newest post, required for next request
                    var epoch = arr["_embedded"]["doc:posts"][0]["creationDate"].epochSecond;
                    setTimeout(updateFeed, 120000, content, isMod, canBlock, epoch); //set new timer (2m)
                    break;
                case 404:
                    content.innerHTML = 'There are no posts.';
                    break;
                default:
                    content.innerHTML = "Unable to load discussions: The service is down or is not enabled for this domain.";
            }
        }
    };
    request.open("GET", "https://services.wikia.com/discussion/" + wgCityId + "/posts?limit=" + rcLimit + "&page=0&responseGroup=small&reported=false&viewableOnly=" + (!isMod).toString(), true);
    request.setRequestHeader('Accept', 'application/hal+json');
    request.send();
}

function createDiscussionsFeed() {
    if(wgNamespaceNumber == -1 && wgTitle == "DiscussionsFeed") { //TODO: i18n make dictionary
        document.title = 'Discussions Feed - ' + wgSiteName;
        var canBlock = Boolean(wgUserGroups.indexOf('sysop') > -1 || wgUserGroups.indexOf('staff') > -1 || wgUserGroups.indexOf('helper') > -1 || wgUserGroups.indexOf('vstf') > -1);
        var isMod = Boolean(canBlock || wgUserGroups.indexOf('threadmoderator') > -1);
        if (window.skin == "oasis") {
            document.getElementById("WikiaPageHeader").getElementsByTagName("h1")[0].innerHTML = "
Discussions Feed
"; //Oasis skin title
        } else if (window.skin == "monobook") {
            document.getElementById("firstHeading").innerHTML = '
Discussions Feed
'; //Monobook skin title
        }
        var content = document.getElementById("mw-content-text");
        content.innerHTML = 'Loading feed...
';
        initFeed(content, isMod, canBlock);
    }
}

//include guard
{
    var j = -1;
    for (var i = 0; i < onloadFuncts.length && j < 0; i++) {
        if (onloadFuncts[i].name == "createDiscussionsFeed") {
            j = i;
        }
    }
    if (j < 0) {
        addOnloadHook(createDiscussionsFeed);
    }
}
<|endoftext|>


<commit_before>// CONSTANTS

// Size of the playing field
var WINDOW_WIDTH = 1280;
var WINDOW_HEIGHT = 800;
var FIELD_WIDTH = 800;
var FIELD_HEIGHT = 800;

// Ship constants
var SHIP_RADIUS = 50;
var BULLET_RADIUS = 5;
var SHIP_MAX_ACCEL_INCREASE = 0.09;
var SHIP_MIN_ACCEL = 0.01;
var MAX_STAT = 1;
var START_STAT = 0.5;
var MAX_TURN_INCREASE = 4.5;
var MIN_TURN = 0.5;
var FUEL_DECREASE_TURN = 0.001;
var FUEL_DECREASE_ENGINE = 0.005;

// Physics constants
var TIME_CONST = 1;
var TIME_CONST_SQU_HALF = TIME_CONST * TIME_CONST / 2;
var DEG_TO_RAD = Math.PI / 180;

// Network constants
var SHIP_UPDATE_RATE = 1;

// Controls
var CTRL_ACCEL = Crafty.keys.W;
var CTRL_DECEL = Crafty.keys.S;
var CTRL_TURN_CW = Crafty.keys.A;
var CTRL_TURN_CCW = Crafty.keys.D;

Crafty.c('socket', {
	initSocket: function(socket) {
		this.socket = socket;
		return this;
	}
});

Crafty.c('ship', {
	init: function() {
		this.requires('2D, DOM');

		this.attr({
			id: null,
			h: SHIP_RADIUS,
			w: SHIP_RADIUS,
			vx: 0,
			vy: 0,
			ax: 0,
			ay: 0,
			engine: START_STAT,
			hull: START_STAT,
			weap: START_STAT,
			rotation: -90,
			kills: 0,
			deaths: 0
		});

		this.origin('center');

		this.ship_R = Crafty.e('2D, DOM, ship_R').attr({h: this.h, w: this.w}).origin('center');
		this.ship_G = Crafty.e('2D, DOM, ship_G').attr({h: this.h, w: this.w}).origin('center');
		this.ship_B = Crafty.e('2D, DOM, ship_B').attr({h: this.h, w: this.w}).origin('center');
		this.engine_R = Crafty.e('2D, DOM, engine_R').attr({h: this.h, w: this.w}).origin('center');
		this.engine_G = Crafty.e('2D, DOM, engine_G').attr({h: this.h, w: this.w}).origin('center');
		this.hull_R = Crafty.e('2D, DOM, hull_R').attr({h: this.h, w: this.w}).origin('center');
		this.hull_G = Crafty.e('2D, DOM, hull_G').attr({h: this.h, w: this.w}).origin('center');
		this.weap_R = Crafty.e('2D, DOM, weap_R').attr({h: this.h, w: this.w}).origin('center');
		this.weap_G = Crafty.e('2D, DOM, weap_G').attr({h: this.h, w: this.w}).origin('center');

		this.bind('EnterFrame', function(e) {
			this.vx = this.vx + this.ax * TIME_CONST;
			this.vy = this.vy + this.ay * TIME_CONST;
			this.x = this.x + this.vx * TIME_CONST + TIME_CONST_SQU_HALF * this.ax;
			while (this.x > FIELD_WIDTH) {
				this.x -= FIELD_WIDTH;
			}
			while (this.x < 0) {
				this.x += FIELD_WIDTH;
			}
			this.y = this.y + this.vy * TIME_CONST + TIME_CONST_SQU_HALF * this.ay;
			while (this.y > FIELD_HEIGHT) {
				this.y -= FIELD_HEIGHT;
			}
			while (this.y < 0) {
				this.y += FIELD_HEIGHT;
			}

			this.ship_R.attr({x: this.x, y: this.y, rotation: this.rotation});
			this.ship_G.attr({x: this.x, y: this.y, rotation: this.rotation});
			this.ship_B.attr({x: this.x, y: this.y, rotation: this.rotation});
			this.engine_R.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: 1 - this.engine});
			this.engine_G.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: this.engine});
			this.hull_R.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: 1 - this.hull});
			this.hull_G.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: this.hull});
			this.weap_R.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: 1 - this.weap});
			this.weap_G.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: this.weap});
		});
	},
	ship: function(id, r, g, b) {
		this.id = id;
		this.ship_R.alpha = r * 0.5;
		this.ship_G.alpha = g * 0.5;
		this.ship_B.alpha = b * 0.5;

		return this;
	},
	updatePos: function(update) {
		this.x = update['x'];
		this.y = update['y'];
		this.rotation = update['theta'];
		this.vx = update['vx'];
		this.vy = update['vy'];
		this.hull = update['health'];
		this.engine = update['fuel'];
		this.weap = update['weapon'];
		this.kills = update['kills'];
		this.deaths = update['deaths'];

		return this;
	},
	remove: function() {
		// handle removal of ship from playing field here
		this.ship_R.destroy();
		this.ship_G.destroy();
		this.ship_B.destroy();
		this.engine_R.destroy();
		this.engine_G.destroy();
		this.hull_R.destroy();
		this.hull_G.destroy();
		this.weap_R.destroy();
		this.weap_G.destroy();
		this.destroy();
	}
});

Crafty.c('player', {
	init: function () {
		this.requires('ship, Keyboard, socket');

		this.attr({
			shoot: true
		});

		this.bind('EnterFrame', function(e) {
			var baseAcc = SHIP_MIN_ACCEL + SHIP_MAX_ACCEL_INCREASE * this.engine;
			var rotationRate = MIN_TURN + MAX_TURN_INCREASE * this.engine;

			var acc = 0;
			if (this.isDown(CTRL_ACCEL)) {
				acc = baseAcc;
				this.engine = Math.max(this.engine - FUEL_DECREASE_ENGINE, 0);
			}
			if (this.isDown(CTRL_DECEL)) {
				acc -= baseAcc /2;
				this.engine = Math.max(this.engine - FUEL_DECREASE_ENGINE, 0);
			}

			if (this.isDown(CTRL_TURN_CW)) {
				if (this.isDown(CTRL_TURN_CCW)) {
					this.engine = Math.max(this.engine - FUEL_DECREASE_TURN * 2, 0);
				} else {
					this.engine = Math.max(this.engine - FUEL_DECREASE_TURN, 0);
					this.rotation = (this.rotation - rotationRate) % 360;
				}
			} else {
				if (this.isDown(CTRL_TURN_CCW)) {
					this.engine = Math.max(this.engine - FUEL_DECREASE_TURN, 0);
					this.rotation = (this.rotation + rotationRate) % 360;
				}
			}

			this.ax = acc * Math.cos(this.rotation * DEG_TO_RAD);
			this.ay = acc * Math.sin(this.rotation * DEG_TO_RAD);

			if (e.frame % SHIP_UPDATE_RATE === 0) {
				this.socket.emit('POS', JSON.stringify({
					id: this.id,
					x: this.x,
					y: this.y,
					theta: this.rotation,
					vx: this.vx,
					vy: this.vy,
					health: this.hull,
					fuel: this.engine,
					weapon: this.weap
				}));
			}
		});
	}
});

Crafty.c('bullet', {
	init: function() {
		this.requires('2D, DOM');

		this.attr({
			id: null,
			h: BULLET_RADIUS,
			w: BULLET_RADIUS,
			vx: 0,
			vy: 0,
			playerId: null,
			power: null,
			bullets: null
		});

		this.bind('EnterFrame', function(e) {
			this.vx = this.vx + this.ax * TIME_CONST;
			this.vy = this.vy + this.ay * TIME_CONST;
			this.x = this.x + this.vx * TIME_CONST;
			while (this.x > FIELD_WIDTH) {
				this.x -= FIELD_WIDTH;
			}
			while (this.x < 0) {
				this.x += FIELD_WIDTH;
			}

			this.y = this.y + this.vy * TIME_CONST;
			while (this.y > FIELD_HEIGHT) {
				this.y -= FIELD_HEIGHT;
			}
			while (this.y < 0) {
				this.y += FIELD_HEIGHT;
			}

			// TODO: decay bullet and kill itself
		});
	},
	bullet: function(id, playerId, x, y, vx, vy, power, bullets) {
		this.id = id;
		this.playerId = playerId;
		this.x = x;
		this.y = y;
		this.vx = vx;
		this.vy = vy;
		this.power = power;
		this.bullets = bullets;

		return this;
	},
	remove: function() {
		delete this.bullets[this.id];
		this.destroy();
	}
});

Crafty.scene('game', function() {
	var socket = io.connect();
	var ships = {};
	var bullets = {};

	socket.on('JOIN', function (data) {
		console.log(data);
		var player = Crafty.e('ship, player').initSocket(socket).ship(
			data['id'],
			data['color']['r'],
			data['color']['g'],
			data['color']['b'])
		.attr({
			x: data['x'],
			y: data['y']
		});

		ships = {};
		ships[data['id']] = player;

		var i;
		for (i in data['ships']) {
			var ship = data.ships[i];
			ships[ship['id']] = Crafty.e('ship').ship(
				ship['id'],
				ship['color']['r'],
				ship['color']['g'],
				ship['color']['b']).updatePos(ship);
		}
	});

	socket.on('DEATH', function (data) {
		console.log(data);
		// TODO: render the death animation
	});

	socket.on('POS', function (data) {
		var pos = JSON.parse(data);
		ships[pos.id].updatePos(pos);
	});

	socket.on('CONN', function (data) {
		console.log(data);
		ships[data['id']] = Crafty.e('ship').ship(
			data['id'],
			data['color']['r'],
			data['color']['g'],
			data['color']['b']
		).attr({
			x: data['x'],
			y: data['y']
		});
	});

	socket.on('DISCONN', function (data) {
		console.log(data);
		ships[data['id']].remove();
		delete ships[data['id']];
	});

	socket.on('BULLET', function (data) {
		console.log(data);
		bullets[data['id']] = Crafty.e('bullet').bullet(
			data['id'],
			data['playerId'],
			data['x'],
			data['y'],
			data['vx'],
			data['vy'],
			data['power'],
			bullets);
	});

	socket.on('BULLET_DEATH', function (data) {
		console.log(data);
		bullets[data['id']].remove();
	});

});

window.onload = function() {
	//start crafty, full screen
	Crafty.init(WINDOW_WIDTH, WINDOW_HEIGHT);
	Crafty.scene('game');
};
<commit_msg>Decreased engine fuel consumption.<commit_after>// CONSTANTS

// Size of the playing field
var WINDOW_WIDTH = 1280;
var WINDOW_HEIGHT = 800;
var FIELD_WIDTH = 800;
var FIELD_HEIGHT = 800;

// Ship constants
var SHIP_RADIUS = 50;
var BULLET_RADIUS = 5;
var SHIP_MAX_ACCEL_INCREASE = 0.09;
var SHIP_MIN_ACCEL = 0.01;
var MAX_STAT = 1;
var START_STAT = 0.5;
var MAX_TURN_INCREASE = 4.5;
var MIN_TURN = 0.5;
var FUEL_DECREASE_TURN = 0.001;
var FUEL_DECREASE_ENGINE = 0.0005;

// Physics constants
var TIME_CONST = 1;
var TIME_CONST_SQU_HALF = TIME_CONST * TIME_CONST / 2;
var DEG_TO_RAD = Math.PI / 180;

// Network constants
var SHIP_UPDATE_RATE = 1;

// Controls
var CTRL_ACCEL = Crafty.keys.W;
var CTRL_DECEL = Crafty.keys.S;
var CTRL_TURN_CW = Crafty.keys.A;
var CTRL_TURN_CCW = Crafty.keys.D;

Crafty.c('socket', {
	initSocket: function(socket) {
		this.socket = socket;
		return this;
	}
});

Crafty.c('ship', {
	init: function() {
		this.requires('2D, DOM');

		this.attr({
			id: null,
			h: SHIP_RADIUS,
			w: SHIP_RADIUS,
			vx: 0,
			vy: 0,
			ax: 0,
			ay: 0,
			engine: START_STAT,
			hull: START_STAT,
			weap: START_STAT,
			rotation: -90,
			kills: 0,
			deaths: 0
		});

		this.origin('center');

		this.ship_R = Crafty.e('2D, DOM, ship_R').attr({h: this.h, w: this.w}).origin('center');
		this.ship_G = Crafty.e('2D, DOM, ship_G').attr({h: this.h, w: this.w}).origin('center');
		this.ship_B = Crafty.e('2D, DOM, ship_B').attr({h: this.h, w: this.w}).origin('center');
		this.engine_R = Crafty.e('2D, DOM, engine_R').attr({h: this.h, w: this.w}).origin('center');
		this.engine_G = Crafty.e('2D, DOM, engine_G').attr({h: this.h, w: this.w}).origin('center');
		this.hull_R = Crafty.e('2D, DOM, hull_R').attr({h: this.h, w: this.w}).origin('center');
		this.hull_G = Crafty.e('2D, DOM, hull_G').attr({h: this.h, w: this.w}).origin('center');
		this.weap_R = Crafty.e('2D, DOM, weap_R').attr({h: this.h, w: this.w}).origin('center');
		this.weap_G = Crafty.e('2D, DOM, weap_G').attr({h: this.h, w: this.w}).origin('center');

		this.bind('EnterFrame', function(e) {
			this.vx = this.vx + this.ax * TIME_CONST;
			this.vy = this.vy + this.ay * TIME_CONST;
			this.x = this.x + this.vx * TIME_CONST + TIME_CONST_SQU_HALF * this.ax;
			while (this.x > FIELD_WIDTH) {
				this.x -= FIELD_WIDTH;
			}
			while (this.x < 0) {
				this.x += FIELD_WIDTH;
			}
			this.y = this.y + this.vy * TIME_CONST + TIME_CONST_SQU_HALF * this.ay;
			while (this.y > FIELD_HEIGHT) {
				this.y -= FIELD_HEIGHT;
			}
			while (this.y < 0) {
				this.y += FIELD_HEIGHT;
			}

			this.ship_R.attr({x: this.x, y: this.y, rotation: this.rotation});
			this.ship_G.attr({x: this.x, y: this.y, rotation: this.rotation});
			this.ship_B.attr({x: this.x, y: this.y, rotation: this.rotation});
			this.engine_R.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: 1 - this.engine});
			this.engine_G.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: this.engine});
			this.hull_R.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: 1 - this.hull});
			this.hull_G.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: this.hull});
			this.weap_R.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: 1 - this.weap});
			this.weap_G.attr({x: this.x, y: this.y, rotation: this.rotation, alpha: this.weap});
		});
	},
	ship: function(id, r, g, b) {
		this.id = id;
		this.ship_R.alpha = r * 0.5;
		this.ship_G.alpha = g * 0.5;
		this.ship_B.alpha = b * 0.5;

		return this;
	},
	updatePos: function(update) {
		this.x = update['x'];
		this.y = update['y'];
		this.rotation = update['theta'];
		this.vx = update['vx'];
		this.vy = update['vy'];
		this.hull = update['health'];
		this.engine = update['fuel'];
		this.weap = update['weapon'];
		this.kills = update['kills'];
		this.deaths = update['deaths'];

		return this;
	},
	remove: function() {
		// handle removal of ship from playing field here
		this.ship_R.destroy();
		this.ship_G.destroy();
		this.ship_B.destroy();
		this.engine_R.destroy();
		this.engine_G.destroy();
		this.hull_R.destroy();
		this.hull_G.destroy();
		this.weap_R.destroy();
		this.weap_G.destroy();
		this.destroy();
	}
});

Crafty.c('player', {
	init: function () {
		this.requires('ship, Keyboard, socket');

		this.attr({
			shoot: true
		});

		this.bind('EnterFrame', function(e) {
			var baseAcc = SHIP_MIN_ACCEL + SHIP_MAX_ACCEL_INCREASE * this.engine;
			var rotationRate = MIN_TURN + MAX_TURN_INCREASE * this.engine;

			var acc = 0;
			if (this.isDown(CTRL_ACCEL)) {
				acc = baseAcc;
				this.engine = Math.max(this.engine - FUEL_DECREASE_ENGINE, 0);
			}
			if (this.isDown(CTRL_DECEL)) {
				acc -= baseAcc /2;
				this.engine = Math.max(this.engine - FUEL_DECREASE_ENGINE, 0);
			}

			if (this.isDown(CTRL_TURN_CW)) {
				if (this.isDown(CTRL_TURN_CCW)) {
					this.engine = Math.max(this.engine - FUEL_DECREASE_TURN * 2, 0);
				} else {
					this.engine = Math.max(this.engine - FUEL_DECREASE_TURN, 0);
					this.rotation = (this.rotation - rotationRate) % 360;
				}
			} else {
				if (this.isDown(CTRL_TURN_CCW)) {
					this.engine = Math.max(this.engine - FUEL_DECREASE_TURN, 0);
					this.rotation = (this.rotation + rotationRate) % 360;
				}
			}

			this.ax = acc * Math.cos(this.rotation * DEG_TO_RAD);
			this.ay = acc * Math.sin(this.rotation * DEG_TO_RAD);

			if (e.frame % SHIP_UPDATE_RATE === 0) {
				this.socket.emit('POS', JSON.stringify({
					id: this.id,
					x: this.x,
					y: this.y,
					theta: this.rotation,
					vx: this.vx,
					vy: this.vy,
					health: this.hull,
					fuel: this.engine,
					weapon: this.weap
				}));
			}
		});
	}
});

Crafty.c('bullet', {
	init: function() {
		this.requires('2D, DOM');

		this.attr({
			id: null,
			h: BULLET_RADIUS,
			w: BULLET_RADIUS,
			vx: 0,
			vy: 0,
			playerId: null,
			power: null,
			bullets: null
		});

		this.bind('EnterFrame', function(e) {
			this.vx = this.vx + this.ax * TIME_CONST;
			this.vy = this.vy + this.ay * TIME_CONST;
			this.x = this.x + this.vx * TIME_CONST;
			while (this.x > FIELD_WIDTH) {
				this.x -= FIELD_WIDTH;
			}
			while (this.x < 0) {
				this.x += FIELD_WIDTH;
			}

			this.y = this.y + this.vy * TIME_CONST;
			while (this.y > FIELD_HEIGHT) {
				this.y -= FIELD_HEIGHT;
			}
			while (this.y < 0) {
				this.y += FIELD_HEIGHT;
			}

			// TODO: decay bullet and kill itself
		});
	},
	bullet: function(id, playerId, x, y, vx, vy, power, bullets) {
		this.id = id;
		this.playerId = playerId;
		this.x = x;
		this.y = y;
		this.vx = vx;
		this.vy = vy;
		this.power = power;
		this.bullets = bullets;

		return this;
	},
	remove: function() {
		delete this.bullets[this.id];
		this.destroy();
	}
});

Crafty.scene('game', function() {
	var socket = io.connect();
	var ships = {};
	var bullets = {};

	socket.on('JOIN', function (data) {
		console.log(data);
		var player = Crafty.e('ship, player').initSocket(socket).ship(
			data['id'],
			data['color']['r'],
			data['color']['g'],
			data['color']['b'])
		.attr({
			x: data['x'],
			y: data['y']
		});

		ships = {};
		ships[data['id']] = player;

		var i;
		for (i in data['ships']) {
			var ship = data.ships[i];
			ships[ship['id']] = Crafty.e('ship').ship(
				ship['id'],
				ship['color']['r'],
				ship['color']['g'],
				ship['color']['b']).updatePos(ship);
		}
	});

	socket.on('DEATH', function (data) {
		console.log(data);
		// TODO: render the death animation
	});

	socket.on('POS', function (data) {
		var pos = JSON.parse(data);
		ships[pos.id].updatePos(pos);
	});

	socket.on('CONN', function (data) {
		console.log(data);
		ships[data['id']] = Crafty.e('ship').ship(
			data['id'],
			data['color']['r'],
			data['color']['g'],
			data['color']['b']
		).attr({
			x: data['x'],
			y: data['y']
		});
	});

	socket.on('DISCONN', function (data) {
		console.log(data);
		ships[data['id']].remove();
		delete ships[data['id']];
	});

	socket.on('BULLET', function (data) {
		console.log(data);
		bullets[data['id']] = Crafty.e('bullet').bullet(
			data['id'],
			data['playerId'],
			data['x'],
			data['y'],
			data['vx'],
			data['vy'],
			data['power'],
			bullets);
	});

	socket.on('BULLET_DEATH', function (data) {
		console.log(data);
		bullets[data['id']].remove();
	});

});

window.onload = function() {
	//start crafty, full screen
	Crafty.init(WINDOW_WIDTH, WINDOW_HEIGHT);
	Crafty.scene('game');
};
<|endoftext|>


<commit_before>// a really basic router, based off backbone

Session.set('currentPage', 'loading');

var Router = Backbone.Router.extend({
  routes: {
    '': 'home',
    'users': 'users',
    'admin': 'admin',
    'posts/new': 'newPost',
    ':year/:day/:month/:slug/edit': 'editPost',
    ':year/:day/:month/:slug': 'post'
  },

  users: function() {
    Session.set('currentPage', 'allUsers');
  },

  admin: function() {
    Session.set('currentPage', 'admin')
  },

  home: function() {
    Session.set('currentPage', 'allPosts')
    Session.set('selected-post-slug', null);
    // wait for the posts to load, then open up the first one
    Meteor.autorun(function() {
      var posts = allPosts().fetch();
      posts[0] && setOpen(posts[0], true);
    });
  },

  newPost: function() {
    Session.set('currentPage', 'allPosts')
  },

  post: function(year, day, month, slug) {
    Session.set('currentPage', 'allPosts')
    Session.set('post-opened-' + slug, true);
    Session.set('selected-post-slug', slug);
  },

  editPost: function(year, day, month, slug) {
    Session.set('currentPage', 'allPosts')
    Session.set('post-opened-' + slug, true);
    Session.set('post-editing-' + slug, true);
  }
});

Meteor.startup(function() {
  Meteor.Router = new Router();
  Backbone.history.start({pushState: true});
});

// some helpers to get URLs
Routes = {
  postUrl: function(post) {
    // probably we should use moment for this
    var date = new Date(post.publishedAt);
    date = date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate();
    return '/' + date + '/' + post.slug;
  },
  editPostUrl: function(post) {
    return Routes.postUrl(post) + '/edit';
  }
}

Handlebars.registerHelper('postUrl', function(post) {
  return Routes.postUrl(post);
});
Handlebars.registerHelper('editPostUrl', function(post) {
  return Routes.editPostUrl(post);
});

// a handlebars helper to render the correct page
Handlebars.registerHelper('renderCurrentPage', function() {
  var name = Session.get('currentPage');
  if (Template[name])
    return Template[name]();
});<commit_msg>Open the first 3 posts.<commit_after>// a really basic router, based off backbone

Session.set('currentPage', 'loading');

var Router = Backbone.Router.extend({
  routes: {
    '': 'home',
    'users': 'users',
    'admin': 'admin',
    'posts/new': 'newPost',
    ':year/:day/:month/:slug/edit': 'editPost',
    ':year/:day/:month/:slug': 'post'
  },

  users: function() {
    Session.set('currentPage', 'allUsers');
  },

  admin: function() {
    Session.set('currentPage', 'admin')
  },

  home: function() {
    Session.set('currentPage', 'allPosts')
    Session.set('selected-post-slug', null);
    // wait for the posts to load, then open up the first one
    Meteor.autorun(function() {
      var posts = allPosts().fetch();
      posts[0] && setOpen(posts[0], true);
      posts[1] && setOpen(posts[1], true);
      posts[2] && setOpen(posts[2], true);
    });
  },

  newPost: function() {
    Session.set('currentPage', 'allPosts')
  },

  post: function(year, day, month, slug) {
    Session.set('currentPage', 'allPosts')
    Session.set('post-opened-' + slug, true);
    Session.set('selected-post-slug', slug);
  },

  editPost: function(year, day, month, slug) {
    Session.set('currentPage', 'allPosts')
    Session.set('post-opened-' + slug, true);
    Session.set('post-editing-' + slug, true);
  }
});

Meteor.startup(function() {
  Meteor.Router = new Router();
  Backbone.history.start({pushState: true});
});

// some helpers to get URLs
Routes = {
  postUrl: function(post) {
    // probably we should use moment for this
    var date = new Date(post.publishedAt);
    date = date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate();
    return '/' + date + '/' + post.slug;
  },
  editPostUrl: function(post) {
    return Routes.postUrl(post) + '/edit';
  }
}

Handlebars.registerHelper('postUrl', function(post) {
  return Routes.postUrl(post);
});
Handlebars.registerHelper('editPostUrl', function(post) {
  return Routes.editPostUrl(post);
});

// a handlebars helper to render the correct page
Handlebars.registerHelper('renderCurrentPage', function() {
  var name = Session.get('currentPage');
  if (Template[name])
    return Template[name]();
});<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './App.css';
const Navbar = require('./Navbar');
const SortButton = require('./SortButton');
const Resources = require('./Resources');
const MyJobs = require('./MyJobs');

// TODO: dummy data, delete to test fetching
const loremipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed gravida est sit amet mi egestas, a pharetra sem hendrerit. Ut sit amet lacinia ex, vel pellentesque metus. In placerat, lacus eget porttitor imperdiet, sem nibh faucibus turpis, ultricies ultricies turpis orci in augue. Integer ut posuere ante. Pellentesque blandit purus at tortor malesuada porttitor venenatis sed lacus.";
var resources = [{ "image": "https://www.sololearn.com/Icons/Courses/1024.png", "url": "https://www.website1.com/", "addedBy": "user1", "name": "abcd", "date": "01/03/2016", "rating": "1/5", "golds": "1", "description": loremipsum },
{ "image": "https://image.flaticon.com/teams/new/1-freepik.jpg", "url": "https://www.website2.com/", "addedBy": "user2", "name": "aaab", "date": "02/14/2017", "rating": "2/5", "golds": "2", "description": loremipsum },
{ "image": "http://www.freeiconspng.com/uploads/flat-mac-icon-15.png", "url": "https://www.website3.com/", "addedBy": "user3", "name": "name3", "date": "01/01/2017", "rating": "3/5", "golds": "3", "description": loremipsum }];

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      fetching: true,
      viewingJobs: false,
      resources: null,
      loggedIn: false,
      username: null,
      sortByDate: true,
      jobs: null,
    };
    this.viewJobs = this.viewJobs.bind(this);
    this.viewResources = this.viewResources.bind(this);
    this.logOut = this.logOut.bind(this);
    this.isAuth = this.isAuth.bind(this);
    this.sortResources = this.sortResources.bind(this);
    this.handleSearch = this.handleSearch.bind(this);
  }

  getJobs() {
    fetch('/api/jobs')
      .then(response => {
        if (!response.ok) {
          throw new Error(`status ${response.status}`);
        }
        return response.json();
      })
      .then(json => {
        this.setState({
          jobs: json,
        });
      }).catch(e => {
      })
  }

  isAuth() {
    fetch('/isauth', { method: 'GET', credentials: 'include' })
      .then(response => {
        if (!response.ok) {
          throw new Error('not logged in');
        }
        return response.json();
      })
      .then(json => {
        this.setState({
          loggedIn: true
        });
      }).catch(e => {
        this.setState({
          loggedIn: false
        });
      });
  }

  componentDidMount() {
    this.isAuth();
    this.getJobs();
    fetch('/api')
      .then(response => {
        if (!response.ok) {
          throw new Error(`status ${response.status}`);
        }
        return response.json();
      })
      .then(json => {
        this.setState({
          resources: json.message,
          fetching: false
        });
      }).catch(e => {
        this.setState({
          resources: `API call failed: ${e}`,
          fetching: false
        });
      })
  }

  viewJobs() {
    this.setState({
      viewingJobs: true
    });
  }

  viewResources() {
    this.setState({
      viewingJobs: false
    });
  }

  logOut() {
    fetch('/logout', { method: 'GET', credentials: 'include' })
      .then(json => {
        this.setState({
          loggedIn: false
        });
      })
  }

  sortResources(sortStatus) {
    //if true, sort by date
    if (sortStatus === true) {
      this.setState({
        sortByDate: true
      });
    } else if (sortStatus === false) {
      this.setState({
        sortByDate: false
      });
    }
  }
  handleSearch(value) {
    // TODO
    //  on search replaces this.state.resources with the searched array
    let searchedArray = [];
    let re = value;
    re = new RegExp(re, "im");

    if (!resources) return;
    for (let cObj of resources) {
      if (re.test(cObj.name) || re.test(cObj.addedBy) || re.test(cObj.description)) searchedArray.push(cObj);
    }
    if (searchedArray.length === 0) {
      console.log("No results found: ", searchedArray);
    } else {
      console.log("Found: ", searchedArray);
    }
    this.setState({
      viewingJobs: false
    });
  }
  render() {
    const isViewingJobs = this.state.viewingJobs;
    return (

        <Navbar
          handleSearch={this.handleSearch}
          loggedIn={this.state.loggedIn}
          viewJobs={this.viewJobs}
          viewResources={this.viewResources}
          logOut={this.logOut}
        />
        {isViewingJobs ? (

              {this.state.fetching
                ? 'Fetching message from API'
                : this.state.resources}

            <MyJobs jobs={this.state.jobs} />

        ) : (

                {this.state.fetching
                  ? 'Fetching message from API'
                  : this.state.resources}

              <SortButton sortResources={this.sortResources} />
              <Resources resources={resources} sortByDate={this.state.sortByDate} />

          )
        }

    );
  }
}

module.exports = App;

<commit_msg>search filter implemented<commit_after>import React, { Component } from 'react';
import './App.css';
const Navbar = require('./Navbar');
const SortButton = require('./SortButton');
const Resources = require('./Resources');
const MyJobs = require('./MyJobs');

class App extends Component {
  constructor(props) {
    super(props);

    // TODO: dummy data, delete to test fetching
    let loremipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed gravida est sit amet mi egestas, a pharetra sem hendrerit. Ut sit amet lacinia ex, vel pellentesque metus. In placerat, lacus eget porttitor imperdiet, sem nibh faucibus turpis, ultricies ultricies turpis orci in augue. Integer ut posuere ante. Pellentesque blandit purus at tortor malesuada porttitor venenatis sed lacus.";
    this.resources = [{ "image": "https://www.sololearn.com/Icons/Courses/1024.png", "url": "https://www.website1.com/", "addedBy": "user1", "name": "abcd", "date": "01/03/2016", "rating": "1/5", "golds": "1", "description": loremipsum },
    { "image": "https://image.flaticon.com/teams/new/1-freepik.jpg", "url": "https://www.website2.com/", "addedBy": "user2", "name": "aaab", "date": "02/14/2017", "rating": "2/5", "golds": "2", "description": loremipsum },
    { "image": "http://www.freeiconspng.com/uploads/flat-mac-icon-15.png", "url": "https://www.website3.com/", "addedBy": "user3", "name": "name3", "date": "01/01/2017", "rating": "3/5", "golds": "3", "description": loremipsum }];

    // TODO: move to assign after fetch
    this.globalResources = this.resources;

    this.state = {
      fetching: true,
      viewingJobs: false,
      resources: null,
      loggedIn: false,
      username: null,
      sortByDate: true,
      jobs: null,
    };
    this.viewJobs = this.viewJobs.bind(this);
    this.viewResources = this.viewResources.bind(this);
    this.logOut = this.logOut.bind(this);
    this.isAuth = this.isAuth.bind(this);
    this.sortResources = this.sortResources.bind(this);
    this.handleSearch = this.handleSearch.bind(this);
  }

  getJobs() {
    fetch('/api/jobs')
      .then(response => {
        if (!response.ok) {
          throw new Error(`status ${response.status}`);
        }
        return response.json();
      })
      .then(json => {
        this.setState({
          jobs: json,
        });
      }).catch(e => {
      })
  }

  isAuth() {
    fetch('/isauth', { method: 'GET', credentials: 'include' })
      .then(response => {
        if (!response.ok) {
          throw new Error('not logged in');
        }
        return response.json();
      })
      .then(json => {
        this.setState({
          loggedIn: true
        });
      }).catch(e => {
        this.setState({
          loggedIn: false
        });
      });
  }

  componentDidMount() {
    this.isAuth();
    this.getJobs();
    fetch('/api')
      .then(response => {
        if (!response.ok) {
          throw new Error(`status ${response.status}`);
        }
        return response.json();
      })
      .then(json => {
        this.setState({
          resources: json.message,
          fetching: false
        });
      }).catch(e => {
        this.setState({
          resources: `API call failed: ${e}`,
          fetching: false
        });
      })
  }

  viewJobs() {
    this.setState({
      viewingJobs: true
    });
  }

  viewResources() {
    this.setState({
      viewingJobs: false
    });
  }

  logOut() {
    fetch('/logout', { method: 'GET', credentials: 'include' })
      .then(json => {
        this.setState({
          loggedIn: false
        });
      })
  }

  sortResources(sortStatus) {
    //if true, sort by date
    if (sortStatus === true) {
      this.setState({
        sortByDate: true
      });
    } else if (sortStatus === false) {
      this.setState({
        sortByDate: false
      });
    }
  }
  handleSearch(value) {
    // TODO
    //  on search replaces this.state.resources with the searched array
    let searchedArray = [];
    let re = value;
    re = new RegExp(re, "im");

    if (!this.globalResources) return;
    for (let cObj of this.globalResources) {
      if (re.test(cObj.name) || re.test(cObj.addedBy) || re.test(cObj.description)) searchedArray.push(cObj);
    }
    if (searchedArray.length === 0) {
      console.log("No results found: ", searchedArray);
    } else {
      console.log("Found: ", searchedArray);
    }

    // todo: change when fetching resources is implemented
    // change variable assign to state.resource assign
    this.resources = searchedArray;
    this.setState({
      viewingJobs: false
    });
  }
  render() {
    const isViewingJobs = this.state.viewingJobs;
    return (

        <Navbar
          handleSearch={this.handleSearch}
          loggedIn={this.state.loggedIn}
          viewJobs={this.viewJobs}
          viewResources={this.viewResources}
          logOut={this.logOut}
        />
        {isViewingJobs ? (

              {this.state.fetching
                ? 'Fetching message from API'
                : this.state.resources}

            <MyJobs jobs={this.state.jobs} />

        ) : (

                {this.state.fetching
                  ? 'Fetching message from API'
                  : this.state.resources}

              <SortButton sortResources={this.sortResources} />
              <Resources resources={this.resources} sortByDate={this.state.sortByDate} />

          )
        }

    );
  }
}

module.exports = App;

<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { Repos, Settings, RepoAdd, UnsubscribeMessage } from './containers'
import { withStyles } from 'material-ui/styles'
import PropTypes from 'prop-types'

import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as actionCreators from './actions'

class AppComponent extends Component {
  render () {
    const { classes } = this.props
    return (

        <RepoAdd className={`${classes.sectionContainer} ${classes.repoAdd}`} />

          <Repos className={`${classes.sectionContainer} ${classes.repos}`} />
          <Settings className={classes.sectionContainer} />

        <UnsubscribeMessage />

    )
  }

  componentDidMount () {
    const jssStyles = document.getElementById('jss-server-side')
    if (jssStyles && jssStyles.parentNode) {
      jssStyles.parentNode.removeChild(jssStyles)
    }
    const { inited, email, fetchProfile } = this.props
    if (inited) {
      return this.processProfile({ email })
    }
    fetchProfile()
      .then(({ profile = {} }) => this.processProfile(profile))
  }

  processProfile ({ email }) {
    this.possiblyUnsubscribe(email)
    window.location.pathname === '/' || window.history.pushState(null, '', '/')
  }

  possiblyUnsubscribe (email) {
    const { pathname } = window.location
    if (pathname.indexOf('/unsubscribe/') !== 0) { return }
    const lambdajwt = (pathname.match(/^\/unsubscribe\/(.+)$/) || [0, 0])[1]
    if (!lambdajwt) { return }
    this.props.unsubscribe(email, lambdajwt)
  }
}

AppComponent.propTypes = {
  classes: PropTypes.object.isRequired,
  email: PropTypes.string.isRequired,
  inited: PropTypes.bool.isRequired
}

const styles = theme => ({
  app: {
    boxSizing: 'border-box',
    height: '100%',
    maxWidth: '900px',
    margin: '0 auto',
    paddingTop: theme.spacing.unit,
    '@media (min-width:700px)': {
      paddingTop: theme.spacing.unit * 2,
    }
  },
  container: {
    '@media (min-width:700px)': {
      flexDirection: 'row'
    },
    display: 'flex',
    flexDirection: 'column'
  },
  sectionContainer: {
    '@media (min-width:700px)': {
      padding: theme.spacing.unit * 4,
      margin: theme.spacing.unit * 2
    },
    padding: theme.spacing.unit * 2,
    margin: theme.spacing.unit
  },
  repoAdd: {
    marginTop: 0
  },
  repos: {
    flex: 1
  }
})

const AppComponentWithStyles = withStyles(styles)(AppComponent)

export const App = connect(
  state => ({
    email: state.email,
    inited: state.inited
  }),
  dispatch => bindActionCreators(actionCreators, dispatch)
)(AppComponentWithStyles)
<commit_msg>refactor(client): classnames in appcomponent<commit_after>import React, { Component } from 'react'
import { Repos, Settings, RepoAdd, UnsubscribeMessage } from './containers'
import { withStyles } from 'material-ui/styles'
import PropTypes from 'prop-types'

import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as actionCreators from './actions'

class AppComponent extends Component {
  render () {
    const { classes } = this.props
    const { app, sectionContainer, repoAdd, repos } = classes;
    return (

        <RepoAdd className={`${sectionContainer} ${repoAdd}`} />

          <Repos className={`${sectionContainer} ${repos}`} />
          <Settings className={sectionContainer} />

        <UnsubscribeMessage />

    )
  }

  componentDidMount () {
    const jssStyles = document.getElementById('jss-server-side')
    if (jssStyles && jssStyles.parentNode) {
      jssStyles.parentNode.removeChild(jssStyles)
    }
    const { inited, email, fetchProfile } = this.props
    if (inited) {
      return this.processProfile({ email })
    }
    fetchProfile()
      .then(({ profile = {} }) => this.processProfile(profile))
  }

  processProfile ({ email }) {
    this.possiblyUnsubscribe(email)
    window.location.pathname === '/' || window.history.pushState(null, '', '/')
  }

  possiblyUnsubscribe (email) {
    const { pathname } = window.location
    if (pathname.indexOf('/unsubscribe/') !== 0) { return }
    const lambdajwt = (pathname.match(/^\/unsubscribe\/(.+)$/) || [0, 0])[1]
    if (!lambdajwt) { return }
    this.props.unsubscribe(email, lambdajwt)
  }
}

AppComponent.propTypes = {
  classes: PropTypes.object.isRequired,
  email: PropTypes.string.isRequired,
  inited: PropTypes.bool.isRequired
}

const styles = theme => ({
  app: {
    boxSizing: 'border-box',
    height: '100%',
    maxWidth: '900px',
    margin: '0 auto',
    paddingTop: theme.spacing.unit,
    '@media (min-width:700px)': {
      paddingTop: theme.spacing.unit * 2,
    }
  },
  container: {
    '@media (min-width:700px)': {
      flexDirection: 'row'
    },
    display: 'flex',
    flexDirection: 'column'
  },
  sectionContainer: {
    '@media (min-width:700px)': {
      padding: theme.spacing.unit * 4,
      margin: theme.spacing.unit * 2
    },
    padding: theme.spacing.unit * 2,
    margin: theme.spacing.unit
  },
  repoAdd: {
    marginTop: 0
  },
  repos: {
    flex: 1
  }
})

const AppComponentWithStyles = withStyles(styles)(AppComponent)

export const App = connect(
  state => ({
    email: state.email,
    inited: state.inited
  }),
  dispatch => bindActionCreators(actionCreators, dispatch)
)(AppComponentWithStyles)
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './css/Main.css';
var moment = require('moment');

function FormatCurrency(amount) {
  var formatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    minimumFractionDigits: 2,
    useGrouping: true
  });
  return formatter.format(amount);
}

class Account extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      "accounts": [
        { "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69", "name": "Checking" },
        { "accountId": "090e4960-df87-48b5-9a65-746c244be206", "name": "Visa" }
      ],
      "budgetItems": [
        {
          "budgetItemId": "247fbfd0-be07-44d3-81b5-35407c7bb667",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-07-01T00:00:00.000-08:00").toISOString(),
          "category": "Mortgage",
          "description": "U.S. Bank Mortgage",
          "cleared": true,
          "amount": -2300.00
        },
        {
          "budgetItemId": "9c58ebcc-6c25-47d3-a400-37f7a628ffe1",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-07-03T00:00:00.00-08:00").toISOString(),
          "category": "Bank Charge",
          "description": "U.S. Bank",
          "cleared": true,
          "amount": -5.95
        },
        {
          "budgetItemId": "4b3aec93-9b80-4283-90a3-a1022fcadb38",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-07-23T00:00:00.00-08:00").toISOString(),
          "category": "Paycheck",
          "description": "Employer Name",
          "cleared": false,
          "amount": 2400.00
        },
        {
          "budgetItemId": "86f3d1a5-21c0-4104-8171-2e6f7c49acbb",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-01T00:00:00.000-08:00").toISOString(),
          "category": "Mortgage",
          "description": "U.S. Bank Mortgage",
          "cleared": true,
          "amount": -2300.00
        },
        {
          "budgetItemId": "260ec1b1-ebea-4161-ae11-f3504c3b9ee9",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-01T00:00:00.000-08:00").toISOString(),
          "category": "Bank Charge",
          "description": "U.S. Bank",
          "cleared": false,
          "amount": -5.95
        },
        {
          "budgetItemId": "e225b1ec-d86f-4cbd-94fe-c251163ece47",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-04T00:00:00.00-08:00").toISOString(),
          "category": "Bill Consolidation",
          "description": "Making it overflow on purpose, to see what happens with property",
          "cleared": false,
          "amount": 153.00
        },
        {
          "budgetItemId": "5541bb6a-ae7f-4f0a-96d3-84329c92f3b1",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-23T00:00:00.00-08:00").toISOString(),
          "category": "Paycheck",
          "description": "Employer Name",
          "cleared": false,
          "amount": 2400.00
        },
        {
          "budgetItemId": "013bd523-d109-4968-8e8a-c5d3b061acea",
          "accountId": "090e4960-df87-48b5-9a65-746c244be206",
          "date": moment("2017-08-07T00:00:00.00-08:00").toISOString(),
          "category": "Haircut",
          "description": "HairM",
          "cleared": true,
          "amount": -25.00
        },
        {
          "budgetItemId": "01dfe563-1c81-43b8-b6be-9f8851aee97e",
          "accountId": "090e4960-df87-48b5-9a65-746c244be206",
          "date": moment("2017-08-11T00:00:00.00-08:00").toISOString(),
          "category": "Natural Gas",
          "description": "NW Natural",
          "cleared": true,
          "amount": -20.62
        }
      ],
      "selectedMonth": moment().toISOString(),
      "selectedAccountId": "65e05f87-188c-468a-a364-dbc8acd56b69"
    };
  }

  getAccountId(selectedAccountName, accounts) {
    return accounts.find(function(account) {
        return (account.name === selectedAccountName);
    }).accountId
  }

  getAccountName(selectedAccountId, accounts) {
    return accounts.find(function(account) {
        return (account.accountId === selectedAccountId);
    }).name
  }

  handleMonthChange = (selectedMonth) => {
    this.setState({
      "accounts": this.state.accounts,
      "budgetItems": this.state.budgetItems,
      "selectedMonth": moment(selectedMonth).toISOString(),
      "selectedAccountId": this.state.selectedAccountId
    });
  }

  handleAccountChange = (selectedAccountName) => {
    var selectedAccountId = this.getAccountId(selectedAccountName, this.state.accounts);
    this.setState({
      "accounts": this.state.accounts,
      "budgetItems": this.state.budgetItems,
      "selectedMonth": this.state.selectedMonth,
      "selectedAccountId": selectedAccountId
    });
  }

  render() {
    const accounts = this.state.accounts;
    const selectedAccountId = this.state.selectedAccountId;
    const selectedAccountName = this.getAccountName(this.state.selectedAccountId, accounts);
    const selectedMonth = this.state.selectedMonth;
    const budgetItems = this.state.budgetItems;

    return (

        <AccountSelector accounts={accounts} selectedAccountName={selectedAccountName} onAccountChange={this.handleAccountChange} />
        <MonthSelector selectedMonth={selectedMonth} onMonthSelect={this.handleMonthChange} />
        <Balance budgetItems={budgetItems} selectedMonth={selectedMonth} selectedAccountId={selectedAccountId} />
        <BudgetList budgetItems={budgetItems} selectedMonth={selectedMonth} selectedAccountId={selectedAccountId} />

    )
  }
}

class AccountSelector extends React.Component {
  constructor(props) {
    super(props);

    var accounts = [];
    this.props.accounts.forEach((account) => {
      accounts.push(<option key={account.accountId}>{account.name}</option>);
    });
    this.state = {
      "accounts": accounts
    };
  }

  selectAccount = (event) => {
    this.props.onAccountChange(event.target.value);
    event.preventDefault();
  }

  render() {
    const accounts = this.state.accounts;
    const selectedAccountName = this.props.selectedAccountName;

    return (

          Account: <select onChange={this.selectAccount} defaultValue={selectedAccountName}>{accounts}</select>

    )
  }
}

class Balance extends React.Component {
  buildState = (props) => {
    var previousMonth = moment(this.props.selectedMonth).add(-1, 'month')
    var currentMonth = moment(this.props.selectedMonth);
    var previousMonthBalance = this.props.budgetItems.reduce((accumulator, budgetItem) => {
        return (moment(budgetItem.date).isSame(previousMonth, 'month'))
          ? accumulator + budgetItem.amount
          : accumulator;
      }, 0);

    return {
      "previousMonthBalance": previousMonthBalance,
      "endMonthBalance": this.props.budgetItems.reduce((accumulator, budgetItem) => {
          return (moment(budgetItem.date).isSame(currentMonth, 'month')
            && budgetItem.accountId === this.props.selectedAccountId)
            ? accumulator + budgetItem.amount
            : accumulator;
        }, previousMonthBalance),
      "clearedBalance": this.props.budgetItems.reduce((accumulator, budgetItem) => {
          return (moment(budgetItem.date).isSame(currentMonth, 'month')
            && budgetItem.cleared
            && budgetItem.accountId === this.props.selectedAccountId)
            ? accumulator + budgetItem.amount
            : accumulator;
        }, previousMonthBalance),
      "currentBalance": this.props.budgetItems.reduce((accumulator, budgetItem) => {
          return (moment(budgetItem.date).isSame(currentMonth, 'month')
            && moment(budgetItem.date).isSameOrBefore(currentMonth, 'date')
            && budgetItem.accountId === this.props.selectedAccountId)
            ? accumulator + budgetItem.amount
            : accumulator;
        }, previousMonthBalance)
    };
  }

  render() {
    const state = this.buildState(this.props);

    const previousMonthBalance = state.previousMonthBalance;
    const endMonthBalance = state.endMonthBalance;
    const clearedBalance = state.clearedBalance;
    const currentBalance = state.currentBalance;

    return (

Balance:

              Previous: {FormatCurrency(previousMonthBalance)}
              Month: {FormatCurrency(endMonthBalance)}

              Cleared: {FormatCurrency(clearedBalance)}
              Current: {FormatCurrency(currentBalance)}

    )
  }
}

class BudgetList extends React.Component {
  buildState = (props) => {
    var selectedMonthBudgetItems = [];
    this.props.budgetItems.forEach((budgetItem) => {
      if (moment(budgetItem.date).isSame(this.props.selectedMonth, 'month')
            && budgetItem.accountId === this.props.selectedAccountId) {
        selectedMonthBudgetItems.push(<BudgetItem key={budgetItem.budgetItemId} date={budgetItem.date} category={budgetItem.category} description={budgetItem.description} cleared={budgetItem.cleared} amount={budgetItem.amount} />);
      }
    });

    return {
      "selectedMonthBudgetItems": selectedMonthBudgetItems
    };
  }

  render() {
    const state = this.buildState(this.props);

    const selectedMonthBudgetItems = state.selectedMonthBudgetItems;

    return (

              Date
              Category
              Description
              C
              Amount

          {selectedMonthBudgetItems}

    )
  }
}

function BudgetItem(props) {
  return (

        {moment(props.date).format("MM/DD/YYYY")}
        {props.category}
        {props.description}
        <input type="checkbox" defaultValue={props.cleared} />
        {FormatCurrency(props.amount)}

  )
}

class MonthSelector extends React.Component {
  selectMonth = (event) => {
    this.props.onMonthSelect(event.target.value);
    event.preventDefault();
  }

  render() {
    const selectedMonth = moment(this.props.selectedMonth).format("YYYY-MM");

    return (

Month/Year: <input type="month" defaultValue={selectedMonth} onChange={this.selectMonth} />

    )
  }
}

class App extends Component {
  render() {
    return (
      <Account />
    );
  }
}

export default App;<commit_msg>Fixing error in setting the default on the grid checkboxes<commit_after>import React, { Component } from 'react';
import './css/Main.css';
var moment = require('moment');

function FormatCurrency(amount) {
  var formatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    minimumFractionDigits: 2,
    useGrouping: true
  });
  return formatter.format(amount);
}

class Account extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      "accounts": [
        { "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69", "name": "Checking" },
        { "accountId": "090e4960-df87-48b5-9a65-746c244be206", "name": "Visa" }
      ],
      "budgetItems": [
        {
          "budgetItemId": "247fbfd0-be07-44d3-81b5-35407c7bb667",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-07-01T00:00:00.000-08:00").toISOString(),
          "category": "Mortgage",
          "description": "U.S. Bank Mortgage",
          "cleared": true,
          "amount": -2300.00
        },
        {
          "budgetItemId": "9c58ebcc-6c25-47d3-a400-37f7a628ffe1",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-07-03T00:00:00.00-08:00").toISOString(),
          "category": "Bank Charge",
          "description": "U.S. Bank",
          "cleared": true,
          "amount": -5.95
        },
        {
          "budgetItemId": "4b3aec93-9b80-4283-90a3-a1022fcadb38",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-07-23T00:00:00.00-08:00").toISOString(),
          "category": "Paycheck",
          "description": "Employer Name",
          "cleared": false,
          "amount": 2400.00
        },
        {
          "budgetItemId": "86f3d1a5-21c0-4104-8171-2e6f7c49acbb",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-01T00:00:00.000-08:00").toISOString(),
          "category": "Mortgage",
          "description": "U.S. Bank Mortgage",
          "cleared": true,
          "amount": -2300.00
        },
        {
          "budgetItemId": "260ec1b1-ebea-4161-ae11-f3504c3b9ee9",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-01T00:00:00.000-08:00").toISOString(),
          "category": "Bank Charge",
          "description": "U.S. Bank",
          "cleared": false,
          "amount": -5.95
        },
        {
          "budgetItemId": "e225b1ec-d86f-4cbd-94fe-c251163ece47",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-04T00:00:00.00-08:00").toISOString(),
          "category": "Bill Consolidation",
          "description": "Making it overflow on purpose, to see what happens with property",
          "cleared": false,
          "amount": 153.00
        },
        {
          "budgetItemId": "5541bb6a-ae7f-4f0a-96d3-84329c92f3b1",
          "accountId": "65e05f87-188c-468a-a364-dbc8acd56b69",
          "date": moment("2017-08-23T00:00:00.00-08:00").toISOString(),
          "category": "Paycheck",
          "description": "Employer Name",
          "cleared": false,
          "amount": 2400.00
        },
        {
          "budgetItemId": "013bd523-d109-4968-8e8a-c5d3b061acea",
          "accountId": "090e4960-df87-48b5-9a65-746c244be206",
          "date": moment("2017-08-07T00:00:00.00-08:00").toISOString(),
          "category": "Haircut",
          "description": "HairM",
          "cleared": true,
          "amount": -25.00
        },
        {
          "budgetItemId": "01dfe563-1c81-43b8-b6be-9f8851aee97e",
          "accountId": "090e4960-df87-48b5-9a65-746c244be206",
          "date": moment("2017-08-11T00:00:00.00-08:00").toISOString(),
          "category": "Natural Gas",
          "description": "NW Natural",
          "cleared": true,
          "amount": -20.62
        }
      ],
      "selectedMonth": moment().toISOString(),
      "selectedAccountId": "65e05f87-188c-468a-a364-dbc8acd56b69"
    };
  }

  getAccountId(selectedAccountName, accounts) {
    return accounts.find(function(account) {
        return (account.name === selectedAccountName);
    }).accountId
  }

  getAccountName(selectedAccountId, accounts) {
    return accounts.find(function(account) {
        return (account.accountId === selectedAccountId);
    }).name
  }

  handleMonthChange = (selectedMonth) => {
    this.setState({
      "accounts": this.state.accounts,
      "budgetItems": this.state.budgetItems,
      "selectedMonth": moment(selectedMonth).toISOString(),
      "selectedAccountId": this.state.selectedAccountId
    });
  }

  handleAccountChange = (selectedAccountName) => {
    var selectedAccountId = this.getAccountId(selectedAccountName, this.state.accounts);
    this.setState({
      "accounts": this.state.accounts,
      "budgetItems": this.state.budgetItems,
      "selectedMonth": this.state.selectedMonth,
      "selectedAccountId": selectedAccountId
    });
  }

  render() {
    const accounts = this.state.accounts;
    const selectedAccountId = this.state.selectedAccountId;
    const selectedAccountName = this.getAccountName(this.state.selectedAccountId, accounts);
    const selectedMonth = this.state.selectedMonth;
    const budgetItems = this.state.budgetItems;

    return (

        <AccountSelector accounts={accounts} selectedAccountName={selectedAccountName} onAccountChange={this.handleAccountChange} />
        <MonthSelector selectedMonth={selectedMonth} onMonthSelect={this.handleMonthChange} />
        <Balance budgetItems={budgetItems} selectedMonth={selectedMonth} selectedAccountId={selectedAccountId} />
        <BudgetList budgetItems={budgetItems} selectedMonth={selectedMonth} selectedAccountId={selectedAccountId} />

    )
  }
}

class AccountSelector extends React.Component {
  constructor(props) {
    super(props);

    var accounts = [];
    this.props.accounts.forEach((account) => {
      accounts.push(<option key={account.accountId}>{account.name}</option>);
    });
    this.state = {
      "accounts": accounts
    };
  }

  selectAccount = (event) => {
    this.props.onAccountChange(event.target.value);
    event.preventDefault();
  }

  render() {
    const accounts = this.state.accounts;
    const selectedAccountName = this.props.selectedAccountName;

    return (

          Account: <select onChange={this.selectAccount} defaultValue={selectedAccountName}>{accounts}</select>

    )
  }
}

class Balance extends React.Component {
  buildState = (props) => {
    var previousMonth = moment(this.props.selectedMonth).add(-1, 'month')
    var currentMonth = moment(this.props.selectedMonth);
    var previousMonthBalance = this.props.budgetItems.reduce((accumulator, budgetItem) => {
        return (moment(budgetItem.date).isSame(previousMonth, 'month'))
          ? accumulator + budgetItem.amount
          : accumulator;
      }, 0);

    return {
      "previousMonthBalance": previousMonthBalance,
      "endMonthBalance": this.props.budgetItems.reduce((accumulator, budgetItem) => {
          return (moment(budgetItem.date).isSame(currentMonth, 'month')
            && budgetItem.accountId === this.props.selectedAccountId)
            ? accumulator + budgetItem.amount
            : accumulator;
        }, previousMonthBalance),
      "clearedBalance": this.props.budgetItems.reduce((accumulator, budgetItem) => {
          return (moment(budgetItem.date).isSame(currentMonth, 'month')
            && budgetItem.cleared
            && budgetItem.accountId === this.props.selectedAccountId)
            ? accumulator + budgetItem.amount
            : accumulator;
        }, previousMonthBalance),
      "currentBalance": this.props.budgetItems.reduce((accumulator, budgetItem) => {
          return (moment(budgetItem.date).isSame(currentMonth, 'month')
            && moment(budgetItem.date).isSameOrBefore(currentMonth, 'date')
            && budgetItem.accountId === this.props.selectedAccountId)
            ? accumulator + budgetItem.amount
            : accumulator;
        }, previousMonthBalance)
    };
  }

  render() {
    const state = this.buildState(this.props);

    const previousMonthBalance = state.previousMonthBalance;
    const endMonthBalance = state.endMonthBalance;
    const clearedBalance = state.clearedBalance;
    const currentBalance = state.currentBalance;

    return (

Balance:

              Previous: {FormatCurrency(previousMonthBalance)}
              Month: {FormatCurrency(endMonthBalance)}

              Cleared: {FormatCurrency(clearedBalance)}
              Current: {FormatCurrency(currentBalance)}

    )
  }
}

class BudgetList extends React.Component {
  buildState = (props) => {
    var selectedMonthBudgetItems = [];
    this.props.budgetItems.forEach((budgetItem) => {
      if (moment(budgetItem.date).isSame(this.props.selectedMonth, 'month')
            && budgetItem.accountId === this.props.selectedAccountId) {
        selectedMonthBudgetItems.push(<BudgetItem key={budgetItem.budgetItemId} date={budgetItem.date} category={budgetItem.category} description={budgetItem.description} cleared={budgetItem.cleared} amount={budgetItem.amount} />);
      }
    });

    return {
      "selectedMonthBudgetItems": selectedMonthBudgetItems
    };
  }

  render() {
    const state = this.buildState(this.props);

    const selectedMonthBudgetItems = state.selectedMonthBudgetItems;

    return (

              Date
              Category
              Description
              C
              Amount

          {selectedMonthBudgetItems}

    )
  }
}

function BudgetItem(props) {
  return (

        {moment(props.date).format("MM/DD/YYYY")}
        {props.category}
        {props.description}
        <input type="checkbox" defaultChecked={props.cleared} />
        {FormatCurrency(props.amount)}

  )
}

class MonthSelector extends React.Component {
  selectMonth = (event) => {
    this.props.onMonthSelect(event.target.value);
    event.preventDefault();
  }

  render() {
    const selectedMonth = moment(this.props.selectedMonth).format("YYYY-MM");

    return (

Month/Year: <input type="month" defaultValue={selectedMonth} onChange={this.selectMonth} />

    )
  }
}

class App extends Component {
  render() {
    return (
      <Account />
    );
  }
}

export default App;<|endoftext|>


<commit_before>import "../assets/styles/main.scss";

import "babel-polyfill";

import module from "./module";
import routes from "./routes";

import "./services/spotify";

import "./components/mediaitem";
import "./components/artistcard";
import "./components/albumcard";

import "./pages/landing";
import "./pages/search";

module.routing(routes);
module.config(($locationProvider) => {
	$locationProvider.html5Mode(false);
})
module.bootstrap();

export default module.name;<commit_msg>old babel-polyfill duplication issue again<commit_after>import "../assets/styles/main.scss";

import module from "./module";
import routes from "./routes";

import "./services/spotify";

import "./components/mediaitem";
import "./components/artistcard";
import "./components/albumcard";

import "./pages/landing";
import "./pages/search";

module.routing(routes);
module.config(($locationProvider) => {
	$locationProvider.html5Mode(false);
})
module.bootstrap();

export default module.name;<|endoftext|>