<commit_before>// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 700;
canvas.height = 500;
document.body.appendChild(canvas);

var G = 10;

function Planet(radius, mass, x, y, color, x_vel, y_vel) {
  this.radius = radius;
  this.mass = mass;
  this.x = x;
  this.y = y;
  this.color = color;
  this.x_vel = x_vel;
  this.y_vel = y_vel;
}

Planet.prototype.draw = function() {
  ctx.beginPath();
  ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
  ctx.fillStyle = this.color;
  ctx.fill();
  ctx.lineWidth = 3; // TODO: make this a function of radius
  ctx.strokeStyle = '#003300';
  ctx.stroke();
};

Planet.prototype.clear = function() {
  ctx.beginPath();
  ctx.arc(this.x, this.y, this.radius + 3, 0, 2 * Math.PI, false);
  ctx.fillStyle = 'white'; // TODO: make this background color
  ctx.fill();
};

Planet.prototype.move = function(modifier) {
  this.clear();
  this.x += this.x_vel * modifier;
  this.y += this.y_vel * modifier;
  this.draw();
};

var planets = new Array();
planets.push(new Planet(20, 1500, 250, 250, 'green', 0, 0));
planets.push(new Planet(5, 30, 30, 100, 'blue', 110, -10));
planets.push(new Planet(5, 30, 400, 400, 'red', 110, -10));

var move = function (modifier) {
  planets.forEach(function(p1) {
    planets.forEach(function(p2) {
      if (p1 == p2) {
        return;
      }

      // Calculate the acceleration of p1

      // TODO: make sure we aren't using integers here
      // TODO: optimize this
      del_x = Math.abs(p2.x - p1.x);
      del_y = Math.abs(p2.y - p1.y);
      distance = Math.sqrt(Math.pow(del_x, 2) + Math.pow(del_y, 2));
      accel = G * p2.mass/Math.pow(distance, 2);
      theta = Math.atan(del_y/del_x);
      accel_x = accel * Math.cos(theta);
      accel_y = accel * Math.sin(theta);
      p1.x_vel += (p2.x - p1.x) > 0 ? accel_x : -accel_x;
      p1.y_vel += (p2.y - p1.y) > 0 ? accel_y : -accel_y;
    });
  });

  planets.forEach(function(p) {
    p.move(modifier);
  });
}

var then = Date.now();
// The main game loop
var main = function () {
  var now = Date.now();
  var delta = now - then;

  move(delta / 1000);

  then = now;
};

setInterval(main, 1);

// canvas.onmousemove = function(e) {
//   if (prevx && prevy) {
//     ctx.moveTo(prevx, prevy);
//     ctx.lineTo(e.x - 10, e.y - 10);
//     ctx.stroke();
//   }
//   prevx = e.x - 10;
//   prevy = e.y - 10;
// }
<commit_msg>Update variables names for better consistency<commit_after>// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 1000;
canvas.height = 700;
document.body.appendChild(canvas);

var G = 10;

function Planet(radius, mass, x, y, color, vel_x, vel_y) {
  this.radius = radius;
  this.mass = mass;
  this.x = x;
  this.y = y;
  this.color = color;
  this.vel_x = vel_x;
  this.vel_y = vel_y;
}

Planet.prototype.draw = function() {
  ctx.beginPath();
  ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
  ctx.fillStyle = this.color;
  ctx.fill();
  ctx.lineWidth = 3; // TODO: make this a function of radius
  ctx.strokeStyle = '#003300';
  ctx.stroke();
};

Planet.prototype.clear = function() {
  ctx.beginPath();
  ctx.arc(this.x, this.y, this.radius + 3, 0, 2 * Math.PI, false);
  ctx.fillStyle = 'white'; // TODO: make this background color
  ctx.fill();
};

Planet.prototype.move = function(modifier) {
  this.clear();
  this.x += this.vel_x * modifier;
  this.y += this.vel_y * modifier;
  this.draw();
};

var planets = new Array();
planets.push(new Planet(20, 1500, 500, 300, 'green', 0, 0));
planets.push(new Planet(5, 30, 30, 100, 'blue', 110, -10));
planets.push(new Planet(5, 30, 800, 700, 'red', 110, -10));

var move = function (modifier) {
  planets.forEach(function(p1) {
    planets.forEach(function(p2) {
      if (p1 == p2) {
        return;
      }

      // Calculate the acceleration of p1

      // TODO: make sure we aren't using integers here
      // TODO: optimize this
      del_x = Math.abs(p2.x - p1.x);
      del_y = Math.abs(p2.y - p1.y);
      distance = Math.sqrt(Math.pow(del_x, 2) + Math.pow(del_y, 2));
      accel = G * p2.mass/Math.pow(distance, 2);
      theta = Math.atan(del_y/del_x);
      accel_x = accel * Math.cos(theta);
      accel_y = accel * Math.sin(theta);
      p1.vel_x += (p2.x - p1.x) > 0 ? accel_x : -accel_x;
      p1.vel_y += (p2.y - p1.y) > 0 ? accel_y : -accel_y;
    });
  });

  // TODO: Check for collisions

  planets.forEach(function(p) {
    p.move(modifier);
  });
}

var then = Date.now();
// The main game loop
var main = function () {
  var now = Date.now();
  var delta = now - then;

  move(delta / 1000);

  then = now;
};

setInterval(main, 1);

// canvas.onmousemove = function(e) {
//   if (prevx && prevy) {
//     ctx.moveTo(prevx, prevy);
//     ctx.lineTo(e.x - 10, e.y - 10);
//     ctx.stroke();
//   }
//   prevx = e.x - 10;
//   prevy = e.y - 10;
// }
<|endoftext|>


<commit_before>// Upon loading, the Google APIs JS client automatically invokes this callback.
googleApiClientReady = function() {
    var scope = angular.element(document.getElementsByTagName("body")).scope();
    scope.$apply(function () {
        scope.initiate();
    });
}

var myApp = angular.module('youcodeio',['ngAnimate']);

myApp.service('googleService', ['$http', '$rootScope', '$q', function ($http, $rootScope, $q,$scope) {

	var deferred = $q.defer();

// Upon loading, the Google APIs JS client automatically invokes this callback.
this.handleClientLoad = function (q,id,name) {

	gapi.client.setApiKey(window.APIKEY);
	return $q(function(resolve, reject) {
		gapi.auth.init(function() {
			gapi.client.load('youtube', 'v3', function() {

				request = gapi.client.youtube.search.list({
					q: q,
					part: 'id,snippet',
					channelId: id,
					order: 'date',
					type: 'video',
					maxResults: '2'
				});
				request.execute(function(response) {
					response.channel_name = name;
					resolve(response);
				});
			});
		});
	});
};

}]);

myApp.controller('Ctrl', function ($q, $scope, googleService) {
	$scope.channels = [];
	$scope.query = "";

	$scope.initiate = function(){

		var savePromises = [];
		$scope.unicorn = true;
		requests = youtube_talks;
		requests = requests.concat(youtube_tuts);

		requests.sort(function(a, b){
			if(a.name < b.name) return -1;
			if(a.name > b.name) return 1;
			return 0;
		})

		angular.forEach(requests, function(value,key) {
			savePromises[key] = googleService.handleClientLoad($scope.query,value.id,value.name);
		});
		$q.all(savePromises).then(function(data){
			$scope.parsingResults(data);
		});
	}

	$scope.parsingResults = function (data){
		$scope.channels = [];

		var videos = [];

		console.log(data);

		angular.forEach(data, function(value,key) {
			$scope.channels[key] = {
					channel_name:value.channel_name,
					channel_video: []
				};
			angular.forEach(value.items, function(result,key2){
			$scope.channels[key].channel_video.push(result.snippet);
			});
		});
		$scope.unicorn = false;
	};
});

<commit_msg>channels modification, in controller<commit_after>// Upon loading, the Google APIs JS client automatically invokes this callback.
googleApiClientReady = function() {
    var scope = angular.element(document.getElementsByTagName("body")).scope();
    scope.$apply(function () {
        scope.initiate();
    });
}

var myApp = angular.module('youcodeio',['ngAnimate']);

myApp.service('googleService', ['$http', '$rootScope', '$q', function ($http, $rootScope, $q,$scope) {

	var deferred = $q.defer();

// Upon loading, the Google APIs JS client automatically invokes this callback.
this.handleClientLoad = function (q,id,name) {
	gapi.client.setApiKey(window.APIKEY);
	return $q(function(resolve, reject) {
		gapi.auth.init(function() {
			var request = "";
			gapi.client.load('youtube', 'v3', function() {
				if(q == 1){
					request = gapi.client.youtube.channels.list({
						part: "brandingSettings,snippet",
						id: id
					});
				}
				else if(q == 2){
					request = gapi.client.youtube.search.list({
						q: q,
						part: 'id,snippet',
						channelId: id,
						order: 'date',
						type: 'video',
						maxResults: '2'
					});
				}
				request.execute(function(response) {
					response.channel_name = name;
					resolve(response);
				});
			});
		});
	});
};

}]);

