<commit_before>import { initOptions, keycloak } from "keycloak"

;(async() => {
  keycloak.onTokenExpired = () =>
    keycloak
      .updateToken()
      .then(() => {
        console.info("Token refreshed")
      })
      .catch(error => {
        console.warn(
          "Keycloak client failed to refresh token, re-authentication is needed"
        )
        console.warn(error)
      })

  try {
    const authenticated = await keycloak.init({ onLoad: initOptions.onLoad })
    if (!authenticated) {
      console.info("Keycloak client not authenticated, reloading page...")
      window.location.reload()
      return
    }
  } catch (error) {
    console.info("Error occurred during Keycloak client initialization")
    console.err(error)
    return
  }

  console.info("Authenticated successfully")
  try {
    require("index.js")
  } catch (error) {
    console.error(error)
  }
})()

export default keycloak
<commit_msg>lint-fix<commit_after>import { initOptions, keycloak } from "keycloak"
;(async() => {
  keycloak.onTokenExpired = () =>
    keycloak
      .updateToken()
      .then(() => {
        console.info("Token refreshed")
      })
      .catch(error => {
        console.warn(
          "Keycloak client failed to refresh token, re-authentication is needed"
        )
        console.warn(error)
      })

  try {
    const authenticated = await keycloak.init({ onLoad: initOptions.onLoad })
    if (!authenticated) {
      console.info("Keycloak client not authenticated, reloading page...")
      window.location.reload()
      return
    }
  } catch (error) {
    console.info("Error occurred during Keycloak client initialization")
    console.err(error)
    return
  }

  console.info("Authenticated successfully")
  try {
    require("index.js")
  } catch (error) {
    console.error(error)
  }
})()

export default keycloak
<|endoftext|>


<commit_before>var canvas = document.getElementById("canvas"),
       ctx = canvas.getContext("2d");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

/*function Obstacle(I) {					PLACEHOLDER
	I.active = true;
	I.color = "white";
	I.y = 0;
	I.width = 30;
	I.height = Math.random() * 1000 + 1;

	I.draw = function() {
		this.draw()
	}
}*/

Game = function(){
	this.player = {
		x: 100,
       		y: 100,
       		w: 52,
	   	h: 60,
		runw: 56,
		runh: 72,
		diry: 1,
		dirx: 1,
		movestat: 2,
		tick: 0,
		idleframe: 0,
		idleframemax: 3,
		idletickmax: 11,
		runframe: 0,
		runframemax: 5,
		runtickmax: 6,
		jumpframe: 0,
		jumpframemax: 6,
		jumptickmax: 6,
		jumptime: 0,
		jumploop: false,
		landing: false,
		img: null
	};
	this.img = new Image();
	this.img.onload = function() {
		game.player.img = game.img;
	}
	this.img.src = "sprites/player/player_spritesheet.png";
	this.player.playeranimate = function(){
		if (this.img === null)
			return;
		switch(this.movestat){
			case 0:	//idle animation
					ctx.drawImage(this.img,18+(this.idleframe*64),24,26,30,this.x,this.y,this.w,this.h);
					if (this.idletick <= this.idletickmax){
						this.idletick++;
					}
					else{
						this.idletick = 0;
						this.idleframe++;
					}
					if (this.idleframe >= this.idleframemax){
						this.idleframe = 0;
					}
					break;
			case 1:	//run animation
					ctx.drawImage(this.img,18+(this.runframe*64),82,30,36,this.x,this.y-12,this.runw,this.runh);
					if (this.runtick <= this.runtickmax){
						this.runtick++;
					}
					else{
						this.runtick = 0;
						this.runframe++;
					}
					if (this.runframe >= this.runframemax){
						this.runframe = 0;
					}
					break;
			case 2: //jumping animation
					if (this.landing === false){
						if (this.jumploop === false){ //jump start
							ctx.drawImage(this.img,18+(this.jumpframe*64),338,30,36,this.x,this.y-12,this.runw,this.runh);
							if (this.tick <= this.jumptickmax){
								this.tick++;
							}
							else{
								this.tick = 0;
								this.jumpframe++;
							}
							if (this.jumpframe >= this.jumpframemax){
								this.jumpframe = 6;
								this.jumploop = true;
								this.jumptickmax = 12;
							}
						}
						else{ //jump midair
							ctx.drawImage(this.img,18+(this.jumpframe*64),338,30,36,this.x,this.y-12,this.runw,this.runh);
							if (this.tick <= this.jumptickmax){
								this.tick++;
							}
							else{
								this.tick = 0;
								if (this.jumpframe === 5){
									this.jumpframe++;
									this.jumptime++;
									}
								else
									this.jumpframe--;
							}
							if (this.jumptime === 10){
								this.jumptime = 0;
								this.landing = true;
							}
						}
					}
					else{ //jump landing
						ctx.drawImage(this.img,466,338,30,36,this.x,this.y-12,this.runw,this.runh);
						this.jumptickmax = 6;
						this.tick = 0;
						if (this.tick <= this.jumptickmax){
							this.tick++;
							console.log("hohoi");
						}
						else{
							this.tick = 0;
							this.movestat = 1;
							this.jumploop = false;
							this.landing = false; //remember to fix landing animation
						}
					}
					break;
			default:
		}
	}

		window.addEventListener("keydown", function(e) {
			game.key = e.keyCode;
		})

		window.addEventListener("keyup", function (e) {
            game.key = false;
        })

	this.animate = function(){
		requestAnimationFrame(game.animate);
		ctx.clearRect(0,0,canvas.width,canvas.height);
		game.player.playeranimate();

		if(game.key && game.key == 39) // Right arrow
			{game.player.x += 2;}
		if(game.key && game.key == 37) // Left Arrow
			{game.player.x -= 2;}
		if(game.key && game.key == 38) // Up Arrow
			{game.player.y -= 4;}
		if(game.key && game.key == 40) // Down arrow
			{game.player.y += 4;}
		if(game.key && game.key == 32) //Spacebar
			{game.player.y -= 10;}
		}

}
var game = new Game();
window.onload = game.animate();
<commit_msg>Create script.js<commit_after>var canvas = document.getElementById("canvas"),
       ctx = canvas.getContext("2d");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.backgroundColor = "blue";

/*function Obstacle(I) {					PLACEHOLDER
	I.active = true;
	I.color = "white";
	I.y = 0;
	I.width = 30;
	I.height = Math.random() * 1000 + 1;

	I.draw = function() {
		this.draw()
	}
}*/

Game = function(){
	this.player = {
		x: 100,
		y: 100,
		w: 52,
	   	h: 60,
		runw: 56,
		runh: 72,
		diry: 1,
		dirx: 1,
		movestat: 0,
		tick: 0,	//frame data starts from here
		idleframe: 0,
		idleframemax: 4,
		idletickmax: 11,
		runframe: 0,
		runframemax: 5,
		runtickmax: 6,
		jumpframe: 0,
		jumpframemax: 6,
		jumptickmax: 6,
		deathframe: 0,
		deathframemax: 7,
		deathtickmax: 10,
		attackframe: 0,
		attackframemax: 5,
		attacktickmax: 3, //frame data ends here
		jumploop: false,
		landing: false,
		jumptime: 0, //placeholder value, should be replaced with the jumping physics later
		img: null
	};
	this.img = new Image();
	this.img.onload = function() {
		game.player.img = game.img;
	}
	this.img.src = "sprites/player/player_spritesheet.png";
	this.player.playeranimate = function(){
		if (this.img === null)
			return;
		switch(this.movestat){
			case 0:	//idle animation
					ctx.drawImage(this.img,18+(this.idleframe*64),24,26,30,this.x,this.y,this.w,this.h);
					if (this.tick <= this.idletickmax){
						this.tick++;
					}
					else{
						this.tick = 0;
						this.idleframe++;
					}
					if (this.idleframe >= this.idleframemax){
						this.idleframe = 0;
					}
					break;
			case 1:	//run animation
					ctx.drawImage(this.img,18+(this.runframe*64),82,30,36,this.x,this.y-12,this.runw,this.runh);
					if (this.tick <= this.runtickmax){
						this.tick++;
					}
					else{
						this.tick = 0;
						this.runframe++;
					}
					if (this.runframe >= this.runframemax){
						this.runframe = 0;
					}
					break;
			case 2: //jumping animation
					if (this.landing === false){
						if (this.jumploop === false){ //jump start
							ctx.drawImage(this.img,18+(this.jumpframe*64),338,30,36,this.x,this.y-12,this.runw,this.runh);
							if (this.tick <= this.jumptickmax){
								this.tick++;
							}
							else{
								this.tick = 0;
								this.jumpframe++;
							}
							if (this.jumpframe >= this.jumpframemax){
								this.jumpframe = 6;
								this.jumploop = true;
								this.jumptickmax = 12;
							}
						}
						else{ //jump midair
							ctx.drawImage(this.img,18+(this.jumpframe*64),338,30,36,this.x,this.y-12,this.runw,this.runh);
							if (this.tick <= this.jumptickmax){
								this.tick++;
							}
							else{
								this.tick = 0;
								if (this.jumpframe === 5){
									this.jumpframe++;
									this.jumptime++;
									}
								else
									this.jumpframe--;
							}
							if (this.jumptime === 10){
								this.jumptime = 0;
								this.landing = true;
								this.jumptickmax = 6;
								this.tick = 0;
							}
						}
					}
					else{ //jump landing
						ctx.drawImage(this.img,466,338,30,36,this.x,this.y-12,this.runw,this.runh);
						if (this.tick <= this.jumptickmax){
							this.tick++;
						}
						else{
							this.tick = 0;
							this.jumploop = false;	//expiriencing technical difficulties right here
							this.landing = false;	//needs still fixing
							this.jumpframe = 7;
							this.movestat = 1;
						}
					}
					break;
			case 3:	//death animation
					ctx.drawImage(this.img,14+(this.deathframe*64),212,30,36,this.x-6,this.y-8,this.runw,this.runh);
					if (this.tick <= this.deathtickmax){
						this.tick++;
					}
					else{
						this.tick = 0;
						this.deathframe++;
					}
					if (this.deathframe >= this.deathframemax){
						this.deathframe = 0;
						this.movestat = -1;
					}
					break;
			case 4: //attack animation
					ctx.drawImage(this.img,18+(this.attackframe*64),148,30,36,this.x,this.y-8,this.runw,this.runh);
					if (this.tick <= this.attacktickmax){
						this.tick++;
					}
					else{
						this.tick = 0;
						this.attackframe++;
					}
					if (this.attackframe >= this.attackframemax){
						this.attackframe = 0;
					}
					break;
					break;
			default:
		}
	}
	this.player.resetframes = function(){ //implemented for future usage
		this.tick = this.idleframe = this.runframe = this.jumpframe = this.deathframe = this.attackframe = 0;
	}

	this.imgcoin = new Image();
	this.imgcoin.src = "sprites/coin/full_coins.png";
	this.Coin = function(coinx, coiny){
		this.x = coinx;
		this.y = coiny;
		this.w = 22.5;
		this.h = 24;
		this.points;
		this.tick = 0;
		this.tickmax = 5;
		this.curframe = 0;
		this.maxframe = 8;
		this.img = game.imgcoin;

		this.coinanimate = function(){
			ctx.drawImage(this.img,(this.curframe*16),0,15,16,this.x,this.y,this.w,this.h);
			if (this.tick <= this.tickmax){
				this.tick++;
			}
			else{
				this.tick = 0;
				this.curframe++;
			}
			if (this.curframe >= this.maxframe){
				this.curframe = 0;
			}
		}
	}

		window.addEventListener("keydown", function(e) {
			if (!(game.player.movestat === 3)){
				game.key = e.keyCode;
			}
		})

		window.addEventListener("keyup", function (e) {
            game.key = false;
        })

	this.animate = function(){
		requestAnimationFrame(game.animate);
		ctx.clearRect(0,0,canvas.width,canvas.height);
		coin.coinanimate(); //in future coins will be animated here, before the player
		game.player.playeranimate();

		if(game.key && game.key == 39) // Right arrow
			{game.player.x += 2;}
		if(game.key && game.key == 37) // Left Arrow
			{game.player.x -= 2;}
		if(game.key && game.key == 38) // Up Arrow
			{game.player.y -= 4;}
		if(game.key && game.key == 40) // Down arrow
			{game.player.y += 4;}
		if(game.key && game.key == 32) //Spacebar
			{game.player.y -= 10;}
		}

}
var game = new Game();
var coin = new game.Coin(200, 100); //placeholder, remove once coin spawning has been implemented
window.onload = game.animate();
<|endoftext|>


