<commit_before>var util    = require('util'),
    winston = require('winston');

var Camera,
    stream,
    isStreaming = false;

function Stream( opts ) {
    if ( !(this instanceof Stream) ) {
        return new Stream( opts );
    }

    var required = ['module', 'preview_path', 'preview', 'photo_path', 'photo'];
    for (var i in required) {
       if ('undefined' === typeof opts || 'undefined' === typeof opts[required[i]]) {
           winston.error('Error: raspberry: must define ' + required[i]);
       }
    }

    this.opts = {};
    this.setOpts(opts);
}

Stream.prototype.setOpts = function(opts) {
    this.opts = util._extend(this.opts, opts);
    this.opts.preview.output = this.formatPath(this.opts.preview_path);
    this.opts.photo.output = this.formatPath(this.opts.photo_path);

    if ('undefined' !== typeof opts.module) {
        var module = this.opts.module;
        winston.info('switch to ' + module + ' camera');
        try {
            Camera = require(module);
        } catch (e) {
            Camera = require('../' + module);
        }
    }
};

Stream.prototype.formatPath = function(path) {
    return path
        .replace('%root%', process.cwd())
        .replace('%ts%', new Date().getTime());
};

Stream.prototype.start = function(callback) {
    if (isStreaming) {
        return;
    }
    winston.info('start stream');

    var self = this;
    stream = new Camera(self.opts.preview);
    stream
        .on('change', function(err, date) {
            callback.call(this, err, date, self.opts.preview.output);
        })
        .start();
    isStreaming = true;
    return true;
};

Stream.prototype.stop = function() {
    winston.info('stop stream');

    stream.stop();
    isStreaming = false;
    return true;
};

Stream.prototype.capture = function(callback) {
    this.stop();
    this.setOpts({}); // update paths

    var self = this;

    winston.info('start capture');
    var capture = new Camera(self.opts.photo);
    capture
        .on('exit', function() {
            callback.call(this, err, new Date().getTime(), self.opts.photo.output);
            self.start(stream.listeners('change')[0]);
        })
        .start();
    return true;
};

module.exports.Stream = Stream;
<commit_msg>Fix capture bug<commit_after>var util    = require('util'),
    winston = require('winston');

var Camera,
    stream,
    isStreaming = false;

function Stream( opts ) {
    if ( !(this instanceof Stream) ) {
        return new Stream( opts );
    }

    var required = ['module', 'preview_path', 'preview', 'photo_path', 'photo'];
    for (var i in required) {
       if ('undefined' === typeof opts || 'undefined' === typeof opts[required[i]]) {
           winston.error('Error: raspberry: must define ' + required[i]);
       }
    }

    this.opts = {};
    this.setOpts(opts);
}

Stream.prototype.setOpts = function(opts) {
    this.opts = util._extend(this.opts, opts);
    this.opts.preview.output = this.formatPath(this.opts.preview_path);
    this.opts.photo.output = this.formatPath(this.opts.photo_path);

    if ('undefined' !== typeof opts.module) {
        var module = this.opts.module;
        winston.info('switch to ' + module + ' camera');
        try {
            Camera = require(module);
        } catch (e) {
            Camera = require('../' + module);
        }
    }
};

Stream.prototype.formatPath = function(path) {
    return path
        .replace('%root%', process.cwd())
        .replace('%ts%', new Date().getTime());
};

Stream.prototype.start = function(callback) {
    if (isStreaming) {
        return;
    }
    winston.info('start stream');

    var self = this;
    stream = new Camera(self.opts.preview);
    stream
        .on('change', function(err, date) {
            callback.call(this, err, date, self.opts.preview.output);
        })
        .start();
    isStreaming = true;
    return true;
};

Stream.prototype.stop = function() {
    winston.info('stop stream');

    stream.stop();
    isStreaming = false;
    return true;
};

Stream.prototype.capture = function(callback) {
    this.stop();
    this.setOpts({}); // update paths

    var self = this;

    winston.info('start capture');
    var capture = new Camera(self.opts.photo);
    capture
        .on('exit', function() {
            callback.call(this, '', new Date().getTime(), self.opts.photo.output);
            self.start(stream.listeners('change')[0]);
        })
        .start();
    return true;
};

module.exports.Stream = Stream;
<|endoftext|>


<commit_before>/** Routes for lecture related operations
  Following RESTful routing **/
module.exports = new function() {
  var _this = this;

  /**
    List all courses
    TODO: pagination sometime later
    **/
  this.index = function(req,res){
    res.render('courses/index', {
    });
  };

  /*
     New page to create a course
  */
  this.add = function(req,res){
    res.render('courses/add',{});
  };

  /**
    Create a course
    This should be only done by users with
    role as a professor
    **/
  this.create = function(req,res){
    res.redirect('/courses/'+id);
  };

  /**
    Show a course
    **/
  this.show = function(req,res){
    //get course with params[id]
    res.render('courses/show',{});
  };

  /*
     Edit a course
  */
  this.edit = function(req,res){
    res.render('courses/edit',{});
  };

  /**
    Update a course
    **/
  this.update = function(req,res){
    res.redirect('/courses/'+id);
  };

  /**
    Remove a course
    **/
  this.destroy = function(req,res){
    //remove all dependent lectures
    res.redirect('/courses/');
  };

  return this;
};
<commit_msg>added some comments for methods<commit_after>/** Routes for lecture related operations
  Following RESTful routing **/
module.exports = new function() {
  var _this = this;

  /**
    List all courses
    TODO: pagination sometime later
    **/
  this.index = function(req,res){
    res.render('courses/index', {
    });
  };

  /*
     New page to create a course
     Only professor should be able to create a course
  */
  this.add = function(req,res){
    //check if the user has Professor as one of the roles
    res.render('courses/add',{});
  };

  /**
    Create a course
    Only professors should be able to create a course
    **/
  this.create = function(req,res){
    //check if the user has Professor as one of the roles
    res.redirect('/courses/'+id);
  };

  /**
    Show a course
    **/
  this.show = function(req,res){
    //get course with params[id]
    res.render('courses/show',{});
  };

  /*
     Edit a course
  */
  this.edit = function(req,res){
    //check if the user is owner of the course (or just any professor can edit?)
    res.render('courses/edit',{});
  };

  /**
    Update a course
    **/
  this.update = function(req,res){
    //check if the user is owner of the course (or just any professor can update?)
    res.redirect('/courses/'+id);
  };

  /**
    Remove a course
    **/
  this.destroy = function(req,res){
    //check the permission
    //remove all dependent lectures
    res.redirect('/courses/');
  };

  return this;
};
<|endoftext|>


<commit_before>var voterClient = function() {
var exports = {};
//////////////////////////////////////////////////////////////////////////////////////////////

var crypto = require('./cryptofunc');
var strHexConversion = require('./strHexConversion');
var unpair = crypto.deconcatenate;
var verif = crypto.verifsig;

// SHORTCUTS

var pair = crypto.concatenate;
var enc  = crypto.pke_encrypt;
var dec  = crypto.pke_decrypt;

// TAGS (in hex encoding)

exports.TAG_ACCEPTED = "00";
exports.TAG_BALLOTS = '01';

exports.TAG_VERIFCODEAUTO = '02';
exports.TAG_VERIFCODEUSER = '03';

// Returns a new voter client instance
exports.create = function(electionID, colServVerifKey, mixServEncKeys, mixServVerifKeys)
{
    ///
    // Method createBallot
    //
    // Returns
	//  	ENC_mix1(electionID, ENC_Mix2( electionID, ... ENC_MixN(electionID, choiceMsg, verificationCode)...)
	//
	// where verificationCode ::= (TAG_VERIFCODEAUTO, receiptID) | (TAG_VERIFCODEUSER, receiptID, userCode)
    //
    // Arguments:
    //	int      	choice
	//	string		userCode: supposed to be a 10 characters string
    //
    // Returns:
    //   a receipt
    //
    function createBallot (choices, userCode) {
    	// TODO choice now is an integer. It could be an arbitrary message

        // Sort choices by number
        choices.sort(function(a,b){return a-b})
    	var choiceMsg = "";
    	for(var i=0; i < choices.length; i++){
    		choices[i] = crypto.int32ToHexString(choices[i]);
    		choiceMsg = choiceMsg + choices[i];
    	}
        var N = mixServEncKeys.length; // the number of mix servers
        var ciphertexts = new Array(N+1); // array with the chain of ciphertexts
        var randomCoins = new Array(N); // array with the used random coins

        if(userCode && userCode !== ''){ // verificationCode := (TAG_VERIFCODEUSER, receiptID, userCodeHex)
        	var userCodeHex = strHexConversion.hexEncode(userCode);
        	var receiptID = crypto.nonce().slice(0,8);
        	// only the first 8 digit of the receiptID are part of the verification code
        	var verificationCode = pair(exports.TAG_VERIFCODEUSER, pair(receiptID, userCodeHex));

        } else {	// verificationCode := (TAG_VERIFCODEAUTO, receiptID)
        	var userCode = ''; // NOTE: if userCode doesn't exist, it is set to the empty string
        	var receiptID = crypto.nonce().slice(0,18);

        	var verificationCode = pair(exports.TAG_VERIFCODEAUTO, receiptID);
        }

        ciphertexts[N] = pair(electionID, pair(choiceMsg, verificationCode));

        // encrypt the message for the chain of mix servers
        for (var i=N-1; i>=0; --i) {
            var r = crypto.pke_generateEncryprionCoins();
        	ciphertexts[i] = enc(mixServEncKeys[i], pair(electionID, ciphertexts[i+1]), r);
            randomCoins[i] = r;
        }

        ballot = ciphertexts[0];

        return { electionID: electionID,
                 ballot: ballot,
                 choice: choices,
                 userCode: userCode,
                 receiptID: receiptID,
                 ciphertexts: ciphertexts,
                 randomCoins: randomCoins};
    }

    ///
    // Method validateReceipt
    //
    // Returns true if the given receipt is valid
    //
    function validateReceipt (receipt) {
        // check if there is no mismatch of election ids
        if (electionID !== receipt.electionID) return false;
        // check the signature
        message = pair(exports.TAG_ACCEPTED, pair(electionID, receipt.ballot));
        return crypto.verifsig(colServVerifKey, message, receipt.signature);
    }

    ///
    // Check the result of the collecting server against the given
    // receipt.
    //
    function checkColServerResult(data, receipt) {
        var res = validServerOutput(receipt.ciphertexts[0], data, colServVerifKey);
        if (res.blame) {
            // We need to add the blaming info to res.
            // In this case it is the signature of the collecting
            // server and expected ballot:
            //
            res.blamingData = {
                electionID: receipt.electionID,
                signature: receipt.signature, // the signature of the collecting server
                ballot: receipt.ballot // the ballot signed by the collecting server (==ciphertexts[0])
            }
        }
        return res;
    }

    ///
    // Check the result of the mix server with the given index
    // against the given receipt.
    //
    function checkMixServerResult(i, data, receipt) {
        var res = validServerOutput(receipt.ciphertexts[i+1], data, mixServVerifKeys[i]);
        if (res.blame) {
            // We need to add the blaming info to res.
            // In this case it input ciphertext (our ciphertex in
            // the output of the previous mix server) and the
            // missing ciphertext (not found in the output)
            //
            res.blamingData = {
                electionID: receipt.electionID,
                mixServer: i,
                mixServerEncKey: mixServEncKeys[i],
                previousCiphertext: receipt.ciphertexts[i],
                missingCiphertext:  receipt.ciphertexts[i+1],
                encryptionRandomness: receipt.randomCoins[i]
            }
        }
        return res;
    }

    // PRIVATE METHODS

    function validServerOutput(item, data, verificationKey) {
		var p = unpair(data);
		data = p.first; // tag,elID,...
		var signature = p.second;
        // check the signature
        if (!verif(verificationKey, data, signature))
            return {ok:false, blame:false, descr:'Wrong signature'};

        data = crypto.splitter(data);

		if (data.nextMessage() !== exports.TAG_BALLOTS) // expected the tag
            return {ok:false, blame:false, descr:'Wrong tag'};

        var x = data.nextMessage();
        if (x !== electionID)  // expected the election id
        {
            return {ok:false, blame:false, descr:'Wrong election ID'};
        }

        // The rest of data is a list of ballots.
        // Make sure that item is on this list.
        for (var i=0; !data.empty(); ++i) {
            if (item === data.nextMessage())
                return {ok:true, blame:false, descr:"Everything is fine"};
        }

        blamingData = {}
        return {ok:false, blame:true, descr:"Ballot not found"};
    }

    return { createBallot: createBallot,
             validateReceipt: validateReceipt,
             checkColServerResult: checkColServerResult,
             checkMixServerResult: checkMixServerResult };
}

//////////////////////////////////////////////////////////////////////////////////////////////
return exports;
}();