myApp.controller('Ctrl', function ($q, $scope, googleService) {
	$scope.channels = [];
	$scope.query = "";

	$scope.initiate = function(){

		var banners = [];
		var savePromises = [];
		$scope.unicorn = true;
		requests = youtube_talks;
		requests = requests.concat(youtube_tuts);

		requests.sort(function(a, b){
			if(a.name < b.name) return -1;
			if(a.name > b.name) return 1;
			return 0;
		})

		angular.forEach(requests, function(value, key){
			banners[key] = googleService.handleClientLoad(1, value.id, value.name)
		});
		$q.all(banners).then(function(d){
			angular.forEach(requests, function(value,key) {
				savePromises[key] = googleService.handleClientLoad(2,value.id,value.name);
			});
			$q.all(savePromises).then(function(data){
				$scope.parsingResults(data, d);
			});
		});
	}

	$scope.parsingResults = function (data, d){
		$scope.channels = [];

		var videos = [];

		angular.forEach(data, function(value,key) {
			$scope.channels[key] = {
					channel_name:d[key].items[0].snippet.title,
					channel_logo: d[key].items[0].snippet.thumbnails.high,
					channel_banner: d[key].items[0].brandingSettings.image.bannerImageUrl,
					channel_video: []
				};
			angular.forEach(value.items, function(result,key2){
			$scope.channels[key].channel_video.push(result.snippet);
			});
		});
		$scope.unicorn = false;
	};
});

<|endoftext|>


<commit_before>(function() {
    'use strict';

    const chalk = require('chalk');
    const request = require('request');
    const SensorTag = require('sensortag');
    const express = require('express');
    const app = express();
    const bodyParser = require("body-parser");
    const chance = require('chance').Chance();
    const _ = require('lodash');

    let serverPort = process.env.AGILE_SERVER_PORT || 8000;
    function errorHandler(err, req, res, next) {
      res.status(500);
      res.render('error', { error: err });
    }

    app.use(bodyParser.json());
    app.use(function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
    });
    app.use(errorHandler);

    let agileDevices = []; // these are "registered devices"
    let wildDevices = [];
    let device;
    let discovery = {
      on: false,
      protocols: [
        {
          "name": "BLE",
          "status": "RUNNING"
        },
        {
          "name": "ZigBee",
          "status": "NONE"
        },
        {
          "name": "ZWave",
          "status": "NONE"
        }
      ]
    }

    app.get('/api/protocols/devices', function(req, res) {
      // only send response if discover mode is turned on.
      if (discovery.on) {
        res.status(200).send(wildDevices)
      } else {
        res.status(200).send([])
      }
    });

    app.get('/api/devices', function(req, res) {
      res.status(200).send(agileDevices)
    });

    app.post('/api/devices', function(req, res) {
      let device = req.body
      agileDevices.push(device)
      _.pullAllWith(wildDevices, [device], _.isEqual);
      res.status(200).send(device)
    });

    app.delete('/api/devices/:deviceid', function(req, res) {
      let deviceid = req.params.deviceid
      device = _.find(agileDevices, { 'id': deviceid });
      wildDevices.push(device)
      _.pullAllWith(agileDevices, [device], _.isEqual);
      res.status(204).send()
    });

    app.get('/api/devices/:deviceid', function(req, res) {
      let deviceid = req.params.deviceid
      device = _.find(agileDevices, { 'id': deviceid });
      res.status(200).send(device)
    });

    app.get('/api/protocols/discovery', function(req, res) {
      res.status(200).send(discovery)
    });

    app.post('/api/protocols/discovery', function(req, res) {
      discovery.on = true
      console.log('AgileServer: discovery started');
      SensorTag.discoverAll(onDiscover);
      res.status(200).send(discovery)
    });

    app.delete('/api/protocols/discovery', function(req, res) {
      discovery.on = false
      SensorTag.stopDiscoverAll(onStopDiscover);
      res.status(204).send()
    });

    app.post('/api/protocols/discovery', function(req, res) {
      discovery.on = true
      res.status(200).send(discovery)
    });

    app.get('/api/protocols/discovery', function(req, res) {
      console.log(discovery.on)
      if (discovery.on)
        res.status(200).send(discovery.protocols)
      else {
        res.status(200).send([])
      }
    });

    app.get('/api/device/:deviceId/:componentId/lastUpdate', function(req, res) {
      let newDate = new Date(Date.now());
      dateString = newDate.toUTCString();

      lastUpdate = {
        id: req.params.componentId,
        value: chance.integer({min: -20, max: 20}),
        time: dateString
      }
      res.status(200).send(lastUpdate)
    });

    app.post('/api/device/:deviceid/:componentid/subscribe', function(req, res) {
      // responds with data stream
      res.status(200)
    });

    app.listen(serverPort, function() {
      console.log(chalk.cyan('Agile Server listening on port '+serverPort));
    });

    function onDiscover(sensorTag) {
      console.log('AgileServer: discovered new device: '+chalk.cyan(sensorTag.type)+' with id: '+chalk.cyan(sensorTag.id));
      let wildDevice = {
        "id": sensorTag.id,
        "name": sensorTag.type,
        "path": "iot.agile.device."+sensorTag.type,
        "streams": [
          {
            "id": "temperature",
            "unit": "celsius"
          },
          {
            "id": "light",
            "unit": "lumen"
          }
        ]
      };
      wildDevices.push(wildDevice);
      console.log(wildDevices);
    }
    function onStopDiscover() {
      console.log('AgileServer: discovery stopped');
    }
})();
<commit_msg>dir is better<commit_after>(function() {
    'use strict';

    const chalk = require('chalk');
    const request = require('request');
    const SensorTag = require('sensortag');
    const express = require('express');
    const app = express();
    const bodyParser = require("body-parser");
    const chance = require('chance').Chance();
    const _ = require('lodash');

    let serverPort = process.env.AGILE_SERVER_PORT || 8000;
    function errorHandler(err, req, res, next) {
      res.status(500);
      res.render('error', { error: err });
    }

    app.use(bodyParser.json());
    app.use(function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
    });
    app.use(errorHandler);

    let agileDevices = []; // these are "registered devices"
    let wildDevices = [];
    let device;
    let discovery = {
      on: false,
      protocols: [
        {
          "name": "BLE",
          "status": "RUNNING"
        },
        {
          "name": "ZigBee",
          "status": "NONE"
        },
        {
          "name": "ZWave",
          "status": "NONE"
        }
      ]
    }

    app.get('/api/protocols/devices', function(req, res) {
      // only send response if discover mode is turned on.
      if (discovery.on) {
        res.status(200).send(wildDevices)
      } else {
        res.status(200).send([])
      }
    });

    app.get('/api/devices', function(req, res) {
      res.status(200).send(agileDevices)
    });

    app.post('/api/devices', function(req, res) {
      let device = req.body
      agileDevices.push(device)
      _.pullAllWith(wildDevices, [device], _.isEqual);
      res.status(200).send(device)
    });

    app.delete('/api/devices/:deviceid', function(req, res) {
      let deviceid = req.params.deviceid
      device = _.find(agileDevices, { 'id': deviceid });
      wildDevices.push(device)
      _.pullAllWith(agileDevices, [device], _.isEqual);
      res.status(204).send()
    });

    app.get('/api/devices/:deviceid', function(req, res) {
      let deviceid = req.params.deviceid
      device = _.find(agileDevices, { 'id': deviceid });
      res.status(200).send(device)
    });

    app.get('/api/protocols/discovery', function(req, res) {
      res.status(200).send(discovery)
    });

    app.post('/api/protocols/discovery', function(req, res) {
      discovery.on = true
      console.log('AgileServer: discovery started');
      SensorTag.discoverAll(onDiscover);
      res.status(200).send(discovery)
    });

    app.delete('/api/protocols/discovery', function(req, res) {
      discovery.on = false
      SensorTag.stopDiscoverAll(onStopDiscover);
      res.status(204).send()
    });

    app.post('/api/protocols/discovery', function(req, res) {
      discovery.on = true
      res.status(200).send(discovery)
    });

    app.get('/api/protocols/discovery', function(req, res) {
      console.log(discovery.on)
      if (discovery.on)
        res.status(200).send(discovery.protocols)
      else {
        res.status(200).send([])
      }
    });

    app.get('/api/device/:deviceId/:componentId/lastUpdate', function(req, res) {
      let newDate = new Date(Date.now());
      dateString = newDate.toUTCString();

      lastUpdate = {
        id: req.params.componentId,
        value: chance.integer({min: -20, max: 20}),
        time: dateString
      }
      res.status(200).send(lastUpdate)
    });

    app.post('/api/device/:deviceid/:componentid/subscribe', function(req, res) {
      // responds with data stream
      res.status(200)
    });

    app.listen(serverPort, function() {
      console.log(chalk.cyan('Agile Server listening on port '+serverPort));
    });

    function onDiscover(sensorTag) {
      console.log('AgileServer: discovered new device: '+chalk.cyan(sensorTag.type)+' with id: '+chalk.cyan(sensorTag.id));
      let wildDevice = {
        "id": sensorTag.id,
        "name": sensorTag.type,
        "path": "iot.agile.device."+sensorTag.type,
        "streams": [
          {
            "id": "temperature",
            "unit": "celsius"
          },
          {
            "id": "light",
            "unit": "lumen"
          }
        ]
      };
      wildDevices.push(wildDevice);
      console.dir(wildDevices);
    }
    function onStopDiscover() {
      console.log('AgileServer: discovery stopped');
    }
})();
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

angular.module('qcmffvl.controllers', [])