<commit_before>import THREE from "three";

class RenderSystem {
  constructor(gameState) {
    this._renderer = new THREE.WebGLRenderer();
    this._renderer.setPixelRatio(window.devicePixelRatio || 1);
    this._renderer.shadowMap.enabled = true;
    this._renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    document.body.appendChild(this._renderer.domElement);

    this.scene = new THREE.Scene();
    this._camera = new THREE.PerspectiveCamera(45, null, 0.1, 100);
    this._camera.position.set(4.5, 10, 3.6);
    this._camera.lookAt(new THREE.Vector3(4.5, 0, 3.5));

    window.addEventListener("resize", () => this._onResize());
    this._onResize();

    this._gameState = gameState;
    this._ground = this._createGround();
    this._hemiLight = this._createHemiLight();
    this._shadowLight = this._createShadowLight();
    this._player = this._createPlayer();
    this._createWalls();
  }

  tick(dt) {
    const player = this._gameState.player;
    this._player.position.set(player.position.x, 0, player.position.y);
    this._player.rotation.y = player.rotation;
    this._renderer.render(this.scene, this._camera);
  }

  _onResize() {
    this._renderer.setSize(window.innerWidth, window.innerHeight);
    this._camera.aspect = window.innerWidth / window.innerHeight;
    this._camera.updateProjectionMatrix();
  }

  _createGround() {
    const geo = new THREE.PlaneGeometry(this._gameState.width, this._gameState.height);
    const mat = new THREE.MeshPhongMaterial({ color: 0xa3845c });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.rotation.x = -Math.PI * 0.5;
    mesh.position.set((this._gameState.width - 1) * 0.5, -0.5, (this._gameState.height - 1) * 0.5);
    mesh.receiveShadow = true;
    this.scene.add(mesh);
    return mesh;
  }

  _createHemiLight() {
    const light = new THREE.HemisphereLight(0xffffbb, 0xa3845c, 1.1);
    light.position.set(0, 10, 0);
    this.scene.add(light);
    return light;
  }

  _createShadowLight() {
    const light = new THREE.DirectionalLight();
    light.position.set(2.5, 5, 3.5);
    light.lookAt(new THREE.Vector3(4.5, 0, 3.5));
    light.shadowMapWidth = 1024;
    light.shadowMapHeight = 1024;
    light.shadowDarkness = 0.3;
    light.shadowCameraNear = 0.1;
    light.shadowCameraFar = 10;
    light.shadowCameraTop = 10;
    light.shadowCameraBottom = -10;
    light.shadowCameraRight = 10;
    light.shadowCameraLeft = -10;
    light.castShadow = true;
    light.onlyShadow = true;
    // light.shadowCameraVisible = true;
    this.scene.add(light);
    return light;
  }

  _createWalls() {
    const state = this._gameState;

    const mat = new THREE.MeshPhongMaterial({ color: 0x6699ff });

    // Faces for each side of the cube
    const px = cubeFaceHelper( 1, 0,  0,              0,  Math.PI * 0.5);
    const nx = cubeFaceHelper(-1, 0,  0,              0, -Math.PI * 0.5);
    const py = cubeFaceHelper( 0, 1,  0, -Math.PI * 0.5,              0);
    const pz = cubeFaceHelper( 0, 0,  1,              0,              0);
    const nz = cubeFaceHelper( 0, 0, -1,              0,  Math.PI      );

    // TODO evaluate merging all wall meshes later...
    for (var x = 0; x < state.width; ++x) {
      for (var y = 0; y < state.height; ++y) {
        const cellData = state.getCellData(x, y);
        if (cellData.isWall) {
          const geo = new THREE.Geometry();

          if (x + 1 < state.width && !state.getCellData(x + 1, y).isWall) { geo.merge(px); }
          if (x > 0 && !state.getCellData(x - 1, y).isWall) { geo.merge(nx); }
          geo.merge(py);
          if (y + 1 < state.height && !state.getCellData(x, y + 1).isWall) { geo.merge(pz); }
          if (y > 0 && !state.getCellData(x, y - 1).isWall) { geo.merge(nz); }

          const mesh = new THREE.Mesh(geo, mat);
          mesh.position.set(x, 0, y);
          mesh.castShadow = true;
          mesh.receiveShadow = true;
          cellData.meshId = mesh.id;
          this.scene.add(mesh);
        }
      }
    }
  }

  _createPlayer() {
    const player = this._gameState.player;

    const mat = new THREE.MeshPhongMaterial({ color: 0x66ff99 });
    const mesh = new THREE.Mesh(player.geometry, mat);
    mesh.castShadow = true;
    mesh.receiveShadow = true;
    this.scene.add(mesh);
    return mesh;
  }
}

function cubeFaceHelper(tranX, tranY, tranZ, rotX, rotY) {
  const plane = new THREE.PlaneGeometry(1, 1);
  if (rotX) { plane.rotateX(rotX); }
  if (rotY) { plane.rotateY(rotY); }
  plane.translate(tranX * 0.5, tranY * 0.5, tranZ * 0.5);
  return plane;
}

export default RenderSystem;
<commit_msg>Set camera behind the player<commit_after>import THREE from "three";

class RenderSystem {
  constructor(gameState) {
    this._renderer = new THREE.WebGLRenderer();
    this._renderer.setPixelRatio(window.devicePixelRatio || 1);
    this._renderer.shadowMap.enabled = true;
    this._renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    document.body.appendChild(this._renderer.domElement);

    this.scene = new THREE.Scene();
    this._camera = new THREE.PerspectiveCamera(45, null, 0.1, 100);
    this._camera.position.set(0, 2, 2);
    this._camera.lookAt(new THREE.Vector3(0, 0.25, -0.5));

    window.addEventListener("resize", () => this._onResize());
    this._onResize();

    this._gameState = gameState;
    this._ground = this._createGround();
    this._hemiLight = this._createHemiLight();
    this._shadowLight = this._createShadowLight();
    this._player = this._createPlayer();
    this._createWalls();

    this._player.add(this._camera);
  }

  tick(dt) {
    const player = this._gameState.player;
    this._player.position.set(player.position.x, 0, player.position.y);
    this._player.rotation.y = player.rotation;
    this._renderer.render(this.scene, this._camera);
  }

  _onResize() {
    this._renderer.setSize(window.innerWidth, window.innerHeight);
    this._camera.aspect = window.innerWidth / window.innerHeight;
    this._camera.updateProjectionMatrix();
  }

  _createGround() {
    const geo = new THREE.PlaneGeometry(this._gameState.width, this._gameState.height);
    const mat = new THREE.MeshPhongMaterial({ color: 0xa3845c });
    const mesh = new THREE.Mesh(geo, mat);
    mesh.rotation.x = -Math.PI * 0.5;
    mesh.position.set((this._gameState.width - 1) * 0.5, -0.5, (this._gameState.height - 1) * 0.5);
    mesh.receiveShadow = true;
    this.scene.add(mesh);
    return mesh;
  }

  _createHemiLight() {
    const light = new THREE.HemisphereLight(0xffffbb, 0xa3845c, 1.1);
    light.position.set(0, 10, 0);
    this.scene.add(light);
    return light;
  }

