<commit_before>var express = require('express');
var fs = require('fs');
var moment = require('moment');
var submission = require('./lib/submission');
var router = express.Router();

router.get('/', function (req, res) {
    'use strict';
    var astats, s = '\n' + Array(32).join('-'),
        user = req.query.user,
        assign = req.query.assign,
        apath = req.query.path,
        date = +new Date();
    res.send('Submission received. Processing...\n');
    if (!user || !assign || !apath ||
        !fs.existsSync(apath) || !(astats = submission.getStats(assign))) {
        submission.addError('Bad submission request from: ' + user, req.query);
        res.send(s + '\nSubmission failed! 400: Bad Request' + s + '\n\n');
    } else {
        res.send('Saving submission (may take a minute)...\n');
        submission.addSubmission(astats, user, assign, apath, date).then(function (sub) {
            s += 'Submission for `' + sub.assign + '` Succeeded!\n';
            s += (sub.count) ? 'Re-submission #' + sub.count : 'First submission';
            s += ' : ' + moment(sub.date).format("DD MMM YY @ HH:mm") + '\n';
            s += (sub.isDir) ? 'Submitted Directory: ' : 'Submitted File: ';
            s += sub.fullpath + '\n' + Array(32).join('-') + '\n\n';
            res.send(s);
        }, function (err) {
            submission.addError('Submission failed: ' + JSON.stringify({
                    user: user,
                    assignment: assign,
                    path: apath,
                    error: err
                }));
            res.send(s + '\nSubmission failed! 500 Internal Server Error' + s + '\n\n');
        });
    }
});<commit_msg>Bad require fix<commit_after>var express = require('express');
var fs = require('fs');
var moment = require('moment');
var submission = require('../lib/submission');
var router = express.Router();

router.get('/', function (req, res) {
    'use strict';
    var astats, s = '\n' + Array(32).join('-'),
        user = req.query.user,
        assign = req.query.assign,
        apath = req.query.path,
        date = +new Date();
    res.send('Submission received. Processing...\n');
    if (!user || !assign || !apath ||
        !fs.existsSync(apath) || !(astats = submission.getStats(assign))) {
        submission.addError('Bad submission request from: ' + user, req.query);
        res.send(s + '\nSubmission failed! 400: Bad Request' + s + '\n\n');
    } else {
        res.send('Saving submission (may take a minute)...\n');
        submission.addSubmission(astats, user, assign, apath, date).then(function (sub) {
            s += 'Submission for `' + sub.assign + '` Succeeded!\n';
            s += (sub.count) ? 'Re-submission #' + sub.count : 'First submission';
            s += ' : ' + moment(sub.date).format("DD MMM YY @ HH:mm") + '\n';
            s += (sub.isDir) ? 'Submitted Directory: ' : 'Submitted File: ';
            s += sub.fullpath + '\n' + Array(32).join('-') + '\n\n';
            res.send(s);
        }, function (err) {
            submission.addError('Submission failed: ' + JSON.stringify({
                    user: user,
                    assignment: assign,
                    path: apath,
                    error: err
                }));
            res.send(s + '\nSubmission failed! 500 Internal Server Error' + s + '\n\n');
        });
    }
});
<|endoftext|>


<commit_before>var chai = require('chai'),
    expect = chai.expect,
    jKif = require('../../../../lib/jkif'),
    ast = require('../../../../lib/ast_constructors/ast_constructors'),
    tt = require('../../../../lib/truth_trees/truth_trees');

describe('#constructTree helper method', function() {

  var parsed = jKif.Parser.parse('');
      // kb = jKif.Utility.knowledgeBase(parsed),
      // ttSent = new tt.TruthTreeSent(kb),
      // constructTreeReturn = ttSent.tree; // constructTree sets ttSent.tree

  var atomicKb = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (and (instance ?CLARK Human)(sexy ?CLARK)))'));
  var ttSentAtomic = new tt.TruthTreeSent(atomicKb);

  console.log(ttSentAtomic.openStacks[0]);
  // it('should return an instance of an Object', function() {
  //   expect(constructTreeReturn).to.be.an.instanceof(Object);
  // });

  // it('should return an Object with trunk, paths, step count, and prop map', function() {
  //   expect(constructTreeReturn).to.have.all.keys(['trunk', 'paths', 'stepCount', 'propMap']);
  // });

  // it('should return a tree with a stepCount of 0 for empty knowledgebase inputs', function() {
  //   expect(constructTreeReturn.stepCount).to.equal(0);
  // });

  // it('should return a tree with a stepCount of 1 for knowledgebase inputs with a single atomic sentence', function() {
  //   var atomicKb = jKif.Utility.knowledgeBase(jKif.Parser.parse('(instance ?CLARK Human)'));
  //   var ttSentAtomic = new tt.TruthTreeSent(atomicKb);
  //   expect(ttSentAtomic.tree.stepCount).to.equal(1);
  // });

  // it('should return a tree with a stepCount of 1 for knowledgebase inputs with a single negation of an atomic sentence', function() {
  //   var atomicNegationKb = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (instance ?CLARK Human))'));
  //   var ttSentAtomicNegation = new tt.TruthTreeSent(atomicNegationKb);
  //   expect(ttSentAtomicNegation.tree.stepCount).to.equal(1);
  // });

  // it('should return a tree with a stepCount of 1 for knowledgebase inputs with a single negation of a molecular negated sentence', function() {
  //   var atomicNegationKb = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (not (instance ?CLARK Human)))'));
  //   var ttSentAtomicNegation = new tt.TruthTreeSent(atomicNegationKb);
  //   expect(ttSentAtomicNegation.tree.stepCount).to.equal(1);
  // });

  // it('should return a tree with the correct open path truth values for nested negations', function() {
  //   var nest1 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (instance ?CLARK Human))'));
  //   var ttSentNest1 = new tt.TruthTreeSent(nest1);
  //   expect(ttSentNest1.tree.paths.open[0].value).to.be.false;
  //   var nest2 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (not (instance ?CLARK Human)))'));
  //   var ttSentNest2 = new tt.TruthTreeSent(nest2);
  //   expect(ttSentNest2.tree.paths.open[0].value).to.be.true;
  //   var nest3 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (not (not (instance ?CLARK Human))))'));
  //   var ttSentNest3 = new tt.TruthTreeSent(nest3);
  //   expect(ttSentNest3.tree.paths.open[0].value).to.be.false;
  //   var nest4 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (not (not (not (instance ?CLARK Human)))))'));
  //   var ttSentNest4 = new tt.TruthTreeSent(nest4);
  //   expect(ttSentNest4.tree.paths.open[0].value).to.be.true;
  // });

  // it('should return a tree with a stepCount of 2 for knowledgebase inputs with a single conjunction sentence', function() {
  //   var conj = jKif.Utility.knowledgeBase(jKif.Parser.parse('(and (instance ?CLARK Human)(subclass Human Entity))'));
  //   var ttConj = new tt.TruthTreeSent(conj);
  //   expect(ttConj.tree.stepCount).to.equal(2);
  // });

  // it('should return a tree with a stepCount of 2 for knowledgebase inputs with a single disjunction sentence', function() {
  //   var dis = jKif.Utility.knowledgeBase(jKif.Parser.parse('(OR (instance ?CLARK Human)(subclass Human Entity))'));
  //   var ttDis = new tt.TruthTreeSent(dis);
  //   expect(ttDis.tree.stepCount).to.equal(2);
  // });

  // it('should return a tree with the correct open path truth values for negated conjunctions', function() {
  //   var negConj = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (and (instance ?CLARK Human)(subclass Human Entity)))'));
  //   var ttNegConj = new tt.TruthTreeSent(negConj);
  //   expect(ttNegConj.tree.paths.open[0].value).to.be.false;
  //   expect(ttNegConj.tree.paths.open[1].value).to.be.false;
  // });

  // it('should return a tree with the correct open path truth values for negated disjunctions', function() {
  //   var negDis = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (or (instance ?CLARK Human)(subclass Human Entity)))'));
  //   var ttNegDis = new tt.TruthTreeSent(negDis);
  //   expect(ttNegDis.tree.paths.open[0].value).to.be.false;
  //   expect(ttNegDis.tree.paths.open[1].value).to.be.false;
  // });

  // it('should return a tree with the correct open path truth values for nested negated conjunctions', function() {
  //   var negConj = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (and (not (instance ?CLARK Human))(subclass Human Entity)))'));
  //   var ttNegConj = new tt.TruthTreeSent(negConj);
  //   expect(ttNegConj.tree.paths.open[0].value).to.be.true;
  //   expect(ttNegConj.tree.paths.open[1].value).to.be.false;
  //   var negConj2 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(and (not (instance ?CLARK Human))(subclass Human Entity))'));
  //   var ttNegConj2 = new tt.TruthTreeSent(negConj2);
  //   expect(ttNegConj2.tree.paths.open[0].value).to.be.false;
  //   expect(ttNegConj2.tree.paths.open[1].value).to.be.true;
  //   var negConj3 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(and (not (instance ?CLARK Human))(not (subclass Human Entity)))'));
  //   var ttNegConj3 = new tt.TruthTreeSent(negConj3);
  //   expect(ttNegConj3.tree.paths.open[0].value).to.be.false;
  //   expect(ttNegConj3.tree.paths.open[1].value).to.be.false;
  // });

  // it('should return a tree with the correct open path truth values for nested negated disjunctions', function() {
  //   var negDis = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (or(not (instance ?CLARK Human))(subclass Human Entity)))'));
  //   var ttNegDis = new tt.TruthTreeSent(negDis);
  //   expect(ttNegDis.tree.paths.open[0].value).to.be.true;
  //   expect(ttNegDis.tree.paths.open[1].value).to.be.false;
  //   var negDis2 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(or (not (instance ?CLARK Human))(subclass Human Entity))'));
  //   var ttNegDis2 = new tt.TruthTreeSent(negDis2);
  //   expect(ttNegDis2.tree.paths.open[0].value).to.be.false;
  //   expect(ttNegDis2.tree.paths.open[1].value).to.be.true;
  //   var negDis3 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(or (not (instance ?CLARK Human))(not (subclass Human Entity)))'));
  //   var ttNegDis3 = new tt.TruthTreeSent(negDis3);
  //   expect(ttNegDis3.tree.paths.open[0].value).to.be.false;
  //   expect(ttNegDis3.tree.paths.open[1].value).to.be.false;
  // });

  // it('should return a tree with a stepCount of 2 for knowledgebase inputs with a single implication sentence (atoms for ant and consq)', function() {
  //   var imp = jKif.Utility.knowledgeBase(jKif.Parser.parse('(=> (instance ?CLARK Human)(subclass Human Entity))'));
  //   var ttImp = new tt.TruthTreeSent(imp);
  //   expect(ttImp.tree.stepCount).to.equal(2);
  // });

  // it('should return a tree with the correct open path truth values for implication sentences', function() {
  //   var imp = jKif.Utility.knowledgeBase(jKif.Parser.parse('(=> (instance ?CLARK Human)(subclass Human Entity))'));
  //   var ttImp = new tt.TruthTreeSent(imp);
  //   expect(ttImp.tree.paths.open[0].value).to.be.true;
  //   expect(ttImp.tree.paths.open[1].value).to.be.true;
  //   var imp2 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(=> (not (instance ?CLARK Human))(subclass Human Entity))'));
  //   var ttImp2 = new tt.TruthTreeSent(imp2);
  //   expect(ttImp2.tree.paths.open[0].value).to.be.false;
  //   expect(ttImp2.tree.paths.open[1].value).to.be.true;
  //   var imp3 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (=> (instance ?CLARK Human)(subclass Human Entity)))'));
  //   var ttImp3 = new tt.TruthTreeSent(imp3);
  //   expect(ttImp3.tree.paths.open[0].value).to.be.false;
  //   expect(ttImp3.tree.paths.open[1].value).to.be.false;
  // });

  // it('should return a tree with a stepCount of 2 for knowledgebase inputs with a single equivalence sentence (atoms for expressions)', function() {
  //   var equiv = jKif.Utility.knowledgeBase(jKif.Parser.parse('(<=> (instance ?CLARK Human)(subclass Human Entity))'));
  //   var ttEquiv = new tt.TruthTreeSent(equiv);
  //   expect(ttEquiv.tree.stepCount).to.equal(2);
  // });

  // it('should return a tree with the correct open path truth values for equivalence sentences', function() {
  //   var equiv = jKif.Utility.knowledgeBase(jKif.Parser.parse('(<=> (instance ?CLARK Human)(subclass Human Entity))'));
  //   var ttEquiv = new tt.TruthTreeSent(equiv);
  //   expect(ttEquiv.tree.paths.open[0].value).to.be.true;
  //   expect(ttEquiv.tree.paths.open[1].value).to.be.true;
  //   var equiv2 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(=> (not (instance ?CLARK Human))(subclass Human Entity))'));
  //   var equiv2 = new tt.TruthTreeSent(equiv2);
  //   expect(equiv2.tree.paths.open[0].value).to.be.false;
  //   expect(equiv2.tree.paths.open[1].value).to.be.true;
  //   var equiv3 = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (<=> (instance ?CLARK Human)(subclass Human Entity)))'));
  //   var ttEquiv3 = new tt.TruthTreeSent(equiv3);
  //   expect(ttEquiv3.tree.paths.open[0].value).to.be.false;
  //   expect(ttEquiv3.tree.paths.open[1].value).to.be.false;
  // });

});
<commit_msg>Remove old tests from construct tree spec in prep for new tests<commit_after>var chai = require('chai'),
    expect = chai.expect,
    jKif = require('../../../../lib/jkif'),
    ast = require('../../../../lib/ast_constructors/ast_constructors'),
    tt = require('../../../../lib/truth_trees/truth_trees');