.controller('MainCtrl', function($scope, API, $route, $http, $location, $timeout, $filter, dialogs, deviceDetector) {

    $scope.main = {
        category: {
            options: [ "Parapente" ],
            checked: "Parapente"
        },
        level: {
            options: [ "Brevet Initial", "Brevet de Pilote", "Brevet de Pilote Confirmé"],
            checked: "Brevet de Pilote"
        },
        nbquestions: {
        	options: [ "10", "30", "60", "90", "Toutes" ],
        	checked: "30"
        },
        // TODO: ajouter "révision" et prepend "examen"
        typeExam: {
            options: [ "Révision", "Examen papier (candidat)", "Examen papier (examinateur)" ],
            // options: [ "Révision", "Examen papier", "Examen numérique"],
            checked: "Révision"
        },
        targetExam: "Examinateur",
        displayLimit: 10000,
        checkAnswers: false,
        score: {
            total: 0,
            nb: 0,
            percentage: 0,
            user: 0
        },
        examMode: false,
        examPapier: false,
        examNumerique: false,
        examPapierCandidat: false,
        examPapierExaminateur: false,
        QCMID: "",
        QCMIDUser: ""
    }
    $scope.main.search  = {
    	num_niveau: $scope.main.level.options.indexOf($scope.main.level.checked)
    }
    $scope.main.limit = $scope.main.nbquestions.checked;
    $scope.reloadQCM = false;
    // automatically removed by a directive when the QCM is loaded
    $scope.loading = true;
    // to force the loading state, regardless of scope.loading
    $scope.forceloading = true;
    $scope.hideNavbarButtons = true;
    $scope.browserCheckOverride = false;

    // store qcm in $parent to allow for offline usage
    if (!$scope.qcm) {
        //console.log("loading JSON");
        $http.get('/json/qcm2014-1.json')
        .success(function(data, status, headers, config){
            $scope.qcm = data;
            $scope.qcmOrig = angular.copy($scope.qcm);
            $scope.generateQCM();
        })
        .error(function() {
            var dlg = dialogs.error('Erreur','Impossible de charger le JSON');
            dlg.result();
        });
    }

    $scope.optionsToArray = function() {
        var opt = [];
        opt[0] = $scope.main.category.options.indexOf($scope.main.category.checked)
        opt[1] = $scope.main.level.options.indexOf($scope.main.level.checked)
        opt[2] = $scope.main.nbquestions.options.indexOf($scope.main.nbquestions.checked)
        return opt;
    },
    $scope.arrayToOptions = function(opt) {
        $scope.main.category.checked = $scope.main.category.options[opt[0]];
        $scope.main.level.checked = $scope.main.level.options[opt[1]];
        $scope.main.nbquestions.checked = $scope.main.nbquestions.options[opt[2]];
    },
    $scope.generateQCM = function(QCMID) {
        $scope.forceloading = true;

        $timeout(function() {
            if (QCMID)
                $scope.arrayToOptions(API.uncomputeID(QCMID).options);
            $scope.qcm = angular.copy($scope.qcmOrig);
            $scope.main.QCMID = API.generateQCM($scope.qcm, $scope.optionsToArray(), QCMID);
        }, 500);
        $timeout(function() {
            $scope.forceloading = false;
        }, 1000);
    },
    $scope.updateQCMID = function() {
        var num = API.uncomputeID($scope.main.QCMID).num;
        $scope.main.QCMID = API.computeID(num, $scope.optionsToArray());
    },
    $scope.reload = function() {
        var dlg = dialogs.confirm('Confirmation','Composer un nouveau questionnaire (ceci effacera vos réponses) ?');
        dlg.result.then(function(btn){
        	$scope.reloadQCM = true;
        },function(btn){
            //cancel
        });
    }

    $scope.scoreClass = function(score) {
        if (score.percentage >= 75) {
            return "good-score";
        } else {
            return "bad-score";
        }
    }
    $scope.resetQCMDisplay = function() {
		$scope.loading = true;
		$scope.main.displayLimit = 0;
		$timeout(function() {
			$scope.main.displayLimit = 10000;
		}, 0);
        if ($scope.qcm && !$scope.main.examMode && $scope.main.checkAnswers) {
            API.untickAnswers($scope.qcm);
            $scope.main.checkAnswers = false;
        }
    }

    $scope.collapseNav = function() {
        $('html').trigger('click');
        $scope.navCollapsed = true;
    }

    $scope.updateExamVariables = function() {
        $scope.main.examMode = ($scope.main.typeExam.checked.indexOf("Examen") != -1);
        if ($scope.main.examMode) {
            $scope.main.examPapier = ($scope.main.typeExam.checked.indexOf("Examen papier") != -1);
            $scope.main.examNumerique = !$scope.main.examPapier;
            $scope.targetCandidat = ($scope.main.typeExam.checked.indexOf("candidat") != -1);
            if ($scope.targetCandidat) {
                $scope.main.targetExam = "Candidat";
            } else {
                $scope.main.targetExam = "Examinateur";
            }
            $scope.main.examPapierCandidat = ($scope.main.examPapier && $scope.targetCandidat);
            $scope.main.examPapierExaminateur = ($scope.main.examPapier && !$scope.targetCandidat);
        } else {
            $scope.main.examPapierExaminateur = $scope.main.examPapierCandidat = $scope.main.examPapier = $scope.main.examNumerique =  false;
        }
    }

    $scope.browserChrome = function() {
        return (deviceDetector.browser == "chrome");
    }

    $scope.isDevURL = function() {
        return ($location.absUrl().indexOf("/dev") != -1);
    }

    $scope.gotoMainURL = function() {
        if ($location.url().indexOf("/qcm") == -1) {
            $location.url("/qcm");
        }
    }

    $scope.collapseNav = function() {
        $scope.navCollapsed = true;
    }

    $scope.resetQCMIDUser = function() {
        $scope.main.QCMIDUser = $scope.main.QCMID;
        $scope.main.formattedQCMIDUser = $filter('formatQCMID')($scope.main.QCMIDUser);
    }

    $scope.fillQCMAnswers = function() {
        $scope.main.checkAnswers = true;
        API.tickAnswers($scope.qcm);
    }

    $scope.unfillQCMAnswers = function() {
        $scope.main.checkAnswers = false;
        API.untickAnswers($scope.qcm);
    }

    $scope.verifyQCMIDUser = function() {
        return API.verifyChecksum($scope.main.QCMIDUser);
    }

    $scope.toggleCheck = function(answer) {
        if ($scope.navCollapsed && !$scope.main.checkAnswers) {
            answer.checked = !answer.checked;
        }
    }

    $scope.$watch("reloadQCM", function(newval, oldval) {
        if (newval) {
            $timeout(function() {
                $scope.reloadQCM = false;
                $scope.resetQCMDisplay();
                $scope.collapseNav();
                $scope.generateQCM();
                // TODO: check if OK to disable
                // $location.path("qcm");
                // $route.reload();
            },500);
        }
        $scope.updateExamVariables();
    })

    $scope.$watch('main.nbquestions.checked', function(newval, oldval) {
        if (newval != oldval) {
            $timeout(function() {
                $scope.resetQCMDisplay();
                $scope.updateQCMID();
                var limit = $scope.main.nbquestions.checked;
                if (limit === "Toutes") {
                    limit = 10000;
                }
                $scope.main.limit = limit;
            },100);
        }
    })

    $scope.$watch('main.level.checked', function(newval, oldval) {
        if (newval != oldval) {
            $timeout(function() {
                $scope.resetQCMDisplay();
                $scope.updateQCMID();
                $scope.main.search.num_niveau = $scope.main.level.options.indexOf($scope.main.level.checked);
            },100);
        }
    });

    $scope.$watch('main.typeExam.checked', function(newval, oldval) {
        if (newval != oldval) {
            $scope.updateExamVariables();
            // back from examPapierExaminateur, we want to erase the answers ticked
            if (!$scope.main.examPapierExaminateur)
                $scope.unfillQCMAnswers();
        }
    });

    $scope.$watch('main.QCMID', function(newval, oldval) {
        if (newval != oldval) {
            // reset dirtiness on form
            $scope.QCMIDUserForm.$setPristine();
            if ($scope.main.QCMIDUser != $scope.main.QCMID) {
                $scope.resetQCMIDUser();
            }
            $scope.main.QCMIDCRC = API.crc($scope.main.QCMID);
        }
    });

    $scope.$watch('main.formattedQCMIDUser', function(newval, oldval) {
        if (newval != oldval) {
            $scope.main.QCMIDUser = $filter('removeSpaces')(newval);
            $scope.main.formattedQCMIDUser = $filter('formatQCMID')($scope.main.QCMIDUser);
            if ($scope.main.QCMIDUser != $scope.main.QCMID  && API.verifyChecksum($scope.main.QCMIDUser)) {
                $scope.generateQCM($scope.main.QCMIDUser);
            }
        }
    });
 })