  _createShadowLight() {
    const light = new THREE.DirectionalLight();
    light.position.set(2.5, 5, 3.5);
    light.lookAt(new THREE.Vector3(4.5, 0, 3.5));
    light.shadowMapWidth = 2048;
    light.shadowMapHeight = 2048;
    light.shadowDarkness = 0.3;
    light.shadowCameraNear = 0.1;
    light.shadowCameraFar = 10;
    light.shadowCameraTop = 10;
    light.shadowCameraBottom = -10;
    light.shadowCameraRight = 10;
    light.shadowCameraLeft = -10;
    light.castShadow = true;
    light.onlyShadow = true;
    // light.shadowCameraVisible = true;
    this.scene.add(light);
    return light;
  }

  _createWalls() {
    const state = this._gameState;

    const mat = new THREE.MeshPhongMaterial({ color: 0x6699ff });

    // Faces for each side of the cube
    const px = cubeFaceHelper( 1, 0,  0,              0,  Math.PI * 0.5);
    const nx = cubeFaceHelper(-1, 0,  0,              0, -Math.PI * 0.5);
    const py = cubeFaceHelper( 0, 1,  0, -Math.PI * 0.5,              0);
    const pz = cubeFaceHelper( 0, 0,  1,              0,              0);
    const nz = cubeFaceHelper( 0, 0, -1,              0,  Math.PI      );

    // TODO evaluate merging all wall meshes later...
    for (var x = 0; x < state.width; ++x) {
      for (var y = 0; y < state.height; ++y) {
        const cellData = state.getCellData(x, y);
        if (cellData.isWall) {
          const geo = new THREE.Geometry();

          if (x + 1 < state.width && !state.getCellData(x + 1, y).isWall) { geo.merge(px); }
          if (x > 0 && !state.getCellData(x - 1, y).isWall) { geo.merge(nx); }
          geo.merge(py);
          if (y + 1 < state.height && !state.getCellData(x, y + 1).isWall) { geo.merge(pz); }
          if (y > 0 && !state.getCellData(x, y - 1).isWall) { geo.merge(nz); }

          const mesh = new THREE.Mesh(geo, mat);
          mesh.position.set(x, 0, y);
          mesh.castShadow = true;
          mesh.receiveShadow = true;
          cellData.meshId = mesh.id;
          this.scene.add(mesh);
        }
      }
    }
  }

  _createPlayer() {
    const player = this._gameState.player;

    const mat = new THREE.MeshPhongMaterial({ color: 0x66ff99 });
    const mesh = new THREE.Mesh(player.geometry, mat);
    mesh.castShadow = true;
    mesh.receiveShadow = true;
    this.scene.add(mesh);
    return mesh;
  }
}

function cubeFaceHelper(tranX, tranY, tranZ, rotX, rotY) {
  const plane = new THREE.PlaneGeometry(1, 1);
  if (rotX) { plane.rotateX(rotX); }
  if (rotY) { plane.rotateY(rotY); }
  plane.translate(tranX * 0.5, tranY * 0.5, tranZ * 0.5);
  return plane;
}

export default RenderSystem;
<|endoftext|>


<commit_before>// TODO: expose all the config stuff in one place

//
// Debug
//
const stringifyObject = require('stringify-object');
function pretty(data) {
    return "
" + stringifyObject(data) + "
";
}

//
// Discogs API
//
var Discogs = require('disconnect').Client;
const UserAgent = 'vinyl-shelf-finder/1.0';
const User = 'valentingalea';
const ALL = 0; // id of main folder
var db = new Discogs(UserAgent).database();
var my_col = new Discogs(UserAgent).user().collection();
var json_col = [];
var total_count = 0;

//
// Discogs requests cache
//
console.log("Loading cache...");
var flatCache = require('flat-cache');
const cache_file = 'discogs';
var cache = flatCache.load(cache_file, __dirname + '/cache/');

//
// Search
//
var fuseJs = require("fuse.js");
var searcher = undefined;

function init_search() {
    console.log("Indexing...");

    var options = {
        keys: [ 'basic_information.title', 'basic_information.artists.name' ],
        threshold: 0.15
    };
    searcher = new fuseJs(json_col, options);
}

//
// Express REST server
//
var express = require('express');
var app = express();

function get_pub_dir() {
    return __dirname + '/public/';
}
app.use(express.static(get_pub_dir()));

var fs = require('fs');

app.get('/', function (req, res) {
    res.sendFile('index.html', { root: get_pub_dir() });
});