if (typeof(module)!=='undefined' && module.exports) {
    module.exports = voterClient;
}

<commit_msg>prevent dublicate choices<commit_after>var voterClient = function() {
var exports = {};
//////////////////////////////////////////////////////////////////////////////////////////////

var crypto = require('./cryptofunc');
var strHexConversion = require('./strHexConversion');
var unpair = crypto.deconcatenate;
var verif = crypto.verifsig;

// SHORTCUTS

var pair = crypto.concatenate;
var enc  = crypto.pke_encrypt;
var dec  = crypto.pke_decrypt;

// TAGS (in hex encoding)

exports.TAG_ACCEPTED = "00";
exports.TAG_BALLOTS = '01';

exports.TAG_VERIFCODEAUTO = '02';
exports.TAG_VERIFCODEUSER = '03';

// Returns a new voter client instance
exports.create = function(electionID, colServVerifKey, mixServEncKeys, mixServVerifKeys)
{
    ///
    // Method createBallot
    //
    // Returns
	//  	ENC_mix1(electionID, ENC_Mix2( electionID, ... ENC_MixN(electionID, choiceMsg, verificationCode)...)
	//
	// where verificationCode ::= (TAG_VERIFCODEAUTO, receiptID) | (TAG_VERIFCODEUSER, receiptID, userCode)
    //
    // Arguments:
    //	int      	choice
	//	string		userCode: supposed to be a 10 characters string
    //
    // Returns:
    //   a receipt
    //
    function createBallot (choices, userCode) {
    	// TODO choice now is an integer. It could be an arbitrary message

        // remove dublicates and sort choices by number
        choices = $.unique(choices);
        choices.sort(function(a,b){return a-b})
    	var choiceMsg = "";
    	for(var i=0; i < choices.length; i++){
    		choices[i] = crypto.int32ToHexString(choices[i]);
    		choiceMsg = choiceMsg + choices[i];
    	}
        var N = mixServEncKeys.length; // the number of mix servers
        var ciphertexts = new Array(N+1); // array with the chain of ciphertexts
        var randomCoins = new Array(N); // array with the used random coins

        if(userCode && userCode !== ''){ // verificationCode := (TAG_VERIFCODEUSER, receiptID, userCodeHex)
        	var userCodeHex = strHexConversion.hexEncode(userCode);
        	var receiptID = crypto.nonce().slice(0,8);
        	// only the first 8 digit of the receiptID are part of the verification code
        	var verificationCode = pair(exports.TAG_VERIFCODEUSER, pair(receiptID, userCodeHex));

        } else {	// verificationCode := (TAG_VERIFCODEAUTO, receiptID)
        	var userCode = ''; // NOTE: if userCode doesn't exist, it is set to the empty string
        	var receiptID = crypto.nonce().slice(0,18);

        	var verificationCode = pair(exports.TAG_VERIFCODEAUTO, receiptID);
        }

        ciphertexts[N] = pair(electionID, pair(choiceMsg, verificationCode));

        // encrypt the message for the chain of mix servers
        for (var i=N-1; i>=0; --i) {
            var r = crypto.pke_generateEncryprionCoins();
        	ciphertexts[i] = enc(mixServEncKeys[i], pair(electionID, ciphertexts[i+1]), r);
            randomCoins[i] = r;
        }

        ballot = ciphertexts[0];

        return { electionID: electionID,
                 ballot: ballot,
                 choice: choices,
                 userCode: userCode,
                 receiptID: receiptID,
                 ciphertexts: ciphertexts,
                 randomCoins: randomCoins};
    }

    ///
    // Method validateReceipt
    //
    // Returns true if the given receipt is valid
    //
    function validateReceipt (receipt) {
        // check if there is no mismatch of election ids
        if (electionID !== receipt.electionID) return false;
        // check the signature
        message = pair(exports.TAG_ACCEPTED, pair(electionID, receipt.ballot));
        return crypto.verifsig(colServVerifKey, message, receipt.signature);
    }

    ///
    // Check the result of the collecting server against the given
    // receipt.
    //
    function checkColServerResult(data, receipt) {
        var res = validServerOutput(receipt.ciphertexts[0], data, colServVerifKey);
        if (res.blame) {
            // We need to add the blaming info to res.
            // In this case it is the signature of the collecting
            // server and expected ballot:
            //
            res.blamingData = {
                electionID: receipt.electionID,
                signature: receipt.signature, // the signature of the collecting server
                ballot: receipt.ballot // the ballot signed by the collecting server (==ciphertexts[0])
            }
        }
        return res;
    }

    ///
    // Check the result of the mix server with the given index
    // against the given receipt.
    //
    function checkMixServerResult(i, data, receipt) {
        var res = validServerOutput(receipt.ciphertexts[i+1], data, mixServVerifKeys[i]);
        if (res.blame) {
            // We need to add the blaming info to res.
            // In this case it input ciphertext (our ciphertex in
            // the output of the previous mix server) and the
            // missing ciphertext (not found in the output)
            //
            res.blamingData = {
                electionID: receipt.electionID,
                mixServer: i,
                mixServerEncKey: mixServEncKeys[i],
                previousCiphertext: receipt.ciphertexts[i],
                missingCiphertext:  receipt.ciphertexts[i+1],
                encryptionRandomness: receipt.randomCoins[i]
            }
        }
        return res;
    }

    // PRIVATE METHODS

    function validServerOutput(item, data, verificationKey) {
		var p = unpair(data);
		data = p.first; // tag,elID,...
		var signature = p.second;
        // check the signature
        if (!verif(verificationKey, data, signature))
            return {ok:false, blame:false, descr:'Wrong signature'};

        data = crypto.splitter(data);

		if (data.nextMessage() !== exports.TAG_BALLOTS) // expected the tag
            return {ok:false, blame:false, descr:'Wrong tag'};

        var x = data.nextMessage();
        if (x !== electionID)  // expected the election id
        {
            return {ok:false, blame:false, descr:'Wrong election ID'};
        }

        // The rest of data is a list of ballots.
        // Make sure that item is on this list.
        for (var i=0; !data.empty(); ++i) {
            if (item === data.nextMessage())
                return {ok:true, blame:false, descr:"Everything is fine"};
        }

        blamingData = {}
        return {ok:false, blame:true, descr:"Ballot not found"};
    }

    return { createBallot: createBallot,
             validateReceipt: validateReceipt,
             checkColServerResult: checkColServerResult,
             checkMixServerResult: checkMixServerResult };
}

//////////////////////////////////////////////////////////////////////////////////////////////
return exports;
}();

if (typeof(module)!=='undefined' && module.exports) {
    module.exports = voterClient;
}

<|endoftext|>


<commit_before>"use strict";