.controller('QCMCtrl', function($scope, $filter, $timeout, API, filterFilter) {
    $scope.main.checkAnswers = false;
    $scope.questions = [];
    $scope.$parent.resetQCMDisplay();
    $scope.$parent.hideNavbarButtons = false;

    $scope.getPoints = function(question) {
        var total = 0;
        for (var i = 0; i < question.ans.length; i++) {
            if (question.ans[i].checked) {
                total += parseInt(question.ans[i].pts);
            }
        }
        if (total < 0) {
            total = 0;
        }
        return total;
    }

    $scope.getScore = function() {
        var arr = filterFilter($scope.qcm, $scope.main.search);
        arr = $filter('limitTo')(arr, $scope.main.limit)
        var score = { user: 0, nb: 0, percentage: 0 };
        for(var i = 0; i < arr.length; i++){
            var question = arr[i];
            score.user += $scope.getPoints(question);
        }
        score.nb = i;
        score.total = i*6;
        if (score.total > 0) {
            score.percentage = Math.round(score.user / score.total * 100);
        }
        return score;
    }

    $scope.tickIfExamPapierExaminateur = function(answer) {
        if ($scope.main.examPapierExaminateur && answer.pts >=0)
            answer.checked = true;
    }

    $scope.successQuestion = function(question) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return ($scope.getPoints(question) === 6);
    }

    $scope.failedQuestion = function(question) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return ($scope.getPoints(question) === 0);
    }

    $scope.warningQuestion = function(question) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        var points = $scope.getPoints(question);
        return (points >= 1 && points <=5);
    }

    $scope.goodAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts >= 0 && answer.checked);
    }

    $scope.badAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts < 0 && answer.checked || answer.pts == 6 && !answer.checked);
    }

    $scope.warningAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts > 0 && answer.pts < 6 && !answer.checked);
    }

    $scope.goodNotCheckedAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts < 0 && !answer.checked);
    }

    $scope.updateScore = function() {
        if ($scope.main.checkAnswers) {
            $scope.main.score = $scope.getScore();
        }
    }

    $scope.$watch('main.checkAnswers', function() {
        $scope.updateScore();
    })

})

.controller('SelfTestCtrl', function($scope, API) {
    $scope.$parent.loading = false;
	$scope.selftest = [];
	$scope.selftest.numitems   = 600;
	$scope.selftest.numruns    = 10000;
	$scope.selftest.showperrun = 60;

	$scope.selftest.qcm = [];
	for(var i = 1; i <= $scope.selftest.numitems; i++) {
		var obj = { question : i , ans : "x", shown : 0 };
		$scope.selftest.qcm.push(obj);
	}
//	console.log($scope.selftest.qcm);
	for(var i = 1; i <= $scope.selftest.numruns; i++){
//		console.log("run " + i );
		API.generateQCM($scope.selftest.qcm);
//		console.log($scope.selftest.qcm);
		for(var j = 0; j < $scope.main.nbquestions.checked ; j++){
			$scope.selftest.qcm[j].shown++;
		}
	}
	for(var i = 0; i < $scope.selftest.numitems; i++) {
		$scope.selftest.qcm[i].percent = (($scope.selftest.qcm[i].shown / $scope.selftest.numruns) * 100).toFixed(2);;
	}

})

.controller('AboutCtrl', function($scope) {
    $scope.$parent.navCollapsed = true;
    $scope.$parent.loading = false;
    $scope.$parent.hideNavbarButtons = true;

    document.body.scrollTop = document.documentElement.scrollTop = 0;
});
<commit_msg>add dev to version when not in production<commit_after>'use strict';

/* Controllers */

angular.module('qcmffvl.controllers', [])

.controller('MainCtrl', function($scope, API, $route, $http, $location, $timeout, $filter, dialogs, deviceDetector) {

    $scope.main = {
        category: {
            options: [ "Parapente" ],
            checked: "Parapente"
        },
        level: {
            options: [ "Brevet Initial", "Brevet de Pilote", "Brevet de Pilote Confirmé"],
            checked: "Brevet de Pilote"
        },
        nbquestions: {
        	options: [ "10", "30", "60", "90", "Toutes" ],
        	checked: "30"
        },
        // TODO: ajouter "révision" et prepend "examen"
        typeExam: {
            options: [ "Révision", "Examen papier (candidat)", "Examen papier (examinateur)" ],
            // options: [ "Révision", "Examen papier", "Examen numérique"],
            checked: "Révision"
        },
        targetExam: "Examinateur",
        displayLimit: 10000,
        checkAnswers: false,
        score: {
            total: 0,
            nb: 0,
            percentage: 0,
            user: 0
        },
        examMode: false,
        examPapier: false,
        examNumerique: false,
        examPapierCandidat: false,
        examPapierExaminateur: false,
        QCMID: "",
        QCMIDUser: ""
    }
    $scope.main.search  = {
    	num_niveau: $scope.main.level.options.indexOf($scope.main.level.checked)
    }
    $scope.main.limit = $scope.main.nbquestions.checked;
    $scope.reloadQCM = false;
    // automatically removed by a directive when the QCM is loaded
    $scope.loading = true;
    // to force the loading state, regardless of scope.loading
    $scope.forceloading = true;
    $scope.hideNavbarButtons = true;
    $scope.browserCheckOverride = false;

    // store qcm in $parent to allow for offline usage
    if (!$scope.qcm) {
        //console.log("loading JSON");
        $http.get('/json/qcm2014-1.json')
        .success(function(data, status, headers, config){
            $scope.qcm = data;
            $scope.qcmOrig = angular.copy($scope.qcm);
            $scope.generateQCM();
        })
        .error(function() {
            var dlg = dialogs.error('Erreur','Impossible de charger le JSON');
            dlg.result();
        });
    }

    $scope.optionsToArray = function() {
        var opt = [];
        opt[0] = $scope.main.category.options.indexOf($scope.main.category.checked)
        opt[1] = $scope.main.level.options.indexOf($scope.main.level.checked)
        opt[2] = $scope.main.nbquestions.options.indexOf($scope.main.nbquestions.checked)
        return opt;
    },
    $scope.arrayToOptions = function(opt) {
        $scope.main.category.checked = $scope.main.category.options[opt[0]];
        $scope.main.level.checked = $scope.main.level.options[opt[1]];
        $scope.main.nbquestions.checked = $scope.main.nbquestions.options[opt[2]];
    },
    $scope.generateQCM = function(QCMID) {
        $scope.forceloading = true;

        $timeout(function() {
            if (QCMID)
                $scope.arrayToOptions(API.uncomputeID(QCMID).options);
            $scope.qcm = angular.copy($scope.qcmOrig);
            $scope.main.QCMID = API.generateQCM($scope.qcm, $scope.optionsToArray(), QCMID);
        }, 500);
        $timeout(function() {
            $scope.forceloading = false;
        }, 1000);
    },
    $scope.updateQCMID = function() {
        var num = API.uncomputeID($scope.main.QCMID).num;
        $scope.main.QCMID = API.computeID(num, $scope.optionsToArray());
    },
    $scope.reload = function() {
        var dlg = dialogs.confirm('Confirmation','Composer un nouveau questionnaire (ceci effacera vos réponses) ?');
        dlg.result.then(function(btn){
        	$scope.reloadQCM = true;
        },function(btn){
            //cancel
        });
    }

    $scope.scoreClass = function(score) {
        if (score.percentage >= 75) {
            return "good-score";
        } else {
            return "bad-score";
        }
    }
    $scope.resetQCMDisplay = function() {
		$scope.loading = true;
		$scope.main.displayLimit = 0;
		$timeout(function() {
			$scope.main.displayLimit = 10000;
		}, 0);
        if ($scope.qcm && !$scope.main.examMode && $scope.main.checkAnswers) {
            API.untickAnswers($scope.qcm);
            $scope.main.checkAnswers = false;
        }
    }

    $scope.collapseNav = function() {
        $('html').trigger('click');
        $scope.navCollapsed = true;
    }

    $scope.updateExamVariables = function() {
        $scope.main.examMode = ($scope.main.typeExam.checked.indexOf("Examen") != -1);
        if ($scope.main.examMode) {
            $scope.main.examPapier = ($scope.main.typeExam.checked.indexOf("Examen papier") != -1);
            $scope.main.examNumerique = !$scope.main.examPapier;
            $scope.targetCandidat = ($scope.main.typeExam.checked.indexOf("candidat") != -1);
            if ($scope.targetCandidat) {
                $scope.main.targetExam = "Candidat";
            } else {
                $scope.main.targetExam = "Examinateur";
            }
            $scope.main.examPapierCandidat = ($scope.main.examPapier && $scope.targetCandidat);
            $scope.main.examPapierExaminateur = ($scope.main.examPapier && !$scope.targetCandidat);
        } else {
            $scope.main.examPapierExaminateur = $scope.main.examPapierCandidat = $scope.main.examPapier = $scope.main.examNumerique =  false;
        }
    }

    $scope.browserChrome = function() {
        return (deviceDetector.browser == "chrome");
    }

    // show magic button when in /dev
    $scope.isDevURL = function() {
        return ($location.absUrl().indexOf("/dev") != -1);
    }

    // we are in a stable version only when a push to prod has been done
    $scope.isProdURL = function() {
        return ($location.absUrl().indexOf("qcm.ffvl.fr") != -1);
    }

    $scope.gotoMainURL = function() {
        if ($location.url().indexOf("/qcm") == -1) {
            $location.url("/qcm");
        }
    }

    $scope.collapseNav = function() {
        $scope.navCollapsed = true;
    }

    $scope.resetQCMIDUser = function() {
        $scope.main.QCMIDUser = $scope.main.QCMID;
        $scope.main.formattedQCMIDUser = $filter('formatQCMID')($scope.main.QCMIDUser);
    }

    $scope.fillQCMAnswers = function() {
        $scope.main.checkAnswers = true;
        API.tickAnswers($scope.qcm);
    }

    $scope.unfillQCMAnswers = function() {
        $scope.main.checkAnswers = false;
        API.untickAnswers($scope.qcm);
    }

    $scope.verifyQCMIDUser = function() {
        return API.verifyChecksum($scope.main.QCMIDUser);
    }

    $scope.toggleCheck = function(answer) {
        if ($scope.navCollapsed && !$scope.main.checkAnswers) {
            answer.checked = !answer.checked;
        }
    }

    $scope.$watch("reloadQCM", function(newval, oldval) {
        if (newval) {
            $timeout(function() {
                $scope.reloadQCM = false;
                $scope.resetQCMDisplay();
                $scope.collapseNav();
                $scope.generateQCM();
                // TODO: check if OK to disable
                // $location.path("qcm");
                // $route.reload();
            },500);
        }
        $scope.updateExamVariables();
    })

    $scope.$watch('main.nbquestions.checked', function(newval, oldval) {
        if (newval != oldval) {
            $timeout(function() {
                $scope.resetQCMDisplay();
                $scope.updateQCMID();
                var limit = $scope.main.nbquestions.checked;
                if (limit === "Toutes") {
                    limit = 10000;
                }
                $scope.main.limit = limit;
            },100);
        }
    })

    $scope.$watch('main.level.checked', function(newval, oldval) {
        if (newval != oldval) {
            $timeout(function() {
                $scope.resetQCMDisplay();
                $scope.updateQCMID();
                $scope.main.search.num_niveau = $scope.main.level.options.indexOf($scope.main.level.checked);
            },100);
        }
    });

    $scope.$watch('main.typeExam.checked', function(newval, oldval) {
        if (newval != oldval) {
            $scope.updateExamVariables();
            // back from examPapierExaminateur, we want to erase the answers ticked
            if (!$scope.main.examPapierExaminateur)
                $scope.unfillQCMAnswers();
        }
    });

    $scope.$watch('main.QCMID', function(newval, oldval) {
        if (newval != oldval) {
            // reset dirtiness on form
            $scope.QCMIDUserForm.$setPristine();
            if ($scope.main.QCMIDUser != $scope.main.QCMID) {
                $scope.resetQCMIDUser();
            }
            $scope.main.QCMIDCRC = API.crc($scope.main.QCMID);
        }
    });

    $scope.$watch('main.formattedQCMIDUser', function(newval, oldval) {
        if (newval != oldval) {
            $scope.main.QCMIDUser = $filter('removeSpaces')(newval);
            $scope.main.formattedQCMIDUser = $filter('formatQCMID')($scope.main.QCMIDUser);
            if ($scope.main.QCMIDUser != $scope.main.QCMID  && API.verifyChecksum($scope.main.QCMIDUser)) {
                $scope.generateQCM($scope.main.QCMIDUser);
            }
        }
    });
 })