app.get('/random', function (req, res) {
    var index = Math.round(Math.random() * total_count);
    var msg = json_col[index];
    res.send(index + "
" + pretty(msg));
});

app.get('/search', function (req, res) {
    console.log("Search request: " + req.query.q);
    var found = searcher.search(req.query.q);

    const size = "150";
    const templ_file = fs.readFileSync(get_pub_dir() + 'results.template.html', 'utf8');

    var send_release_to_client = function (input, entry) {
        var html = input;

        html = html.replace("${size}", size);
        html = html.replace('${entry.title}', entry.basic_information.title);
        html = html.replace("${entry.artists}", entry.basic_information.artists[0].name);
        html = html.replace("${entry.cover}", entry.basic_information.cover_image);

        return html;
    };

    var client_str = "";
    for (var i = 0; i < found.length; i++) {
        client_str += send_release_to_client(templ_file, found[i]);

        // cut short to not overload with request
        // TODO: pagination support
        if (i > 10) break;
    }

    res.send(client_str);
});

app.get('/all', function (req, res) {
    res.send(pretty(json_col));
});

app.get('/test', function (req, res) {
    res.send(UserAgent);
});

app.get('/detail/:id(\\d+)', function (req, res) {
    db.getRelease(req.params.id, function(err, data){
        if (err) return;
        res.send(pretty(data));
    });
});

//
// Main
//
console.log("Starting...");

var get_folder = my_col.getFolder(User, ALL);

const page_items = 100;
var page_count = 0;
var page_iter = 1;

function get_page(n) {
    if (typeof cache.getKey(n) === "undefined") {
        process.stdout.write('Downloading page ' + n + '...');

        return my_col.getReleases(User, ALL, { page: n, per_page: page_items });
    } else {
        process.stdout.write('Readback cached page ' + n + '...');

        return new Promise(function (resolve, reject) {
            return resolve(cache.getKey(n));
        });
    }
}

function start_server(){
    const port = 8080;
    app.listen(port, function () {
        console.log('Listening on ' + port + '...');
    });
}

function async_loop() {
    if (page_iter <= page_count) {
        return get_page(page_iter).then(function (data) {
            console.log("done");

            var old_data = cache.getKey(page_iter);
            if (typeof old_data === "undefined") {
                cache.setKey(page_iter, data);
                cache.save({noPrune: true});
                console.log("Cached page " + page_iter);
            }

			// TODO: async cache the cover img here
			// TODO: also resize img

            json_col = json_col.concat(data.releases);

            page_iter++;
            async_loop();
        }, function (err) {
            console.log(err);
        });
    } else {
        init_search();
        start_server();
    }
};

// build the collection & then start server
get_folder
.then(function (data){
    total_count = data.count;
    page_count = Math.round(data.count / page_items);
    console.log("Found " + total_count + " records, retrieving all in " + page_count + " steps...");

    var old_count = cache.getKey('count');
    if (old_count != total_count) {
        console.log("Cache invalidated!");

        flatCache.clearCacheById(cache_file);
        cache.setKey('count', total_count);
        cache.save({noPrune: true});
    }

    async_loop();
}, function(err) {
    console.log(err);
});<commit_msg>moved config vars at top<commit_after>//
// Config
//
const UserAgent = 'vinyl-shelf-finder/1.0';
const User = 'valentingalea';
const ALL = 0; // id of main folder
const thumb_size = "150";
const max_results = 10;
const port = 8080;

//
// Debug
//
const stringifyObject = require('stringify-object');
function pretty(data) {
    return "
" + stringifyObject(data) + "
";
}

//
// Discogs API
//
var Discogs = require('disconnect').Client;
var db = new Discogs(UserAgent).database();
var my_col = new Discogs(UserAgent).user().collection();
var json_col = [];
var total_count = 0;

//
// Discogs requests cache
//
console.log("Loading cache...");
var flatCache = require('flat-cache');
const cache_file = 'discogs';
var cache = flatCache.load(cache_file, __dirname + '/cache/');

//
// Search
//
var fuseJs = require("fuse.js");
var searcher = undefined;

function init_search() {
    console.log("Indexing...");

    var options = {
        keys: [ 'basic_information.title', 'basic_information.artists.name' ],
        threshold: 0.15
    };
    searcher = new fuseJs(json_col, options);
}

//
// Express REST server
//
var express = require('express');
var app = express();

function get_pub_dir() {
    return __dirname + '/public/';
}
app.use(express.static(get_pub_dir()));

var fs = require('fs');

app.get('/', function (req, res) {
    res.sendFile('index.html', { root: get_pub_dir() });
});

app.get('/random', function (req, res) {
    var index = Math.round(Math.random() * total_count);
    var msg = json_col[index];
    res.send(index + "
" + pretty(msg));
});

app.get('/search', function (req, res) {
    console.log("Search request: " + req.query.q);
    var found = searcher.search(req.query.q);

    const templ_file = fs.readFileSync(get_pub_dir() + 'results.template.html', 'utf8');

    var send_release_to_client = function (input, entry) {
        var html = input;

        html = html.replace("${size}", thumb_size);
        html = html.replace('${entry.title}', entry.basic_information.title);
        html = html.replace("${entry.artists}", entry.basic_information.artists[0].name);
        html = html.replace("${entry.cover}", entry.basic_information.cover_image);

        return html;
    };

    var client_str = "";
    for (var i = 0; i < found.length; i++) {
        client_str += send_release_to_client(templ_file, found[i]);

        // cut short to not overload with requests
        // TODO: pagination support
        if (i > max_results) break;
    }

    res.send(client_str);
});

app.get('/all', function (req, res) {
    res.send(pretty(json_col));
});

app.get('/test', function (req, res) {
    res.send(UserAgent);
});

app.get('/detail/:id(\\d+)', function (req, res) {
    db.getRelease(req.params.id, function(err, data){
        if (err) return;
        res.send(pretty(data));
    });
});

//
// Main
//
console.log("Starting...");

var get_folder = my_col.getFolder(User, ALL);

const page_items = 100; // max API limit is 100
var page_count = 0;
var page_iter = 1;

function get_page(n) {
    if (typeof cache.getKey(n) === "undefined") {
        process.stdout.write('Downloading page ' + n + '...');

        return my_col.getReleases(User, ALL, { page: n, per_page: page_items });
    } else {
        process.stdout.write('Readback cached page ' + n + '...');

        return new Promise(function (resolve, reject) {
            return resolve(cache.getKey(n));
        });
    }
}

function start_server(){
    app.listen(port, function () {
        console.log('Listening on ' + port + '...');
    });
}

function async_loop() {
    if (page_iter <= page_count) {
        return get_page(page_iter).then(function (data) {
            console.log("done");

            var old_data = cache.getKey(page_iter);
            if (typeof old_data === "undefined") {
                cache.setKey(page_iter, data);
                cache.save({noPrune: true});
                console.log("Cached page " + page_iter);
            }

			// TODO: async cache the cover img here
			// TODO: also resize img

            json_col = json_col.concat(data.releases);

            page_iter++;
            async_loop();
        }, function (err) {
            console.log(err);
        });
    } else {
        init_search();
        start_server();
    }
};

// build the collection & then start server
get_folder
.then(function (data){
    total_count = data.count;
    page_count = Math.round(data.count / page_items);
    console.log("Found " + total_count + " records, retrieving all in " + page_count + " steps...");

    var old_count = cache.getKey('count');
    if (old_count != total_count) {
        console.log("Cache invalidated!");

        flatCache.clearCacheById(cache_file);
        cache.setKey('count', total_count);
        cache.save({noPrune: true});
    }

    async_loop();
}, function(err) {
    console.log(err);
});<|endoftext|>


<commit_before>'use strict';
/**
 * Controls the communication with LibreOffice
 */

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

const async = require('async');
const fs = require('fs').promises;
const log4js = require('log4js');
const os = require('os');
const path = require('path');
const settings = require('./Settings');
const spawn = require('child_process').spawn;

const libreOfficeLogger = log4js.getLogger('LibreOffice');

const doConvertTask = async (task) => {
  const tmpDir = os.tmpdir();

  libreOfficeLogger.debug(
      `Converting ${task.srcFile} to format ${task.type}. The result will be put in ${tmpDir}`);
  const soffice = spawn(settings.soffice, [
    '--headless',
    '--invisible',
    '--nologo',
    '--nolockcheck',
    '--writer',
    '--convert-to',
    task.type,
    task.srcFile,
    '--outdir',
    tmpDir,
  ]);
  soffice.stdin.end();
  // Soffice/libreoffice is buggy and often hangs.
  // To remedy this we kill the spawned process after a while.
  // TODO: Use the timeout option once support for Node.js < v15.13.0 is dropped.
  const hangTimeout = setTimeout(() => {
    soffice.kill();
  }, 120000);
  let stdoutBuffer = '';
  soffice.stdout.on('data', (data) => { stdoutBuffer += data.toString(); });
  soffice.stderr.on('data', (data) => { stdoutBuffer += data.toString(); });
  await new Promise((resolve, reject) => {
    soffice.on('exit', (code) => {
      clearTimeout(hangTimeout);
      if (code !== 0) {
        const err =
            new Error(`LibreOffice died with exit code ${code} and message: ${stdoutBuffer}`);
        libreOfficeLogger.error(err.stack);
        return reject(err);
      }
      resolve();
    });
  });

  const filename = path.basename(task.srcFile);
  const sourceFile = `${filename.substr(0, filename.lastIndexOf('.'))}.${task.fileExtension}`;
  const sourcePath = path.join(tmpDir, sourceFile);
  libreOfficeLogger.debug(`Renaming ${sourcePath} to ${task.destFile}`);
  await fs.rename(sourcePath, task.destFile);
};

// Conversion tasks will be queued up, so we don't overload the system
const queue = async.queue(doConvertTask, 1);

/**
 * Convert a file from one type to another
 *
 * @param  {String}     srcFile     The path on disk to convert
 * @param  {String}     destFile    The path on disk where the converted file should be stored
 * @param  {String}     type        The type to convert into
 * @param  {Function}   callback    Standard callback function
 */
exports.convertFile = async (srcFile, destFile, type) => {
  // Used for the moving of the file, not the conversion
  const fileExtension = type;

  if (type === 'html') {
    // "html:XHTML Writer File:UTF8" does a better job than normal html exports
    if (path.extname(srcFile).toLowerCase() === '.doc') {
      type = 'html';
    }
    // PDF files need to be converted with LO Draw ref https://github.com/ether/etherpad-lite/issues/4151
    if (path.extname(srcFile).toLowerCase() === '.pdf') {
      type = 'html:XHTML Draw File';
    }
  }

  // soffice can't convert from html to doc directly (verified with LO 5 and 6)
  // we need to convert to odt first, then to doc
  // to avoid `Error: no export filter for /tmp/xxxx.doc` error
  if (type === 'doc') {
    const intermediateFile = destFile.replace(/\.doc$/, '.odt');
    await queue.pushAsync({srcFile, destFile: intermediateFile, type: 'odt', fileExtension: 'odt'});
    await queue.pushAsync({srcFile: intermediateFile, destFile, type, fileExtension});
  } else {
    await queue.pushAsync({srcFile, destFile, type, fileExtension});
  }
};
<commit_msg>LibreOffice: Improve logging<commit_after>'use strict';
/**
 * Controls the communication with LibreOffice
 */

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

const async = require('async');
const fs = require('fs').promises;
const log4js = require('log4js');
const os = require('os');
const path = require('path');
const runCmd = require('./run_cmd');
const settings = require('./Settings');

const logger = log4js.getLogger('LibreOffice');

const doConvertTask = async (task) => {
  const tmpDir = os.tmpdir();
  const p = runCmd([
    settings.soffice,
    '--headless',
    '--invisible',
    '--nologo',
    '--nolockcheck',
    '--writer',
    '--convert-to',
    task.type,
    task.srcFile,
    '--outdir',
    tmpDir,
  ], {stdio: [
    null,
    (line) => logger.info(`[${p.child.pid}] stdout: ${line}`),
    (line) => logger.error(`[${p.child.pid}] stderr: ${line}`),
  ]});
  logger.info(`[${p.child.pid}] Converting ${task.srcFile} to ${task.type} in ${tmpDir}`);
  // Soffice/libreoffice is buggy and often hangs.
  // To remedy this we kill the spawned process after a while.
  // TODO: Use the timeout option once support for Node.js < v15.13.0 is dropped.
  const hangTimeout = setTimeout(() => {
    logger.error(`[${p.child.pid}] Conversion timed out; killing LibreOffice...`);
    p.child.kill();
  }, 120000);
  try {
    await p;
  } catch (err) {
    logger.error(`[${p.child.pid}] Conversion failed: ${err.stack || err}`);
    throw err;
  } finally {
    clearTimeout(hangTimeout);
  }
  logger.info(`[${p.child.pid}] Conversion done.`);
  const filename = path.basename(task.srcFile);
  const sourceFile = `${filename.substr(0, filename.lastIndexOf('.'))}.${task.fileExtension}`;
  const sourcePath = path.join(tmpDir, sourceFile);
  logger.debug(`Renaming ${sourcePath} to ${task.destFile}`);
  await fs.rename(sourcePath, task.destFile);
};

// Conversion tasks will be queued up, so we don't overload the system
const queue = async.queue(doConvertTask, 1);

/**
 * Convert a file from one type to another
 *
 * @param  {String}     srcFile     The path on disk to convert
 * @param  {String}     destFile    The path on disk where the converted file should be stored
 * @param  {String}     type        The type to convert into
 * @param  {Function}   callback    Standard callback function
 */
exports.convertFile = async (srcFile, destFile, type) => {
  // Used for the moving of the file, not the conversion
  const fileExtension = type;

  if (type === 'html') {
    // "html:XHTML Writer File:UTF8" does a better job than normal html exports
    if (path.extname(srcFile).toLowerCase() === '.doc') {
      type = 'html';
    }
    // PDF files need to be converted with LO Draw ref https://github.com/ether/etherpad-lite/issues/4151
    if (path.extname(srcFile).toLowerCase() === '.pdf') {
      type = 'html:XHTML Draw File';
    }
  }

  // soffice can't convert from html to doc directly (verified with LO 5 and 6)
  // we need to convert to odt first, then to doc
  // to avoid `Error: no export filter for /tmp/xxxx.doc` error
  if (type === 'doc') {
    const intermediateFile = destFile.replace(/\.doc$/, '.odt');
    await queue.pushAsync({srcFile, destFile: intermediateFile, type: 'odt', fileExtension: 'odt'});
    await queue.pushAsync({srcFile: intermediateFile, destFile, type, fileExtension});
  } else {
    await queue.pushAsync({srcFile, destFile, type, fileExtension});
  }
};
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const app = express()
const port = process.env.PORT || 3000
app.set('port', port)
const request = require('request');

// MIDDLEWARE (transform stream)
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.get('/maps/api/geocode/*', (req, res) => {
  let apiCall = req.url.slice('/maps/api/geocode/'.length)
  let apiReq = `https://maps.googleapis.com/${apiCall}`
  request.get(apiReq, (err, _, body) => {
    res.send(body)
  });
});

app.listen(port, () =>
  console.log(`Listening on port: ${port}`)
)
<commit_msg>working on GET command<commit_after>'use strict'

const express = require('express')
const app = express()
const port = process.env.PORT || 3000
app.set('port', port)
const request = require('request');

// MIDDLEWARE (transform stream)
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.get('/maps/api/*', (req, res) => {
  let apiCall = req.url.slice('/maps/api/'.length)
  let apiReq = `https://maps.googleapis.com/${apiCall}`
  request.get(apiReq, (err, _, body) => {
    res.send(body)
  });
});

app.listen(port, () =>
  console.log(`Listening on port: ${port}`)
)
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Bonnie Schulkin. All Rights Reserved.
 *
 * This file is part of BoxCharter.
 *
 * BoxCharter is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * BoxCharter is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with BoxCharter. If not, see <http://www.gnu.org/licenses/>.
 *
 */

/**
 * Header component
 * @module
 * Header
 */

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { BrowserRouter, Link } from 'react-router-dom'
import { NO_TAB, SIGN_IN, SIGN_UP, SIGN_OUT, USER_PROFILE, } from './tabNames'
import NavLink from './NavLink'
import { setActiveNavTab } from './navActions'
import boxcharter48 from '../../public/images/boxcharter-48.png'

class Header extends Component {
  renderLinks() {
    if (this.props.auth.authenticated) {
      return [
        <NavLink key="1" linkRoute="/user-profile" linkText={USER_PROFILE} />,
        <NavLink key="2" linkRoute="/sign-out" linkText={SIGN_OUT} />
      ]
    } else {
      return [
          <NavLink key="1" linkRoute="/sign-in" linkText={SIGN_IN} />,
          <NavLink key="2" linkRoute="/sign-up" linkText={SIGN_UP} />
        ]
    }
  }

  brandClickHandler() {
    // clear active nav tab
    this.props.setActiveNavTab('')
  }

  render() {
    return (

          <Link to="/" className="logo-and-title" onClick={this.brandClickHandler.bind(this)}>

            BoxCharter
          </Link>

          {this.renderLinks()}

    )
  }
}

function mapStateToProps({ auth }) {
  return { auth }
}

export default connect(mapStateToProps, { setActiveNavTab })(Header);<commit_msg>Change image reference to link within jsx<commit_after>/*
 * Copyright (c) 2017 Bonnie Schulkin. All Rights Reserved.
 *
 * This file is part of BoxCharter.
 *
 * BoxCharter is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * BoxCharter is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with BoxCharter. If not, see <http://www.gnu.org/licenses/>.
 *
 */

/**
 * Header component
 * @module
 * Header
 */

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { BrowserRouter, Link } from 'react-router-dom'
import { NO_TAB, SIGN_IN, SIGN_UP, SIGN_OUT, USER_PROFILE, } from './tabNames'
import NavLink from './NavLink'
import { setActiveNavTab } from './navActions'

class Header extends Component {
  renderLinks() {
    if (this.props.auth.authenticated) {
      return [
        <NavLink key="1" linkRoute="/user-profile" linkText={USER_PROFILE} />,
        <NavLink key="2" linkRoute="/sign-out" linkText={SIGN_OUT} />
      ]
    } else {
      return [
          <NavLink key="1" linkRoute="/sign-in" linkText={SIGN_IN} />,
          <NavLink key="2" linkRoute="/sign-up" linkText={SIGN_UP} />
        ]
    }
  }

  brandClickHandler() {
    // clear active nav tab
    this.props.setActiveNavTab('')
  }

  render() {
    return (

          <Link to="/" className="logo-and-title" onClick={this.brandClickHandler.bind(this)}>

            BoxCharter
          </Link>

          {this.renderLinks()}

    )
  }
}

function mapStateToProps({ auth }) {
  return { auth }
}

export default connect(mapStateToProps, { setActiveNavTab })(Header);<|endoftext|>


<commit_before>;(function($) {
  var columns = 0;
  var padding_width = 0;
  var content_width = 0;
  var scroll_width = 0;
  var content, slider, padding;

  //Cargo-culting from colorbox
  var twoup = $.fn.twoup = $.twoup = function(column_rule) {
    if(content) {
      alert("You already have a twoup!");
      return;
    }

    twoup.content = content = $("

").css({ "-webkit-column-rule": column_rule, "-moz-column-rule": column_rule, "column-rule": column_rule });
    twoup.slider = slider = $("

");
    twoup.padding = padding = $(this).css({ "overflow": "hidden" });

    var children = padding.children().detach();
    padding.append(slider);
    slider.append(content);
    content.append(children);

    if(!twoup.enabled()) return;

    $(window).resize(twoup.layout).resize();

    $(window).bind('hashchange', function() {
      slider.stop(true, true).animate({ "margin-left": -((twoup.page() - 1) * scroll_width) + "px" }, 500, "swing");
    }).trigger('hashchange');

    $(window).keydown(function(event) {
      if(event.keyCode == 32 || event.keyCode == 39) {
        event.preventDefault();
        twoup.page(1, true);
      }
      else if(event.keyCode == 8 || event.keyCode == 37) {
        event.preventDefault();
        twoup.page(-1, true);
      }
    });

    return this;
  };

  twoup.enabled = function() {
    //at the moment, only WebKit and MSIE10 has proper support for css3 columns AND getting the right width for a column element with overflow
    return $.browser.webkit || ($.browser.msie && $.browser.version >= 10);
  }

  twoup.columns = function() {
    return Math.max(1, Math.floor($(window).width() / (18 * padding_width)));
  };

  twoup.column_width = function() {
    return twoup.enabled() ? parseInt(content.css("-webkit-column-width") || content.css("-moz-column-width") || content.css("column-width")) : content.width()
  };

  twoup.pages = function() {
    return Math.ceil(content_width / scroll_width);
  };

  twoup.bound_page_number = function(number) {
    var index = parseInt(number);
    if(isNaN(index) || index < 1) index = 1;
    if(index > twoup.pages()) index = twoup.pages();

    return index;
  };

  twoup.page_spread = function() {
    var pages = [];
    for(var i = twoup.page(); i < twoup.pages(), pages.length < twoup.columns(); i++) pages.push(i);
    return pages;
  };

  twoup.page = function() {
    if(arguments.length == 2 && arguments[1]) twoup.page(twoup.page() + arguments[0]);
    else if(arguments.length == 1) utils.page(twoup.bound_page_number(arguments[0]));
    else return twoup.bound_page_number(utils.page());
  };

  twoup.layout = function() {
    padding_width = parseInt(padding.css("padding-top"));

    var old_columns = columns;
    columns = twoup.columns();

    var column_gap_width = (padding_width * 2) + parseInt(content.css("-webkit-column-rule-width") || content.css("column-rule-width"));
    var inner_width = window.innerWidth - (padding_width * 2);
    var inner_height = window.innerHeight - (padding_width * 2);
    var column_width = Math.floor((inner_width - (column_gap_width * (columns - 1))) / columns);
    scroll_width = inner_width + column_gap_width;

    padding.css({ "width": inner_width + "px", "height": inner_height + "px", "overflow": "hidden" });
    content.css({ "width": inner_width + "px", "height": inner_height + "px", "-webkit-column-width": column_width + "px",
     "-moz-column-width": column_width + "px", "column-width": column_width + "px", "-webkit-column-gap": column_gap_width + "px",
     "-moz-column-gap": column_gap_width + "px", "column-gap": column_gap_width + "px" });
    content_width = content[0].scrollWidth;

    if(columns != old_columns) $(window).trigger("onhashchange");
  };
})(jQuery);
<commit_msg>Animation is too slow on mobile devices<commit_after>;(function($) {
  var columns = 0;
  var padding_width = 0;
  var content_width = 0;
  var scroll_width = 0;
  var content, slider, padding;

  //Cargo-culting from colorbox
  var twoup = $.fn.twoup = $.twoup = function(column_rule) {
    if(content) {
      alert("You already have a twoup!");
      return;
    }

    twoup.content = content = $("

").css({ "-webkit-column-rule": column_rule, "-moz-column-rule": column_rule, "column-rule": column_rule });
    twoup.slider = slider = $("

");
    twoup.padding = padding = $(this).css({ "overflow": "hidden" });

    var children = padding.children().detach();
    padding.append(slider);
    slider.append(content);
    content.append(children);

    if(!twoup.enabled()) return;

    $(window).resize(twoup.layout).resize();

    $(window).bind('hashchange', function() {
      slider.css({ "margin-left": -((twoup.page() - 1) * scroll_width) + "px" });
    }).trigger('hashchange');

    $(window).keydown(function(event) {
      if(event.keyCode == 32 || event.keyCode == 39) {
        event.preventDefault();
        twoup.page(1, true);
      }
      else if(event.keyCode == 8 || event.keyCode == 37) {
        event.preventDefault();
        twoup.page(-1, true);
      }
    });

    return this;
  };

  twoup.enabled = function() {
    //at the moment, only WebKit and MSIE10 has proper support for css3 columns AND getting the right width for a column element with overflow
    return $.browser.webkit || ($.browser.msie && $.browser.version >= 10);
  }

  twoup.columns = function() {
    return Math.max(1, Math.floor($(window).width() / (18 * padding_width)));
  };

  twoup.column_width = function() {
    return twoup.enabled() ? parseInt(content.css("-webkit-column-width") || content.css("-moz-column-width") || content.css("column-width")) : content.width()
  };

  twoup.pages = function() {
    return Math.ceil(content_width / scroll_width);
  };

  twoup.bound_page_number = function(number) {
    var index = parseInt(number);
    if(isNaN(index) || index < 1) index = 1;
    if(index > twoup.pages()) index = twoup.pages();

    return index;
  };

  twoup.page_spread = function() {
    var pages = [];
    for(var i = twoup.page(); i < twoup.pages(), pages.length < twoup.columns(); i++) pages.push(i);
    return pages;
  };

  twoup.page = function() {
    if(arguments.length == 2 && arguments[1]) twoup.page(twoup.page() + arguments[0]);
    else if(arguments.length == 1) utils.page(twoup.bound_page_number(arguments[0]));
    else return twoup.bound_page_number(utils.page());
  };

  twoup.layout = function() {
    padding_width = parseInt(padding.css("padding-top"));

    var old_columns = columns;
    columns = twoup.columns();

    var column_gap_width = (padding_width * 2) + parseInt(content.css("-webkit-column-rule-width") || content.css("column-rule-width"));
    var inner_width = window.innerWidth - (padding_width * 2);
    var inner_height = window.innerHeight - (padding_width * 2);
    var column_width = Math.floor((inner_width - (column_gap_width * (columns - 1))) / columns);
    scroll_width = inner_width + column_gap_width;

    padding.css({ "width": inner_width + "px", "height": inner_height + "px", "overflow": "hidden" });
    content.css({ "width": inner_width + "px", "height": inner_height + "px", "-webkit-column-width": column_width + "px",
     "-moz-column-width": column_width + "px", "column-width": column_width + "px", "-webkit-column-gap": column_gap_width + "px",
     "-moz-column-gap": column_gap_width + "px", "column-gap": column_gap_width + "px" });
    content_width = content[0].scrollWidth;

    if(columns != old_columns) $(window).trigger("onhashchange");
  };
})(jQuery);
<|endoftext|>


<commit_before>angular.module('MyDemoApp', [
        'ngSanitize',
        'ngAnimate',
        'ui.router',
        'ui.bootstrap',
        'ui.jassa',
        'ui.jassa.edit',
        'ui.jassa.edit.tpls',
        'ui.codemirror',
        'ui.jassa.openlayers',
        'ui.jassa.rex',
        'dddi',
        'pascalprecht.translate',
        'base64'
   ], [ '$rootScopeProvider', function($rootScopeProvider) {
     $rootScopeProvider.digestTtl(10);
}])

.config(['$locationProvider', function($locationProvider) {
/*
    $locationProvider
        .html5Mode(true)
        .hashPrefix('!');
*/
}])

.config(['$translateProvider', function($translateProvider) {
    $translateProvider.useStaticFilesLoader({
        prefix: 'data/',
        suffix: '.json'
    });

    $translateProvider.preferredLanguage('en');
    $translateProvider.fallbackLanguage('en');
}])

.config([function() {
    // Setup drop down menu
    jQuery('.dropdown-toggle').dropdown();

    // Fix input element click problem
    jQuery('.dropdown input, .dropdown label').click(function(e) {
      e.stopPropagation();
    });
}])

.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("/home");

    // Now set up the states
    $stateProvider
        .state('home', {
            url: '/home',
            templateUrl: 'partials/home.html',
           // controller: 'SearchCtrl'
        })
        .state('profile', {
            url: "/profile",
            templateUrl: "partials/profile.html",
        })
        ;
}])

.controller('AppCtrl', ['$scope', function($scope) {

}])

.run(['$rootScope', '$translate', function($rootScope, $translate) {
    var global = $rootScope.global = $rootScope.global || {};
    var ui = global.ui = global.ui || {};

    ui.availableLangs = ['en', 'de'];
    ui.lang = 'en';

    $rootScope.$watch('global.ui.lang', function(lang) {
//alert('Switching to: ' + lang);
        $translate.use(lang);
    });

}])

;

<commit_msg>removed file<commit_after><|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var app = express();

var MongoClient = require("mongodb").MongoClient;
var db = require("mongoose");

app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true
}));