describe('#construct helper method', function() {

  var parsed = jKif.Parser.parse(''),
      kb = jKif.Utility.knowledgeBase(parsed),
      ttSent = new tt.TruthTreeSent(kb),
      atomicKb = jKif.Utility.knowledgeBase(jKif.Parser.parse('(not (instance ?CLARK Human))(instance ?CLARK Human)')),
      ttSentAtomic = new tt.TruthTreeSent(atomicKb);

  it('should return an instance of an Object', function() {
    expect(ttSent).to.be.an.instanceof(Object);
  });

});
<|endoftext|>


<commit_before>import axios from 'axios';

import config from '../env/config';

const ACCESS_TOKEN = '';

export async function uploadImage (image) {
  const path = `${config.dropBoxApi.uploadPath}${image.name}`;

  const { data } = await axios({
    method: 'post',
    headers: {
      'Authorization': `Bearer ${ACCESS_TOKEN}`,
      'Content-Type': 'application/octet-stream',
      'Dropbox-API-Arg': `{ "path": "${path}" }`,
    },
    url: config.dropBoxApi.uploadUrl,
    data: image,
  });

  return data;
}

export async function deleteImage (path) {
  const { data } = await axios({
    method: 'post',
    headers: {
      'Authorization': `Bearer ${ACCESS_TOKEN}`,
      'Content-Type': 'application/json',
    },
    url: config.dropBoxApi.deleteUrl,
    data: {
      path,
    },
  });

  return data;
}
<commit_msg>Try to fetch image thumbnail<commit_after>import axios from 'axios';

import config from '../env/config';

const ACCESS_TOKEN = '';

export async function uploadImage (image) {
  const path = `${config.dropBoxApi.uploadPath}${image.name}`;

  const { data: file } = await axios({
    method: 'post',
    headers: {
      'Authorization': `Bearer ${ACCESS_TOKEN}`,
      'Content-Type': 'application/octet-stream',
      'Dropbox-API-Arg': `{ "path": "${path}" }`,
    },
    url: config.dropBoxApi.uploadUrl,
    data: image,
  });

  const data = await getThumbnail(file.path_lower);

  return {
    ...file,
    image: data,
  };
}

export async function getThumbnail (path) {
  const { data } = await axios({
    method: 'post',
    headers: {
      'Authorization': `Bearer ${ACCESS_TOKEN}`,
      'Content-Type': 'application/json',
      'Dropbox-API-Arg': `{ "path": "${path}" }`,
    },
    // url: 'https://content.dropboxapi.com/2/files/get_thumbnail',
    url: 'https://content.dropboxapi.com/2/files/download',
  });

  return data;
}

export async function deleteImage (path) {
  const { data } = await axios({
    method: 'post',
    headers: {
      'Authorization': `Bearer ${ACCESS_TOKEN}`,
      'Content-Type': 'application/json',
    },
    url: config.dropBoxApi.deleteUrl,
    data: {
      path,
    },
  });

  return data;
}
<|endoftext|>


<commit_before>var mongo = require(__dirname + '/../lib/database');
var config = require(__dirname + '/../_config_');
var _ = require('lodash');
var async = require('async');

function __search(db, query, options, callback)
{
	db.collection('tweets').find(query, options || null, function(err, res) {
		if (err) {
			callback(err);
			return;
		}
		res.toArray(function(err, docs) {
			if (err) {
				callback(err);
				return;
			}

	        var tweets = _.map(docs, function(tweet){
	        	return {
					tweet: tweet.text,
					handle: tweet.user.screen_name,
					avatar: tweet.user.profile_image_url,
					link: 'https://twitter.com/#!/' + tweet.user.id + '/status/' + tweet._id + '/',
					retweet_link: 'https://twitter.com/intent/retweet?tweet_id=' + tweet._id,
					category: 'politician',	// :TODO:
					followers: tweet.user.followers_count
	        	}
	        });

	        callback(null, tweets);
		});
	});
}

// :TODO: pull and cache legislator twitter details to query against tweets

module.exports = function(req) {
	mongo.get().then(function(db) {
		var searchOptions = {sort : [["created_at", 'desc']], limit : 200};	// :TODO: make configurable

		var queries = [
			// normal users
			[{"user.followers_count": {$lt : config.tweet_follower_celebrity_count}}, searchOptions],
			// celebs
			[{"user.followers_count": {$gte : config.tweet_follower_celebrity_count}}, searchOptions],
			// :TODO: legislators
			[{}, searchOptions],
			// :SHONK: this one is the thing I'm going to use to make a count()
			'COUNT'
		];

		async.map(queries, function(query, callback) {
			if ('COUNT' === query) {
				db.collection('tweets').count(callback);
			} else {
				__search(db, query[0], query[1], callback);
			}
		}, function(err, results) {
			if (err) throw err;

			var tweets = {
				'latest' : {
					'public' : results[0],
					'celebrities' : results[1],
					'legislators' : results[2], // :TODO:
				},
				'offset' : 0,	// :TODO: when we need paging
				'total' : results[3],
			};
		    req.io.emit('get_tweets', tweets);
		});
	}, function(err) {
		throw err;
	});

};
<commit_msg>hooked up querying of legislator tweets<commit_after>var mongo = require(__dirname + '/../lib/database');
var config = require(__dirname + '/../_config_');
var async = require('async');

var memberCSV = require('au-legislator-contacts-csv');

function __search(db, query, options, callback)
{
	db.collection('tweets').find(query, options || null, function(err, res) {
		if (err) {
			callback(err);
			return;
		}
		res.toArray(function(err, docs) {
			if (err) {
				callback(err);
				return;
			}

	        var tweets = docs.map(function(tweet){
	        	return {
					tweet: tweet.text,
					handle: tweet.user.screen_name,
					avatar: tweet.user.profile_image_url,
					link: 'https://twitter.com/#!/' + tweet.user.id + '/status/' + tweet._id + '/',
					retweet_link: 'https://twitter.com/intent/retweet?tweet_id=' + tweet._id,
					followers: tweet.user.followers_count
	        	}
	        });

	        callback(null, tweets);
		});
	});
}

// :TODO: pull and cache legislator twitter details to query against tweets