.controller('QCMCtrl', function($scope, $filter, $timeout, API, filterFilter) {
    $scope.main.checkAnswers = false;
    $scope.questions = [];
    $scope.$parent.resetQCMDisplay();
    $scope.$parent.hideNavbarButtons = false;

    $scope.getPoints = function(question) {
        var total = 0;
        for (var i = 0; i < question.ans.length; i++) {
            if (question.ans[i].checked) {
                total += parseInt(question.ans[i].pts);
            }
        }
        if (total < 0) {
            total = 0;
        }
        return total;
    }

    $scope.getScore = function() {
        var arr = filterFilter($scope.qcm, $scope.main.search);
        arr = $filter('limitTo')(arr, $scope.main.limit)
        var score = { user: 0, nb: 0, percentage: 0 };
        for(var i = 0; i < arr.length; i++){
            var question = arr[i];
            score.user += $scope.getPoints(question);
        }
        score.nb = i;
        score.total = i*6;
        if (score.total > 0) {
            score.percentage = Math.round(score.user / score.total * 100);
        }
        return score;
    }

    $scope.tickIfExamPapierExaminateur = function(answer) {
        if ($scope.main.examPapierExaminateur && answer.pts >=0)
            answer.checked = true;
    }

    $scope.successQuestion = function(question) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return ($scope.getPoints(question) === 6);
    }

    $scope.failedQuestion = function(question) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return ($scope.getPoints(question) === 0);
    }

    $scope.warningQuestion = function(question) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        var points = $scope.getPoints(question);
        return (points >= 1 && points <=5);
    }

    $scope.goodAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts >= 0 && answer.checked);
    }

    $scope.badAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts < 0 && answer.checked || answer.pts == 6 && !answer.checked);
    }

    $scope.warningAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts > 0 && answer.pts < 6 && !answer.checked);
    }

    $scope.goodNotCheckedAnswer = function(answer) {
        if ($scope.main.examPapier || !$scope.main.checkAnswers)
            return false;
        return (answer.pts < 0 && !answer.checked);
    }

    $scope.updateScore = function() {
        if ($scope.main.checkAnswers) {
            $scope.main.score = $scope.getScore();
        }
    }

    $scope.$watch('main.checkAnswers', function() {
        $scope.updateScore();
    })

})

.controller('SelfTestCtrl', function($scope, API) {
    $scope.$parent.loading = false;
	$scope.selftest = [];
	$scope.selftest.numitems   = 600;
	$scope.selftest.numruns    = 10000;
	$scope.selftest.showperrun = 60;

	$scope.selftest.qcm = [];
	for(var i = 1; i <= $scope.selftest.numitems; i++) {
		var obj = { question : i , ans : "x", shown : 0 };
		$scope.selftest.qcm.push(obj);
	}
//	console.log($scope.selftest.qcm);
	for(var i = 1; i <= $scope.selftest.numruns; i++){
//		console.log("run " + i );
		API.generateQCM($scope.selftest.qcm);
//		console.log($scope.selftest.qcm);
		for(var j = 0; j < $scope.main.nbquestions.checked ; j++){
			$scope.selftest.qcm[j].shown++;
		}
	}
	for(var i = 0; i < $scope.selftest.numitems; i++) {
		$scope.selftest.qcm[i].percent = (($scope.selftest.qcm[i].shown / $scope.selftest.numruns) * 100).toFixed(2);;
	}

})

.controller('AboutCtrl', function($scope) {
    $scope.$parent.navCollapsed = true;
    $scope.$parent.loading = false;
    $scope.$parent.hideNavbarButtons = true;

    document.body.scrollTop = document.documentElement.scrollTop = 0;
});
<|endoftext|>


<commit_before>/**
 * Copyright 2012 Palomino Labs, Inc.
 *
 * 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.
 */

/**
 * A proxy for communicating with StackMob's REST API.
 *
 * @author Tyler Wolf
 */
Ext.define("Ux.palominolabs.stackmob.data.proxy.StackMob", {
    extend: 'Ext.data.proxy.Rest',
    alias: 'proxy.stackmob',

    conn: Ux.palominolabs.stackmob.data.StackMobConnector,

    config: {
        // Disable cache busting, since StackMob rejects the GET params added by ServerProxy.
        noCache: false
    },

    /**
     * Specialized version of getHeaders which merges in the optional headers for StackMob
     * @return {Object} Headers
     */
    getHeaders: function(operation) {
        var me = this;
        return Ext.applyIf(me._headers || {}, me._getAdditionalHeaders(operation));
    },

    /**
     * Specialized version of getParams which returns an empty object
     * @private
     */
    getParams: function(operation) {
        return {};
    },

    /**
     * Specialized version of buildRequest which assembles the correct headers for StackMob.
     * @param {Ext.data.Operation} operation The {@link Ext.data.Operation Operation} object to execute
     * @return {Ext.data.Request} The request object
     */
    buildRequest: function(operation) {
        var me = this,
            params = Ext.applyIf(operation.getParams() || {}, me.getExtraParams() || {}),
            url = operation.getUrl(),
            headers = me.getHeaders(operation),
            request;

        params = Ext.applyIf(params, me.getParams(operation));

        request = Ext.create('Ext.data.Request', {
            headers  : headers,
            params   : params,
            action   : operation.getAction(),
            records  : operation.getRecords(),
            url      : url,
            operation: operation,
            proxy    : me
        });

        request.setUrl(me.buildUrl(request));

        operation.setRequest(request);
        return request;
    },

    /**
     * Specialized version of doRequest with operation-specific and request-specific headers
     * @protected
     */
    doRequest: function(operation, callback, scope) {
        var me = this,
            writer  = me.getWriter(),
            request = me.buildRequest(operation);

        request.setConfig({
            headers        : me.getHeaders(operation),
            timeout        : me.getTimeout(),
            method         : me.getMethod(request),
            callback       : me.createRequestCallback(request, operation, callback, scope),
            scope          : me
        });

        if (operation.getWithCredentials() || me.getWithCredentials()) {
            request.setWithCredentials(true);
        }

        // We now always have the writer prepare the request
        request = writer.write(request);

        // Use the StackMobAjax object, which will add any required StackMob authentication headers
        Ux.palominolabs.stackmob.StackMobAjax.request(request.getCurrentConfig());

        return request;
    },

    /**
     * Specialized version of encodeSorters which assembles the sorters into StackMob's desired format
     * @param {Ext.util.Sorter[]} sorters The array of {@link Ext.util.Sorter Sorter} objects
     * @return {String} The encoded sorters
     */
    encodeSorters: function(sorters) {
        var min = [],
            length = sorters.length,
            i = 0;

        for (; i < length; i++) {
            min[i] = [sorters[i].getProperty(), sorters[i].getDirection()].join(":");
        }
        return min.join(",");

    },

    /**
     * Assembles an object containing additional headers, such as paging
     * @param {Ext.data.Operation} operation The operation
     * @return {Object} Headers
     * @private
     */
    _getAdditionalHeaders: function(operation) {
        var me = this,
            headers = {},
            start = operation.getStart(),
            limit = operation.getLimit(),
            sorters = operation.getSorters(),
            end;

        if (me.getEnablePagingParams() && (start !== null) && (limit !== null)) {
            end = start + limit - 1;
            headers['Range'] = ['objects=', start, '-', end].join("");
        }

        if (sorters && sorters.length > 0) {
            headers['X-StackMob-OrderBy'] = me.encodeSorters(sorters);
        }

        return headers;
    }

});<commit_msg>After the previous refactor, it is no longer necessary to override buildRequest.<commit_after>/**
 * Copyright 2012 Palomino Labs, Inc.
 *
 * 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.
 */