({define:typeof define!="undefined"?define:function(deps, factory){module.exports = factory(exports, require("./parser"));}}).
define(["exports", "./parser"], function(exports, parser){

	function short(fullname){
		var n = fullname.split(":");
		return (n[0]+n[1].charAt(0).toUpperCase()+n[1].substr(1)).replace(/#|-/g,"");
	}

	function Transpiler(execute){
		this.dict = {};
		this.lib = {};
		this.cache = [];
		this.count = 0;
	}

	Transpiler.prototype.use = function(value,params,callback){
		// TODO filter and separate core definitions
		var modulePath = params.modules || "raddle/modules.json";
		var textPrefix = params.moduleTextPrefix || "text!";
		var defaultNamespace = params.defaultNamespace || "fn";
		var use = value.args;
		var self = this;
		// TODO: core is bound, use namespace mapping for external modules
		// OR assume flat collections
		require(use,function(){
			var libs = Array.prototype.slice.call(arguments);
			libs.forEach(function(lib,i){
				for(var k in lib){
					var name = use[i].split("/")[0]+":"+k;
					if(!self.lib[name]) self.lib[name] = lib[k];
				}
			});
			var reqs = use.map(function(_){
				return textPrefix+"raddled/"+_+".rdl";
			});
			require(reqs,function(){
				var deps = Array.prototype.slice.call(arguments);
				deps.forEach(function(dep,i){
					var parsed = parser.parse(dep);
					if(parsed.args.length) self.process(parsed,{use:use[i]},callback);
				});
				if(callback) callback();
			});
		});
	};

	Transpiler.prototype.transpile = function(value,params){
		this.cache = [];
		var ret = this.process(value,params).filter(function(_){
			return !!_;
		}).pop();
		if(params.callback) {

		}
		return ret;
	};

	Transpiler.prototype.process = function(value,params,callback){
		var args = Array.prototype.slice.call(arguments);
		var value = args.shift();
		var params = args.length>1 && typeof args[0]!="function" ? args.shift() : {};
		var callback = args.shift();
		if(typeof value == "string") value = parser.parse(value);
		if(value.name=="use"){
			this.use(value,params,callback);
		} else if(value.name=="define"){
			this.define(value,params);
		} else if(value.name=="" && value.args) {
			var self=this,use,define=[],args=[];
			value.args.forEach(function(arg){
				if(arg.name=="use") {
					use = arg;
				} else if(arg.name=="define"){
					define.push(arg);
				} else {
					args.push(arg);
				}
			});
			var cb = !params.use && !!callback ? callback : function(){};
			callback = function(){
				define.forEach(function(arg){
					self.define(arg,params);
				});
				var ret = args.map(function(arg){
					return self.process(arg,params,callback);
				}).pop();
				// always return a function
				if(!ret) ret = function anon0() {};
				cb(null,ret);
			};
			use ? this.use(use,params,callback) : callback();
		} else {
			value.top = true;
			return this.compile(value,null,false,params);
		}
	};

	function typeOf(o) {
		return o === undefined ? "undefined" : o === null ? "null" : o.constructor.name.toLowerCase();
	}

	Transpiler.prototype.typeCheck = function(value,type){
		// TODO check occurrence and function arity+types
		var t = typeOf(type) == "array" ? "function" : type.replace(/\?|\+|\*|-/,"");
		return typeOf(value)==t || t=="any";
	};

	var autoConverted = {
		"true": true,
		"false": false,
		"null": null,
		"undefined": undefined,
		"Infinity": Infinity,
		"-Infinity": -Infinity
	};

	Transpiler.prototype.convert = function(string){
		if(autoConverted.hasOwnProperty(string)){
			return autoConverted[string];
		}
		var number = +string;
		if(isNaN(number) || number.toString() !== string){
			/*var isoDate = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?Z$/.exec(x);
			if (isoDate) {
			date = new Date(Date.UTC(+isoDate[1], +isoDate[2] - 1, +isoDate[3], +isoDate[4], +isoDate[5], +isoDate[6], +isoDate[7] || 0));
			}*/
			string = decodeURIComponent(string);
			if(exports.jsonQueryCompatible){
				if(string.charAt(0) == "'" && string.charAt(string.length-1) == "'"){
					return JSON.parse('"' + string.substring(1,string.length-1) + '"');
				}
			}
			return string;
		}
		return number;
	};

	Transpiler.prototype.getFunction = function(fullname){
		return this.lib[fullname];
	};

	Transpiler.prototype.getFunctionDef = function(qname,arity){
		if(!this.dict[qname]) return;
		return this.dict[qname][arity+1] ? this.dict[qname][arity+1] : this.dict[qname][0];
	};

	Transpiler.prototype.coerce = function(value,type){
		// should we infer and check?
		if (type === 'string') {
			value = value ? '' + value : '';
		} else if (type === 'number') {
			value = +value;
		} else if (type === 'boolean') {
			value = !!value;
//		} else if (type === 'array') {
//			if(!(value instanceof Array)) value = new Array();
//		} else if (type === 'object') {
//			if(!(value instanceof Object)) value = new Object();
		} else if (type instanceof Array) {
			var def = this.dict[value];
			value = this.lib[def.module][value];
		}
		return value;
	};

	Transpiler.prototype.type = function(t){
		var ts = ["null","number","string","boolean","node","map","function","any"];
		// return tuple: [type,cardinality]
		var rt = new Array(2);
		var card = -1;
		var type = 0;
		// TODO ?
		var re = /(\*)|(\+)|(\-)/;
		var gr = t.match(re);
		if(gr) {
			var i=0,l=gr.length;
			for(;i<l;i++){
				if(gr[i+1]) break;
			}
			card = i;
		}
		type = ts.indexOf(t.replace(re,""));
		return [type,card];
	};

	Transpiler.prototype.matchTypes = function(i,o){
		var ti = this.type(i);
		var to = this.type(o);
		//console.warn(i,ti,"->",o,to);
		// cardinality checks:
		// string->string* -1->0 => allow
		// string*->string 0->-1 => deny
		// string->string+ -1->1 => deny
		// string*->string+ 0->1 => allow (runtime check)
		// string->any 2->7 => allow
		// any->string 7->2 => allow (infer+check @ runtime)
		var d = to[1]-ti[1];
		return (ti[0]==to[0] || to[0]==7 || ti[0]==7) && d>=0 && d<=1;
	};

	Transpiler.prototype.compile = function(value,parent,compose,params){
		var self = this;
		var isSeq = typeOf(value)=="array";
		var top = isSeq ? false : value.top;
		var fargs = parent ? parent.args.map(function(_,i){
			return "arg" + (i+1);
		}).join(",") : "arg0";
		var fname = "anon"+this.count;
		if(parent){
			var parity = parent.more ? "N" : parent.args.length;
			fname = short(parent.name+"#"+parity);
		} else if(top) {
			this.count++;
		}
		if(isSeq) {
			var seq = value.map(function(_){
				if(typeOf(_)=="query"){
					// compose the functions in the array
					return "arg0 = "+this.compile(_,null,true,params).toString()+";\n";
				} else {
					return _;
				}
			},this);
			var pre = parent ? "var arg0;\n" : "";
			return new Function("return function "+fname+"("+fargs+"){\n"+pre+seq.join("")+"return arg0;\n}")();
		}
		var name = value.name,
			args = value.args,
			defaultNamespace = params.defaultNamespace || "fn";
		if(!name.match(/:/)) name = defaultNamespace+":"+name;
		var def = this.getFunctionDef(name,args.length);
		var fullname = name+"#"+(def.more ? "N" : def.args.length);
		if(this.cache.indexOf(fullname)==-1) this.cache.push(fullname);
		args = args.map(function(_){
			if(typeOf(_) == "array") {
				return this.compile(_,null,null,params).toString();
			} else if(typeOf(_) == "query") {
				return this.compile(_,null,null,params).toString();
			} else if(_.match(/^(\.\/)|\.$/)) {
				return _;
			} else if(_.match(/^\$[0-9]+$/)) {
				return _.replace(/^\$([0-9]+)$/,"arg$1");
			} else {
				var r = this.convert(_);
				if(typeof r=="string" && r.match(/^.+#[0-9]+$/)){
					var fullname = (r.indexOf(":")>-1 ? r : "core:"+r);
					if(this.cache.indexOf(fullname)==-1) this.cache.push(fullname);
					return short(fullname);
				}
				// check type here
				//if(!this.typeCheck(r,t)){
				//	throw new Error("Expected type ",t," for argument value ",r);
				//}
				return JSON.stringify(r);
			}
		},this);
		var args2 = args.reduce(function(pre,cur,i){
			if(cur.match(/^(\.\/)|\.$/)) {
				pre.push("arg0");
			} else {
				var s = pre.length-1;
				var last = pre[s];
				if(last.match(/^(\.\/)|\.$/) || s<1) {
					pre.push(cur);
				} else {
					pre[s] = last + "," + cur;
				}
			}
			return pre;
		},[short(fullname) + "("]);
		args2.push(")");
		var fn = args2.join("");
		if(compose) return fn;
		var fns = "\n";
		if(top) {
			for(var i=0;i<this.cache.length;i++){
				var f = this.getFunction(this.cache[i]);
				fns += "var "+short(this.cache[i])+"="+f.toString()+";\n";
			}
		}
		return new Function("return function "+fname+"("+fargs+"){ "+fns+"return "+fn+";}")();
	};

	Transpiler.prototype.define = function(value,params){
		this.cache = [];
		var l = value.args.length;
		var parts = value.args[0].split(":");
		var name = parts.pop();
		var module = "";
		var ns = parts.length ? parts[0] : "local";
		var type, args = [], qname;
		var body,def;
		if(l==2){
			// lookup
			def = this.dict[value.args[1]];
			if(!def) {
				throw new Error("Unknown reference in definition "+name);
			}
			type = def.type;
			args = def.args;
			body = def.body;
			module = def.module;
			qname = ns+":"+name;
		} else if(l==3 || l==4){
			if(l==3) {
				module = params.use;
				if(ns=="local"){
					ns = module.split("/")[0];
				}
			} else {
				body = value.args[3];
				module = ns;
			}
			// core
			args = value.args[1];
			type = value.args[2];
			qname = ns+":"+name;
		}
		var len = args.length;
		// check if more argument of last type is allowed
		var last = args[len-1];
		var more = typeOf(last) == "string" ? last.substr(-1) === "-" : false;
		var arity = more ? -1 : len;
		var existing = this.getFunctionDef(qname,arity);
		if(existing) return existing;
		def = {
			name:qname,
			type:type,
			args:args,
			more:more,
			body:body,
			module:module
		};
		if(!this.dict[qname]){
			this.dict[qname] = [];
		}
		this.dict[qname][arity+1] = def;
		if(l==4) {
			// compile definition
			this.lib[qname+"#"+(arity<0 ? "N" : arity)] = this.compile(body,def,false,params);
		}
		return def;
	};
	exports.Transpiler = Transpiler;

	return exports;
});<commit_msg>check sequence type, throw error if not compatible<commit_after>"use strict";

({define:typeof define!="undefined"?define:function(deps, factory){module.exports = factory(exports, require("./parser"));}}).
define(["exports", "./parser"], function(exports, parser){

	function short(fullname){
		var n = fullname.split(":");
		return (n[0]+n[1].charAt(0).toUpperCase()+n[1].substr(1)).replace(/#|-/g,"");
	}

	function Transpiler(execute){
		this.dict = {};
		this.lib = {};
		this.cache = [];
		this.count = 0;
	}

	Transpiler.prototype.use = function(value,params,callback){
		// TODO filter and separate core definitions
		var modulePath = params.modules || "raddle/modules.json";
		var textPrefix = params.moduleTextPrefix || "text!";
		var defaultNamespace = params.defaultNamespace || "fn";
		var use = value.args;
		var self = this;
		// TODO: core is bound, use namespace mapping for external modules
		// OR assume flat collections
		require(use,function(){
			var libs = Array.prototype.slice.call(arguments);
			libs.forEach(function(lib,i){
				for(var k in lib){
					var name = use[i].split("/")[0]+":"+k;
					if(!self.lib[name]) self.lib[name] = lib[k];
				}
			});
			var reqs = use.map(function(_){
				return textPrefix+"raddled/"+_+".rdl";
			});
			require(reqs,function(){
				var deps = Array.prototype.slice.call(arguments);
				deps.forEach(function(dep,i){
					var parsed = parser.parse(dep);
					if(parsed.args.length) self.process(parsed,{use:use[i]},callback);
				});
				if(callback) callback();
			});
		});
	};

	Transpiler.prototype.transpile = function(value,params){
		this.cache = [];
		var ret = this.process(value,params).filter(function(_){
			return !!_;
		}).pop();
		if(params.callback) {

		}
		return ret;
	};

	Transpiler.prototype.process = function(value,params,callback){
		var args = Array.prototype.slice.call(arguments);
		var value = args.shift();
		var params = args.length>1 && typeof args[0]!="function" ? args.shift() : {};
		var callback = args.shift();
		if(typeof value == "string") value = parser.parse(value);
		if(value.name=="use"){
			this.use(value,params,callback);
		} else if(value.name=="define"){
			this.define(value,params);
		} else if(value.name=="" && value.args) {
			var self=this,use,define=[],args=[];
			value.args.forEach(function(arg){
				if(arg.name=="use") {
					use = arg;
				} else if(arg.name=="define"){
					define.push(arg);
				} else {
					args.push(arg);
				}
			});
			var cb = !params.use && !!callback ? callback : function(){};
			callback = function(){
				define.forEach(function(arg){
					self.define(arg,params);
				});
				var ret = args.map(function(arg){
					return self.process(arg,params,callback);
				}).pop();
				// always return a function
				if(!ret) ret = function anon0() {};
				cb(null,ret);
			};
			use ? this.use(use,params,callback) : callback();
		} else {
			value.top = true;
			return this.compile(value,null,false,params);
		}
	};

	function typeOf(o) {
		return o === undefined ? "undefined" : o === null ? "null" : o.constructor.name.toLowerCase();
	}

	Transpiler.prototype.typeCheck = function(value,type){
		// TODO check occurrence and function arity+types
		var t = typeOf(type) == "array" ? "function" : type.replace(/\?|\+|\*|-/,"");
		return typeOf(value)==t || t=="any";
	};

	var autoConverted = {
		"true": true,
		"false": false,
		"null": null,
		"undefined": undefined,
		"Infinity": Infinity,
		"-Infinity": -Infinity
	};

	Transpiler.prototype.convert = function(string){
		if(autoConverted.hasOwnProperty(string)){
			return autoConverted[string];
		}
		var number = +string;
		if(isNaN(number) || number.toString() !== string){
			/*var isoDate = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?Z$/.exec(x);
			if (isoDate) {
			date = new Date(Date.UTC(+isoDate[1], +isoDate[2] - 1, +isoDate[3], +isoDate[4], +isoDate[5], +isoDate[6], +isoDate[7] || 0));
			}*/
			string = decodeURIComponent(string);
			if(exports.jsonQueryCompatible){
				if(string.charAt(0) == "'" && string.charAt(string.length-1) == "'"){
					return JSON.parse('"' + string.substring(1,string.length-1) + '"');
				}
			}
			return string;
		}
		return number;
	};

	Transpiler.prototype.getFunction = function(fullname){
		return this.lib[fullname] ? this.lib[fullname] : this.lib[fullname.replace(/#.*$/,"")];
	};

	Transpiler.prototype.getFunctionDef = function(qname,arity){
		if(!this.dict[qname]) return;
		return this.dict[qname][arity+1] ? this.dict[qname][arity+1] : this.dict[qname][0];
	};

	Transpiler.prototype.coerce = function(value,type){
		// should we infer and check?
		if (type === 'string') {
			value = value ? '' + value : '';
		} else if (type === 'number') {
			value = +value;
		} else if (type === 'boolean') {
			value = !!value;
//		} else if (type === 'array') {
//			if(!(value instanceof Array)) value = new Array();
//		} else if (type === 'object') {
//			if(!(value instanceof Object)) value = new Object();
		} else if (type instanceof Array) {
			var def = this.dict[value];
			value = this.lib[def.module][value];
		}
		return value;
	};

	Transpiler.prototype.type = function(t){
		var ts = ["null","number","string","boolean","node","map","function","any"];
		// return tuple: [type,cardinality]
		var rt = new Array(2);
		var card = -1;
		var type = 0;
		// TODO ?
		var re = /(\*)|(\+)|(\-)/;
		var gr = t.match(re);
		if(gr) {
			var i=0,l=gr.length;
			for(;i<l;i++){
				if(gr[i+1]) break;
			}
			card = i;
		}
		type = ts.indexOf(t.replace(re,""));
		return [type,card];
	};

	Transpiler.prototype.matchTypes = function(i,o){
		var ti = this.type(i);
		var to = this.type(o);
		//console.warn(i,ti,"->",o,to);
		// cardinality checks:
		// string->string* -1->0 => allow
		// string*->string 0->-1 => deny
		// string->string+ -1->1 => deny
		// string*->string+ 0->1 => allow (runtime check)
		// string->any 2->7 => allow
		// any->string 7->2 => allow (infer+check @ runtime)
		var d = to[1]-ti[1];
		return (ti[0]==to[0] || to[0]==7 || ti[0]==7) && d>=0 && d<=1;
	};

	Transpiler.prototype.getSeqType = function(seq){
		var type = 0;
		for(var i=0,l=seq.length;i<l;i++){
			var itemType = typeOf(seq[i])=="query" ? 1 : seq[i].indexOf(":") > -1 ? 2 : 3;
			if(type<1 || type==itemType){
					type = itemType;
			} else {
				throw new Error("Mixing sequence types is not allowed");
			}
		}
		return type;
	};

	Transpiler.prototype.compile = function(value,parent,compose,params){
		var self = this;
		var isSeq = typeOf(value)=="array";
		var ret,seqType;
		if(isSeq) {
			seqType = this.getSeqType(value);
			if(seqType==1) {
				ret = value.reduce(function(pre,cur,i){
					if(typeOf(cur)=="query"){
						// compose the functions in the array
						var c = self.compile(cur,null,true,params);
						console.log(c)
						var p = c.length>1 ? c[1].split(",") : [];
						if(parent && p.length>0 && p[0]=="arg0") p.shift();
						var t = (p.length && i>0 ? "," : "") + p.join(",");
						return c[0]+pre+t+")";
					}
				},"");
			} else {
				if(seqType==2){
					ret = {};
					var vals = value.forEach(function(_){
						var p = _.split(":");
						ret[p[0].trim()] = this.convert(p[1].trim());
					},this);
				} else {
					ret = value.map(function(_){
						return this.convert(_);
					},this);
				}
				return JSON.stringify(ret);
			}
		}
		var top = isSeq ? false : value.top;
		var fargs = parent ? parent.args.map(function(_,i){
			return "arg" + (i+1);
		}).join(",") : "arg0";
		var fname = "anon"+this.count;
		if(parent){
			var parity = parent.more ? "N" : parent.args.length;
			fname = short(parent.name+"#"+parity);
		} else if(top) {
			this.count++;
		}
		if(isSeq && seqType==1){
			//var pre = parent ? "var arg0;\n" : "";
			return new Function("return function "+fname+"("+fargs+"){\nreturn "+ret+";\n}")();
		}
		var name = value.name,
			args = value.args,
			defaultNamespace = params.defaultNamespace || "fn";
		if(!name.match(/:/)) name = defaultNamespace+":"+name;
		var def = this.getFunctionDef(name,args.length);
		var fullname = name+"#"+(def.more ? "N" : def.args.length);
		if(this.cache.indexOf(fullname)==-1) this.cache.push(fullname);
		// exec is true if there are no args or the args don't contain variables
		args = args.map(function(_){
			if(typeOf(_) == "array") {
				return this.compile(_,null,null,params).toString();
			} else if(typeOf(_) == "query") {
				return this.compile(_,null,null,params).toString();
			} else if(_.match(/^(\.\/)|\.$/)) {
				return _;
			} else if(_.match(/^\$[0-9]+$/)) {
				return _.replace(/^\$([0-9]+)$/,"arg$1");
			} else {
				var r = this.convert(_);
				if(typeof r=="string" && r.match(/^.+#[0-9]+$/)){
					var fullname = (r.indexOf(":")>-1 ? r : "core:"+r);
					if(this.cache.indexOf(fullname)==-1) this.cache.push(fullname);
					return short(fullname);
				}
				// check type here
				//if(!this.typeCheck(r,t)){
				//	throw new Error("Expected type ",t," for argument value ",r);
				//}
				return JSON.stringify(r);
			}
		},this);
		var args2 = args.reduce(function(pre,cur,i){
			if(cur.match(/^(\.\/)|\.$/)) {
				pre.push("arg0");
			} else {
				var s = pre.length-1;
				var last = pre[s];
				if(last.match(/^(\.\/)|\.$/) || s<1) {
					pre.push(cur);
				} else {
					pre[s] = last + "," + cur;
				}
			}
			return pre;
		},[short(fullname) + "("]);
		if(compose) return args2;
		args2.push(")");
		var fn = args2.join("");
		if(!parent && !top) return fn;
		var fns = "\n";
		if(top) {
			for(var i=0;i<this.cache.length;i++){
				var f = this.getFunction(this.cache[i]);
				var r = new RegExp(f.name+"\\s?\\(","g");
				fns += f.toString().replace(r,short(this.cache[i])+"(")+";\n";
			}
		}
		return new Function("return function "+fname+"("+fargs+"){ "+fns+"return "+fn+";\n}")();
	};

	Transpiler.prototype.define = function(value,params){
		this.cache = [];
		var l = value.args.length;
		var parts = value.args[0].split(":");
		var name = parts.pop();
		var module = "";
		var ns = parts.length ? parts[0] : "local";
		var type, args = [], qname;
		var body,def;
		if(l==2){
			// lookup
			def = this.dict[value.args[1]];
			if(!def) {
				throw new Error("Unknown reference in definition "+name);
			}
			type = def.type;
			args = def.args;
			body = def.body;
			module = def.module;
			qname = ns+":"+name;
		} else if(l==3 || l==4){
			if(l==3) {
				module = params.use;
				if(ns=="local"){
					ns = module.split("/")[0];
				}
			} else {
				body = value.args[3];
				module = ns;
			}
			// core
			args = value.args[1];
			type = value.args[2];
			qname = ns+":"+name;
		}
		var len = args.length;
		// check if more argument of last type is allowed
		var last = args[len-1];
		var more = typeOf(last) == "string" ? last.substr(-1) === "-" : false;
		var arity = more ? -1 : len;
		var existing = this.getFunctionDef(qname,arity);
		if(existing) return existing;
		def = {
			name:qname,
			type:type,
			args:args,
			more:more,
			body:body,
			module:module
		};
		if(!this.dict[qname]){
			this.dict[qname] = [];
		}
		this.dict[qname][arity+1] = def;
		if(l==4) {
			// compile definition
			this.lib[qname+"#"+(arity<0 ? "N" : arity)] = this.compile(body,def,false,params);
		}
		return def;
	};
	exports.Transpiler = Transpiler;

	return exports;
});<|endoftext|>


<commit_before>'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const shim = require('@html-next/flexi-layouts/lib/pod-templates-shim');

shim(EmberApp);

module.exports = function(defaults) {
  const app = new EmberApp(defaults, {
    emberCliConcat: {
      js: {
        concat: true,
        useAsync: true
      },
      css: {
        concat: false
      }
    },
    'esw-index': {
      location: '_empty.html'
    },
    fingerprint: {
      extensions: ['js', 'css', 'map']
    },
    inlineContent: {
      app: 'inline/styles/app.css',
      'asset-cache': {
        include: [
          'assets/**/*',
          'index.html',
          'contact/index.html',
          'ember-consulting/index.html',
          'open-source/index.html'
        ]
      },
      contact: 'inline/styles/contact.css',
      'ember-consulting': 'inline/styles/ember-consulting.css',
      fonts: 'inline/styles/fonts.css',
      'google-analytics': {
        file: 'inline/ga.js',
        enabled: process.env.EMBER_ENV === 'production'
      },
      home: 'inline/styles/home.css',
      loadCSS: 'inline/loadCSS.js',
      'loading-indicator': {
        file: 'inline/loading-indicator.html',
        enabled: false
      },
      'open-source': 'inline/styles/open-source.css'
    },
    prember: {
      urls: [
        '/',
        '/ember-consulting',
        '/open-source',
        '/contact'
      ]
    },
    SRI: {
      enabled: false
    },
    treeShaking: {
      enabled: true,
      include: [
        'ember-validators/format.js',
        'ember-validators/presence.js'
      ]
    },
    vendorFiles: { 'jquery.js': null }
  });

  return app.toTree();
};
<commit_msg>Remove index<commit_after>'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const shim = require('@html-next/flexi-layouts/lib/pod-templates-shim');

shim(EmberApp);

module.exports = function(defaults) {
  const app = new EmberApp(defaults, {
    emberCliConcat: {
      js: {
        concat: true,
        useAsync: true
      },
      css: {
        concat: false
      }
    },
    'esw-index': {
      location: '_empty.html'
    },
    fingerprint: {
      extensions: ['js', 'css', 'map']
    },
    inlineContent: {
      app: 'inline/styles/app.css',
      'asset-cache': {
        include: [
          'assets/**/*',
          'contact/index.html',
          'ember-consulting/index.html',
          'open-source/index.html'
        ]
      },
      contact: 'inline/styles/contact.css',
      'ember-consulting': 'inline/styles/ember-consulting.css',
      fonts: 'inline/styles/fonts.css',
      'google-analytics': {
        file: 'inline/ga.js',
        enabled: process.env.EMBER_ENV === 'production'
      },
      home: 'inline/styles/home.css',
      loadCSS: 'inline/loadCSS.js',
      'loading-indicator': {
        file: 'inline/loading-indicator.html',
        enabled: false
      },
      'open-source': 'inline/styles/open-source.css'
    },
    prember: {
      urls: [
        '/',
        '/ember-consulting',
        '/open-source',
        '/contact'
      ]
    },
    SRI: {
      enabled: false
    },
    treeShaking: {
      enabled: true,
      include: [
        'ember-validators/format.js',
        'ember-validators/presence.js'
      ]
    },
    vendorFiles: { 'jquery.js': null }
  });

  return app.toTree();
};
<|endoftext|>


<commit_before>/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-addon');

module.exports = function(defaults) {
  var app = new EmberApp(defaults, {
    // Add options here
  });

  /*
    This build file specifes the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree();
};
<commit_msg>Temp fix for failing test<commit_after>/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-addon');
module.exports = function(/* defaults */) { // Temp fix for failing test
  var app = new EmberApp(/* defaults, */ {
    // Add options here
  });

  /*
    This build file specifies the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree();
};
<|endoftext|>


<commit_before>"use strict";

function centered_modal(message) {
    var result = new Modal();
    result.message = message;
    var screen_frame = Screen.mainScreen().frameInRectangle();
    var result_frame = result.frame();
    result.origin = {
        x: 0.5 * (screen_frame.width - result_frame.width),
        y: 0.5 * (screen_frame.height - result_frame.height),
    };
    return result;
}

var h_reload = Phoenix.bind('r', ['alt'], function () {
    Phoenix.reload();
});

/* Window Handling */

function move_window(rect, screen) {
    screen = screen || Screen.mainScreen();
    var scr = screen.visibleFrameInRectangle();
    var r = {
        x: Math.round(scr.x + rect.x*scr.width),
        y: Math.round(scr.y + rect.y*scr.height),
        width: Math.round(scr.width * rect.width),
        height: Math.round(scr.height * rect.height),
    };
    Window.focusedWindow().setFrame(r);
}

function move_window_to_next_screen() {
    var currW = Window.focusedWindow();
    var cwFrame = currW.frame();
    var currScreen = currW.screen();
    var nextScreen = currScreen.next();
    var currScreenSize = currScreen.visibleFrameInRectangle();
    var relative = {
        x: (cwFrame.x - currScreenSize.x) / currScreenSize.width,
        y: (cwFrame.y - currScreenSize.y) / currScreenSize.height,
        width: cwFrame.width / currScreenSize.width,
        height: cwFrame.height / currScreenSize.height,
    };
    move_window(relative, nextScreen);
}

/* Support a prefix key with multiple suffix keys */

function PrefixKey(key, modifiers, description) {
    this.modal = centered_modal(description);
    this.suffixes = [];
    this.handlers = [];
    var that = this;
    this.prefix = Phoenix.bind(key, modifiers, function () {
        that.enableSuffixes();
        that.modal.show();
    });
}

PrefixKey.prototype.enableSuffixes = function () {
    var that = this;
    this.suffixes.forEach(function (x) {
        var h = Phoenix.bind(x.key, x.modifiers, function () {
            that.disableSuffixes();
            x.cb();
            that.modal.close();
            Phoenix.reload();
        });
        h.enable();
        that.handlers.push(h);
    });
};
PrefixKey.prototype.disableSuffixes = function () {
    this.handlers.forEach( function (x) {
        x.disable();
    });
    this.handlers = [];
};
PrefixKey.prototype.addSuffix = function (key, modifiers, cb) {
    this.suffixes.push({key: key, modifiers: modifiers, cb: cb});
};

/* Window handling prefix key */

var wPrefix = new PrefixKey('space', ['ctrl', 'alt', 'cmd'],
    "h - Left Half\nl - Right Half\ng - Wide Center\nm - Max\no - big left\np - big right\ns - next screen\nesc - Abort");
wPrefix.addSuffix('h', [], function () {
    move_window({x: 0, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('l', [], function () {
    move_window({x: 0.5, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('g', [], function () {
    move_window({x: 0.15, y: 0, width: 0.7, height: 1.0});
});
wPrefix.addSuffix('m', [], function () {
    move_window({x: 0, y: 0, width: 1.0, height: 1.0});
});
wPrefix.addSuffix('c', [], function () {
    move_window({x: 0.2, y: 0.2, width: 0.6, height: 0.6});
});
wPrefix.addSuffix('o', [], function () {
    move_window({x: 0, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('p', [], function () {
    move_window({x: 0.1, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('s', [], function () {
    move_window_to_next_screen();
});
wPrefix.addSuffix('escape', [], function () {});
wPrefix.addSuffix('space', ['ctrl', 'alt', 'cmd'], function () {});

<commit_msg>New keys for slightly smaller right and left windows.<commit_after>"use strict";

function centered_modal(message) {
    var result = new Modal();
    result.message = message;
    var screen_frame = Screen.mainScreen().frameInRectangle();
    var result_frame = result.frame();
    result.origin = {
        x: 0.5 * (screen_frame.width - result_frame.width),
        y: 0.5 * (screen_frame.height - result_frame.height),
    };
    return result;
}

var h_reload = Phoenix.bind('r', ['alt'], function () {
    Phoenix.reload();
});

/* Window Handling */

function move_window(rect, screen) {
    screen = screen || Screen.mainScreen();
    var scr = screen.visibleFrameInRectangle();
    var r = {
        x: Math.round(scr.x + rect.x*scr.width),
        y: Math.round(scr.y + rect.y*scr.height),
        width: Math.round(scr.width * rect.width),
        height: Math.round(scr.height * rect.height),
    };
    Window.focusedWindow().setFrame(r);
}

function move_window_to_next_screen() {
    var currW = Window.focusedWindow();
    var cwFrame = currW.frame();
    var currScreen = currW.screen();
    var nextScreen = currScreen.next();
    var currScreenSize = currScreen.visibleFrameInRectangle();
    var relative = {
        x: (cwFrame.x - currScreenSize.x) / currScreenSize.width,
        y: (cwFrame.y - currScreenSize.y) / currScreenSize.height,
        width: cwFrame.width / currScreenSize.width,
        height: cwFrame.height / currScreenSize.height,
    };
    move_window(relative, nextScreen);
}

/* Spaces */

/* Support a prefix key with multiple suffix keys */

function PrefixKey(key, modifiers, description) {
    this.modal = centered_modal(description);
    this.suffixes = [];
    this.handlers = [];
    var that = this;
    this.prefix = Phoenix.bind(key, modifiers, function () {
        that.enableSuffixes();
        that.modal.show();
    });
}

PrefixKey.prototype.enableSuffixes = function () {
    var that = this;
    this.suffixes.forEach(function (x) {
        var h = Phoenix.bind(x.key, x.modifiers, function () {
            that.disableSuffixes();
            x.cb();
            that.modal.close();
            Phoenix.reload();
        });
        h.enable();
        that.handlers.push(h);
    });
};
PrefixKey.prototype.disableSuffixes = function () {
    this.handlers.forEach( function (x) {
        x.disable();
    });
    this.handlers = [];
};
PrefixKey.prototype.addSuffix = function (key, modifiers, cb) {
    this.suffixes.push({key: key, modifiers: modifiers, cb: cb});
};

/* Window handling prefix key */

var wPrefix = new PrefixKey('space', ['ctrl', 'alt', 'cmd'],
    "h - Left Half\nl - Right Half\ng - Wide Center\nm - Max\no - big left\np - big right\ns - next screen\nesc - Abort");
wPrefix.addSuffix('h', [], function () {
    move_window({x: 0, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('l', [], function () {
    move_window({x: 0.5, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('g', [], function () {
    move_window({x: 0.15, y: 0, width: 0.7, height: 1.0});
});
wPrefix.addSuffix('m', [], function () {
    move_window({x: 0, y: 0, width: 1.0, height: 1.0});
});
wPrefix.addSuffix('c', [], function () {
    move_window({x: 0.2, y: 0.2, width: 0.6, height: 0.6});
});
wPrefix.addSuffix('o', [], function () {
    move_window({x: 0, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('o', ['shift'], function () {
    move_window({x: 0, y: 0, width: 0.8, height: 1.0});
});
wPrefix.addSuffix('p', [], function () {
    move_window({x: 0.1, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('p', ['shift'], function () {
    move_window({x: 0.2, y: 0, width: 0.8, height: 1.0});
});
wPrefix.addSuffix('s', [], function () {
    move_window_to_next_screen();
});
wPrefix.addSuffix('escape', [], function () {});
wPrefix.addSuffix('space', ['ctrl', 'alt', 'cmd'], function () {});

<|endoftext|>


<commit_before>//
// Drawphone Words
//

var fs = require('fs');
var path = require('path');

function WordPacks () {
	this.wordPacks = [];
}

WordPacks.prototype.loadAll = function () {
	var self = this;
	//reads each txt file in the words folder
	//the name of the file will be the name of the pack
	fs.readdirSync(path.join(__dirname, '../words')).forEach(function(file) {
		//removes the .txt from the end of the filename
		var packName = file.substring(0, file.length - 4);

		var pathToTxt = __dirname + '/../words/' + file;
		var arrayOfWords = fs.readFileSync(pathToTxt).toString().split(/\r?\n/);

		//remove all blank lines
		var newArrayOfWords = [];
		for (var i = 0; i < arrayOfWords.length; i++) {
			var thisWord = arrayOfWords[i].trim();
			if (thisWord !== '') {
				newArrayOfWords.push(thisWord);
			}
		}
		arrayOfWords = newArrayOfWords;

		//can't have an empty list!
		if (arrayOfWords.length === 0) {
			console.log(packName + '.txt is empty. Please add some words, or delete it.');
			process.exit(1);
		}

		self.wordPacks.push(new WordPack(packName, arrayOfWords));
	});
};

WordPacks.prototype.get = function (packName) {
	for (var i = 0; i < this.wordPacks.length; i++) {
		var thisPack = this.wordPacks[i];
		if (thisPack.name === packName) {
			return thisPack;
		}
	}
	return false;
};

WordPacks.prototype.getRandomWord = function (packName) {
	var thisPack = this.get(packName);
	if (thisPack) {
		return thisPack.getRandomWord();
	} else {
		console.err('Pack ' + packName + ' does not exist.');
		process.exit(1);
	}
};

WordPacks.getAllPackNames = function () {
	var names = [];
	fs.readdirSync(path.join(__dirname, '..\\words')).forEach(function(file) {
		//removes the .txt from the end of the filename
		var packName = file.substring(0, file.length - 4);
		names.push(packName);
	});
	return names;
};

function WordPack (name, words) {
	this.name = name;
	this.words = words;
}

WordPack.prototype.getRandomWord = function () {
	return this.words[Math.floor(Math.random() * this.words.length)];
};

module.exports = WordPacks;
<commit_msg>Whoops, forgot one.<commit_after>//
// Drawphone Words
//

var fs = require('fs');
var path = require('path');

function WordPacks () {
	this.wordPacks = [];
}

WordPacks.prototype.loadAll = function () {
	var self = this;
	//reads each txt file in the words folder
	//the name of the file will be the name of the pack
	fs.readdirSync(path.join(__dirname, '../words')).forEach(function(file) {
		//removes the .txt from the end of the filename
		var packName = file.substring(0, file.length - 4);

		var pathToTxt = __dirname + '/../words/' + file;
		var arrayOfWords = fs.readFileSync(pathToTxt).toString().split(/\r?\n/);

		//remove all blank lines
		var newArrayOfWords = [];
		for (var i = 0; i < arrayOfWords.length; i++) {
			var thisWord = arrayOfWords[i].trim();
			if (thisWord !== '') {
				newArrayOfWords.push(thisWord);
			}
		}
		arrayOfWords = newArrayOfWords;

		//can't have an empty list!
		if (arrayOfWords.length === 0) {
			console.log(packName + '.txt is empty. Please add some words, or delete it.');
			process.exit(1);
		}

		self.wordPacks.push(new WordPack(packName, arrayOfWords));
	});
};

WordPacks.prototype.get = function (packName) {
	for (var i = 0; i < this.wordPacks.length; i++) {
		var thisPack = this.wordPacks[i];
		if (thisPack.name === packName) {
			return thisPack;
		}
	}
	return false;
};

WordPacks.prototype.getRandomWord = function (packName) {
	var thisPack = this.get(packName);
	if (thisPack) {
		return thisPack.getRandomWord();
	} else {
		console.err('Pack ' + packName + ' does not exist.');
		process.exit(1);
	}
};

WordPacks.getAllPackNames = function () {
	var names = [];
	fs.readdirSync(path.join(__dirname, '../words')).forEach(function(file) {
		//removes the .txt from the end of the filename
		var packName = file.substring(0, file.length - 4);
		names.push(packName);
	});
	return names;
};

function WordPack (name, words) {
	this.name = name;
	this.words = words;
}

WordPack.prototype.getRandomWord = function () {
	return this.words[Math.floor(Math.random() * this.words.length)];
};

module.exports = WordPacks;
<|endoftext|>


<commit_before>/**
 * Created by chris on 8/22/2015.
 */

function objIndexOf(myArray, searchTerm, property) {
    for(var i = 0, len = myArray.length; i < len; i++) {
        if (myArray[i][property] === searchTerm) return i;
    }
    return -1;
}

var pyfotoApp = angular.module('pyfotoApp', ['ngRoute']);

pyfotoApp.directive("starRating", function(){

return {
			restrict : 'A',
			template : '
'
					 + '
'
					 + ''
					 + '
'
					 + '
',
			scope : {
				ratingValue : '=',
				max : '=',
				onRatingSelected : '&'
			},
			link : function(scope, elem, attrs) {
				var updateStars = function() {
					scope.stars = [];
					for ( var i = 0; i < scope.max; i++) {
						scope.stars.push({
							filled : i < scope.ratingValue
						});
					}
				};

				scope.toggle = function(index) {
					scope.ratingValue = index + 1;
					scope.onRatingSelected({
						rating : index + 1
					});
				};

				scope.$watch('ratingValue',
					function(oldVal, newVal) {
						if (newVal >= 0) {
							updateStars();
						}
					}
				);
			}
		};

});

pyfotoApp.run(function($rootScope, $location, $http) {
    /* polluting the root scope to a minimum. */
    $rootScope.globals = {
        tags: [],
        currentFilters: {},
        searchRating: 0
        };

    $rootScope.pushUniqueTag = function(tag, my_array){
        if (my_array == undefined){
            my_array = $rootScope.globals.tags;
        }
        if (objIndexOf(my_array, "tag", tag.tag) == -1) {
            if (! "highlight" in tag){
                tag.highlight = false;
            }
            my_array.push(tag);
        }
    };

    $rootScope.highlightTag = function(tag, remove){
        //var item = $.grep($scope.globals.tags, function(e){ return e.tag === tag});
        var remove_tag = remove || false;
        angular.forEach($rootScope.globals.tags, function(item) {
            if (item.tag == tag) {
                item.highlight = !remove_tag;
            }
        });
    };

    $rootScope.unhighlightAll = function(){
        angular.forEach($rootScope.globals.tags, function(item) {
            item.highlight = false;
        });
    };

    // This is here because we should only have to get all tags once, hopefully, kinda
    $http.get("/tag")
        .success(function (response) {
            angular.forEach(response.data, function(value){
                $rootScope.pushUniqueTag(value);
            });
        });

    $rootScope.pushUniqueTag({tag: "untagged", private: 0});

    // Ok, so, this is all kinda silly right now, but this is so it can be exampled for advnced searches later

    $rootScope.getFilters = function(){
       var url = "&";
        if (angular.equals({}, $rootScope.globals.currentFilters)){
            return url;
        } else if ("tags" in $rootScope.globals.currentFilters){
            url += "search="+ $rootScope.globals.currentFilters["tags"] + "&searchType=tag";
        } else if ("string" in $rootScope.globals.currentFilters){
            url += "search="+ $rootScope.globals.currentFilters["string"]  + "&searchType=string";
        } else if ("rating" in $rootScope.globals.currentFilters){
            url += "search="+ $rootScope.globals.currentFilters["rating"] + "&searchType=rating";
        }
        return url;
    };

    $rootScope.paramFilters = function(){
        if (angular.equals({}, $rootScope.globals.currentFilters)){
            return {};
        } else if ("tags" in $rootScope.globals.currentFilters){
            return {search: $rootScope.globals.currentFilters["tags"], searchType: "tag"};
        } else if ("string" in $rootScope.globals.currentFilters){
            return {search: $rootScope.globals.currentFilters["string"], searchType: "string"};
        } else if ("rating" in $rootScope.globals.currentFilters){
            return {search: $rootScope.globals.currentFilters["rating"], searchType: "rating" };
        }
        return {};
    };

    $rootScope.setFilters = function(params){
        if ("search" in params){
            if (! ("search_type" in params)){
                $rootScope.globals.currentFilters["tags"] = params.search;
            } else {
                $rootScope.globals.currentFilters[params.search_type] = params.search;
            }
        }
        console.log($rootScope.globals.currentFilters);
    };

});

pyfotoApp.controller('searchController', ['$scope', '$http', '$routeParams', '$rootScope', '$location', function($scope, $http, $routeParams, $rootScope, $location) {
        $scope.globals = $rootScope.globals;

        $scope.performSearch = function(term) {
            $location.url('/search').search('search', term);
        };

}]);

pyfotoApp.controller('galleryController', ['$scope', '$http', '$routeParams', '$rootScope', '$location',  function($scope, $http, $routeParams, $rootScope, $location) {
    $rootScope.setFilters($routeParams);
    $scope.get_filters = $rootScope.getFilters();
    $scope.globals = $rootScope.globals;

    $scope.searchRating = 0;

    if ("rating" in $scope.globals.currentFilters){
        $scope.searchRating = $scope.globals.currentFilters.rating;
    }

    $scope.galleryImages = [];

    $rootScope.unhighlightAll();

    if(! ("string" in $scope.globals.currentFilters) &&
        ! ("rating" in $scope.globals.currentFilters) &&
        ! ("tags" in $scope.globals.currentFilters)){
            $http.get("/file")
              .success(function (response) {
                    $scope.galleryImages = response.data;
                    $scope.globals.currentFilters = {};
                });

    } else if ("string" in $scope.globals.currentFilters) {

        $http.get("/search?search=" + $scope.globals.currentFilters.string)
            .success(function (response) {
                $scope.galleryImages = response.data;
            });
    } else if ("rating" in $scope.globals.currentFilters) {
        $http.get("/search?search=" + $scope.globals.currentFilters.rating + "&search_type=rating")
            .success(function (response) {
                $scope.galleryImages = response.data;
            });
    } else if ("tags" in $scope.globals.currentFilters) {
        $http.get("/search?search=" + $scope.globals.currentFilters.tags)
            .success(function (response) {
                $scope.galleryImages = response.data;
                // TODO add code to highlight tags
            });
    } else {
        alert("Should not be here, how'd you do that?");
    }

    $scope.performRatingSearch = function(rating) {
        $rootScope.globals.currentFilters = {};
        $location.url('/search').search({search: rating, search_type: "rating"});
    };

    $scope.nextPage = function(){
        var highest = Math.max.apply(Math,$scope.galleryImages.map(function(o){return o.id;}));
        var url = "/next/" + highest + "?count=100";
        url += $rootScope.get_filters;

        $http.get(url)
            .success(function (response) {
                if (response.data.length == 0){
                    return false;
                }
                else {
                    angular.forEach(response.data, function(value){
                        $scope.galleryImages.push(value);
                        if ($scope.galleryImages.length >= 1000){
                            $scope.galleryImages.splice(0,1);
                        }
                    });
                }
            })
    };

}]);

pyfotoApp.controller('indexController', ['$scope', '$http', '$routeParams', '$rootScope', '$location',  '$interval', function($scope, $http, $routeParams, $rootScope, $location, $interval) {
    $rootScope.setFilters($routeParams);
    $scope.get_filters = $rootScope.getFilters();
    $scope.globals = $rootScope.globals;

    $scope.image_id = $routeParams.imageId;

    $scope.my_tags = [];
    $scope.showFilename = true;
    $scope.scroller = null;
    $scope.scrolling = $routeParams.scrolling || false;
    $scope.rating = 0;

    $scope.update = function(response){
        $scope.image_info = response.data[0];
        $scope.rating = $scope.image_info.rating;

        angular.forEach(response.data[0].tags, function(item){
           $scope.my_tags.push(item.tag);
            if(item.private == false){
               $scope.highlightTag(item.tag);
           }
        });

        $(".main-image").css('background-image', 'url(/item/' + $scope.image_info.path + ')');

        $scope.showFilename = true;

        if ($scope.scrolling){
        $scope.scroller = $interval(function(){
            $scope.nextItem();
        }, 2500, 1);

        }

    };

    $scope.deleteImage = function(){
          $http.delete("/file/" + $scope.image_id)
              .success(function (response) {
                    //TODO if there is no next item, go to previous.
                    $scope.nextItem();
                });

    };

    $scope.nextItem = function(){
        var url = "/next/" + $scope.image_id + "?count=1";
        url += $rootScope.getFilters();
        console.log(url);

        $http.get(url)
            .success(function (response) {
                if (response.data.length == 0){
                    $scope.scrollOff();
                }
                else {
                    $location.url("/image/"+ response.data[0].id).search($rootScope.paramFilters()).search({"scrolling": $scope.scrolling});
                }
            })
    };

    $scope.prevItem = function(){
        var url = "/prev/" + $scope.image_id + "?count=1";
        url += $rootScope.getFilters();

        $http.get(url)
            .success(function (response) {
                if (response.data.length == 0){
                    $scope.scrollOff();
                } else {
                    $location.url("/image/"+ response.data[0].id).search($rootScope.paramFilters());
                }
            })
    };

    $scope.addTagToFile = function(){
        if ($scope.tagInput == "" || $scope.tagInput == undefined){
            alert("You're an idiot");
            return false;
        }

        $http.post("/file/" + $scope.image_id + "/tag/" + $scope.tagInput, {})
        .success(function (response) {
                var newtag = {tag: $scope.tagInput, private: 0, highlight: true};
                $scope.global.tags.push(newtag);
                $scope.tagInput = "";
            });
    };

    $scope.modifyTag = function(tag, action){
        if (tag.tag == "untagged") {
            console.log("Someone tried to modify 'untagged', hehe");
            return false;
        }

        if($scope.my_tags.indexOf(tag.tag) >= 0){
            console.log("removing");
            $http.delete("/file/" + $scope.image_id + "/tag/" + tag.tag)
                .success(function (response) {
                   $rootScope.highlightTag(tag.tag, true);
                   $scope.my_tags.splice($scope.my_tags.indexOf(tag.tag),1);
                });
        } else {
            console.log("adding");
            $http.post("/file/" + $scope.image_id + "/tag/" + tag.tag, {})
                .success(function (response) {
                    $rootScope.highlightTag(tag.tag);
                    $scope.my_tags.push(tag.tag);
                });
        }

    };

    $scope.keyHandler = function(e){
        if(e.keyCode === 39) {
            //right arrow
            $scope.nextItem();
        } else if(e.keyCode === 37) {
            //left arrow
            $scope.prevItem();
        }
    };

    $scope.openImage = function(file_id){
        $http.get("/file/" + file_id)
            .success(function (response) {
                if (response.data == undefined || response.data.length == 0){
                    alert("Cannot open file");

                } else {
                    $scope.update(response);
                }
            })
    };

    $scope.rateFunction = function(rating) {

        $http.put("/file/" + $scope.image_id, {rating: rating})
            .error(function(data){
           alert("Not able to update file rating");
        });
    };

    $scope.updateFilename = function(){
      if ($scope.newName == undefined || $scope.newName == ""){
          $scope.showFilename = true;
          return false;
      }

        $http.put("/file/" + $scope.image_id, {name: $scope.newName})
            .success(function(data){
                $scope.image_info.name = $scope.newName;
                $scope.showFilename = true;
            })
            .error(function(data){
           alert("Not able to update filename");
        });

    };

    $scope.scrollOn = function(){
        $scope.scrolling = true;
        $scope.scroller = $interval(function(){
            $scope.nextItem();
        }, 2500, 1);

    };

    $scope.scrollOff = function(){
        $interval.cancel($scope.scroller);
    };

    var $doc = angular.element(document);

    $doc.on('keydown', $scope.keyHandler);
    $scope.$on('$destroy',function(){
        $doc.off('keydown', $scope.keyHandler);
    });

    $rootScope.unhighlightAll();
    $scope.openImage($scope.image_id);

    $scope.$on('$destroy', function iVeBeenDismissed() {
        $scope.scrollOff();
    })

}]);

pyfotoApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            redirectTo: '/search'
        })
        .when('/search', {
            templateUrl: '/template/gallery.html',
            controller: 'galleryController'
        })
        .when('/image/:imageId', {
            templateUrl: '/template/image.html',
            controller: 'indexController'
        })
}]);<commit_msg>Fixing play mode to properly denote it has stopped at end of images.<commit_after>/**
 * Created by chris on 8/22/2015.
 */

function objIndexOf(myArray, searchTerm, property) {
    for(var i = 0, len = myArray.length; i < len; i++) {
        if (myArray[i][property] === searchTerm) return i;
    }
    return -1;
}

var pyfotoApp = angular.module('pyfotoApp', ['ngRoute']);

pyfotoApp.directive("starRating", function(){

return {
			restrict : 'A',
			template : '
'
					 + '
'
					 + ''
					 + '
'
					 + '
',
			scope : {
				ratingValue : '=',
				max : '=',
				onRatingSelected : '&'
			},
			link : function(scope, elem, attrs) {
				var updateStars = function() {
					scope.stars = [];
					for ( var i = 0; i < scope.max; i++) {
						scope.stars.push({
							filled : i < scope.ratingValue
						});
					}
				};

				scope.toggle = function(index) {
					scope.ratingValue = index + 1;
					scope.onRatingSelected({
						rating : index + 1
					});
				};

				scope.$watch('ratingValue',
					function(oldVal, newVal) {
						if (newVal >= 0) {
							updateStars();
						}
					}
				);
			}
		};

});

pyfotoApp.run(function($rootScope, $location, $http) {
    /* polluting the root scope to a minimum. */
    $rootScope.globals = {
        tags: [],
        currentFilters: {},
        searchRating: 0
        };

    $rootScope.pushUniqueTag = function(tag, my_array){
        if (my_array == undefined){
            my_array = $rootScope.globals.tags;
        }
        if (objIndexOf(my_array, "tag", tag.tag) == -1) {
            if (! "highlight" in tag){
                tag.highlight = false;
            }
            my_array.push(tag);
        }
    };

    $rootScope.highlightTag = function(tag, remove){
        //var item = $.grep($scope.globals.tags, function(e){ return e.tag === tag});
        var remove_tag = remove || false;
        angular.forEach($rootScope.globals.tags, function(item) {
            if (item.tag == tag) {
                item.highlight = !remove_tag;
            }
        });
    };

    $rootScope.unhighlightAll = function(){
        angular.forEach($rootScope.globals.tags, function(item) {
            item.highlight = false;
        });
    };

    // This is here because we should only have to get all tags once, hopefully, kinda
    $http.get("/tag")
        .success(function (response) {
            angular.forEach(response.data, function(value){
                $rootScope.pushUniqueTag(value);
            });
        });

    $rootScope.pushUniqueTag({tag: "untagged", private: 0});

    // Ok, so, this is all kinda silly right now, but this is so it can be exampled for advnced searches later

    $rootScope.getFilters = function(){
       var url = "&";
        if (angular.equals({}, $rootScope.globals.currentFilters)){
            return url;
        } else if ("tags" in $rootScope.globals.currentFilters){
            url += "search="+ $rootScope.globals.currentFilters["tags"] + "&searchType=tag";
        } else if ("string" in $rootScope.globals.currentFilters){
            url += "search="+ $rootScope.globals.currentFilters["string"]  + "&searchType=string";
        } else if ("rating" in $rootScope.globals.currentFilters){
            url += "search="+ $rootScope.globals.currentFilters["rating"] + "&searchType=rating";
        }
        return url;
    };

    $rootScope.paramFilters = function(){
        if (angular.equals({}, $rootScope.globals.currentFilters)){
            return {};
        } else if ("tags" in $rootScope.globals.currentFilters){
            return {search: $rootScope.globals.currentFilters["tags"], searchType: "tag"};
        } else if ("string" in $rootScope.globals.currentFilters){
            return {search: $rootScope.globals.currentFilters["string"], searchType: "string"};
        } else if ("rating" in $rootScope.globals.currentFilters){
            return {search: $rootScope.globals.currentFilters["rating"], searchType: "rating" };
        }
        return {};
    };

    $rootScope.setFilters = function(params){
        if ("search" in params){
            if (! ("search_type" in params)){
                $rootScope.globals.currentFilters["tags"] = params.search;
            } else {
                $rootScope.globals.currentFilters[params.search_type] = params.search;
            }
        }
        console.log($rootScope.globals.currentFilters);
    };

});

pyfotoApp.controller('searchController', ['$scope', '$http', '$routeParams', '$rootScope', '$location', function($scope, $http, $routeParams, $rootScope, $location) {
        $scope.globals = $rootScope.globals;

        $scope.performSearch = function(term) {
            $location.url('/search').search('search', term);
        };

}]);

pyfotoApp.controller('galleryController', ['$scope', '$http', '$routeParams', '$rootScope', '$location',  function($scope, $http, $routeParams, $rootScope, $location) {
    $rootScope.setFilters($routeParams);
    $scope.get_filters = $rootScope.getFilters();
    $scope.globals = $rootScope.globals;

    $scope.searchRating = 0;

    if ("rating" in $scope.globals.currentFilters){
        $scope.searchRating = $scope.globals.currentFilters.rating;
    }

    $scope.galleryImages = [];

    $rootScope.unhighlightAll();

    if(! ("string" in $scope.globals.currentFilters) &&
        ! ("rating" in $scope.globals.currentFilters) &&
        ! ("tags" in $scope.globals.currentFilters)){
            $http.get("/file")
              .success(function (response) {
                    $scope.galleryImages = response.data;
                    $scope.globals.currentFilters = {};
                });

    } else if ("string" in $scope.globals.currentFilters) {

        $http.get("/search?search=" + $scope.globals.currentFilters.string)
            .success(function (response) {
                $scope.galleryImages = response.data;
            });
    } else if ("rating" in $scope.globals.currentFilters) {
        $http.get("/search?search=" + $scope.globals.currentFilters.rating + "&search_type=rating")
            .success(function (response) {
                $scope.galleryImages = response.data;
            });
    } else if ("tags" in $scope.globals.currentFilters) {
        $http.get("/search?search=" + $scope.globals.currentFilters.tags)
            .success(function (response) {
                $scope.galleryImages = response.data;
                // TODO add code to highlight tags
            });
    } else {
        alert("Should not be here, how'd you do that?");
    }

    $scope.performRatingSearch = function(rating) {
        $rootScope.globals.currentFilters = {};
        $location.url('/search').search({search: rating, search_type: "rating"});
    };

    $scope.nextPage = function(){
        var highest = Math.max.apply(Math,$scope.galleryImages.map(function(o){return o.id;}));
        var url = "/next/" + highest + "?count=100";
        url += $rootScope.get_filters;

        $http.get(url)
            .success(function (response) {
                if (response.data.length == 0){
                    return false;
                }
                else {
                    angular.forEach(response.data, function(value){
                        $scope.galleryImages.push(value);
                        if ($scope.galleryImages.length >= 1000){
                            $scope.galleryImages.splice(0,1);
                        }
                    });
                }
            })
    };

}]);

pyfotoApp.controller('indexController', ['$scope', '$http', '$routeParams', '$rootScope', '$location',  '$interval', function($scope, $http, $routeParams, $rootScope, $location, $interval) {
    $rootScope.setFilters($routeParams);
    $scope.get_filters = $rootScope.getFilters();
    $scope.globals = $rootScope.globals;

    $scope.image_id = $routeParams.imageId;

    $scope.my_tags = [];
    $scope.showFilename = true;
    $scope.scroller = null;
    $scope.scrolling = $routeParams.scrolling || false;
    $scope.rating = 0;

    $scope.update = function(response){
        $scope.image_info = response.data[0];
        $scope.rating = $scope.image_info.rating;

        angular.forEach(response.data[0].tags, function(item){
           $scope.my_tags.push(item.tag);
            if(item.private == false){
               $scope.highlightTag(item.tag);
           }
        });

        $(".main-image").css('background-image', 'url(/item/' + $scope.image_info.path + ')');

        $scope.showFilename = true;

        if ($scope.scrolling){
        $scope.scroller = $interval(function(){
            $scope.nextItem();
        }, 2500, 1);

        }

    };

    $scope.deleteImage = function(){
          $http.delete("/file/" + $scope.image_id)
              .success(function (response) {
                    //TODO if there is no next item, go to previous.
                    $scope.nextItem();
                });

    };

    $scope.nextItem = function(){
        var url = "/next/" + $scope.image_id + "?count=1";
        url += $rootScope.getFilters();
        console.log(url);

        $http.get(url)
            .success(function (response) {
                if (response.data.length == 0){
                    $scope.scrollOff();
                }
                else {
                    $location.url("/image/"+ response.data[0].id).search($rootScope.paramFilters()).search({"scrolling": $scope.scrolling});
                }
            })
    };

    $scope.prevItem = function(){
        var url = "/prev/" + $scope.image_id + "?count=1";
        url += $rootScope.getFilters();

        $http.get(url)
            .success(function (response) {
                if (response.data.length == 0){
                    $scope.scrollOff();
                } else {
                    $location.url("/image/"+ response.data[0].id).search($rootScope.paramFilters());
                }
            })
    };

    $scope.addTagToFile = function(){
        if ($scope.tagInput == "" || $scope.tagInput == undefined){
            alert("You're an idiot");
            return false;
        }

        $http.post("/file/" + $scope.image_id + "/tag/" + $scope.tagInput, {})
        .success(function (response) {
                var newtag = {tag: $scope.tagInput, private: 0, highlight: true};
                $scope.global.tags.push(newtag);
                $scope.tagInput = "";
            });
    };

    $scope.modifyTag = function(tag, action){
        if (tag.tag == "untagged") {
            console.log("Someone tried to modify 'untagged', hehe");
            return false;
        }

        if($scope.my_tags.indexOf(tag.tag) >= 0){
            console.log("removing");
            $http.delete("/file/" + $scope.image_id + "/tag/" + tag.tag)
                .success(function (response) {
                   $rootScope.highlightTag(tag.tag, true);
                   $scope.my_tags.splice($scope.my_tags.indexOf(tag.tag),1);
                });
        } else {
            console.log("adding");
            $http.post("/file/" + $scope.image_id + "/tag/" + tag.tag, {})
                .success(function (response) {
                    $rootScope.highlightTag(tag.tag);
                    $scope.my_tags.push(tag.tag);
                });
        }

    };

    $scope.keyHandler = function(e){
        if(e.keyCode === 39) {
            //right arrow
            $scope.nextItem();
        } else if(e.keyCode === 37) {
            //left arrow
            $scope.prevItem();
        }
    };

    $scope.openImage = function(file_id){
        $http.get("/file/" + file_id)
            .success(function (response) {
                if (response.data == undefined || response.data.length == 0){
                    alert("Cannot open file");

                } else {
                    $scope.update(response);
                }
            })
    };

    $scope.rateFunction = function(rating) {

        $http.put("/file/" + $scope.image_id, {rating: rating})
            .error(function(data){
           alert("Not able to update file rating");
        });
    };

    $scope.updateFilename = function(){
      if ($scope.newName == undefined || $scope.newName == ""){
          $scope.showFilename = true;
          return false;
      }

        $http.put("/file/" + $scope.image_id, {name: $scope.newName})
            .success(function(data){
                $scope.image_info.name = $scope.newName;
                $scope.showFilename = true;
            })
            .error(function(data){
           alert("Not able to update filename");
        });

    };

    $scope.scrollOn = function(){
        $scope.scrolling = true;
        $scope.scroller = $interval(function(){
            $scope.nextItem();
        }, 2500, 1);

    };

    $scope.scrollOff = function(){
        $scope.scrolling = false;
        $interval.cancel($scope.scroller);
    };

    var $doc = angular.element(document);

    $doc.on('keydown', $scope.keyHandler);
    $scope.$on('$destroy',function(){
        $doc.off('keydown', $scope.keyHandler);
    });

    $rootScope.unhighlightAll();
    $scope.openImage($scope.image_id);

    $scope.$on('$destroy', function iVeBeenDismissed() {
        $scope.scrollOff();
    })

}]);

pyfotoApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            redirectTo: '/search'
        })
        .when('/search', {
            templateUrl: '/template/gallery.html',
            controller: 'galleryController'
        })
        .when('/image/:imageId', {
            templateUrl: '/template/image.html',
            controller: 'indexController'
        })
}]);<|endoftext|>


<commit_before>/*  ============================================================================

 Copyright (C) 2006-2016 Talend Inc. - www.talend.com

 This source code is available under agreement available at
 https://github.com/Talend/data-prep/blob/master/LICENSE

 You should have received a copy of the agreement
 along with this program; if not, write to Talend SA
 9 rue Pages 92150 Suresnes, France

 ============================================================================*/

/**
 * @ngdoc controller
 * @name talend.sunchoke.filter-item-value.controller:ScFilterValueCtrl
 * @description FilterItemValue controller.
 */
export default class ScFilterValueCtrl {
    constructor($element) {
        'ngInject';
        this.$element = $element;
    }

    $onInit() {
        this.valueToDisplay = this.renderValueFn({
            value: this.filterValue
        });
    }

    /**
     * @ngdoc method
     * @name removeEmptyValue
     * @methodOf talend.sunchoke.filter-item-value.controller:checkEmpty
     * @description Remove 'empty' when editing null value
     */
    removeEmptyValue() {
        if (this.valueToDisplay === 'empty') {
            this.valueToDisplay = '';
        }
    }

    /**
     * @ngdoc method
     * @name $onChanges
     * @methodOf talend.sunchoke.filter-item-value.controller:ScFilterValueCtrl
     * @description Manage filter values changes
     */
    $onChanges(changes) {
        const model = changes.filterValue;
        if (model) {
            const newModel = model.currentValue;
            if (newModel || newModel === '') {
                this.valueToDisplay = this.renderValueFn({
                    value: newModel
                });
            }
        }
    }

    /**
     * @ngdoc method
     * @name $onChanges
     * @methodOf talend.sunchoke.filter-item-value.controller:ScFilterValueCtrl
     * @description Manage keyboard action on normal filter (not range)
     */
    onKeydown(event) {
        // keydown escape
        if (event && event.which === 27) {
            this.valueToDisplay = this.filterValue;
        }

        // keydown enter
        if (event && event.which === 13) {
            this.onEdit({
                newValue: this.valueToDisplay
            });

            //Blur input to hide edit mode
            this.$element.find('input').blur();
        }
    }
}<commit_msg>TDS-904: filter value ignored value when it was false, on change<commit_after>/*  ============================================================================

 Copyright (C) 2006-2016 Talend Inc. - www.talend.com

 This source code is available under agreement available at
 https://github.com/Talend/data-prep/blob/master/LICENSE

 You should have received a copy of the agreement
 along with this program; if not, write to Talend SA
 9 rue Pages 92150 Suresnes, France

 ============================================================================*/

/**
 * @ngdoc controller
 * @name talend.sunchoke.filter-item-value.controller:ScFilterValueCtrl
 * @description FilterItemValue controller.
 */
export default class ScFilterValueCtrl {
    constructor($element) {
        'ngInject';
        this.$element = $element;
    }

    $onInit() {
        this.valueToDisplay = this.renderValueFn({
            value: this.filterValue
        });
    }

    /**
     * @ngdoc method
     * @name removeEmptyValue
     * @methodOf talend.sunchoke.filter-item-value.controller:checkEmpty
     * @description Remove 'empty' when editing null value
     */
    removeEmptyValue() {
        if (this.valueToDisplay === 'empty') {
            this.valueToDisplay = '';
        }
    }

    /**
     * @ngdoc method
     * @name $onChanges
     * @methodOf talend.sunchoke.filter-item-value.controller:ScFilterValueCtrl
     * @description Manage filter values changes
     */
    $onChanges(changes) {
        const model = changes.filterValue;
        if (model) {
            const newModel = model.currentValue;
            if (newModel || newModel === false || newModel === '') {
                this.valueToDisplay = this.renderValueFn({
                    value: newModel
                });
            }
        }
    }

    /**
     * @ngdoc method
     * @name $onChanges
     * @methodOf talend.sunchoke.filter-item-value.controller:ScFilterValueCtrl
     * @description Manage keyboard action on normal filter (not range)
     */
    onKeydown(event) {
        // keydown escape
        if (event && event.which === 27) {
            this.valueToDisplay = this.filterValue;
        }

        // keydown enter
        if (event && event.which === 13) {
            this.onEdit({
                newValue: this.valueToDisplay
            });

            //Blur input to hide edit mode
            this.$element.find('input').blur();
        }
    }
}<|endoftext|>