//Connect mongoose to the database
var accConn = db.createConnection('mongodb://127.0.0.1:27017/accel');
var aniConn = db.createConnection('mongodb://127.0.0.1:27017/animation');

//Check if both connections to the databases was successful
// var DB = accConn.Connection;
// DB.on('error', console.error.bind(console, 'connection error:'));
// DB.once('open', function(){
//   console.log("Connection to database established");
// });
// DB = aniConn.Connection;
// DB.on('error', console.error.bind(console, 'connection error:'));
// DB.once('open', function(){
//   console.log("Connection to database established");
// });

//Create the schemas that will hold the data in Mongodb
//These schemas are used for data validation and other db stuff
var accelScheme = db.Schema({id: Number, x: Number, y: Number, z: Number});
var earScheme = db.Schema({timestamp: Number, value: Number});
var animateScheme = db.Schema({keyframe: Number, rightArm: Number, leftArm: Number, rightLeg: Number, leftLeg: Number});

//Compile the shemas into models
var accel = accConn.model('accel', accelScheme);
var ear = accConn.model('ear', earScheme);
var animate = aniConn.model('animate', animateScheme);

/*
var db;
MongoClient.connect("mongodb://127.0.0.1:27017/accel", function(error, database) {
    if (error) throw error;
    console.log("Connection to database established");
    db = database;
});
var dbAnimation;
MongoClient.connect("mongodb://127.0.0.1:27017/animation", function(error, database) {
    if (error) throw error;
    console.log("Connection to animation database established");
    dbAnimation = database;
});
*/

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});
app.get('/index', function (req, res) {
   res.sendFile( __dirname + "/" + "index.htm" );
})