module.exports = function(req) {
	mongo.get().then(function(db) {
	memberCSV.get().then(function(members) {

		// reduce members down to twatter names
		members = members.map(function(m) {
			return m.twitter ? m.twitter.match(/https?:\/\/(www\.)?twitter.com\/(#!\/)?(.*?)(\/|$)/)[3] : false;
		}).filter(function(m) {
			return !!m;
		});

		var searchOptions = {sort : [["created_at", 'desc']], limit : 200};	// :TODO: make configurable

		var queries = [
			// normal users
			[{
				"user.followers_count": {$lt : config.tweet_follower_celebrity_count},
				"user.screen_name": {$nin : members},
			}, searchOptions],
			// celebs
			[{
				"user.followers_count": {$gte : config.tweet_follower_celebrity_count},
				"user.screen_name": {$nin : members},
			}, searchOptions],
			[{
				"user.screen_name": {$in : members}
			}, searchOptions],
			// :SHONK: random string ID used to change inner behaviour of the below
			'COUNT'
		];

		async.map(queries, function(query, callback) {
			if ('COUNT' === query) {
				db.collection('tweets').count(callback);
			} else {
				__search(db, query[0], query[1], callback);
			}
		}, function(err, results) {
			if (err) throw err;

			var tweets = {
				'latest' : {
					'public' : results[0],
					'celebrities' : results[1],
					'legislators' : results[2], // :TODO:
				},
				'offset' : 0,	// :TODO: when we need paging
				'total' : results[3],
			};
		    req.io.emit('get_tweets', tweets);
		});

	}, function(err) {
		throw err;
	})}, function(err) {
		throw err;
	});

};
<|endoftext|>


<commit_before>/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var mouseChange = require('mouse-change');
var mouseWheel = require('mouse-wheel');
var cartesianConstants = require('../cartesian/constants');

module.exports = createCamera;

function Camera2D(element, plot) {
    this.element = element;
    this.plot = plot;
    this.mouseListener = null;
    this.wheelListener = null;
    this.lastInputTime = Date.now();
    this.lastPos = [0, 0];
    this.boxEnabled = false;
    this.boxInited = false;
    this.boxStart = [0, 0];
    this.boxEnd = [0, 0];
    this.dragStart = [0, 0];
}

function createCamera(scene) {
    var element = scene.mouseContainer,
        plot = scene.glplot,
        result = new Camera2D(element, plot);

    function unSetAutoRange() {
        scene.xaxis.autorange = false;
        scene.yaxis.autorange = false;
    }

    function getSubplotConstraint() {
        // note: this assumes we only have one x and one y axis on this subplot
        // when this constraint is lifted this block won't make sense
        var constraints = scene.graphDiv._fullLayout._axisConstraintGroups;
        var xaId = scene.xaxis._id;
        var yaId = scene.yaxis._id;
        for(var i = 0; i < constraints.length; i++) {
            if(constraints[i][xaId] !== -1) {
                if(constraints[i][yaId] !== -1) return true;
                break;
            }
        }
        return false;
    }

    result.mouseListener = mouseChange(element, function(buttons, x, y) {
        var dataBox = scene.calcDataBox(),
            viewBox = plot.viewBox;

        var lastX = result.lastPos[0],
            lastY = result.lastPos[1];

        var MINDRAG = cartesianConstants.MINDRAG * plot.pixelRatio;
        var MINZOOM = cartesianConstants.MINZOOM * plot.pixelRatio;

        var dx, dy;

        x *= plot.pixelRatio;
        y *= plot.pixelRatio;

        // mouseChange gives y about top; convert to about bottom
        y = (viewBox[3] - viewBox[1]) - y;

        function updateRange(i0, start, end) {
            var range0 = Math.min(start, end),
                range1 = Math.max(start, end);

            if(range0 !== range1) {
                dataBox[i0] = range0;
                dataBox[i0 + 2] = range1;
                result.dataBox = dataBox;
                scene.setRanges(dataBox);
            }
            else {
                scene.selectBox.selectBox = [0, 0, 1, 1];
                scene.glplot.setDirty();
            }
        }

        switch(scene.fullLayout.dragmode) {
            case 'zoom':
                if(buttons) {
                    var dataX = x /
                            (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) +
                        dataBox[0];
                    var dataY = y /
                            (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) +
                        dataBox[1];

                    if(!result.boxInited) {
                        result.boxStart[0] = dataX;
                        result.boxStart[1] = dataY;
                        result.dragStart[0] = x;
                        result.dragStart[1] = y;
                    }

                    result.boxEnd[0] = dataX;
                    result.boxEnd[1] = dataY;

                    // we need to mark the box as initialized right away
                    // so that we can tell the start and end pionts apart
                    result.boxInited = true;

                    // but don't actually enable the box until the cursor moves
                    if(!result.boxEnabled && (
                        result.boxStart[0] !== result.boxEnd[0] ||
                        result.boxStart[1] !== result.boxEnd[1])
                    ) {
                        result.boxEnabled = true;
                    }

                    // constrain aspect ratio if the axes require it
                    var smallDx = Math.abs(result.dragStart[0] - x) < MINZOOM;
                    var smallDy = Math.abs(result.dragStart[1] - y) < MINZOOM;
                    if(getSubplotConstraint() && !(smallDx && smallDy)) {
                        dx = result.boxEnd[0] - result.boxStart[0];
                        dy = result.boxEnd[1] - result.boxStart[1];
                        var dydx = (dataBox[3] - dataBox[1]) / (dataBox[2] - dataBox[0]);

                        if(Math.abs(dx * dydx) > Math.abs(dy)) {
                            result.boxEnd[1] = result.boxStart[1] +
                                Math.abs(dx) * dydx * (Math.sign(dy) || 1);

                            // gl-select-box clips to the plot area bounds,
                            // which breaks the axis constraint, so don't allow
                            // this box to go out of bounds
                            if(result.boxEnd[1] < dataBox[1]) {
                                result.boxEnd[1] = dataBox[1];
                                result.boxEnd[0] = result.boxStart[0] +
                                    (dataBox[1] - result.boxStart[1]) / Math.abs(dydx);
                            }
                            else if(result.boxEnd[1] > dataBox[3]) {
                                result.boxEnd[1] = dataBox[3];
                                result.boxEnd[0] = result.boxStart[0] +
                                    (dataBox[3] - result.boxStart[1]) / Math.abs(dydx);
                            }
                        }
                        else {
                            result.boxEnd[0] = result.boxStart[0] +
                                Math.abs(dy) / dydx * (Math.sign(dx) || 1);

                            if(result.boxEnd[0] < dataBox[0]) {
                                result.boxEnd[0] = dataBox[0];
                                result.boxEnd[1] = result.boxStart[1] +
                                    (dataBox[0] - result.boxStart[0]) * Math.abs(dydx);
                            }
                            else if(result.boxEnd[0] > dataBox[2]) {
                                result.boxEnd[0] = dataBox[2];
                                result.boxEnd[1] = result.boxStart[1] +
                                    (dataBox[2] - result.boxStart[0]) * Math.abs(dydx);
                            }
                        }
                    }
                    // otherwise clamp small changes to the origin so we get 1D zoom
                    else {
                        if(smallDx) result.boxEnd[0] = result.boxStart[0];
                        if(smallDy) result.boxEnd[1] = result.boxStart[1];
                    }
                }
                else if(result.boxEnabled) {
                    dx = result.boxStart[0] !== result.boxEnd[0];
                    dy = result.boxStart[1] !== result.boxEnd[1];
                    if(dx || dy) {
                        if(dx) {
                            updateRange(0, result.boxStart[0], result.boxEnd[0]);
                            scene.xaxis.autorange = false;
                        }
                        if(dy) {
                            updateRange(1, result.boxStart[1], result.boxEnd[1]);
                            scene.yaxis.autorange = false;
                        }
                        scene.relayoutCallback();
                    }
                    else {
                        scene.glplot.setDirty();
                    }
                    result.boxEnabled = false;
                    result.boxInited = false;
                }
                break;

            case 'pan':
                result.boxEnabled = false;
                result.boxInited = false;

                if(buttons) {
                    if(!result.panning) {
                        result.dragStart[0] = x;
                        result.dragStart[1] = y;
                    }

                    if(Math.abs(result.dragStart[0] - x) < MINDRAG) x = result.dragStart[0];
                    if(Math.abs(result.dragStart[1] - y) < MINDRAG) y = result.dragStart[1];

                    dx = (lastX - x) * (dataBox[2] - dataBox[0]) /
                        (plot.viewBox[2] - plot.viewBox[0]);
                    dy = (lastY - y) * (dataBox[3] - dataBox[1]) /
                        (plot.viewBox[3] - plot.viewBox[1]);

                    dataBox[0] += dx;
                    dataBox[2] += dx;
                    dataBox[1] += dy;
                    dataBox[3] += dy;

                    scene.setRanges(dataBox);

                    result.panning = true;
                    result.lastInputTime = Date.now();
                    unSetAutoRange();
                    scene.cameraChanged();
                    scene.handleAnnotations();
                }
                else if(result.panning) {
                    result.panning = false;
                    scene.relayoutCallback();
                }
                break;
        }

        result.lastPos[0] = x;
        result.lastPos[1] = y;
    });

    result.wheelListener = mouseWheel(element, function(dx, dy) {
        var dataBox = scene.calcDataBox(),
            viewBox = plot.viewBox;

        var lastX = result.lastPos[0],
            lastY = result.lastPos[1];

        switch(scene.fullLayout.dragmode) {
            case 'zoom':
                break;

            case 'pan':
                var scale = Math.exp(0.1 * dy / (viewBox[3] - viewBox[1]));

                var cx = lastX /
                        (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) +
                    dataBox[0];
                var cy = lastY /
                        (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) +
                    dataBox[1];

                dataBox[0] = (dataBox[0] - cx) * scale + cx;
                dataBox[2] = (dataBox[2] - cx) * scale + cx;
                dataBox[1] = (dataBox[1] - cy) * scale + cy;
                dataBox[3] = (dataBox[3] - cy) * scale + cy;

                scene.setRanges(dataBox);

                result.lastInputTime = Date.now();
                unSetAutoRange();
                scene.cameraChanged();
                scene.handleAnnotations();
                scene.relayoutCallback();
                break;
        }

        return true;
    });

    return result;
}
<commit_msg>Fix aggressive zooming<commit_after>/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var mouseChange = require('mouse-change');
var mouseWheel = require('mouse-wheel');
var cartesianConstants = require('../cartesian/constants');

module.exports = createCamera;

function Camera2D(element, plot) {
    this.element = element;
    this.plot = plot;
    this.mouseListener = null;
    this.wheelListener = null;
    this.lastInputTime = Date.now();
    this.lastPos = [0, 0];
    this.boxEnabled = false;
    this.boxInited = false;
    this.boxStart = [0, 0];
    this.boxEnd = [0, 0];
    this.dragStart = [0, 0];
}

function createCamera(scene) {
    var element = scene.mouseContainer,
        plot = scene.glplot,
        result = new Camera2D(element, plot);

    function unSetAutoRange() {
        scene.xaxis.autorange = false;
        scene.yaxis.autorange = false;
    }

    function getSubplotConstraint() {
        // note: this assumes we only have one x and one y axis on this subplot
        // when this constraint is lifted this block won't make sense
        var constraints = scene.graphDiv._fullLayout._axisConstraintGroups;
        var xaId = scene.xaxis._id;
        var yaId = scene.yaxis._id;
        for(var i = 0; i < constraints.length; i++) {
            if(constraints[i][xaId] !== -1) {
                if(constraints[i][yaId] !== -1) return true;
                break;
            }
        }
        return false;
    }

    result.mouseListener = mouseChange(element, function(buttons, x, y) {
        var dataBox = scene.calcDataBox(),
            viewBox = plot.viewBox;

        var lastX = result.lastPos[0],
            lastY = result.lastPos[1];

        var MINDRAG = cartesianConstants.MINDRAG * plot.pixelRatio;
        var MINZOOM = cartesianConstants.MINZOOM * plot.pixelRatio;

        var dx, dy;

        x *= plot.pixelRatio;
        y *= plot.pixelRatio;

        // mouseChange gives y about top; convert to about bottom
        y = (viewBox[3] - viewBox[1]) - y;

        function updateRange(i0, start, end) {
            var range0 = Math.min(start, end),
                range1 = Math.max(start, end);

            if(range0 !== range1) {
                dataBox[i0] = range0;
                dataBox[i0 + 2] = range1;
                result.dataBox = dataBox;
                scene.setRanges(dataBox);
            }
            else {
                scene.selectBox.selectBox = [0, 0, 1, 1];
                scene.glplot.setDirty();
            }
        }

        switch(scene.fullLayout.dragmode) {
            case 'zoom':
                if(buttons) {
                    var dataX = x /
                            (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) +
                        dataBox[0];
                    var dataY = y /
                            (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) +
                        dataBox[1];

                    if(!result.boxInited) {
                        result.boxStart[0] = dataX;
                        result.boxStart[1] = dataY;
                        result.dragStart[0] = x;
                        result.dragStart[1] = y;
                    }

                    result.boxEnd[0] = dataX;
                    result.boxEnd[1] = dataY;

                    // we need to mark the box as initialized right away
                    // so that we can tell the start and end points apart
                    result.boxInited = true;

                    // but don't actually enable the box until the cursor moves
                    if(!result.boxEnabled && (
                        result.boxStart[0] !== result.boxEnd[0] ||
                        result.boxStart[1] !== result.boxEnd[1])
                    ) {
                        result.boxEnabled = true;
                    }

                    // constrain aspect ratio if the axes require it
                    var smallDx = Math.abs(result.dragStart[0] - x) < MINZOOM;
                    var smallDy = Math.abs(result.dragStart[1] - y) < MINZOOM;
                    if(getSubplotConstraint() && !(smallDx && smallDy)) {
                        dx = result.boxEnd[0] - result.boxStart[0];
                        dy = result.boxEnd[1] - result.boxStart[1];
                        var dydx = (dataBox[3] - dataBox[1]) / (dataBox[2] - dataBox[0]);

                        if(Math.abs(dx * dydx) > Math.abs(dy)) {
                            result.boxEnd[1] = result.boxStart[1] +
                                Math.abs(dx) * dydx * (Math.sign(dy) || 1);

                            // gl-select-box clips to the plot area bounds,
                            // which breaks the axis constraint, so don't allow
                            // this box to go out of bounds
                            if(result.boxEnd[1] < dataBox[1]) {
                                result.boxEnd[1] = dataBox[1];
                                result.boxEnd[0] = result.boxStart[0] +
                                    (dataBox[1] - result.boxStart[1]) / Math.abs(dydx);
                            }
                            else if(result.boxEnd[1] > dataBox[3]) {
                                result.boxEnd[1] = dataBox[3];
                                result.boxEnd[0] = result.boxStart[0] +
                                    (dataBox[3] - result.boxStart[1]) / Math.abs(dydx);
                            }
                        }
                        else {
                            result.boxEnd[0] = result.boxStart[0] +
                                Math.abs(dy) / dydx * (Math.sign(dx) || 1);

                            if(result.boxEnd[0] < dataBox[0]) {
                                result.boxEnd[0] = dataBox[0];
                                result.boxEnd[1] = result.boxStart[1] +
                                    (dataBox[0] - result.boxStart[0]) * Math.abs(dydx);
                            }
                            else if(result.boxEnd[0] > dataBox[2]) {
                                result.boxEnd[0] = dataBox[2];
                                result.boxEnd[1] = result.boxStart[1] +
                                    (dataBox[2] - result.boxStart[0]) * Math.abs(dydx);
                            }
                        }
                    }
                    // otherwise clamp small changes to the origin so we get 1D zoom
                    else {
                        if(smallDx) result.boxEnd[0] = result.boxStart[0];
                        if(smallDy) result.boxEnd[1] = result.boxStart[1];
                    }
                }
                else if(result.boxEnabled) {
                    dx = result.boxStart[0] !== result.boxEnd[0];
                    dy = result.boxStart[1] !== result.boxEnd[1];
                    if(dx || dy) {
                        if(dx) {
                            updateRange(0, result.boxStart[0], result.boxEnd[0]);
                            scene.xaxis.autorange = false;
                        }
                        if(dy) {
                            updateRange(1, result.boxStart[1], result.boxEnd[1]);
                            scene.yaxis.autorange = false;
                        }
                        scene.relayoutCallback();
                    }
                    else {
                        scene.glplot.setDirty();
                    }
                    result.boxEnabled = false;
                    result.boxInited = false;
                }
                // if box was inited but button released then - reset the box
                else if(result.boxInited) {
                    result.boxInited = false;
                }
                break;

            case 'pan':
                result.boxEnabled = false;
                result.boxInited = false;

                if(buttons) {
                    if(!result.panning) {
                        result.dragStart[0] = x;
                        result.dragStart[1] = y;
                    }

                    if(Math.abs(result.dragStart[0] - x) < MINDRAG) x = result.dragStart[0];
                    if(Math.abs(result.dragStart[1] - y) < MINDRAG) y = result.dragStart[1];

                    dx = (lastX - x) * (dataBox[2] - dataBox[0]) /
                        (plot.viewBox[2] - plot.viewBox[0]);
                    dy = (lastY - y) * (dataBox[3] - dataBox[1]) /
                        (plot.viewBox[3] - plot.viewBox[1]);

                    dataBox[0] += dx;
                    dataBox[2] += dx;
                    dataBox[1] += dy;
                    dataBox[3] += dy;

                    scene.setRanges(dataBox);

                    result.panning = true;
                    result.lastInputTime = Date.now();
                    unSetAutoRange();
                    scene.cameraChanged();
                    scene.handleAnnotations();
                }
                else if(result.panning) {
                    result.panning = false;
                    scene.relayoutCallback();
                }
                break;
        }

        result.lastPos[0] = x;
        result.lastPos[1] = y;
    });

    result.wheelListener = mouseWheel(element, function(dx, dy) {
        var dataBox = scene.calcDataBox(),
            viewBox = plot.viewBox;

        var lastX = result.lastPos[0],
            lastY = result.lastPos[1];

        switch(scene.fullLayout.dragmode) {
            case 'zoom':
                break;

            case 'pan':
                var scale = Math.exp(0.1 * dy / (viewBox[3] - viewBox[1]));

                var cx = lastX /
                        (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) +
                    dataBox[0];
                var cy = lastY /
                        (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) +
                    dataBox[1];

                dataBox[0] = (dataBox[0] - cx) * scale + cx;
                dataBox[2] = (dataBox[2] - cx) * scale + cx;
                dataBox[1] = (dataBox[1] - cy) * scale + cy;
                dataBox[3] = (dataBox[3] - cy) * scale + cy;

                scene.setRanges(dataBox);

                result.lastInputTime = Date.now();
                unSetAutoRange();
                scene.cameraChanged();
                scene.handleAnnotations();
                scene.relayoutCallback();
                break;
        }

        return true;
    });

    return result;
}
<|endoftext|>


<commit_before>/**
 * luckyslider
 *
 * Copyright 2016, sDofeen
 * Free to use and abuse under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */
!function(a){a.fn.luckySlider=function(b){function c(b,c){function h(){b.find('._ls__list-item[data-item="'+e+'"]').addClass("_ls-active"),d.dots&&b.find('._ls__dots-item[data-dot="'+e+'"]').addClass("_ls-active")}function i(){var c=a(this),g=b.find("._ls__list-item"),i=b.find("._ls__dots-item"),k=c.hasClass("_ls__dots-item"),l=c.hasClass("_ls__nav-prev");return!c.hasClass("_ls-disabled")&&!c.hasClass("_ls-active")&&(g.removeClass("_ls-active"),i.removeClass("_ls-active"),k?e=c.data("dot"):l?1===e?d.cycle&&(e=f):e--:e===f?d.cycle&&(e=1):e++,h(),void(d.cycle||j()))}function j(){b.find("._ls__nav-prev").removeClass("_ls-disabled"),b.find("._ls__nav-next").removeClass("_ls-disabled"),1===e&&b.find("._ls__nav-prev").addClass("_ls-disabled"),e===f&&b.find("._ls__nav-next").addClass("_ls-disabled")}var d=a.extend({start:1,nav:!0,dots:!0,cycle:!0,auto:!1,timeout:3e3},c),e=d.start,f=b.children().length;if(b.addClass("_ls").children().addClass("_ls__list-item").each(function(b,c){a(c).attr("data-item",Number(b+1))}),b.append('

'),b.find("._ls__wrapper").append('

'),b.find("._ls__list-item").appendTo(b.find("._ls__list")),d.nav&&(b.find("._ls__wrapper").append('

'),b.find("._ls__nav").append(''),b.find("._ls__nav").append(''),b.find("._ls__nav ._ls__nav-prev, ._ls__nav ._ls__nav-next").on("click",i)),d.dots){b.append('

');for(var g=0;g<f;g++)b.find("._ls__dots").append('');b.find("._ls__dots-item").on("click",i)}d.auto&&setInterval(function(){i(b.find("._ls__next"))},d.timeout),h(),d.cycle||j()}return this.each(function(d,e){c(a(e),b)})}}(jQuery);
<commit_msg>beforeChange & afterChange callbacks<commit_after>/**
 * luckyslider
 *
 * Copyright 2016, sDofeen
 * Free to use and abuse under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */
!function(a){a.fn.luckySlider=function(b){function c(b,c){function h(){b.find('._ls__list-item[data-item="'+e+'"]').addClass("_ls-active"),d.dots&&b.find('._ls__dots-item[data-dot="'+e+'"]').addClass("_ls-active")}function i(){d.beforeChange&&a.isFunction(d.beforeChange)&&d.beforeChange.call();var c=a(this),g=b.find("._ls__list-item"),i=b.find("._ls__dots-item"),k=c.hasClass("_ls__dots-item"),l=c.hasClass("_ls__nav-prev");return!c.hasClass("_ls-disabled")&&!c.hasClass("_ls-active")&&(g.removeClass("_ls-active"),i.removeClass("_ls-active"),k?e=c.data("dot"):l?1===e?d.cycle&&(e=f):e--:e===f?d.cycle&&(e=1):e++,h(),d.cycle||j(),void(d.afterChange&&a.isFunction(d.afterChange)&&d.afterChange.call()))}function j(){b.find("._ls__nav-prev").removeClass("_ls-disabled"),b.find("._ls__nav-next").removeClass("_ls-disabled"),1===e&&b.find("._ls__nav-prev").addClass("_ls-disabled"),e===f&&b.find("._ls__nav-next").addClass("_ls-disabled")}var d=a.extend({start:1,nav:!0,dots:!0,cycle:!0,auto:!1,timeout:3e3},c),e=d.start,f=b.children().length;if(b.addClass("_ls").children().addClass("_ls__list-item").each(function(b,c){a(c).attr("data-item",Number(b+1))}),b.append('

'),b.find("._ls__wrapper").append('

'),b.find("._ls__list-item").appendTo(b.find("._ls__list")),d.nav&&(b.find("._ls__wrapper").append('

'),b.find("._ls__nav").append(''),b.find("._ls__nav").append(''),b.find("._ls__nav ._ls__nav-prev, ._ls__nav ._ls__nav-next").on("click",i)),d.dots){b.append('

');for(var g=0;g<f;g++)b.find("._ls__dots").append('');b.find("._ls__dots-item").on("click",i)}d.auto&&setInterval(function(){i(b.find("._ls__next"))},d.timeout),h(),d.cycle||j()}return this.each(function(d,e){c(a(e),b)})}}(jQuery);<|endoftext|>


<commit_before>import Vuetify from 'vuetify'
import VBtn from 'vuetify/es5/components/VBtn'
import VIcon from 'vuetify/es5/components/VIcon'
import VGrid from 'vuetify/es5/components/VGrid'
import CodeEditor from '@/components/shared/CodeEditor'
import ResizableContainer from '@/components/shared/ResizableContainer'
import PrintPretty from '@/components/shared/PrintPretty'
import { createLocalVue, mount } from '@vue/test-utils'

describe('PrintPretty.vue', () => {
  let localVue = createLocalVue()
  localVue.use(Vuetify, {
    components: {
      CodeEditor,
      ResizableContainer,
      VBtn,
      VIcon,
      VGrid
    }
  })

  it('should render correct default contents', () => {
    const wrapper = mount(PrintPretty, {localVue})
    const height = 'height: 600px'
    expect(wrapper.find('div > div').attributes().style).contains(height)
  })
})
<commit_msg>fix spec<commit_after>import Vuex from 'vuex'
import Vuetify from 'vuetify'
import VBtn from 'vuetify/es5/components/VBtn'
import VIcon from 'vuetify/es5/components/VIcon'
import VGrid from 'vuetify/es5/components/VGrid'
import CodeEditor from '@/components/shared/CodeEditor'
import ResizableContainer from '@/components/shared/ResizableContainer'
import PrintPretty from '@/components/shared/PrintPretty'
import { createLocalVue, mount } from '@vue/test-utils'
import { theme } from '@/store/modules/theme'

describe('PrintPretty.vue', () => {
  let localVue
  let store

  before(() => {
    localVue = createLocalVue()

    localVue = createLocalVue()
    localVue.use(Vuex)
    localVue.use(Vuetify, {
      components: {
        CodeEditor,
        ResizableContainer,
        VBtn,
        VIcon,
        VGrid
      }
    })
    store = new Vuex.Store({
      modules: {theme}
    })
  })

  it('should render correct default contents', () => {
    const wrapper = mount(PrintPretty, {localVue, store})
    const height = 'height: 600px'
    expect(wrapper.find('div > div').attributes().style).contains(height)
  })
})
<|endoftext|>


<commit_before>function getIPAddress() {
  var interfaces = require('os').networkInterfaces();
  for (var devName in interfaces) {
    var iface = interfaces[devName];

    for (var i = 0; i < iface.length; i++) {
      var alias = iface[i];
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)
        return alias.address;
    }
  }

  return '0.0.0.0';
}

var localIP = getIPAddress();

var port = 4242;
var io = require('socket.io').listen(port),
	Gamepad = require('./Gamepad'),
	Channel = require('./Channel'),
	StatusCode = require('./StatusCode'),
	HashList = require('./HashList');

io.set('log level', 0);

var channelHash = new HashList ();
var gamepadHash = new HashList ();

function getGamepad (socket) {
	var gamepad = gamepadHash.get(socket.id);
	if (gamepad) return gamepad;
	gamepad = new Gamepad (socket);
	gamepadHash.push(gamepad);
	return gamepad;
}

io.sockets.on('connection', function (socket) {
	console.log("Socket connection!");

	socket.on('openChannel', function (channelID) { // {channelID, adress}
		if (channelHash.get(channelID)) return socket.emit('openChannelCallback', {statusCode:StatusCode.ChannelAlreadyExists, localIP:localIP});
		var channel = new Channel (socket, channelID);
		channelHash.push(channel);
		socket.emit('openChannelCallback', {statusCode:StatusCode.OK, localIP:localIP});

		socket.on('disconnect', function () {
			channel.gamepads.forEach(function (gamepad) {
				gamepad.channelDied();
				gamepadHash.remove(gamepad);
			});
			channel.gamepads.clear();
			channelHash.remove(channel);
		});

	});

	socket.on('connectToChannel', function (data) {
		var channel = channelHash.get(data.channel);
		if (!channel) return socket.emit('connectToChannelCallback', StatusCode.ChannelNotFound);
		var gamepad = getGamepad(socket);
		channel.connectGamepad(gamepad, data.g);

		gamepad.socket.on('disconnect', function () {
			gamepadHash.remove(gamepad);
			channel.gamepadDisconnected(gamepad);
		});

	});

	socket.on('gamepadPacket', function (data) {
		data.id = socket.id;
		var gamepad = getGamepad(socket);
		var channel = gamepad.channel;
		if (!channel) return;
		gamepad.channel.gotGamepadPacket(data);
	});

});

console.log("ludumpad-server is listening on port "+port+"!\n");<commit_msg>General update<commit_after>function getIPAddress() {
  var interfaces = require('os').networkInterfaces();
  for (var devName in interfaces) {
    var iface = interfaces[devName];

    for (var i = 0; i < iface.length; i++) {
      var alias = iface[i];
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)
        return alias.address;
    }
  }

  return '0.0.0.0';
}

var localIP = getIPAddress();
console.log("Local IP is "+localIP);

var port = 4242;
var io = require('socket.io').listen(port),
	Gamepad = require('./Gamepad'),
	Channel = require('./Channel'),
	StatusCode = require('./StatusCode'),
	HashList = require('./HashList');

io.set('log level', 0);

var channelHash = new HashList ();
var gamepadHash = new HashList ();

function getGamepad (socket) {
	var gamepad = gamepadHash.get(socket.id);
	if (gamepad) return gamepad;
	gamepad = new Gamepad (socket);
	gamepadHash.push(gamepad);
	return gamepad;
}

io.sockets.on('connection', function (socket) {
	console.log("Socket connection!");

	socket.on('openChannel', function (channelID) { // {channelID, adress}
		if (channelHash.get(channelID)) return socket.emit('openChannelCallback', {statusCode:StatusCode.ChannelAlreadyExists, localIP:localIP});
		var channel = new Channel (socket, channelID);
		channelHash.push(channel);
		socket.emit('openChannelCallback', {statusCode:StatusCode.OK, localIP:localIP});

		socket.on('disconnect', function () {
			channel.gamepads.forEach(function (gamepad) {
				gamepad.channelDied();
				gamepadHash.remove(gamepad);
			});
			channel.gamepads.clear();
			channelHash.remove(channel);
		});

	});

	socket.on('connectToChannel', function (data) {
		var channel = channelHash.get(data.channel);
		if (!channel) return socket.emit('connectToChannelCallback', StatusCode.ChannelNotFound);
		var gamepad = getGamepad(socket);
		channel.connectGamepad(gamepad, data.g);

		gamepad.socket.on('disconnect', function () {
			gamepadHash.remove(gamepad);
			channel.gamepadDisconnected(gamepad);
		});

	});

	socket.on('gamepadPacket', function (data) {
		data.id = socket.id;
		var gamepad = getGamepad(socket);
		var channel = gamepad.channel;
		if (!channel) return;
		gamepad.channel.gotGamepadPacket(data);
	});

});

console.log("ludumpad-server is listening on port "+port+"!\n");<|endoftext|>


<commit_before>const { Configuration } = require('@schul-cloud/commons');
const { userModel, displayName } = require('../user/model');
const { schoolModel, SCHOOL_FEATURES } = require('../school/model');
const roleModel = require('../role/model');
const { courseModel, COURSE_FEATURES } = require('../user-group/model');
const { teamsModel, TEAM_FEATURES } = require('../teams/model');
const { ObjectId } = require('../../helper/compare');

const getUserData = (userId) =>
	userModel
		.findOne(
			{ _id: userId },
			{
				_id: 1,
				firstName: 1,
				lastName: 1,
				roles: 1,
				email: 1,
				schoolId: 1,
			}
		)
		.lean()
		.exec();

const getSchoolData = (schoolId) =>
	schoolModel
		.findOne(
			{ _id: schoolId },
			{
				_id: 1,
				name: 1,
				features: 1,
			}
		)
		.lean()
		.exec();

const getAllCourseDataForUser = (userId) =>
	courseModel
		.find(
			{
				$or: [{ userIds: userId }, { teacherIds: userId }, { substitutionIds: userId }],
			},
			{
				_id: 1,
				name: 1,
				userIds: 1,
				teacherIds: 1,
				substitutionIds: 1,
				features: 1,
			}
		)
		.lean()
		.exec();

const getAllTeamsDataForUser = (userId) =>
	teamsModel.find(
		{ userIds: { $elemMatch: { userId } } },
		{
			_id: 1,
			name: 1,
			userIds: 1,
			features: 1,
		}
	);

let roles;

const getRoles = async () => {
	if (!roles) {
		const [teacherRoleId, adminRoleId, teamOwnerId, teamAdminId, teamLeaderId] = await Promise.all([
			roleModel
				.findOne({ name: 'teacher' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id),
			roleModel
				.findOne({ name: 'administrator' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id),
			roleModel
				.findOne({ name: 'teamowner' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id.toString()),
			roleModel
				.findOne({ name: 'teamadministrator' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id.toString()),
			roleModel
				.findOne({ name: 'teamleader' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id.toString()),
		]);
		roles = {
			teacherRoleId,
			adminRoleId,
			teamOwnerId,
			teamAdminId,
			teamLeaderId,
		};
	}
	return roles;
};

/* {
	method: 'adduser',
    school:{
		id: 1223435,
		has_allhands_channel : true,
		name: "Peanuts High"
    },
    user: {
        id: 1234566@matrix.schul-cloud.org,
        name: "Joe Cool"",
		is_school_admin: true,
		is_school_teacher: true,
    },
    room: {
		id: 1234566,
		name: 'Mathe 6b',
		description: 'Kurs',
		type: 'course',
		is_moderator: false,
		bidirectional: true
    }
} */

const buildCourseObject = (course, userId) => ({
	id: course._id.toString(),
	name: course.name,
	description: 'Kurs',
	type: 'course',
	bidirectional: (course.features || []).includes(COURSE_FEATURES.MESSENGER),
	is_moderator: course.teacherIds
		.concat(course.substitutionIds)
		.some((moderatorId) => ObjectId.equal(moderatorId, userId)),
});

const buildTeamObject = async (team, userId, moderatorRoles) => {
	const { teamAdminId, teamLeaderId, teamOwnerId } = moderatorRoles;
	const isModerator = team.userIds.some((user) => {
		if (!ObjectId.equal(user.userId, userId)) {
			return false; // other user
		}
		return [teamAdminId, teamLeaderId, teamOwnerId].includes(user.role.toString());
	});
	return {
		id: team._id.toString(),
		name: team.name,
		description: 'Team',
		type: 'team',
		bidirectional: (team.features || []).includes(TEAM_FEATURES.MESSENGER),
		is_moderator: isModerator,
	};
};

const buildMessageObject = async (data) => {
	const user = data.user || (await getUserData(data.userId));
	const school = data.school || (await getSchoolData(user.schoolId));
	const moderatorRoles = await getRoles();
	const rooms = [];
	if (data.courses) {
		data.courses.forEach((course) => {
			rooms.push(buildCourseObject(course, data.userId));
		});
	}
	if (data.teams) {
		await Promise.all(
			data.teams.map(async (team) => {
				const teamObject = await buildTeamObject(team, data.userId, moderatorRoles);
				rooms.push(teamObject);
			})
		);
	}
	const servername = Configuration.get('MATRIX_SERVERNAME');

	return {
		method: 'adduser',
		school: {
			id: school._id.toString(),
			has_allhands_channel: (school.features || []).includes(SCHOOL_FEATURES.MESSENGER_SCHOOL_ROOM),
			name: school.name,
		},
		user: {
			id: `@sso_${user._id.toString()}:${servername}`,
			name: displayName(user),
			email: user.email,
			is_school_admin: user.roles.some((roleId) => ObjectId.equal(roleId, moderatorRoles.adminRoleId)),
			is_school_teacher: user.roles.some((roleId) => ObjectId.equal(roleId, moderatorRoles.teacherRoleId)),
		},
		rooms,
	};
};

const buildAddUserMessage = async (data) => {
	if (data.fullSync) {
		data.courses = await getAllCourseDataForUser(data.userId);
		data.teams = await getAllTeamsDataForUser(data.userId);
	}
	return buildMessageObject(data);
};

const messengerIsActivatedForSchool = async (data) => {
	if (data.userId) {
		data.user = await getUserData(data.userId);
		data.school = await getSchoolData(data.user.schoolId);
	}

	if (data.schoolId) {
		data.school = await getSchoolData(data.schoolId);
	}

	return data.school && Array.isArray(data.school.features) && data.school.features.includes(SCHOOL_FEATURES.MESSENGER);
};

module.exports = { buildAddUserMessage, messengerIsActivatedForSchool };
<commit_msg>messenger: move news and teachers room configuration into server<commit_after>const { Configuration } = require('@schul-cloud/commons');
const { userModel, displayName } = require('../user/model');
const { schoolModel, SCHOOL_FEATURES } = require('../school/model');
const roleModel = require('../role/model');
const { courseModel, COURSE_FEATURES } = require('../user-group/model');
const { teamsModel, TEAM_FEATURES } = require('../teams/model');
const { ObjectId } = require('../../helper/compare');

const getUserData = (userId) =>
	userModel
		.findOne(
			{ _id: userId },
			{
				_id: 1,
				firstName: 1,
				lastName: 1,
				roles: 1,
				email: 1,
				schoolId: 1,
			}
		)
		.lean()
		.exec();

const getSchoolData = (schoolId) =>
	schoolModel
		.findOne(
			{ _id: schoolId },
			{
				_id: 1,
				name: 1,
				features: 1,
			}
		)
		.lean()
		.exec();

const getAllCourseDataForUser = (userId) =>
	courseModel
		.find(
			{
				$or: [{ userIds: userId }, { teacherIds: userId }, { substitutionIds: userId }],
			},
			{
				_id: 1,
				name: 1,
				userIds: 1,
				teacherIds: 1,
				substitutionIds: 1,
				features: 1,
			}
		)
		.lean()
		.exec();

const getAllTeamsDataForUser = (userId) =>
	teamsModel.find(
		{ userIds: { $elemMatch: { userId } } },
		{
			_id: 1,
			name: 1,
			userIds: 1,
			features: 1,
		}
	);

let roles;

const getRoles = async () => {
	if (!roles) {
		const [teacherRoleId, adminRoleId, teamOwnerId, teamAdminId, teamLeaderId] = await Promise.all([
			roleModel
				.findOne({ name: 'teacher' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id),
			roleModel
				.findOne({ name: 'administrator' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id),
			roleModel
				.findOne({ name: 'teamowner' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id.toString()),
			roleModel
				.findOne({ name: 'teamadministrator' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id.toString()),
			roleModel
				.findOne({ name: 'teamleader' }, { _id: 1 })
				.lean()
				.exec()
				.then((r) => r._id.toString()),
		]);
		roles = {
			teacherRoleId,
			adminRoleId,
			teamOwnerId,
			teamAdminId,
			teamLeaderId,
		};
	}
	return roles;
};

/*
{
  "method": "adduser",
  "welcome": {
    "text": "Welcome to messenger"
  },
  "user": {
    "id": "@sso_0000d224816abba584714c9c:matrix.server.com",
    "name": "Marla Mathe",
    "email": "(optional)",
    "password": "(optional)"
  },
  "rooms": [
    {
      "type": "(optional, default: room)",
      "id": "0000dcfbfb5c7a3f00bf21ab",
      "name": "Mathe",
      "description": "Kurs",
      "bidirectional": false,
      "is_moderator": false
    }
  ]
}
*/

const buildCourseObject = (course, userId) => ({
	id: course._id.toString(),
	name: course.name,
	description: 'Kurs',
	type: 'course',
	bidirectional: (course.features || []).includes(COURSE_FEATURES.MESSENGER),
	is_moderator: course.teacherIds
		.concat(course.substitutionIds)
		.some((moderatorId) => ObjectId.equal(moderatorId, userId)),
});

const buildTeamObject = async (team, userId, moderatorRoles) => {
	const { teamAdminId, teamLeaderId, teamOwnerId } = moderatorRoles;
	const isModerator = team.userIds.some((user) => {
		if (!ObjectId.equal(user.userId, userId)) {
			return false; // other user
		}
		return [teamAdminId, teamLeaderId, teamOwnerId].includes(user.role.toString());
	});
	return {
		id: team._id.toString(),
		name: team.name,
		description: 'Team',
		type: 'team',
		bidirectional: (team.features || []).includes(TEAM_FEATURES.MESSENGER),
		is_moderator: isModerator,
	};
};

const buildMessageObject = async (data) => {
	const user = data.user || (await getUserData(data.userId));
	const school = data.school || (await getSchoolData(user.schoolId));
	const moderatorRoles = await getRoles();
	const schoolRoomEnabled = (school.features || []).includes(SCHOOL_FEATURES.MESSENGER_SCHOOL_ROOM);
	const teachersRoomEnabled = true;
	const isTeacher = user.roles.some((roleId) => ObjectId.equal(roleId, moderatorRoles.teacherRoleId));
	const isAdmin = user.roles.some((roleId) => ObjectId.equal(roleId, moderatorRoles.adminRoleId));
	const isTeacheOrAdmin = isTeacher || isAdmin;

	const rooms = [];
	if (data.courses) {
		data.courses.forEach((course) => {
			rooms.push(buildCourseObject(course, data.userId));
		});
	}
	if (data.teams) {
		await Promise.all(
			data.teams.map(async (team) => {
				const teamObject = await buildTeamObject(team, data.userId, moderatorRoles);
				rooms.push(teamObject);
			})
		);
	}
	if (schoolRoomEnabled) {
		rooms.push({
			type: 'news',
			id: school._id.toString(),
			name: 'Ankündigungen',
			description: school.name,
			bidirectional: false,
			is_moderator: isTeacheOrAdmin,
		});
	}
	if (teachersRoomEnabled && isTeacheOrAdmin) {
		rooms.push({
			type: 'teachers',
			id: school._id.toString(),
			name: 'Lehrerzimmer',
			description: school.name,
			bidirectional: true,
			is_moderator: isAdmin,
		});
	}

	const servername = Configuration.get('MATRIX_SERVERNAME');

	return {
		method: 'adduser',
		user: {
			id: `@sso_${user._id.toString()}:${servername}`,
			name: displayName(user),
		},
		rooms,
	};
};

const buildAddUserMessage = async (data) => {
	if (data.fullSync) {
		data.courses = await getAllCourseDataForUser(data.userId);
		data.teams = await getAllTeamsDataForUser(data.userId);
	}
	return buildMessageObject(data);
};

const messengerIsActivatedForSchool = async (data) => {
	if (data.userId) {
		data.user = await getUserData(data.userId);
		data.school = await getSchoolData(data.user.schoolId);
	}

	if (data.schoolId) {
		data.school = await getSchoolData(data.schoolId);
	}

	return data.school && Array.isArray(data.school.features) && data.school.features.includes(SCHOOL_FEATURES.MESSENGER);
};

module.exports = { buildAddUserMessage, messengerIsActivatedForSchool };
<|endoftext|>


<commit_before>if (el.classList)
  el.classList.remove(className);
else
  el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
<commit_msg>fix: ie8 regex in removeClass<commit_after>if (el.classList)
  el.classList.remove(className);
else
  el.className = el.className.replace(new RegExp('(^|\\b)(\\s+)' + className.split(' ').join('(\\s+)|(\\s+)') + '(\\s+)(\\b|$|\s+$)', 'g'), ' ');
<|endoftext|>


<commit_before><commit_msg>Oh yeah, that bit.<commit_after><|endoftext|>


<commit_before>define(['itemObjectModel', 'mac/roman'], function(itemOM, macRoman) {

  'use strict';

  function findNullOffset(bytes, pos) {
    var offset = 0;
    while (bytes[pos + offset]) offset++;
    return offset;
  }

  function versionString(bytes, pos) {
    if (!bytes[pos + 3]) return null;
    var versionString = bytes[pos] + '.' + (bytes[pos + 1] >> 4);
    if (bytes[pos + 1] & 7) versionString += '.' + (bytes[pos + 1] & 7);
    switch(bytes[pos + 2]) {
      case 0x20: versionString += 'dev'; break;
      case 0x40: versionString += 'a'; break;
      case 0x60: versionString += 'b'; break;
      case 0x80:
        if (bytes[pos + 3]) versionString += 'rel';
        break;
      default: versionString += '[u' + bytes[pos+2] + ']'; break;
    }
    if (bytes[pos + 3]) versionString += bytes[pos + 3];
    return versionString;
  }

  function open(item) {
    function onBlock(item, byteSource) {
      return byteSource.slice(0, 12).getBytes().then(function(headerBytes) {
        var dv = new DataView(
          headerBytes.buffer, headerBytes.byteOffset, headerBytes.byteLength);
        var length = dv.getUint32(0, false);
        var name = macRoman(headerBytes, 4, 4);
        var id = dv.getInt32(8, false);
        var blockItem = itemOM.createItem(name + " " + id);
        item.addItem(blockItem);
        if (length > 8) {
          blockItem.byteSource = byteSource.slice(12, length);
          switch (name) {
            case 'STAK':
              blockItem.startAddingItems();
              blockItem.notifyPopulating(blockItem.getBytes().then(function(bytes) {
                var stack = new StackView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
                blockItem.setDataObject(stack);
                for (var i = 0; i < stack.patternCount; i++) {
                  var patternItem = itemOM.createItem('pattern ' + i);
                  var patternData = stack.getRawPattern(i);
                  patternItem.withPixels(8, 8, function(pixelData) {
                    for (var y = 0; y < 8; y++) {
                      for (var x = 0; x < 8; x++) {
                        if (patternData[y] & (0x80 >> x)) {
                          pixelData[4 * (y*8 + x) + 3] = 0xff;
                        }
                      }
                    }
                  });
                  blockItem.addItem(patternItem);
                }
                var scriptItem = itemOM.createItem('script');
                scriptItem.setDataObject(stack.getScript());
                blockItem.addItem(scriptItem);
              }));
              break;
            case 'CARD': case 'BKGD':
              blockItem.startAddingItems();
              blockItem.notifyPopulating(blockItem.getBytes().then(function(bytes) {
                var card = new CardView(name === 'BKGD', bytes.buffer, bytes.byteOffset, bytes.byteLength);
                blockItem.setDataObject(card);
                if (card.cardScript) {
                  var scriptItem = itemOM.createItem('script');
                  scriptItem.setDataObject(card.cardScript);
                  blockItem.addItem(scriptItem);
                }
              }));
              break;
          }
        }
        if (byteSource.byteLength >= (length + 12)) {
          return onBlock(item, byteSource.slice(length));
        }
      });
    }
    return onBlock(item, item.byteSource);
  }

  function StackView(buffer, byteOffset, byteLength) {
    this.dataView = new DataView(buffer, byteOffset, byteLength);
    this.bytes = new Uint8Array(buffer, byteOffset, byteLength);
  }
  StackView.prototype = {
    toJSON: function() {
      return {
        version1: this.version1,
        version2: this.version2,
        version3: this.version3,
        version4: this.version4,
        cardCount: this.cardCount,
        listBlockID: this.listBlockID,
        userLevelSetting: this.userLevelSetting,
        canPeek: this.canPeek,
        canAbort: this.canAbort,
        hasPrivateAccess: this.hasPrivateAccess,
        canDelete: this.canDelete,
        canModify: this.canModify,
        screenHeight: this.screenHeight,
        screenWidth: this.screenWidth,
      };
    },
    // unknown_0x00: 0x20 bytes
    get cardCount() {
      return this.dataView.getUint32(0x20, false);
    },
    // unknown_0x24: card ID for unknown reasons
    get listBlockID() {
      return this.dataView.getInt32(0x28, false);
    },
    // unknown_0x2C: 0x10 bytes
    get userLevelSetting() {
      return this.dataView.getUint16(0x3C, false);
    },
    // unknown_0x3E: 0x02 bytes
    get flags() {
      return this.dataView.getUint16(0x40, false);
    },
    get canPeek() {
      return !(this.flags & (1 << 10));
    },
    get canAbort() {
      return !(this.flags & (1 << 11));
    },
    get hasPrivateAccess() {
      return !!(this.flags & (1 << 13));
    },
    get canDelete() {
      return !(this.flags & (1 << 14));
    },
    get canModify() {
      return !(this.flags & (1 << 15));
    },
    // unknown_0x42: 0x12 bytes
    get version1() {
      return versionString(this.bytes, 0x54);
    },
    get version2() {
      return versionString(this.bytes, 0x58);
    },
    get version3() {
      return versionString(this.bytes, 0x5C);
    },
    get version4() {
      return versionString(this.bytes, 0x60);
    },
    // unknown_0x64: 0x148 bytes
    get screenHeight() {
      return this.dataView.getUint16(0x1ac, false);
    },
    get screenWidth() {
      return this.dataView.getUint16(0x1ae, false);
    },
    // unknown_0x1AE: 0x106 bytes
    get patternCount() {
      return 40;
    },
    getRawPattern: function(n) {
      return this.bytes.subarray(0x2B4 + n * 8, 0x2B4 + (n + 1) * 8);
    },
    // unknown_0x3F4: 0x200 bytes
    getScript: function() {
      return macRoman(this.bytes, 0x5F4).replace(/\0.*/, '');
    },
  };

  function CardView(isBackground, buffer, byteOffset, byteLength) {
    this.isBackground = isBackground;
    this.dataView = new DataView(buffer, byteOffset, byteLength);
    this.bytes = new Uint8Array(buffer, byteOffset, byteLength);
  }
  CardView.prototype = {
    toJSON: function() {
      return {
        pictureBitmapID: this.pictureBitmapID,
        flags: this.flags,
        backgroundID: this.backgroundID,
        scriptType: this.scriptType,
        parts: this.parts,
        partContents: this.partContents,
        cardName: this.cardName,
        osaScript: this.osaScript,
      };
    },
    // unknown_0x0000: 4 bytes
    get pictureBitmapID() {
      return this.dataView.getInt32(0x4, false); // 0 = transparent
    },
    get flags() {
      return this.dataView.getUint16(0x8, false);
    },
    get canDelete() {
      return !(this.flags & (1 << 14));
    },
    get hideCardPicture() {
      return !!(this.flags & (1 << 13));
    },
    get dontSearch() {
      return !!(this.flags & (1 << 11));
    },
    // unknown_0x0A: 0xE bytes
    get backgroundID() {
      return this.isBackground ? null : this.dataView.getInt32(0x18, false);
    },
    offsetForBackground: function(v) {
      return this.isBackground ? v - 4 : v;
    },
    get partCount() {
      return this.dataView.getUint16(this.offsetForBackground(0x1C), false);
    },
    // unknown_0x1E: 0x6 bytes
    get partContentCount() {
      return this.dataView.getUint16(this.offsetForBackground(0x24), false);
    },
    get scriptType() {
      return this.dataView.getUint32(this.offsetForBackground(0x24), false);
    },
    get parts() {
      var parts = new Array(this.partCount);
      var pos = this.offsetForBackground(0x2A);
      for (var i = 0; i < parts.length; i++) {
        var len = this.dataView.getUint16(pos, false);
        parts[i] = new PartView(this.bytes.buffer, this.bytes.byteOffset + pos, len);
        pos += len + len%2;
      }
      parts.afterPos = pos;
      Object.defineProperty(this, 'parts', {value:parts});
      return parts;
    },
    get partContents() {
      var contents = new Array(this.partContentCount);
      var pos = this.parts.afterPos;
      for (var i = 0; i < contents.length; i++) {
        var len = this.dataView.getUint16(pos + 2, false);
        contents[i] = new ContentsView(this.bytes.buffer, this.bytes.byteOffset + pos, 4 + len);
        pos += 4 + len + len%2;
      }
      contents.afterPos = pos;
      Object.defineProperty(this, 'partContents', {value:contents});
      return contents;
    },
    get cardNamePos() {
      return this.partContents.afterPos;
    },
    get cardName() {
      var len = findNullOffset(this.bytes, this.cardNamePos);
      var val = macRoman(this.bytes, this.partContents.afterPos, len);
      Object.defineProperty(this, 'cardName', {value:val});
      return val;
    },
    get cardNameAfterPos() {
      return this.cardNamePos + this.cardName.length + 1;
    },
    get cardScriptPos() {
      return this.cardNameAfterPos;
    },
    get cardScript() {
      var len = findNullOffset(this.bytes, this.cardScriptPos);
      var val = macRoman(this.bytes, this.cardScriptPos, len);
      Object.defineProperty(this, 'cardScript', {value:val});
      return val;
    },
    get cardScriptAfterPos() {
      return this.cardScriptPos + this.cardScript.length + 1;
    },
    get osaScript() {
      var pos = this.cardScriptAfterPos;
      if (pos + 4 >= this.bytes.length) return null;
      var offset = this.dataView.getUint16(pos, false);
      var len = this.dataView.getUint16(pos + 2, false);
      if (len === 0) return null;
      pos = pos + 2 + offset;
      return macRoman(this.bytes, pos, len);
    },
  };

  function PartView(buffer, byteOffset, byteLength) {

  }

  function ContentsView(buffer, byteOffset, byteLength) {

  }

  return open;

});
<commit_msg>Support null cardScript anyway<commit_after>define(['itemObjectModel', 'mac/roman'], function(itemOM, macRoman) {

  'use strict';

  function findNullOffset(bytes, pos) {
    var offset = 0;
    while (bytes[pos + offset]) offset++;
    return offset;
  }

  function versionString(bytes, pos) {
    if (!bytes[pos + 3]) return null;
    var versionString = bytes[pos] + '.' + (bytes[pos + 1] >> 4);
    if (bytes[pos + 1] & 7) versionString += '.' + (bytes[pos + 1] & 7);
    switch(bytes[pos + 2]) {
      case 0x20: versionString += 'dev'; break;
      case 0x40: versionString += 'a'; break;
      case 0x60: versionString += 'b'; break;
      case 0x80:
        if (bytes[pos + 3]) versionString += 'rel';
        break;
      default: versionString += '[u' + bytes[pos+2] + ']'; break;
    }
    if (bytes[pos + 3]) versionString += bytes[pos + 3];
    return versionString;
  }

  function open(item) {
    function onBlock(item, byteSource) {
      return byteSource.slice(0, 12).getBytes().then(function(headerBytes) {
        var dv = new DataView(
          headerBytes.buffer, headerBytes.byteOffset, headerBytes.byteLength);
        var length = dv.getUint32(0, false);
        var name = macRoman(headerBytes, 4, 4);
        var id = dv.getInt32(8, false);
        var blockItem = itemOM.createItem(name + " " + id);
        item.addItem(blockItem);
        if (length > 8) {
          blockItem.byteSource = byteSource.slice(12, length);
          switch (name) {
            case 'STAK':
              blockItem.startAddingItems();
              blockItem.notifyPopulating(blockItem.getBytes().then(function(bytes) {
                var stack = new StackView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
                blockItem.setDataObject(stack);
                for (var i = 0; i < stack.patternCount; i++) {
                  var patternItem = itemOM.createItem('pattern ' + i);
                  var patternData = stack.getRawPattern(i);
                  patternItem.withPixels(8, 8, function(pixelData) {
                    for (var y = 0; y < 8; y++) {
                      for (var x = 0; x < 8; x++) {
                        if (patternData[y] & (0x80 >> x)) {
                          pixelData[4 * (y*8 + x) + 3] = 0xff;
                        }
                      }
                    }
                  });
                  blockItem.addItem(patternItem);
                }
                var scriptItem = itemOM.createItem('script');
                scriptItem.setDataObject(stack.getScript());
                blockItem.addItem(scriptItem);
              }));
              break;
            case 'CARD': case 'BKGD':
              blockItem.startAddingItems();
              blockItem.notifyPopulating(blockItem.getBytes().then(function(bytes) {
                var card = new CardView(name === 'BKGD', bytes.buffer, bytes.byteOffset, bytes.byteLength);
                blockItem.setDataObject(card);
                if (card.cardScript) {
                  var scriptItem = itemOM.createItem('script');
                  scriptItem.setDataObject(card.cardScript);
                  blockItem.addItem(scriptItem);
                }
              }));
              break;
          }
        }
        if (byteSource.byteLength >= (length + 12)) {
          return onBlock(item, byteSource.slice(length));
        }
      });
    }
    return onBlock(item, item.byteSource);
  }

  function StackView(buffer, byteOffset, byteLength) {
    this.dataView = new DataView(buffer, byteOffset, byteLength);
    this.bytes = new Uint8Array(buffer, byteOffset, byteLength);
  }
  StackView.prototype = {
    toJSON: function() {
      return {
        version1: this.version1,
        version2: this.version2,
        version3: this.version3,
        version4: this.version4,
        cardCount: this.cardCount,
        listBlockID: this.listBlockID,
        userLevelSetting: this.userLevelSetting,
        canPeek: this.canPeek,
        canAbort: this.canAbort,
        hasPrivateAccess: this.hasPrivateAccess,
        canDelete: this.canDelete,
        canModify: this.canModify,
        screenHeight: this.screenHeight,
        screenWidth: this.screenWidth,
      };
    },
    // unknown_0x00: 0x20 bytes
    get cardCount() {
      return this.dataView.getUint32(0x20, false);
    },
    // unknown_0x24: card ID for unknown reasons
    get listBlockID() {
      return this.dataView.getInt32(0x28, false);
    },
    // unknown_0x2C: 0x10 bytes
    get userLevelSetting() {
      return this.dataView.getUint16(0x3C, false);
    },
    // unknown_0x3E: 0x02 bytes
    get flags() {
      return this.dataView.getUint16(0x40, false);
    },
    get canPeek() {
      return !(this.flags & (1 << 10));
    },
    get canAbort() {
      return !(this.flags & (1 << 11));
    },
    get hasPrivateAccess() {
      return !!(this.flags & (1 << 13));
    },
    get canDelete() {
      return !(this.flags & (1 << 14));
    },
    get canModify() {
      return !(this.flags & (1 << 15));
    },
    // unknown_0x42: 0x12 bytes
    get version1() {
      return versionString(this.bytes, 0x54);
    },
    get version2() {
      return versionString(this.bytes, 0x58);
    },
    get version3() {
      return versionString(this.bytes, 0x5C);
    },
    get version4() {
      return versionString(this.bytes, 0x60);
    },
    // unknown_0x64: 0x148 bytes
    get screenHeight() {
      return this.dataView.getUint16(0x1ac, false);
    },
    get screenWidth() {
      return this.dataView.getUint16(0x1ae, false);
    },
    // unknown_0x1AE: 0x106 bytes
    get patternCount() {
      return 40;
    },
    getRawPattern: function(n) {
      return this.bytes.subarray(0x2B4 + n * 8, 0x2B4 + (n + 1) * 8);
    },
    // unknown_0x3F4: 0x200 bytes
    getScript: function() {
      return macRoman(this.bytes, 0x5F4).replace(/\0.*/, '');
    },
  };

  function CardView(isBackground, buffer, byteOffset, byteLength) {
    this.isBackground = isBackground;
    this.dataView = new DataView(buffer, byteOffset, byteLength);
    this.bytes = new Uint8Array(buffer, byteOffset, byteLength);
  }
  CardView.prototype = {
    toJSON: function() {
      return {
        pictureBitmapID: this.pictureBitmapID,
        flags: this.flags,
        backgroundID: this.backgroundID,
        scriptType: this.scriptType,
        parts: this.parts,
        partContents: this.partContents,
        cardName: this.cardName,
        osaScript: this.osaScript,
      };
    },
    // unknown_0x0000: 4 bytes
    get pictureBitmapID() {
      return this.dataView.getInt32(0x4, false); // 0 = transparent
    },
    get flags() {
      return this.dataView.getUint16(0x8, false);
    },
    get canDelete() {
      return !(this.flags & (1 << 14));
    },
    get hideCardPicture() {
      return !!(this.flags & (1 << 13));
    },
    get dontSearch() {
      return !!(this.flags & (1 << 11));
    },
    // unknown_0x0A: 0xE bytes
    get backgroundID() {
      return this.isBackground ? null : this.dataView.getInt32(0x18, false);
    },
    offsetForBackground: function(v) {
      return this.isBackground ? v - 4 : v;
    },
    get partCount() {
      return this.dataView.getUint16(this.offsetForBackground(0x1C), false);
    },
    // unknown_0x1E: 0x6 bytes
    get partContentCount() {
      return this.dataView.getUint16(this.offsetForBackground(0x24), false);
    },
    get scriptType() {
      return this.dataView.getUint32(this.offsetForBackground(0x24), false);
    },
    get parts() {
      var parts = new Array(this.partCount);
      var pos = this.offsetForBackground(0x2A);
      for (var i = 0; i < parts.length; i++) {
        var len = this.dataView.getUint16(pos, false);
        parts[i] = new PartView(this.bytes.buffer, this.bytes.byteOffset + pos, len);
        pos += len + len%2;
      }
      parts.afterPos = pos;
      Object.defineProperty(this, 'parts', {value:parts});
      return parts;
    },
    get partContents() {
      var contents = new Array(this.partContentCount);
      var pos = this.parts.afterPos;
      for (var i = 0; i < contents.length; i++) {
        var len = this.dataView.getUint16(pos + 2, false);
        contents[i] = new ContentsView(this.bytes.buffer, this.bytes.byteOffset + pos, 4 + len);
        pos += 4 + len + len%2;
      }
      contents.afterPos = pos;
      Object.defineProperty(this, 'partContents', {value:contents});
      return contents;
    },
    get cardNamePos() {
      return this.partContents.afterPos;
    },
    get cardName() {
      var len = findNullOffset(this.bytes, this.cardNamePos);
      var val = macRoman(this.bytes, this.partContents.afterPos, len);
      Object.defineProperty(this, 'cardName', {value:val});
      return val;
    },
    get cardNameAfterPos() {
      return this.cardNamePos + this.cardName.length + 1;
    },
    get cardScriptPos() {
      return this.cardNameAfterPos;
    },
    get cardScript() {
      var len = findNullOffset(this.bytes, this.cardScriptPos);
      var val = macRoman(this.bytes, this.cardScriptPos, len);
      Object.defineProperty(this, 'cardScript', {value:val});
      return val;
    },
    get cardScriptAfterPos() {
      return this.cardScriptPos + (this.cardScript || '').length + 1;
    },
    get osaScript() {
      var pos = this.cardScriptAfterPos;
      if (pos + 4 >= this.bytes.length) return null;
      var offset = this.dataView.getUint16(pos, false);
      var len = this.dataView.getUint16(pos + 2, false);
      if (len === 0) return null;
      pos = pos + 2 + offset;
      return macRoman(this.bytes, pos, len);
    },
  };

  function PartView(buffer, byteOffset, byteLength) {

  }

  function ContentsView(buffer, byteOffset, byteLength) {

  }

  return open;

});
<|endoftext|>


<commit_before>import istanbul from 'rollup-plugin-istanbul';

//import istanbul from 'rollup-plugin-istanbul';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import multiEntry from 'rollup-plugin-multi-entry';

export default {
  input: 'tests/**/*-test.js',
  output: {
    file: 'build/bundle-test.js',
    format: 'cjs',
    sourcemap: true,
    interop: false
  },
  external: [
    'ava',
    'fs',
    'path',
    'url',
    'os',
    'net',
    'tls',
    'util',
    'events',
    'https',
    'http',
    'zlib',
    'stream',
    'tty'
  ],
  plugins: [multiEntry(), resolve(), //istanbul({
  //  exclude: ['tests/**/*-test.js']
  //})
  commonjs(), istanbul({
    exclude: ['tests/**/*-test.js', 'node_modules/**/*']
  })]
};
<commit_msg>chore(rollup): disable istanbul<commit_after>//import istanbul from 'rollup-plugin-istanbul';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import multiEntry from 'rollup-plugin-multi-entry';

export default {
  input: 'tests/**/*-test.js',
  output: {
    file: 'build/bundle-test.js',
    format: 'cjs',
    sourcemap: true,
    interop: false
  },
  external: [
    'ava',
    'fs',
    'path',
    'url',
    'os',
    'net',
    'tls',
    'util',
    'events',
    'https',
    'http',
    'zlib',
    'stream',
    'tty'
  ],
  plugins: [multiEntry(), resolve(),
  commonjs() /*, istanbul({
    exclude: ['tests/**/*-test.js', 'node_modules/**/*']
  })*/]
};
<|endoftext|>