/**
 * A proxy for communicating with StackMob's REST API.
 *
 * @author Tyler Wolf
 */
Ext.define("Ux.palominolabs.stackmob.data.proxy.StackMob", {
    extend: 'Ext.data.proxy.Rest',
    alias: 'proxy.stackmob',

    conn: Ux.palominolabs.stackmob.data.StackMobConnector,

    config: {
        // Disable cache busting, since StackMob rejects the GET params added by ServerProxy.
        noCache: false
    },

    /**
     * Specialized version of getHeaders which merges in the optional headers (operation-specific) for StackMob
     * @param {Ext.data.Operation} operation The operation
     * @return {Object} Headers
     */
    getHeaders: function(operation) {
        var me = this;
        return Ext.applyIf(me._headers || {}, me._getAdditionalHeaders(operation));
    },

    /**
     * Specialized version of getParams which returns an empty object
     * @private
     */
    getParams: function(operation) {
        return {};
    },

    /**
     * Specialized version of doRequest with operation-specific and request-specific headers
     * @protected
     */
    doRequest: function(operation, callback, scope) {
        var me = this,
            writer  = me.getWriter(),
            request = me.buildRequest(operation);

        request.setConfig({
            headers        : me.getHeaders(operation),
            timeout        : me.getTimeout(),
            method         : me.getMethod(request),
            callback       : me.createRequestCallback(request, operation, callback, scope),
            scope          : me
        });

        if (operation.getWithCredentials() || me.getWithCredentials()) {
            request.setWithCredentials(true);
        }

        // We now always have the writer prepare the request
        request = writer.write(request);

        // Use the StackMobAjax object, which will add any required StackMob authentication headers
        Ux.palominolabs.stackmob.StackMobAjax.request(request.getCurrentConfig());

        return request;
    },

    /**
     * Specialized version of encodeSorters which assembles the sorters into StackMob's desired format
     * @param {Ext.util.Sorter[]} sorters The array of {@link Ext.util.Sorter Sorter} objects
     * @return {String} The encoded sorters
     */
    encodeSorters: function(sorters) {
        var min = [],
            length = sorters.length,
            i = 0;

        for (; i < length; i++) {
            min[i] = [sorters[i].getProperty(), sorters[i].getDirection()].join(":");
        }
        return min.join(",");

    },

    /**
     * Assembles an object containing additional headers, such as paging
     * @param {Ext.data.Operation} operation The operation
     * @return {Object} Headers
     * @private
     */
    _getAdditionalHeaders: function(operation) {
        var me = this,
            headers = {},
            start = operation.getStart(),
            limit = operation.getLimit(),
            sorters = operation.getSorters(),
            end;

        if (me.getEnablePagingParams() && (start !== null) && (limit !== null)) {
            end = start + limit - 1;
            headers['Range'] = ['objects=', start, '-', end].join("");
        }

        if (sorters && sorters.length > 0) {
            headers['X-StackMob-OrderBy'] = me.encodeSorters(sorters);
        }

        return headers;
    }

});<|endoftext|>


<commit_before>/**
 * Widget to that routes to the narrative interface, or creates new naarratives for you
 *
 * @author Michael Sneddon <mwsneddon@lbl.gov>
 * @public
 */