app.get('/', function (req, res) {
   res.sendFile( __dirname + "/public/" + "home.htm" );
})

app.get('/controller', function(req, res) {
   res.sendFile(__dirname + "/public/DashboardControl.htm");
})

// This responds with the lastest accel data
app.get('/accel', function (req, res) {
  accel.find({id:1}, function(err, data){
    if(err) console.log("There was an error getting the data");
    res.json(data);
  });
   //  db.collection("Acceleration").find().toArray(function (error, results) {
   //      if (error)
   //      {
   //        throw error;
   //      }
   //      else if(results.length == 0)
   //      {
		 //  console.log("There is nothing in the database");
   //        res.send("There is nothing");
   //      }
   //      else
   //      {
   // 	      res.send(results[results.length -1]);
   //      }
   // });
})

// This takes the accel data and stores it in the database
app.post('/accel', function (req, res) {
    req.body.id = 1;
    //db.collection("Acceleration").save({id:req.body.id, x:req.body.x, y:req.body.y, z:req.body.z});

    var acceleraionData = new accel({id:req.body.id, x:req.body.x, y:req.body.y, z:req.body.z});
    acceleraionData.save(function (err, accelData){
      if(err) console.log("There was a problem saving the data");
    });
    res.send("These values are saved are " + req.body.id + " : " + req.body.x );
})

app.post('/animation', function (req, res)
{
  console.log("Recieved animation post");
  console.log(req.body);
  var animationData = new animate({keyframe:req.body.keyframe,
                                   rightArm:req.body.rightArm,
                                   leftArm:req.body.leftArm,
                                   rightLeg:req.body.rightLeg,
                                   leftLeg:req.body.leftLeg});
  animationData.save(function(err, data){
    if(err) console.log("There was an error saving the data");
  })
  // dbAnimation.collection(req.body.collection).insert({keyframe:req.body.keyframe,
  //                                                     rightArm:req.body.rightArm,
  //                                                     leftArm:req.body.leftArm,
  //                                                     rightLeg:req.body.rightLeg,
  //                                                     leftLeg:req.body.leftLeg});
  res.send("Saved keyframe " + req.body.keyframe + " to the database"); //I need to use Jade or something to be able to show interesting stuff here
})

app.post('/GetAnimationData', function(req, res) {
  var kf = parseInt(req.body.keyframe);
  var actions;
  animate.findOne({keyframe:kf}, function(err, data){
    if(!err)
    {
      res.json(data);
    }
    else
    {
      console.log(err);
    }
  });
  // dbAnimation.collection(req.body.collection).find({keyframe:kf}).limit(1).toArray(function (error, results) {
  //   if(error)
  //   {
  //     console.log(error);
  //     return;
  //   }
  //   else if(results.length == 0)
  //   {
  //     console.log("No data");
  //     return;
  //   }
  //   else{
  //     console.log("Data sent");
  //     res.json(results[0]);
  //   }
  // });
})

// Post request to store data from the ear
app.post('/earData', function (req, res) {
  //Collection is in the accel db for the moment
   var earData = new ear({"timestamp":req.body.timestamp,"value":req.body.value});
   earData.save(function(err, earData){
    if(err)
    {
      console.log("There was was an error");
      res.send("There was an error");
    }
    else
    {
      res.send("The data was saved");
    }
   });
   // db.collection("Ear").save({"timestamp":req.body.timestamp,"value":req.body.value});
})

//Get request to get the ear data
app.get('/earData', function(req, res){
  // db.collection("Ear").find().toArray(function (error, results) {
  //       if (error)
  //       {
  //         throw error;
  //       }
  //       else if(results.length == 0)
  //       {
		//       console.log("There is nothing in the database");
  //         res.send("There is nothing");
  //       }
  //       else
  //       {
  //  	      res.send(results);
  //       }
  // })
  ear.find({}, function(err, data){
    if(!err)
      res.send(data);
    else
      console.log("There was an error");
  });
})

// This is for Naomi
app.get('/Page1', function (req, res) {
   console.log("Naomi connected");
   res.sendFile( __dirname + "/public/" + "page1.htm" );
})

// This responds a GET request for abcd, abxcd, ab123cd, and so on
app.post('/ab*cd', function(req, res) {
   console.log("Got a GET request for /ab*cd");
   console.log(req.body);
   res.send('Page Pattern Match');
})

var server = app.listen(8081, function () {

   var host = server.address().address
   var port = server.address().port

   console.log("Example app listening at http://%s:%s", host, port)
})
<commit_msg>Small and probably useless changes<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var app = express();

var MongoClient = require("mongodb").MongoClient;
var db = require("mongoose");

app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true
}));

//Connect mongoose to the database
var accConn = db.createConnection('mongodb://127.0.0.1:27017/accel');
var aniConn = db.createConnection('mongodb://127.0.0.1:27017/animation');

//Check if both connections to the databases was successful
// var DB = accConn.Connection;
// DB.on('error', console.error.bind(console, 'connection error:'));
// DB.once('open', function(){
//   console.log("Connection to database established");
// });
// DB = aniConn.Connection;
// DB.on('error', console.error.bind(console, 'connection error:'));
// DB.once('open', function(){
//   console.log("Connection to database established");
// });

//Create the schemas that will hold the data in Mongodb
//These schemas are used for data validation and other db stuff
var accelScheme = db.Schema({id: Number, x: Number, y: Number, z: Number});
var earScheme = db.Schema({timestamp: Number, value: Number});
var animateScheme = db.Schema({keyframe: Number, rightArm: Number, leftArm: Number, rightLeg: Number, leftLeg: Number});

//Compile the shemas into models
var accel = accConn.model('accel', accelScheme);
var ear = accConn.model('ear', earScheme);
var animate = aniConn.model('animate', animateScheme);

/*
var db;
MongoClient.connect("mongodb://127.0.0.1:27017/accel", function(error, database) {
    if (error) throw error;
    console.log("Connection to database established");
    db = database;
});
var dbAnimation;
MongoClient.connect("mongodb://127.0.0.1:27017/animation", function(error, database) {
    if (error) throw error;
    console.log("Connection to animation database established");
    dbAnimation = database;
});
*/

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});
app.get('/index', function (req, res) {
   res.sendFile( __dirname + "/" + "index.htm" );
})

app.get('/', function (req, res) {
   res.sendFile( __dirname + "/public/" + "home.htm" );
})

app.get('/controller', function(req, res) {
   res.sendFile(__dirname + "/public/DashboardControl.htm");
})

// This responds with the lastest accel data
app.get('/accel', function (req, res) {
  accel.find({id:1}, function(err, data){
    if(err) console.log("There was an error getting the data");
    res.json(data);
  });
   //  db.collection("Acceleration").find().toArray(function (error, results) {
   //      if (error)
   //      {
   //        throw error;
   //      }
   //      else if(results.length == 0)
   //      {
		 //  console.log("There is nothing in the database");
   //        res.send("There is nothing");
   //      }
   //      else
   //      {
   // 	      res.send(results[results.length -1]);
   //      }
   // });
})

// This takes the accel data and stores it in the database
app.post('/accel', function (req, res) {
    req.body.id = 1;
    //db.collection("Acceleration").save({id:req.body.id, x:req.body.x, y:req.body.y, z:req.body.z});

    var acceleraionData = new accel({id:req.body.id, x:req.body.x, y:req.body.y, z:req.body.z});
    acceleraionData.save(function (err, accelData){
      if(err) console.log("There was a problem saving the data");
    });
    res.send("These values are saved are " + req.body.id + " : " + req.body.x );
})

app.post('/animation', function (req, res)
{
  console.log("Recieved animation post");
  console.log(req.body);
  var animationData = new animate({keyframe:req.body.keyframe,
                                   rightArm:req.body.rightArm,
                                   leftArm:req.body.leftArm,
                                   rightLeg:req.body.rightLeg,
                                   leftLeg:req.body.leftLeg});
  animationData.save(function(err, data){
    if(err) console.log("There was an error saving the data");
  })
  // dbAnimation.collection(req.body.collection).insert({keyframe:req.body.keyframe,
  //                                                     rightArm:req.body.rightArm,
  //                                                     leftArm:req.body.leftArm,
  //                                                     rightLeg:req.body.rightLeg,
  //                                                     leftLeg:req.body.leftLeg});
  res.send("Saved keyframe " + req.body.keyframe + " to the database"); //I need to use Jade or something to be able to show interesting stuff here
})

app.post('/GetAnimationData', function(req, res) {
  var kf = parseInt(req.body.keyframe);
  var actions;
  animate.findOne({keyframe:kf}, function(err, data){
    if(!err)
    {
      console.log(data);
      res.json(data);
    }
    else
    {
      console.log(err);
    }
  });
  // dbAnimation.collection(req.body.collection).find({keyframe:kf}).limit(1).toArray(function (error, results) {
  //   if(error)
  //   {
  //     console.log(error);
  //     return;
  //   }
  //   else if(results.length == 0)
  //   {
  //     console.log("No data");
  //     return;
  //   }
  //   else{
  //     console.log("Data sent");
  //     res.json(results[0]);
  //   }
  // });
})

// Post request to store data from the ear
app.post('/earData', function (req, res) {
  //Collection is in the accel db for the moment
   var earData = new ear({"timestamp":req.body.timestamp,"value":req.body.value});
   earData.save(function(err, earData){
    if(err)
    {
      console.log("There was was an error");
      res.send("There was an error");
    }
    else
    {
      res.send("The data was saved");
    }
   });
   // db.collection("Ear").save({"timestamp":req.body.timestamp,"value":req.body.value});
})

//Get request to get the ear data
app.get('/earData', function(req, res){
  // db.collection("Ear").find().toArray(function (error, results) {
  //       if (error)
  //       {
  //         throw error;
  //       }
  //       else if(results.length == 0)
  //       {
		//       console.log("There is nothing in the database");
  //         res.send("There is nothing");
  //       }
  //       else
  //       {
  //  	      res.send(results);
  //       }
  // })
  ear.find({}, function(err, data){
    if(!err)
      res.send(data);
    else
      console.log("There was an error");
  });
})

// This is for Naomi
app.get('/Page1', function (req, res) {
   console.log("Naomi connected");
   res.sendFile( __dirname + "/public/" + "page1.htm" );
})

// This responds a GET request for abcd, abxcd, ab123cd, and so on
app.post('/ab*cd', function(req, res) {
   console.log("Got a GET request for /ab*cd");
   console.log(req.body);
   res.send('Page Pattern Match');
})

var server = app.listen(8081, function () {

   var host = server.address().address
   var port = server.address().port

   console.log("Example app listening at http://%s:%s", host, port)
})
<|endoftext|>


<commit_before>import React from 'react'

import withI18n from '../components/hoc/with-i18n'

import Page from '../components/page'
import Content from '../components/content'
import Hero from '../components/home/hero'
import Catalogs from '../components/home/catalogs'
import Events from '../components/home/events'
import NewsletterForm from '../components/home/newsletter-form'

const catalogs = [
  {
    '_id': '5387761fb01aa2342e124c96',
    'name': 'GrandLyon Smart Data',
    'service': {
      'location': 'https://download.data.grandlyon.com/catalogue/srv/fr/csw',
      'sync': {
        'status': 'successful',
        'finishedAt': '2017-01-23T01:03:24.373Z'
      }
    },
    'metrics': {
      'datasets': {
        'partitions': {
          'download': {
            'not-determined': 31,
            'yes': 409
          },
          'openness': {
            'not-determined': 17,
            'yes': 423
          },
          'dataType': {
            'none': 2,
            'grid': 218,
            'vector': 220
          }
        },
        'totalCount': 440
      },
      'records': {
        'totalCount': 846
      }
    }
  },
  {
    '_id': '54d5de332eb5568ca8350f3f',
    'name': 'Région Bretagne',
    'service': {
      'location': 'http://applications.region-bretagne.fr/geonetwork/srv/fre/csw',
      'sync': {
        'status': 'successful',
        'finishedAt': '2017-01-23T01:07:06.331Z'
      }
    },
    'metrics': {
      'datasets': {
        'partitions': {
          'download': {
            'not-determined': 11,
            'yes': 79
          },
          'openness': {
            'not-determined': 10,
            'yes': 80
          },
          'dataType': {
            'grid': 1,
            'vector': 89
          }
        },
        'totalCount': 90
      },
      'records': {
        'totalCount': 94
      }
    }
  },
  {
    '_id': '54f5a39a62781800bf6db9e6',
    'name': 'Adour-Garonne (EauFrance)',
    'service': {
      'location': 'http://catalogue.adour-garonne.eaufrance.fr/catalog/srv/fre/csw-sie-seul',
      'sync': {
        'status': 'successful',
        'finishedAt': '2017-01-23T01:05:21.864Z'
      }
    },
    'metrics': {
      'datasets': {
        'partitions': {
          'download': {
            'not-determined': 9,
            'yes': 64
          },
          'openness': {
            'not-determined': 13,
            'yes': 60
          },
          'dataType': {
            'none': 21,
            'vector': 52
          }
        },
        'totalCount': 73
      },
      'records': {
        'partitions': {
          'metadataType': {
            'Dublin Core': 29,
            'ISO 19139': 75
          },
          'recordType': {
            'service': 2,
            'other': 29,
            'dataset': 73
          }
        },
        'totalCount': 104
      }
    }
  }
]

class IndexPage extends React.PureComponent {
  render() {
    return (
      <Page>
        <Content clouds>
          <Hero />

          <Catalogs catalogs={catalogs} />
          <Events />
        </Content>

        <NewsletterForm />
      </Page>
    )
  }
}

export default withI18n('home')(IndexPage)
<commit_msg>Make index page a functional component<commit_after>import React from 'react'

import withI18n from '../components/hoc/with-i18n'

import Page from '../components/page'
import Content from '../components/content'
import Hero from '../components/home/hero'
import Catalogs from '../components/home/catalogs'
import Events from '../components/home/events'
import NewsletterForm from '../components/home/newsletter-form'