(function( $, undefined ) {

    $.KBWidget({
        name: "kbaseNarrativeManager",
        parent: "kbaseAuthenticatedWidget",
        version: "1.0.0",

	/*
	params should have the following fields:

	action: start | new

	*/
        options: {
	    loadingImage: "assets/img/ajax-loader.gif",
            ws_url: "https://kbase.us/services/ws",
            nms_url: "https://kbase.us/services/narrative_method_store/rpc",
            params: null
        },

        manager:null,

        ws_name: null,
        nar_name: null,

        $mainPanel: null,
        $newNarrativeLink: null, // when a new narrative is created, gives a place to link to it

        init: function(options) {
            this._super(options);

	    // must be logged in!
	    if (!this._attributes.auth) { window.location.replace("#/login/"); }
	    if (!this._attributes.auth.token) { window.location.replace("#/login/"); }
	    if (!this._attributes.auth.user_id) { window.location.replace("#/login/"); }

            this.$mainPanel = $('
').css({'height':'300px'}).append(' loading...');
            this.$elem.append(this.$mainPanel);

            this.manager = new NarrativeManager({ws_url:this.options.ws_url, nms_url:this.options.nms_url},this._attributes.auth);

	    this.determineActionAndDoIt();

            return this;
        },

	determineActionAndDoIt: function() {
	    var self = this;
	    if (self.options.params) {
		// START - load up last narrative, or start the user's first narrative
		if (self.options.params.action === 'start') {
		    self.manager.detectStartSettings(self.options.params,
			function(result) {
			    console.log(result);
			    if (result.last_narrative) {
				// we have a last_narrative, so go there
				//console.log('should redirect...');
				self.$mainPanel.html('redirecting to /narrative/ws.'+result.last_narrative.ws_info[0]+'.obj.'+result.last_narrative.nar_info[0]+'');
				window.location.replace("/narrative/ws."+result.last_narrative.ws_info[0]+".obj."+result.last_narrative.nar_info[0]);
			    } else {
				// we need to construct a new narrative- we have a first timer
				self.manager.createTempNarrative(
				    { cells:[],parameters:[],importData : [] },
				    function(info) {
					var newWsId = info.nar_info[6];
					var newNarId = info.nar_info[0];
					self.$mainPanel.html('redirecting to /narrative/ws.'+newWsId+'.obj.'+newNarId+'');
					window.location.replace("/narrative/ws."+newWsId+".obj."+newNarId);
				    },
				    function(error) {
					console.error(error);
					$mainPanel.html('Unexpected error in loading KBase.');
				    }
				);
			    }
			},
			function(error) {
			    console.error(error);
			});
		} else if (self.options.params.action === 'new') {

		    var importData = null;
		    if (self.options.params.copydata) {
			importData = self.options.params.copydata.split(';');
		    }

		    var cells=[];
		    if (self.options.params.app) {
			cells = [ {app:self.options.params.app} ];
		    }
		    self.manager.createTempNarrative(
				    { cells:cells,parameters:[],importData : importData },
				    function(info) {
					var newWsId = info.nar_info[6];
					var newNarId = info.nar_info[0];
					self.$mainPanel.html('redirecting to /narrative/ws.'+newWsId+'.obj.'+newNarId+'');
					window.location.replace("/narrative/ws."+newWsId+".obj."+newNarId);
				    },
				    function(error) {
					console.error(error);
					$mainPanel.html('Unexpected error in loading KBase.');
				    }
				);
		} else {
		    self.$mainPanel.html('action "'+self.options.params.action+'" not supported; only "start" or "new" accepted.');
		}

		// else do something if action isn't correct!!

	    } // else do something if params weren't defined!!
	}
    });

})( jQuery );
<commit_msg>Clean up narrative manager whitespace<commit_after>/**
 * Widget to that routes to the narrative interface, or creates new narratives for you
 *
 * @author Michael Sneddon <mwsneddon@lbl.gov>
 * @public
 */
(function( $, undefined ) {

    $.KBWidget({
        name: "kbaseNarrativeManager",
        parent: "kbaseAuthenticatedWidget",
        version: "1.0.0",

        /*
          params should have the following fields:

          action: start | new
         */
        options: {
            loadingImage: "assets/img/ajax-loader.gif",
            nms_url: "https://kbase.us/services/narrative_method_store/rpc",
            ws_url: "https://kbase.us/services/ws",
//            ws_url: "https://dev03.berkeley.kbase.us/services/ws",
            params: null
        },

        manager:null,

        ws_name: null,
        nar_name: null,

        $mainPanel: null,
        $newNarrativeLink: null, // when a new narrative is created, gives a place to link to it

        init: function(options) {
            this._super(options);

            // must be logged in!
            if (!this._attributes.auth) {
                window.location.replace("#/login/");
            }
            if (!this._attributes.auth.token) {
                window.location.replace("#/login/");
            }
            if (!this._attributes.auth.user_id) {
                window.location.replace("#/login/");
            }

            this.$mainPanel = $('
').css({'height': '300px'})
                    .append(' loading...');
            this.$elem.append(this.$mainPanel);

            this.manager = new NarrativeManager({ws_url:this.options.ws_url,
                nms_url:this.options.nms_url},this._attributes.auth);

            this.determineActionAndDoIt();

            return this;
        },

        determineActionAndDoIt: function() {
            var self = this;
            if (self.options.params) {
                // START - load up last narrative, or start the user's first narrative
                if (self.options.params.action === 'start') {
                    self.manager.detectStartSettings(self.options.params,
                            function(result) {
                                console.log(result);
                                if (result.last_narrative) {
                                    // we have a last_narrative, so go there
                                    //console.log('should redirect...');
                                    self.$mainPanel.html(
                                            'redirecting to /narrative/ws.' +
                                            result.last_narrative.ws_info[0] +
                                            '.obj.' +
                                            result.last_narrative.nar_info[0] +
                                            '');
                                    window.location.replace("/narrative/ws." +
                                            result.last_narrative.ws_info[0] +
                                            ".obj." +
                                            result.last_narrative.nar_info[0]);
                                } else {
                                    //we need to construct a new narrative- we have a first timer
                                    self.manager.createTempNarrative(
                                            { cells:[],parameters:[],importData : [] },
                                            function(info) {
                                                var newWsId = info.nar_info[6];
                                                var newNarId = info.nar_info[0];
                                                self.$mainPanel.html(
                                                        'redirecting to /narrative/ws.' +
                                                        newWsId + '.obj.' +
                                                        newNarId + '');
                                                window.location.replace(
                                                        "/narrative/ws." +
                                                        newWsId + ".obj." +
                                                        newNarId);
                                            },
                                            function(error) {
                                                console.error(error);
                                                $mainPanel.html(
                                                        'Unexpected error in loading KBase.');
                                            }
                                    );
                                }
                        },
                        function(error) {
                            console.error(error);
                        });
                } else if (self.options.params.action === 'new') {

                    var importData = null;
                    if (self.options.params.copydata) {
                        importData = self.options.params.copydata.split(';');
                    }

                    var cells=[];
                    if (self.options.params.app) {
                        cells = [ {app:self.options.params.app} ];
                    }
                    self.manager.createTempNarrative(
                            { cells:cells,parameters:[],importData : importData },
                            function(info) {
                                var newWsId = info.nar_info[6];
                                var newNarId = info.nar_info[0];
                                self.$mainPanel.html(
                                        'redirecting to /narrative/ws.' + newWsId + '.obj.' +
                                        newNarId + '');
                                window.location.replace(
                                        "/narrative/ws." + newWsId + ".obj." +
                                        newNarId);
                            },
                            function(error) {
                                console.error(error);
                                $mainPanel.html(
                                        'Unexpected error in loading KBase.');
                            }
                    );
                } else {
                    self.$mainPanel.html('action "' +
                            self.options.params.action +
                            '" not supported; only "start" or "new" accepted.');
                }

                // else do something if action isn't correct!!

            } // else do something if params weren't defined!!
        }
    });

})( jQuery );
<|endoftext|>


<commit_before>/*jshint node:true*/
/*global test, suite, setup, teardown*/

'use strict';

var assert = require('assert');
var tika = require('../');

suite('document tests', function() {
	test('text content-type', function(done) {
		tika.contentType('test/data/file.txt', function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain');
			done();
		});
	});

	test('text content-type and charset', function(done) {
		tika.contentType('test/data/file.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=ISO-8859-1');
			done();
		});
	});

	test('extract from txt', function(done) {
		tika.text('test/data/file.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n\n');
			done();
		});
	});

	test('extract meta from txt', function(done) {
		tika.meta('test/data/file.txt', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.txt']);
			assert.deepEqual(meta['Content-Type'], ['text/plain; charset=ISO-8859-1']);
			assert.deepEqual(meta['Content-Encoding'], ['ISO-8859-1']);
			done();
		});
	});

	test('extract from extensionless txt', function(done) {
		tika.text('test/data/extensionless/txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n\n');
			done();
		});
	});

	test('extract from doc', function(done) {
		tika.text('test/data/file.doc', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract meta from doc', function(done) {
		tika.meta('test/data/file.doc', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.doc']);
			assert.deepEqual(meta['Content-Type'], ['application/msword']);
			assert.deepEqual(meta['dcterms:created'], ['2013-12-06T21:15:26Z']);
			done();
		});
	});

	test('extract from extensionless doc', function(done) {
		tika.text('test/data/extensionless/doc', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract from docx', function(done) {
		tika.text('test/data/file.docx', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract meta from docx', function(done) {
		tika.meta('test/data/file.docx', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.docx']);
			assert.deepEqual(meta['Content-Type'], ['application/vnd.openxmlformats-officedocument.wordprocessingml.document']);
			assert.deepEqual(meta['Application-Name'], ['LibreOffice/4.1.3.2$MacOSX_x86 LibreOffice_project/70feb7d99726f064edab4605a8ab840c50ec57a']);
			done();
		});
	});

	test('extract from extensionless docx', function(done) {
		tika.text('test/data/extensionless/docx', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract meta from extensionless docx', function(done) {
		tika.meta('test/data/extensionless/docx', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['docx']);
			assert.deepEqual(meta['Content-Type'], ['application/vnd.openxmlformats-officedocument.wordprocessingml.document']);
			assert.deepEqual(meta['Application-Name'], ['LibreOffice/4.1.3.2$MacOSX_x86 LibreOffice_project/70feb7d99726f064edab4605a8ab840c50ec57a']);
			done();
		});
	});

	test('extract from pdf', function(done) {
		tika.text('test/data/file.pdf', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'Just some text.');
			done();
		});
	});

	test('extract meta from pdf', function(done) {
		tika.meta('test/data/file.pdf', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.pdf']);
			assert.deepEqual(meta['Content-Type'], ['application/pdf']);
			assert.deepEqual(meta.producer, ['LibreOffice 4.1']);
			done();
		});
	});

	test('extract from extensionless pdf', function(done) {
		tika.text('test/data/extensionless/pdf', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'Just some text.');
			done();
		});
	});

	test('extract meta from extensionless pdf', function(done) {
		tika.meta('test/data/extensionless/pdf', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['pdf']);
			assert.deepEqual(meta['Content-Type'], ['application/pdf']);
			assert.deepEqual(meta.producer, ['LibreOffice 4.1']);
			done();
		});
	});

	test('extract from protected pdf', function(done) {
		tika.text('test/data/protected/file.pdf', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'Just some text.');
			done();
		});
	});

	test('extract meta from protected pdf', function(done) {
		tika.meta('test/data/protected/file.pdf', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.pdf']);
			assert.deepEqual(meta['Content-Type'], ['application/pdf']);
			assert.deepEqual(meta.producer, ['LibreOffice 4.1']);
			done();
		});
	});
});

suite('obscure document tests', function() {
	test('extract from Word 2003 XML', function(done) {
		tika.text('test/data/obscure/word2003.xml', function(err, text) {
			assert.ifError(err);
			assert.ok(-1 !== text.indexOf('Just some text.'));
			assert.ok(-1 === text.indexOf('<?xml'));
			done();
		});
	});
});

suite('structured data tests', function() {
	test('extract from plain XML', function(done) {
		tika.text('test/data/structured/plain.xml', function(err, text) {
			assert.ifError(err);
			assert.ok(-1 !== text.indexOf('Just some text.'));
			assert.ok(-1 === text.indexOf('<?xml'));
			done();
		});
	});
});

suite('image tests', function() {
	test('extract from png', function(done) {
		tika.text('test/data/file.png', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract from extensionless png', function(done) {
		tika.text('test/data/extensionless/png', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract from gif', function(done) {
		tika.text('test/data/file.gif', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract meta from gif', function(done) {
		tika.meta('test/data/file.gif', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.gif']);
			assert.deepEqual(meta['Content-Type'], ['image/gif']);
			assert.deepEqual(meta['Dimension ImageOrientation'], ['Normal']);
			done();
		});
	});

	test('extract from extensionless gif', function(done) {
		tika.text('test/data/extensionless/gif', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract meta from extensionless gif', function(done) {
		tika.meta('test/data/extensionless/gif', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['gif']);
			assert.deepEqual(meta['Content-Type'], ['image/gif']);
			assert.deepEqual(meta['Dimension ImageOrientation'], ['Normal']);
			done();
		});
	});
});

suite('non-utf8 encoded document tests', function() {
	test('extract Windows Latin 1 text', function(done) {
		tika.text('test/data/nonutf8/windows-latin1.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Algún pequeño trozo de texto.\n\n');
			done();
		});
	});

	test('Windows Latin 1 text content-type and charset', function(done) {
		tika.contentType('test/data/nonutf8/windows-latin1.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=ISO-8859-1');
			done();
		});
	});

	test('extract UTF-16 English-language text', function(done) {
		tika.text('test/data/nonutf8/utf16-english.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n\n');
			done();
		});
	});

	test('UTF-16 English-language text content-type and charset', function(done) {
		tika.contentType('test/data/nonutf8/utf16-english.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=UTF-16LE');
			done();
		});
	});

	test('extract UTF-16 Chinese (Simplified) text', function(done) {
		tika.text('test/data/nonutf8/utf16-chinese.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '\u53ea\u662f\u4e00\u4e9b\u6587\u5b57\u3002\n\n');
			done();
		});
	});

	test('UTF-16 Chinese (Simplified) text content-type and charset', function(done) {
		tika.contentType('test/data/nonutf8/utf16-chinese.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=UTF-16LE');
			done();
		});
	});
});

suite('archive tests', function() {
	test('compressed archive test', function(done) {
		tika.text('test/data/archive/files.zip', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'file1.txt\nSome text 1.\n\n\n\n\nfile2.txt\nSome text 2.\n\n\n\n\nfile3.txt\nSome text 3.');
			done();
		});
	});

	test('twice compressed archive test', function(done) {
		tika.text('test/data/archive/files-files.zip', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'file4.txt\nSome text 4.\n\n\n\n\nfile5.txt\nSome text 5.\n\n\n\n\nfile6.txt\nSome text 6.\n\n\n\n\nfiles.zip\n\n\nfile1.txt\n\nSome text 1.\n\n\n\n\n\n\n\nfile2.txt\n\nSome text 2.\n\n\n\n\n\n\n\nfile3.txt\n\nSome text 3.');
			done();
		});
	});
});