const catalogs = [
  {
    '_id': '5387761fb01aa2342e124c96',
    'name': 'GrandLyon Smart Data',
    'service': {
      'location': 'https://download.data.grandlyon.com/catalogue/srv/fr/csw',
      'sync': {
        'status': 'successful',
        'finishedAt': '2017-01-23T01:03:24.373Z'
      }
    },
    'metrics': {
      'datasets': {
        'partitions': {
          'download': {
            'not-determined': 31,
            'yes': 409
          },
          'openness': {
            'not-determined': 17,
            'yes': 423
          },
          'dataType': {
            'none': 2,
            'grid': 218,
            'vector': 220
          }
        },
        'totalCount': 440
      },
      'records': {
        'totalCount': 846
      }
    }
  },
  {
    '_id': '54d5de332eb5568ca8350f3f',
    'name': 'Région Bretagne',
    'service': {
      'location': 'http://applications.region-bretagne.fr/geonetwork/srv/fre/csw',
      'sync': {
        'status': 'successful',
        'finishedAt': '2017-01-23T01:07:06.331Z'
      }
    },
    'metrics': {
      'datasets': {
        'partitions': {
          'download': {
            'not-determined': 11,
            'yes': 79
          },
          'openness': {
            'not-determined': 10,
            'yes': 80
          },
          'dataType': {
            'grid': 1,
            'vector': 89
          }
        },
        'totalCount': 90
      },
      'records': {
        'totalCount': 94
      }
    }
  },
  {
    '_id': '54f5a39a62781800bf6db9e6',
    'name': 'Adour-Garonne (EauFrance)',
    'service': {
      'location': 'http://catalogue.adour-garonne.eaufrance.fr/catalog/srv/fre/csw-sie-seul',
      'sync': {
        'status': 'successful',
        'finishedAt': '2017-01-23T01:05:21.864Z'
      }
    },
    'metrics': {
      'datasets': {
        'partitions': {
          'download': {
            'not-determined': 9,
            'yes': 64
          },
          'openness': {
            'not-determined': 13,
            'yes': 60
          },
          'dataType': {
            'none': 21,
            'vector': 52
          }
        },
        'totalCount': 73
      },
      'records': {
        'partitions': {
          'metadataType': {
            'Dublin Core': 29,
            'ISO 19139': 75
          },
          'recordType': {
            'service': 2,
            'other': 29,
            'dataset': 73
          }
        },
        'totalCount': 104
      }
    }
  }
]

const IndexPage = () => (
  <Page>
    <Content clouds>
      <Hero />

      <Catalogs catalogs={catalogs} />
      <Events />
    </Content>

    <NewsletterForm />
  </Page>
)

export default withI18n('home')(IndexPage)
<|endoftext|>


<commit_before>$(function() {

  /* L20n */

  var parser = new L20n.Parser(L20n.EventEmitter);
  var compiler = new L20n.Compiler(L20n.EventEmitter, L20n.Parser);

  compiler.setGlobals({
    get hour() {
      return new Date().getHours();
    },
  });

  parser.addEventListener('error', function(e) {
    $("#errors").append("
Syntax error at position " + e.pos + "

" + e.message + "
");
  });
  compiler.addEventListener('error', function(e) {
    $("#errors").append("
" + e.name + " in entity " + e.entry + "

" + e.message + "
");
  });

  function update() {
    $("#output").empty();
    $("#errors").empty();
    var code = source.getValue();
    var ast = parser.parse(code);
    var data;
    try {
      var data = JSON.parse(context.getValue());
    } catch (e) {}
    var entries = compiler.compile(ast);
    for (var id in entries) {
      if (entries[id].expression) {
        continue;
        $("#output").append("

" + id + "()

");
      }
      var val;
      try {
        val = entries[id].toString(data);
      } catch (e) {
        if (e instanceof compiler.ValueError) {
          val = e.source;
        } else {
          $("#output").append("

" + e.entry + "

");
          continue;
        }
      }
      $("#output").append("

" + id + "

" + val + "

");
    }
  }

  /* ACE */

  var source = ace.edit("source");
  source.setShowPrintMargin(false);
  source.setDisplayIndentGuides(false);
  source.getSession().setUseWrapMode(true);
  source.setTheme("ace/theme/solarized_light");
  source.getSession().setMode("ace/mode/php");
  source.getSession().on('change', update);

  var context = ace.edit("context");
  context.setShowPrintMargin(false);
  context.setHighlightActiveLine(false);
  context.setHighlightGutterLine(false);
  context.setHighlightSelectedWord(false);
  context.getSession().setMode("ace/mode/json");
  context.getSession().on('change', update);

  /* Linkify */

  function utf8_to_b64(str) {
      return window.btoa(unescape(encodeURIComponent(str)));
  }

  function b64_to_utf8(str) {
      return decodeURIComponent(escape(window.atob(str)));
  }

  function linkify() {
    var state = {
      source: source.getValue(),
      context: context.getValue(),
    }
    return window.location.href.split("#")[0] + '#' + utf8_to_b64(JSON.stringify(state));
  }

  /* Main Code */

  var hash = window.location.hash.slice(1);
  var state = {
    source: (
      "<title \"L20n tinker\">\n" +
      "\n" +
      "<hello[timeOfDay(@hour)] {\n" +
      "  morning: \"Good morning!\",\n" +
      "  afternoon: \"Good afternoon!\",\n" +
      "  evening: \"Good evening!\",\n" +
      " *other: \"Hello!\"\n" +
      "}>\n" +
      "\n" +
      "<welcome \"Welcome to {{ title }}\">\n" +
      "\n" +
      "<turnout[plural($people)] {\n" +
      "  one: \"There's one person in the room.\",\n" +
      "  many: \"There are {{ $people }} people in the room.\"\n" +
      "}>\n" +
      "\n" +
      "<plural($n) { $n == 1 ? \"one\" : \"many\" }>\n" +
      "<timeOfDay($h) { $h < 6 ? \"night\" :\n" +
      "                   $h < 12 ? \"morning\" :\n" +
      "                     $h < 18 ? \"afternoon\" :\n" +
      "                       \"evening\" }>\n"
    ),
    context: (
      "{\n" +
      "  \"people\": 7\n" +
      "}"
    ),
  }

  if (hash) {
    state = JSON.parse(b64_to_utf8(hash));
  }
  source.setValue(state.source);
  context.setValue(state.context);
  source.clearSelection();
  context.clearSelection();

  $('#share').popover({
    placement: 'bottom',
    html: true,
    title: 'Share URL',
    content: '<input id="share-url" type="text">',
  }).click(function() {
    $('#share-url').val(linkify()).focus().select();
    $(this).popover('toggle');
  });
});
<commit_msg>Add @os global<commit_after>$(function() {

  /* L20n */

  var parser = new L20n.Parser(L20n.EventEmitter);
  var compiler = new L20n.Compiler(L20n.EventEmitter, L20n.Parser);

  compiler.setGlobals({
    get hour() {
      return new Date().getHours();
    },
    get os() {
      if (/^MacIntel/.test(navigator.platform)) {
        return 'mac';
      }
      if (/^Linux/.test(navigator.platform)) {
        return 'linux';
      }
      if (/^Win/.test(navigatgor.platform)) {
        return 'win';
      }
      return 'unknown';
    },
  });

  parser.addEventListener('error', function(e) {
    $("#errors").append("
Syntax error at position " + e.pos + "

" + e.message + "
");
  });
  compiler.addEventListener('error', function(e) {
    $("#errors").append("
" + e.name + " in entity " + e.entry + "

" + e.message + "
");
  });

  function update() {
    $("#output").empty();
    $("#errors").empty();
    var code = source.getValue();
    var ast = parser.parse(code);
    var data;
    try {
      var data = JSON.parse(context.getValue());
    } catch (e) {}
    var entries = compiler.compile(ast);
    for (var id in entries) {
      if (entries[id].expression) {
        continue;
        $("#output").append("

" + id + "()

");
      }
      var val;
      try {
        val = entries[id].toString(data);
      } catch (e) {
        if (e instanceof compiler.ValueError) {
          val = e.source;
        } else {
          $("#output").append("

" + e.entry + "

");
          continue;
        }
      }
      $("#output").append("

" + id + "

" + val + "

");
    }
  }

  /* ACE */

  var source = ace.edit("source");
  source.setShowPrintMargin(false);
  source.setDisplayIndentGuides(false);
  source.getSession().setUseWrapMode(true);
  source.setTheme("ace/theme/solarized_light");
  source.getSession().setMode("ace/mode/php");
  source.getSession().on('change', update);

  var context = ace.edit("context");
  context.setShowPrintMargin(false);
  context.setHighlightActiveLine(false);
  context.setHighlightGutterLine(false);
  context.setHighlightSelectedWord(false);
  context.getSession().setMode("ace/mode/json");
  context.getSession().on('change', update);

  /* Linkify */

  function utf8_to_b64(str) {
      return window.btoa(unescape(encodeURIComponent(str)));
  }

  function b64_to_utf8(str) {
      return decodeURIComponent(escape(window.atob(str)));
  }

  function linkify() {
    var state = {
      source: source.getValue(),
      context: context.getValue(),
    }
    return window.location.href.split("#")[0] + '#' + utf8_to_b64(JSON.stringify(state));
  }

  /* Main Code */

  var hash = window.location.hash.slice(1);
  var state = {
    source: (
      "<title \"L20n tinker\">\n" +
      "\n" +
      "<hello[timeOfDay(@hour)] {\n" +
      "  morning: \"Good morning!\",\n" +
      "  afternoon: \"Good afternoon!\",\n" +
      "  evening: \"Good evening!\",\n" +
      " *other: \"Hello!\"\n" +
      "}>\n" +
      "\n" +
      "<welcome \"Welcome to {{ title }}\">\n" +
      "\n" +
      "<turnout[plural($people)] {\n" +
      "  one: \"There's one person in the room.\",\n" +
      "  many: \"There are {{ $people }} people in the room.\"\n" +
      "}>\n" +
      "\n" +
      "<plural($n) { $n == 1 ? \"one\" : \"many\" }>\n" +
      "<timeOfDay($h) { $h < 6 ? \"night\" :\n" +
      "                   $h < 12 ? \"morning\" :\n" +
      "                     $h < 18 ? \"afternoon\" :\n" +
      "                       \"evening\" }>\n"
    ),
    context: (
      "{\n" +
      "  \"people\": 7\n" +
      "}"
    ),
  }

  if (hash) {
    state = JSON.parse(b64_to_utf8(hash));
  }
  source.setValue(state.source);
  context.setValue(state.context);
  source.clearSelection();
  context.clearSelection();

  $('#share').popover({
    placement: 'bottom',
    html: true,
    title: 'Share URL',
    content: '<input id="share-url" type="text">',
  }).click(function() {
    $('#share-url').val(linkify()).focus().select();
    $(this).popover('toggle');
  });
});
<|endoftext|>