suite('error handling tests', function() {
	test('extract from encrypted doc', function(done) {
		tika.text('test/data/encrypted/file.doc', function(err, text) {
			assert.ok(err);
			assert.ok(-1 !== err.toString().indexOf('EncryptedDocumentException: Cannot process encrypted word file'));
			done();
		});
	});

	test('extract from encrypted pdf', function(done) {
		tika.text('test/data/encrypted/file.pdf', function(err, text) {
			assert.ok(err);
			assert.ok(-1 !== err.toString().indexOf('WrappedIOException: Error decrypting document'));
			done();
		});
	});
});
<commit_msg>Add zip content-type test<commit_after>/*jshint node:true*/
/*global test, suite, setup, teardown*/

'use strict';

var assert = require('assert');
var tika = require('../');

suite('document tests', function() {
	test('detect txt content-type', function(done) {
		tika.contentType('test/data/file.txt', function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain');
			done();
		});
	});

	test('detect txt content-type and charset', function(done) {
		tika.contentType('test/data/file.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=ISO-8859-1');
			done();
		});
	});

	test('extract from txt', function(done) {
		tika.text('test/data/file.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n\n');
			done();
		});
	});

	test('extract meta from txt', function(done) {
		tika.meta('test/data/file.txt', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.txt']);
			assert.deepEqual(meta['Content-Type'], ['text/plain; charset=ISO-8859-1']);
			assert.deepEqual(meta['Content-Encoding'], ['ISO-8859-1']);
			done();
		});
	});

	test('extract from extensionless txt', function(done) {
		tika.text('test/data/extensionless/txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n\n');
			done();
		});
	});

	test('extract from doc', function(done) {
		tika.text('test/data/file.doc', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract meta from doc', function(done) {
		tika.meta('test/data/file.doc', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.doc']);
			assert.deepEqual(meta['Content-Type'], ['application/msword']);
			assert.deepEqual(meta['dcterms:created'], ['2013-12-06T21:15:26Z']);
			done();
		});
	});

	test('extract from extensionless doc', function(done) {
		tika.text('test/data/extensionless/doc', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract from docx', function(done) {
		tika.text('test/data/file.docx', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract meta from docx', function(done) {
		tika.meta('test/data/file.docx', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.docx']);
			assert.deepEqual(meta['Content-Type'], ['application/vnd.openxmlformats-officedocument.wordprocessingml.document']);
			assert.deepEqual(meta['Application-Name'], ['LibreOffice/4.1.3.2$MacOSX_x86 LibreOffice_project/70feb7d99726f064edab4605a8ab840c50ec57a']);
			done();
		});
	});

	test('extract from extensionless docx', function(done) {
		tika.text('test/data/extensionless/docx', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n');
			done();
		});
	});

	test('extract meta from extensionless docx', function(done) {
		tika.meta('test/data/extensionless/docx', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['docx']);
			assert.deepEqual(meta['Content-Type'], ['application/vnd.openxmlformats-officedocument.wordprocessingml.document']);
			assert.deepEqual(meta['Application-Name'], ['LibreOffice/4.1.3.2$MacOSX_x86 LibreOffice_project/70feb7d99726f064edab4605a8ab840c50ec57a']);
			done();
		});
	});

	test('extract from pdf', function(done) {
		tika.text('test/data/file.pdf', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'Just some text.');
			done();
		});
	});

	test('extract meta from pdf', function(done) {
		tika.meta('test/data/file.pdf', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.pdf']);
			assert.deepEqual(meta['Content-Type'], ['application/pdf']);
			assert.deepEqual(meta.producer, ['LibreOffice 4.1']);
			done();
		});
	});

	test('extract from extensionless pdf', function(done) {
		tika.text('test/data/extensionless/pdf', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'Just some text.');
			done();
		});
	});

	test('extract meta from extensionless pdf', function(done) {
		tika.meta('test/data/extensionless/pdf', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['pdf']);
			assert.deepEqual(meta['Content-Type'], ['application/pdf']);
			assert.deepEqual(meta.producer, ['LibreOffice 4.1']);
			done();
		});
	});

	test('extract from protected pdf', function(done) {
		tika.text('test/data/protected/file.pdf', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'Just some text.');
			done();
		});
	});

	test('extract meta from protected pdf', function(done) {
		tika.meta('test/data/protected/file.pdf', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.pdf']);
			assert.deepEqual(meta['Content-Type'], ['application/pdf']);
			assert.deepEqual(meta.producer, ['LibreOffice 4.1']);
			done();
		});
	});
});

suite('obscure document tests', function() {
	test('extract from Word 2003 XML', function(done) {
		tika.text('test/data/obscure/word2003.xml', function(err, text) {
			assert.ifError(err);
			assert.ok(-1 !== text.indexOf('Just some text.'));
			assert.ok(-1 === text.indexOf('<?xml'));
			done();
		});
	});
});

suite('structured data tests', function() {
	test('extract from plain XML', function(done) {
		tika.text('test/data/structured/plain.xml', function(err, text) {
			assert.ifError(err);
			assert.ok(-1 !== text.indexOf('Just some text.'));
			assert.ok(-1 === text.indexOf('<?xml'));
			done();
		});
	});
});

suite('image tests', function() {
	test('extract from png', function(done) {
		tika.text('test/data/file.png', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract from extensionless png', function(done) {
		tika.text('test/data/extensionless/png', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract from gif', function(done) {
		tika.text('test/data/file.gif', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract meta from gif', function(done) {
		tika.meta('test/data/file.gif', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['file.gif']);
			assert.deepEqual(meta['Content-Type'], ['image/gif']);
			assert.deepEqual(meta['Dimension ImageOrientation'], ['Normal']);
			done();
		});
	});

	test('extract from extensionless gif', function(done) {
		tika.text('test/data/extensionless/gif', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '');
			done();
		});
	});

	test('extract meta from extensionless gif', function(done) {
		tika.meta('test/data/extensionless/gif', function(err, meta) {
			assert.ifError(err);
			assert.ok(meta);
			assert.deepEqual(meta.resourceName, ['gif']);
			assert.deepEqual(meta['Content-Type'], ['image/gif']);
			assert.deepEqual(meta['Dimension ImageOrientation'], ['Normal']);
			done();
		});
	});
});

suite('non-utf8 encoded document tests', function() {
	test('extract Windows Latin 1 text', function(done) {
		tika.text('test/data/nonutf8/windows-latin1.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Algún pequeño trozo de texto.\n\n');
			done();
		});
	});

	test('Windows Latin 1 text content-type and charset', function(done) {
		tika.contentType('test/data/nonutf8/windows-latin1.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=ISO-8859-1');
			done();
		});
	});

	test('extract UTF-16 English-language text', function(done) {
		tika.text('test/data/nonutf8/utf16-english.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, 'Just some text.\n\n');
			done();
		});
	});

	test('UTF-16 English-language text content-type and charset', function(done) {
		tika.contentType('test/data/nonutf8/utf16-english.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=UTF-16LE');
			done();
		});
	});

	test('extract UTF-16 Chinese (Simplified) text', function(done) {
		tika.text('test/data/nonutf8/utf16-chinese.txt', function(err, text) {
			assert.ifError(err);
			assert.equal(text, '\u53ea\u662f\u4e00\u4e9b\u6587\u5b57\u3002\n\n');
			done();
		});
	});

	test('UTF-16 Chinese (Simplified) text content-type and charset', function(done) {
		tika.contentType('test/data/nonutf8/utf16-chinese.txt', true, function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'text/plain; charset=UTF-16LE');
			done();
		});
	});
});

suite('archive tests', function() {
	test('extract from compressed archive', function(done) {
		tika.text('test/data/archive/files.zip', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'file1.txt\nSome text 1.\n\n\n\n\nfile2.txt\nSome text 2.\n\n\n\n\nfile3.txt\nSome text 3.');
			done();
		});
	});

	test('detect compressed archive content-type', function(done) {
		tika.contentType('test/data/archive/files.zip', function(err, contentType) {
			assert.ifError(err);
			assert.equal(contentType, 'application/zip');
			done();
		});
	});

	test('extract from twice compressed archive', function(done) {
		tika.text('test/data/archive/files-files.zip', function(err, text) {
			assert.ifError(err);
			assert.equal(text.trim(), 'file4.txt\nSome text 4.\n\n\n\n\nfile5.txt\nSome text 5.\n\n\n\n\nfile6.txt\nSome text 6.\n\n\n\n\nfiles.zip\n\n\nfile1.txt\n\nSome text 1.\n\n\n\n\n\n\n\nfile2.txt\n\nSome text 2.\n\n\n\n\n\n\n\nfile3.txt\n\nSome text 3.');
			done();
		});
	});
});

suite('error handling tests', function() {
	test('extract from encrypted doc', function(done) {
		tika.text('test/data/encrypted/file.doc', function(err, text) {
			assert.ok(err);
			assert.ok(-1 !== err.toString().indexOf('EncryptedDocumentException: Cannot process encrypted word file'));
			done();
		});
	});

	test('extract from encrypted pdf', function(done) {
		tika.text('test/data/encrypted/file.pdf', function(err, text) {
			assert.ok(err);
			assert.ok(-1 !== err.toString().indexOf('WrappedIOException: Error decrypting document'));
			done();
		});
	});
});
<|endoftext|>