<commit_before>$(document).ready(function(){
	// $( "#editorDiv").load( "examples/simple.cnc" );
	$( "#editorDiv").load( "examples/complete.cnc" );

	initScreen();

	$(window).resize(function () {
		initScreen();
	});

	$("#btnStart").click(function (){

		if($(this).text() === "Start"){
			run();
			$(this).text("Stop");
		} else {
			stop();
			$(this).text("Start");
		}
	});

	context.codeRunner = new Worker('js/parser.js');
	context.speedBreaker = new Worker('js/speedbreaker.js');

	$("#speedSlider").change(function(){
		// console.log("slider value = " + $(this).val());
		context.speedBreaker.postMessage({type: 'setSpeed', speed: $(this).val()});
	});
	context.speedBreaker.postMessage({type: 'setSpeed', speed: $('#speedSlider').val()});

});

function stop(){
	context.codeRunner && context.codeRunner.terminate();
}

function run(){
	test();
	// fire google analytics event tracking
	// ga('send', 'event', 'Simulation', 'Run');

	var cnc = document.getElementById(context.getCncCanvasId());
	var cncCtx = cnc.getContext("2d");

	delete context.prevPoint;

	graphics.initSimulation();

	// codeRunner is a worker thread that parses the CNC program and executes the code
	// context.codeRunner = new Worker('js/parser.js');

	var codeLines = $('#editorDiv').val().toUpperCase().split('\n');
	var billet = getBillet(codeLines);

	// to reset canvas

	cnc.width = cnc.width;

	cncCtx.translate(billet.length, Math.ceil(cnc.height/2));
	graphics.drawBillet(billet);

	var code =  $('#editorDiv').val().toUpperCase();
	var codeArray = code.split('\n');

	console.log('Number of lines of code: ' + codeArray.length);

	var currentIndex = 0;
	var preIndex = 0;
	var editorHeight = $("#runtimeEditor").height();
	var scrollPosition = 20;
	var scrollValue = 20;
	var data = {
		isCncCode: true,
		cncCode: codeArray[currentIndex].trim()
	}

	console.log('Now executing: ' + data.cncCode);
	context.codeRunner.postMessage(data);

	// Event handler for the run button
	context.codeRunner.addEventListener('message', function(e){
		// if(e.data.type === 'toolDrawPoint' || e.data.type === 'parsingComplete') {
			context.speedBreaker.postMessage(e.data);
		// }
		// else if(e.data.type === 'lineSimulationComplete'){
		// 	if(currentIndex < codeArray.length - 1) {
		// 		data.cncCode = codeArray[++currentIndex].trim();
		// 		context.codeRunner.postMessage(data);
		// 		console.log('Now executing: ' + data.cncCode);
		// 	}
		// }

	}, false);

	// Event handler for the run button
	context.speedBreaker.addEventListener('message', function(e){

		// console.log(e.data);
		if(context.prevPoint) {
			graphics.drawGhostTool(cncCtx, context.prevPoint);
		}

		// if(e.data.type === 'toolDrawPointReady') {

		// } else

		if(e.data.type === 'parsingComplete') {
			if(currentIndex < codeArray.length - 1) {
				data.cncCode = codeArray[++currentIndex].trim();
				context.codeRunner.postMessage(data);
				$("#line-" + preIndex).css("background-color", "#A1A194");
				$("#line-" + currentIndex).css("background-color", "#CECEBB");
				console.log('Now executing: ' + data.cncCode);
				preIndex = currentIndex;
				scrollPosition = scrollPosition + 20;

				if(scrollPosition > editorHeight){
					$("#runtimeEditor").scrollTop(scrollValue);
					scrollValue += 20;
				}
			} else {
				$("#line-" + preIndex).css("background-color", "#A1A194");
				$("#runtimeEditor").animate({scrollTop : 0}, 700);
			}
		} else {
			graphics.drawTool(cncCtx, e.data.position);
			context.prevPoint = e.data.position;
		}

	}, false);
}

// input: array of code lines
// returns: Billet object {radius: value, length: value}
// throws: exception if [BILLET, X\d or Z\d not found
function getBillet(codeArray){

	var billetLine;
	var found = false;

	for(line in codeArray){
		billetLine = codeArray[line];
		if(billetLine.indexOf('[BILLET') >= 0) {
			found = true;
			break;
		}
	}

	if(!found){
		var errMessage = 'Billet size not found';
		console.log(errMessage);
		throw  errMessage;
	}

	var radiusPattern = /\sX\d+\s/;
	var radius = radiusPattern.exec(billetLine);

	if(!radius){
		var errMessage = 'Billet radius not found';
		console.log(errMessage);
		throw  errMessage;
	}

	var lengthPattern = /\sZ\d+\s?/;
	var length = lengthPattern.exec(billetLine);

	if(!length){
		var errMessage = 'Billet length not found';
		console.log(errMessage);
		throw  errMessage;
	}

	var numberPattern = /\d+/;

	radius = numberPattern.exec(radius);
	length = numberPattern.exec(length);

	var billet = {'radius':radius[0], 'length': length[0], 'properties': config.billetProperties};

	return billet;
}

function initScreen(){

	var windowHeight = $(window).height();
	var windowWidth = $(window).width();

	// Setting toolbar
	$('#toolbar').css('height',  config.homeProperties.toolbarHeight + 'px');

	// Setting editor
	$('#editor').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#editor').css('width', config.homeProperties.editorWidth + 'px');

	// Line numbers
	$('#lineNumbers').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#lineNumbers').css('width' , (config.homeProperties.lineNumbersWidth) + 'px');

	// Setting editorDiv
	$('#editorDiv').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#editorDiv').width((config.homeProperties.editorWidth - config.homeProperties.lineNumbersWidth) + 'px');
	// $('#editorDiv').css('padding-left', config.leftPadding + 'px');
	// $('#editorDiv').css('padding-top', config.topPadding + 'px');

	// Setting simulator
	$('#simulator').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#simulator').css('width' , (windowWidth - config.homeProperties.editorWidth) + 'px');

	// Setting footer
	$('#footer').css('height', config.homeProperties.footerHeight + 'px');

	// // Options overlay
	// $('#options').css('height', (window.innerHeight - config.toolbarHeight - config.footerHeight) + 'px');

	// Setting CNC
	$( "#cncCanvas" ).remove();
	var cnc = document.createElement('canvas');
	cnc.setAttribute('id', 'cncCanvas');
	cnc.height = (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight);
	cnc.width = (windowWidth - config.homeProperties.editorWidth);
	var simulator = document.getElementById('simulator');
	simulator.appendChild(cnc);

}
<commit_msg>reset start button after simulation complete<commit_after>$(document).ready(function(){
	// $( "#editorDiv").load( "examples/simple.cnc" );
	$( "#editorDiv").load( "examples/complete.cnc" );

	initScreen();

	$(window).resize(function () {
		initScreen();
	});

	$("#btnStart").click(function (){

		if($(this).text() === "Start"){
			run();
			$(this).text("Stop");
		} else {
			stop();
			$(this).text("Start");
		}
	});

	context.codeRunner = new Worker('js/parser.js');
	context.speedBreaker = new Worker('js/speedbreaker.js');

	$("#speedSlider").change(function(){
		// console.log("slider value = " + $(this).val());
		context.speedBreaker.postMessage({type: 'setSpeed', speed: $(this).val()});
	});
	context.speedBreaker.postMessage({type: 'setSpeed', speed: $('#speedSlider').val()});

});

function stop(){
	context.codeRunner && context.codeRunner.terminate();
}

function run(){
	test();
	// fire google analytics event tracking
	// ga('send', 'event', 'Simulation', 'Run');

	var cnc = document.getElementById(context.getCncCanvasId());
	var cncCtx = cnc.getContext("2d");

	delete context.prevPoint;

	graphics.initSimulation();

	// codeRunner is a worker thread that parses the CNC program and executes the code
	// context.codeRunner = new Worker('js/parser.js');

	var codeLines = $('#editorDiv').val().toUpperCase().split('\n');
	var billet = getBillet(codeLines);

	// to reset canvas

	cnc.width = cnc.width;

	cncCtx.translate(billet.length, Math.ceil(cnc.height/2));
	graphics.drawBillet(billet);

	var code =  $('#editorDiv').val().toUpperCase();
	var codeArray = code.split('\n');

	console.log('Number of lines of code: ' + codeArray.length);

	var currentIndex = 0;
	var preIndex = 0;
	var editorHeight = $("#runtimeEditor").height();
	var scrollPosition = 20;
	var scrollValue = 20;
	var data = {
		isCncCode: true,
		cncCode: codeArray[currentIndex].trim()
	}

	console.log('Now executing: ' + data.cncCode);
	context.codeRunner.postMessage(data);

	// Event handler for the run button
	context.codeRunner.addEventListener('message', function(e){
		// if(e.data.type === 'toolDrawPoint' || e.data.type === 'parsingComplete') {
			context.speedBreaker.postMessage(e.data);
		// }
		// else if(e.data.type === 'lineSimulationComplete'){
		// 	if(currentIndex < codeArray.length - 1) {
		// 		data.cncCode = codeArray[++currentIndex].trim();
		// 		context.codeRunner.postMessage(data);
		// 		console.log('Now executing: ' + data.cncCode);
		// 	}
		// }

	}, false);

	// Event handler for the run button
	context.speedBreaker.addEventListener('message', function(e){

		// console.log(e.data);
		if(context.prevPoint) {
			graphics.drawGhostTool(cncCtx, context.prevPoint);
		}

		// if(e.data.type === 'toolDrawPointReady') {

		// } else

		if(e.data.type === 'parsingComplete') {
			if(currentIndex < codeArray.length - 1) {
				data.cncCode = codeArray[++currentIndex].trim();
				context.codeRunner.postMessage(data);
				$("#line-" + preIndex).css("background-color", "#A1A194");
				$("#line-" + currentIndex).css("background-color", "#CECEBB");
				console.log('Now executing: ' + data.cncCode);
				preIndex = currentIndex;
				scrollPosition = scrollPosition + 20;

				if(scrollPosition > editorHeight){
					$("#runtimeEditor").scrollTop(scrollValue);
					scrollValue += 20;
				}
			} else {
				$("#btnStart").text("Start");
				$("#line-" + preIndex).css("background-color", "#A1A194");
				$("#runtimeEditor").animate({scrollTop : 0}, 700);
			}
		} else {
			graphics.drawTool(cncCtx, e.data.position);
			context.prevPoint = e.data.position;
		}

	}, false);
}

// input: array of code lines
// returns: Billet object {radius: value, length: value}
// throws: exception if [BILLET, X\d or Z\d not found
function getBillet(codeArray){

	var billetLine;
	var found = false;

	for(line in codeArray){
		billetLine = codeArray[line];
		if(billetLine.indexOf('[BILLET') >= 0) {
			found = true;
			break;
		}
	}

	if(!found){
		var errMessage = 'Billet size not found';
		console.log(errMessage);
		throw  errMessage;
	}

	var radiusPattern = /\sX\d+\s/;
	var radius = radiusPattern.exec(billetLine);

	if(!radius){
		var errMessage = 'Billet radius not found';
		console.log(errMessage);
		throw  errMessage;
	}

	var lengthPattern = /\sZ\d+\s?/;
	var length = lengthPattern.exec(billetLine);

	if(!length){
		var errMessage = 'Billet length not found';
		console.log(errMessage);
		throw  errMessage;
	}

	var numberPattern = /\d+/;

	radius = numberPattern.exec(radius);
	length = numberPattern.exec(length);

	var billet = {'radius':radius[0], 'length': length[0], 'properties': config.billetProperties};

	return billet;
}

function initScreen(){

	var windowHeight = $(window).height();
	var windowWidth = $(window).width();

	// Setting toolbar
	$('#toolbar').css('height',  config.homeProperties.toolbarHeight + 'px');

	// Setting editor
	$('#editor').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#editor').css('width', config.homeProperties.editorWidth + 'px');

	// Line numbers
	$('#lineNumbers').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#lineNumbers').css('width' , (config.homeProperties.lineNumbersWidth) + 'px');

	// Setting editorDiv
	$('#editorDiv').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#editorDiv').width((config.homeProperties.editorWidth - config.homeProperties.lineNumbersWidth) + 'px');
	// $('#editorDiv').css('padding-left', config.leftPadding + 'px');
	// $('#editorDiv').css('padding-top', config.topPadding + 'px');

	// Setting simulator
	$('#simulator').css('height', (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight) + 'px');
	$('#simulator').css('width' , (windowWidth - config.homeProperties.editorWidth) + 'px');

	// Setting footer
	$('#footer').css('height', config.homeProperties.footerHeight + 'px');

	// // Options overlay
	// $('#options').css('height', (window.innerHeight - config.toolbarHeight - config.footerHeight) + 'px');

	// Setting CNC
	$( "#cncCanvas" ).remove();
	var cnc = document.createElement('canvas');
	cnc.setAttribute('id', 'cncCanvas');
	cnc.height = (windowHeight - config.homeProperties.toolbarHeight - config.homeProperties.footerHeight);
	cnc.width = (windowWidth - config.homeProperties.editorWidth);
	var simulator = document.getElementById('simulator');
	simulator.appendChild(cnc);

}
<|endoftext|>


<commit_before>var Reaction = require("../reaction")
  , get = require("../util").get
  , rules = require("../rules")

var VariableReaction = Reaction.extend({

  setFrom: function(el, model, key) {
    var newVal = get(model, key)
    if(this.isInput) {
      if(el.attr("type") === "radio")  {
        if(el.val() == newVal) {
          $(el).prop("checked", true)
        }
      } else if(newVal !== $(el).val()) {
        $(el).val(newVal)
      }
    } else {
      $(el).html(newVal)
    }
  },

  init: function(el, model, stack, next) {
    this.setFrom(el, model, this.variableName)
    next(stack)
  },

  observe: function(el, model) {
    this.el = el
    this.model = model

    var key = this.variableName
    if(this.isInput) {
      el.on("input.endDash change.endDash", function() {
        model.model.set(key, el.val())
      })
    }

    model.on("change:" + key, function() {
      this.setFrom(el, model, key)
    }, this)
  },

  stopObserving: function() {
    this.el.off("input.endDash change.endDash")
    this.model.off(null, null, this)
  }
}, {
  selector: "[class]",

  reactIf: function(el) {
    return rules.variable(el)
  },

  parse: function(el) {
    return {
      isInput: el.is(":input:not(button)"),
      variableName: rules.variable(el)
    }
  },

})

module.exports = VariableReaction
<commit_msg>Fix issue with jsdom radio buttons and not having a presenter<commit_after>var Reaction = require("../reaction")
  , get = require("../util").get
  , rules = require("../rules")

var VariableReaction = Reaction.extend({

  setFrom: function(el, model, key) {
    var newVal = get(model, key)
    if(this.isInput) {
      if(el.attr("type") === "radio")  {
        if(el.val() == newVal) {
          $(el).prop("checked", true)
        } else {
          $(el).prop("checked", false)
        }
      } else if(newVal !== $(el).val()) {
        $(el).val(newVal)
      }
    } else {
      $(el).html(newVal)
    }
  },

  init: function(el, model, stack, next) {
    this.setFrom(el, model, this.variableName)
    next(stack)
  },

  observe: function(el, model) {
    this.el = el
    this.model = model

    var key = this.variableName
    if(this.isInput) {
      el.on("input.endDash change.endDash", function() {
        var mod = (model.model) ? model.model : model
        mod.set(key, el.val())
      })
    }

    model.on("change:" + key, function() {
      this.setFrom(el, model, key)
    }, this)
  },

  stopObserving: function() {
    this.el.off("input.endDash change.endDash")
    this.model.off(null, null, this)
  }
}, {
  selector: "[class]",

  reactIf: function(el) {
    return rules.variable(el)
  },

  parse: function(el) {
    return {
      isInput: el.is(":input:not(button)"),
      variableName: rules.variable(el)
    }
  },

})

module.exports = VariableReaction
<|endoftext|>


<commit_before>var curGuests = -1;
var numGuestsAllowed = -1;
var numGuests = -1;
var names = '';
var guestAllowed = false;
var showRsvp = function(hideStageLeft){
    toggle(false, true, false, false);
    //TODO: issue ajax for number
    setActive("rsvpmenu");
    if (hideStageLeft){
        toggleStageLeft();
    }
    if (curGuests != null){ //hide body
        setClass("rsvpbody", false);
        setClass("editbody", true);
    }else{
        setClass("editbody", false);
    }
};
var showForm = function(){
    var rsvpbody = document.getElementById("rsvpbody");
    if (rsvpbody.classList.contains("hidden")){
        setClass("rsvpbody", true);
        setClass("editbody", false);
    }
}

var showInfo = function(hideStageLeft){
    toggle(false, false, true, false);
    setActive("infomenu");
    if (hideStageLeft){
        toggleStageLeft();
    }
}
var showContact = function(hideStageLeft){
    toggle(false, false, false, true);
    setActive("contactmenu");
    if (hideStageLeft){
        toggleStageLeft();
    }
}
/* hides certain items in the UI */
var toggle = function(landing, rsvp, info, contact){
    setClass("choices", true);
    setClass("landing", landing);
    setClass("rsvp", rsvp);
    setClass("rsvpform", rsvp);
    setClass("rsvpconfirm", !rsvp);
    setClass("info", info);
    setClass("contact", contact);
}
var options = ["rsvpmenu", "infomenu", "contactmenu"];
/* Bolds the selected in the non-mobile UI*/
var setActive = function(activeItem){
    for (var i = 0; i < options.length; i++){
        document.getElementById(options[i]).classList.remove("active");
        document.getElementById(options[i] + "StageLeft").classList.remove("active");
    }
    document.getElementById(activeItem).classList.add("active");
    document.getElementById(activeItem + "StageLeft").classList.add("active");
}
var submitRsvp = function(){
    var yes = document.getElementById("attendyes");
    var no = document.getElementById("attendno");
    var guest = document.getElementById("attendwithguest");
    if (yes.checked){
        if (document.getElementById("numGuests")){
            var guestSelector = document.getElementById("numGuests").value;
            numGuests = parseInt(guestSelector);
        }else{
            numGuests = 1;
        }
    }else if (guest.checked){
        numGuests = 2;
    }else if (no.checked){
        numGuests = 0;
    }else{
        return;
    }
    var req = new XMLHttpRequest();
    req.open("get", "/rsvp?code=" +document.getElementById('code').value + "&numGuests=" + numGuests, true);
    req.onreadystatechange = function(){
        if (req.readyState == 4){
            if (req.status == 200){
                var response = JSON.parse(req.response);
                if (response["errorCode"]){
                    alert(response["details"]);
                }else{
                    setClass("rsvpform", false);
                    setClass("rsvpconfirm", true);
                    document.getElementById("rsvpconfirmmsg").innerHTML = 'Thanks for the RSVP!';
                    updateRsvpCount(response);
                }
            }else{
                alert('Could not rsvp');
            }
        }
    }
    req.send();

}
var showSubmitButton = function(){
    document.getElementById("submitbutton").classList.remove("hidden");
}
var submitCode = function(){
    var req = new XMLHttpRequest();
    req.open("get", "/login?code=" +document.getElementById('code').value, true);
    //    req.open("post", "/rsvp", true);
    //    var params = "code=" + document.getElementById("code").value;
    req.onreadystatechange = function(){
        if (req.readyState == 4){
            if (req.status == 200){
                var response = JSON.parse(req.response);
                if (response["errorCode"]){
                    alert(response["details"]);
                }else{
                    names = response.result["name"];
                    document.getElementById("names").innerHTML = names;
                    numGuestsAllowed = response.result["primaryGuests"];
                    guestAllowed = response.result["additionalGuestAllowed"];
                    if (guestAllowed){
                        document.getElementById("guestoption").classList.remove("hidden");
                    }
                    alterPicklist(numGuestsAllowed);
                    updateRsvpCount(response);
                    showRsvp();
                    document.getElementById("headline").classList.remove("hidden");
                }
            }else{
                alert('Could not submit');
            }
        }
    }
    req.send();
    //    req.send(params);
}
var updateRsvpCount = function(response){
    curGuests = response.result["seatsReserved"];
    if (curGuests != null){
        var numActualString = curGuests + " seats";
        if (curGuests == 1){
            numActualString = "one seat";
        }
        document.getElementById("subGreeting").innerHTML = "You're currently confirmed for " + numActualString + ".";
        if (curGuests > 0){
            if (guestAllowed && curGuests == 2){
                document.getElementById("attendwithguest").checked='yes';
            }else{
                document.getElementById("attendyes").checked='yes';
                if (document.getElementById("numGuests")){
                   document.getElementById("numGuests").options[curGuests-1].selected=true;
                }
            }
        }else{
            document.getElementById("attendno").checked='yes';
        }
    }else{
        document.getElementById("submitbutton").classList.add("hidden");
    }

}

var alterPicklist = function(maxGuests){
    if (maxGuests > 1){
        var newPicklist = " <select id=\"numGuests\">";
        var i = 1;
        for (i ; i <= maxGuests; i++){ //
            newPicklist += "<option value=\"" + i + "\">" + i + "</option>";
        }
        newPicklist += "</select> seat(s).";
        document.getElementById("guestSelector").innerHTML = newPicklist;
        document.getElementById("numGuests").options[i-2].selected=true;
        document.getElementById("subGreeting").innerHTML = "We've saved " + maxGuests + " seats for you at our wedding."
    }else{
        document.getElementById("subGreeting").innerHTML = "We've saved a seat for you at our wedding."
        document.getElementById("guestSelector").innerHTML = "a seat for me.";
    }

}
var setClass = function(elemName, show){
    var elem = document.getElementById(elemName);
    if(show){
        elem.classList.remove("hidden");
    }else{
        elem.classList.add("hidden");
    }
}

var toggleStageLeft = function(){
    var stageLeft = document.getElementById("viewport");
    if (stageLeft.classList.contains("hideStageLeft")){
        stageLeft.classList.remove("hideStageLeft");
    }else{
        stageLeft.classList.add("hideStageLeft");
    }

}
<commit_msg>Update call to action<commit_after>var curGuests = -1;
var numGuestsAllowed = -1;
var numGuests = -1;
var names = '';
var guestAllowed = false;
var showRsvp = function(hideStageLeft){
    toggle(false, true, false, false);
    //TODO: issue ajax for number
    setActive("rsvpmenu");
    if (hideStageLeft){
        toggleStageLeft();
    }
    if (curGuests != null){ //hide body
        setClass("rsvpbody", false);
        setClass("editbody", true);
    }else{
        setClass("editbody", false);
    }
};
var showForm = function(){
    var rsvpbody = document.getElementById("rsvpbody");
    if (rsvpbody.classList.contains("hidden")){
        setClass("rsvpbody", true);
        setClass("editbody", false);
    }
}

var showInfo = function(hideStageLeft){
    toggle(false, false, true, false);
    setActive("infomenu");
    if (hideStageLeft){
        toggleStageLeft();
    }
}
var showContact = function(hideStageLeft){
    toggle(false, false, false, true);
    setActive("contactmenu");
    if (hideStageLeft){
        toggleStageLeft();
    }
}
/* hides certain items in the UI */
var toggle = function(landing, rsvp, info, contact){
    setClass("choices", true);
    setClass("landing", landing);
    setClass("rsvp", rsvp);
    setClass("rsvpform", rsvp);
    setClass("rsvpconfirm", !rsvp);
    setClass("info", info);
    setClass("contact", contact);
}
var options = ["rsvpmenu", "infomenu", "contactmenu"];
/* Bolds the selected in the non-mobile UI*/
var setActive = function(activeItem){
    for (var i = 0; i < options.length; i++){
        document.getElementById(options[i]).classList.remove("active");
        document.getElementById(options[i] + "StageLeft").classList.remove("active");
    }
    document.getElementById(activeItem).classList.add("active");
    document.getElementById(activeItem + "StageLeft").classList.add("active");
}
var submitRsvp = function(){
    var yes = document.getElementById("attendyes");
    var no = document.getElementById("attendno");
    var guest = document.getElementById("attendwithguest");
    if (yes.checked){
        if (document.getElementById("numGuests")){
            var guestSelector = document.getElementById("numGuests").value;
            numGuests = parseInt(guestSelector);
        }else{
            numGuests = 1;
        }
    }else if (guest.checked){
        numGuests = 2;
    }else if (no.checked){
        numGuests = 0;
    }else{
        return;
    }
    var req = new XMLHttpRequest();
    req.open("get", "/rsvp?code=" +document.getElementById('code').value + "&numGuests=" + numGuests, true);
    req.onreadystatechange = function(){
        if (req.readyState == 4){
            if (req.status == 200){
                var response = JSON.parse(req.response);
                if (response["errorCode"]){
                    alert(response["details"]);
                }else{
                    setClass("rsvpform", false);
                    setClass("rsvpconfirm", true);
                    document.getElementById("rsvpconfirmmsg").innerHTML = 'Thanks for the RSVP!';
                    updateRsvpCount(response);
                }
            }else{
                alert('Could not rsvp');
            }
        }
    }
    req.send();

}
var showSubmitButton = function(){
    document.getElementById("submitbutton").classList.remove("hidden");
}
var submitCode = function(){
    var req = new XMLHttpRequest();
    req.open("get", "/login?code=" +document.getElementById('code').value, true);
    //    req.open("post", "/rsvp", true);
    //    var params = "code=" + document.getElementById("code").value;
    req.onreadystatechange = function(){
        if (req.readyState == 4){
            if (req.status == 200){
                var response = JSON.parse(req.response);
                if (response["errorCode"]){
                    alert(response["details"]);
                }else{
                    names = response.result["name"];
                    document.getElementById("names").innerHTML = names;
                    numGuestsAllowed = response.result["primaryGuests"];
                    guestAllowed = response.result["additionalGuestAllowed"];
                    if (guestAllowed){
                        document.getElementById("guestoption").classList.remove("hidden");
                    }
                    alterPicklist(numGuestsAllowed);
                    updateRsvpCount(response);
                    showRsvp();
                    document.getElementById("headline").classList.remove("hidden");
                }
            }else{
                alert('Could not submit');
            }
        }
    }
    req.send();
    //    req.send(params);
}
var updateRsvpCount = function(response){
    curGuests = response.result["seatsReserved"];
    if (curGuests != null){
        var numActualString = curGuests + " seats";
        if (curGuests == 1){
            numActualString = "one seat";
        }
        document.getElementById("subGreeting").innerHTML = "You're currently confirmed for " + numActualString + ".";
        if (curGuests > 0){
            if (guestAllowed && curGuests == 2){
                document.getElementById("attendwithguest").checked='yes';
            }else{
                document.getElementById("attendyes").checked='yes';
                if (document.getElementById("numGuests")){
                   document.getElementById("numGuests").options[curGuests-1].selected=true;
                }
            }
        }else{
            document.getElementById("attendno").checked='yes';
        }
    }else{
        document.getElementById("submitbutton").classList.add("hidden");
    }

}

var alterPicklist = function(maxGuests){
    if (maxGuests > 1){
        var newPicklist = " <select id=\"numGuests\">";
        var i = 1;
        for (i ; i <= maxGuests; i++){ //
            newPicklist += "<option value=\"" + i + "\">" + i + "</option>";
        }
        newPicklist += "</select> seat(s).";
        document.getElementById("guestSelector").innerHTML = newPicklist;
        document.getElementById("numGuests").options[i-2].selected=true;
    }else{
        document.getElementById("guestSelector").innerHTML = "a seat for me.";
    }
    document.getElementById("subGreeting").innerHTML = "Will you be celebrating with us?"

}
var setClass = function(elemName, show){
    var elem = document.getElementById(elemName);
    if(show){
        elem.classList.remove("hidden");
    }else{
        elem.classList.add("hidden");
    }
}

var toggleStageLeft = function(){
    var stageLeft = document.getElementById("viewport");
    if (stageLeft.classList.contains("hideStageLeft")){
        stageLeft.classList.remove("hideStageLeft");
    }else{
        stageLeft.classList.add("hideStageLeft");
    }

}
<|endoftext|>


<commit_before>// Cert will be located depending on your machine
// Mac OS X: /Users/user/Library/Application Support/Lnd/tls.cert
// Linux: ~/.lnd/tls.cert
// Windows: TODO find out where cert is located for windows machine
import { userInfo } from 'os'

export default {
  lightningRpc: `${__dirname}/rpc.proto`,
  lightningHost: 'localhost:10009',
  cert: '/Users/'+ userInfo().username+'/Library/Application\ Support/Lnd/tls.cert'
}
<commit_msg>es6 :) fixes #24<commit_after>// Cert will be located depending on your machine
// Mac OS X: /Users/user/Library/Application Support/Lnd/tls.cert
// Linux: ~/.lnd/tls.cert
// Windows: TODO find out where cert is located for windows machine
import { userInfo } from 'os'

export default {
  lightningRpc: `${__dirname}/rpc.proto`,
  lightningHost: 'localhost:10009',
  cert: `/Users/${userInfo().username}/Library/Application\ Support/Lnd/tls.cert`
}
<|endoftext|>


<commit_before>"use strict";

var Core = require("lapis-core/index.js");
var Data = require("lazuli-data/index.js");
var IO = require("lazuli-io/index.js");

/**
* To represent a functional area of the system
*/
module.exports = Core.Base.clone({
    id: "Area",
    title: null,                     // name of this area
    security: null,                     // security object for this area
});

module.exports.defbind("setupTextStrings", "clone", function () {
    this.text_strings = {};
    // areas[this.id] = this;
    Data.areas.add(this);
    this.path = IO.File.getDirectory("../" + module.id);
});

module.exports.define("unpack", function () {
    this.throwError("deprecated");
});

module.exports.define("generateDemoData", function () {
    return undefined;
});
<commit_msg>fix area paths<commit_after>"use strict";

var Core = require("lapis-core/index.js");
var Data = require("lazuli-data/index.js");
var Rhino = require("lazuli-rhino/index.js");

/**
* To represent a functional area of the system
*/
module.exports = Core.Base.clone({
    id: "Area",
    title: null,                     // name of this area
    security: null,                     // security object for this area
});

module.exports.defbind("setupTextStrings", "clone", function () {
    this.text_strings = {};
    // areas[this.id] = this;
    Data.areas.add(this);
    // this won't work!
    // this.path = IO.File.getDirectory("../" + module.id);
});

module.exports.define("getPath", function () {
    if (!this.path) {
        this.path = Rhino.app.sapphire_dir + "/" + this.id;
    }
    return this.path;
});

module.exports.define("unpack", function () {
    this.throwError("deprecated");
});

module.exports.define("generateDemoData", function () {
    return undefined;
});
<|endoftext|>


<commit_before>function ddg_spice_github_jobs(github) {
	if(github.length > 0) {
		var query = DDG.get_query();
		var re = /(?:\s*(?:i\s+|we\s+)?(?:need|want|deserve|seek|get)\s+(?:an?\s+)?)?(?:(.+)\s+)(?:jobs?|work|employment)(?:\s+(?:in\s+)?(.+))?/;
		var description = query.replace(re, "$1");
		var location = query.replace(re, "$2");
		var moreat = "https://jobs.github.com/positions?description=" +  encodeURIComponent(description) + "&location=" +  encodeURIComponent(location);
		var out = ''
		out += '

';
		for(var i = 0;i < github.length;i++) {
			out += '
' + github[i].title
                +  ' in ' + github[i].location + ' (' + github[i].company + ')
';
		}
		out += '
';
		var items = [[]];
		items[0]['a'] = out;
		items[0]['h'] = query + ' (Github Jobs)';
		items[0]['s'] = 'Github';
		items[0]['u'] = moreat;
		items[0]['force_big_header'] = true;

		nra(items);
	}
}
<commit_msg>s/github/GitHub/g<commit_after>function ddg_spice_github_jobs(github) {
	if(github.length > 0) {
		var query = DDG.get_query();
		var re = /(?:\s*(?:i\s+|we\s+)?(?:need|want|deserve|seek|get)\s+(?:an?\s+)?)?(?:(.+)\s+)(?:jobs?|work|employment)(?:\s+(?:in\s+)?(.+))?/;
		var description = query.replace(re, "$1");
		var location = query.replace(re, "$2");
		var moreat = "https://jobs.github.com/positions?description=" +  encodeURIComponent(description) + "&location=" +  encodeURIComponent(location);
		var out = ''
		out += '

';
		for(var i = 0;i < github.length;i++) {
			out += '
' + github[i].title
                +  ' in ' + github[i].location + ' (' + github[i].company + ')
';
		}
		out += '
';
		var items = [[]];
		items[0]['a'] = out;
		items[0]['h'] = query + ' (GitHub Jobs)';
		items[0]['s'] = 'GitHub';
		items[0]['u'] = moreat;
		items[0]['force_big_header'] = true;

		nra(items);
	}
}
<|endoftext|>


<commit_before>import { ecc_config, hash } from "../ecc"

ecc_config.address_prefix = "GLS";

//let chain_id = ""
//for(let i = 0; i < 32; i++) chain_id += "00"
let chain_id = "d8cbe510924d8ab4b13e1a0269836cf37fdf91ad814b3574f353c7be5a625050"

module.exports = {
    address_prefix: "GLS",
    expire_in_secs: 15,
    chain_id
}
<commit_msg> new chainid<commit_after>import { ecc_config, hash } from "../ecc"

ecc_config.address_prefix = "GLS";

//let chain_id = ""
//for(let i = 0; i < 32; i++) chain_id += "00"
let chain_id = "782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de12"

module.exports = {
    address_prefix: "GLS",
    expire_in_secs: 15,
    chain_id
}
<|endoftext|>


<commit_before>var utils = require('../utils/httpUtils.js');
var _ = require('underscore');
var constants = require('../utils/constants.js');

exports.create = function(options) {
  var optionsToSend = {
    accessToken : options.accessToken
  };

  var listAttachments = function(getOptions, callback) {
    optionsToSend.url = buildUrl(getOptions);
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var listAttachmentVersions = function(getOptions, callback) {
    optionsToSend.url = buildUrl(getOptions) + '/versions';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var addAttachment = function(postOptions, callback) {
    optionsToSend.url = buildUrl(postOptions);
    return utils.post(_.extend(optionsToSend, postOptions), callback);
  };

  var attachNewVersion = function(postOptions, callback) {
    optionsToSend.url = buildUrl(postOptions) + '/versions';
    return utils.post(_.extend(optionsToSend, postOptions), callback);
  };

  var deleteAttachment = function(deleteOptions, callback) {
    optionsToSend.url = buildUrl(deleteOptions);
    return utils.delete(_.extend(optionsToSend, deleteOptions), callback);
  };

  var deleteAllAttachmentVersions = function(deleteOptions, callback) {
    optionsToSend.url = buildUrl(deleteOptions) + '/versions';
    return utils.delete(_.extend(optionsToSend, deleteOptions), callback);
  };

  var buildUrl = function(urlOptions) {
    return options.apiUrls.sheets + urlOptions.sheetId + '/attachments/' + (urlOptions.attachmentId || '');
  };

  return {
    getAttachment : listAttachments,
    listAttachments : listAttachments,
    listAttachmentVersions : listAttachmentVersions,
    addAttachment : addAttachment,
    attachNewVersion : attachNewVersion,
    deleteAttachment : deleteAttachment,
    deleteAllAttachmentVersions : deleteAllAttachmentVersions

  };
};
<commit_msg>Split URL and File sheet attachment endpoints.<commit_after>var utils = require('../utils/httpUtils.js');
var _ = require('underscore');
var constants = require('../utils/constants.js');

exports.create = function(options) {
  var optionsToSend = {
    accessToken : options.accessToken
  };

  var listAttachments = function(getOptions, callback) {
    optionsToSend.url = buildUrl(getOptions);
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var listAttachmentVersions = function(getOptions, callback) {
    optionsToSend.url = buildUrl(getOptions) + '/versions';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var addUrlAttachment = function(postOptions, callback) {
    optionsToSend.url = buildUrl(postOptions);
    return utils.post(_.extend(optionsToSend, postOptions), callback);
  };

  var addFileAttachment = function(postOptions, callback) {
    optionsToSend.url = buildUrl(postOptions);
    return utils.postFile(_.extend(optionsToSend, postOptions), callback);
  };

  var attachNewVersion = function(postOptions, callback) {
    optionsToSend.url = buildUrl(postOptions) + '/versions';
    return utils.postFile(_.extend(optionsToSend, postOptions), callback);
  };

  var deleteAttachment = function(deleteOptions, callback) {
    optionsToSend.url = buildUrl(deleteOptions);
    return utils.delete(_.extend(optionsToSend, deleteOptions), callback);
  };

  var deleteAllAttachmentVersions = function(deleteOptions, callback) {
    optionsToSend.url = buildUrl(deleteOptions) + '/versions';
    return utils.delete(_.extend(optionsToSend, deleteOptions), callback);
  };

  var buildUrl = function(urlOptions) {
    return options.apiUrls.sheets + urlOptions.sheetId + '/attachments/' + (urlOptions.attachmentId || '');
  };

  return {
    getAttachment : listAttachments,
    listAttachments : listAttachments,
    listAttachmentVersions : listAttachmentVersions,
    addUrlAttachment : addUrlAttachment,
    addFileAttachment : addFileAttachment,
    attachNewVersion : attachNewVersion,
    deleteAttachment : deleteAttachment,
    deleteAllAttachmentVersions : deleteAllAttachmentVersions

  };
};
<|endoftext|>


<commit_before>
var XhrCorsReceiver = function(url) {
    var that = this;
    var buf_pos = 0;
    var orsc = function (xhr, e, abort_reason) {
        if ((xhr.readyState === 3 || xhr.readyState === 4) &&
            xhr.responseText && xhr.status === 200) {
            var msgs = [];
            while (1) {
                var buf = xhr.responseText.slice(buf_pos);
                var p = buf.indexOf('\n');
                if (p === -1) break;
                buf_pos += p+1;
                var msg = buf.slice(0, p);
                that.dispatchEvent(new SimpleEvent('message', {'data': msg}));
            }
        }
        if (xhr.readyState === 4 || abort_reason) {
            var reason = abort_reason ? 'user' :
                (xhr.status === 200 ? 'network' : 'permanent');
            that.xhr_close = null;
            that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
        }
    };
    var createXhr = (opts.cors && window.XDomainRequest) ?
                                    utils.createXDR : utils.createXHR;
    that.xhr_close = createXhr('POST', url, null, orsc);
};

XhrReceiver.prototype = new REventTarget();

XhrReceiver.prototype.abort = function() {
    var that = this;
    if (that.xhr_close) {
        that.xhr_close(true);
    }
};
<commit_msg>IE doesn't like peeking into responseText and status on readyState=3.<commit_after>
var XhrReceiver = function(url, opts) {
    var that = this;
    var buf_pos = 0;
    var orsc = function (xhr, e, abort_reason) {
        if (xhr.readyState === 3 || xhr.readyState === 4) {
            // IE doesn't like peeking into responseText or status on
            // readystate=3
            try {
                var responseText = xhr.responseText;
                var status = xhr.status;
            } catch (x) {}
            if (responseText && status === 200) {
                var msgs = [];
                while (1) {
                    var buf = responseText.slice(buf_pos);
                    var p = buf.indexOf('\n');
                    if (p === -1) break;
                    buf_pos += p+1;
                    var msg = buf.slice(0, p);
                    that.dispatchEvent(new SimpleEvent('message', {'data': msg}));
                }
            }
        }
        if (xhr.readyState === 4 || abort_reason) {
            var reason = abort_reason ? 'user' :
                (xhr.status === 200 ? 'network' : 'permanent');
            that.xhr_close = null;
            that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
        }
    };
    var createXhr = (opts.cors && window.XDomainRequest) ?
                                    utils.createXDR : utils.createXHR;
    that.xhr_close = createXhr('POST', url, null, orsc);
};

XhrReceiver.prototype = new REventTarget();

XhrReceiver.prototype.abort = function() {
    var that = this;
    if (that.xhr_close) {
        that.xhr_close(true);
    }
};
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var en = require('./en');
var es = require('./es');

module.exports.help = function(t) {
  // English
  t.en = en;

  // Spanish
  t.es = es;
}<commit_msg>[translations] - Restore paths to dictionaries<commit_after>/**
 * Module dependencies.
 */

var en = require('./lib/en');
var es = require('./lib/es');

module.exports.help = function(t) {
  // English
  t.en = en;

  // Spanish
  t.es = es;
}<|endoftext|>


<commit_before>
/**
 * Module requirements.
 */

var Transport = require('../transport')
  , parser = require('../parser')
  , debug = require('debug')('engine:transport')

/**
 * Exports the constructor.
 */

module.exports = Polling;

/**
 * HTTP polling constructor.
 *
 * @api public.
 */

function Polling (req) {
  Transport.call(this, req);
};

/**
 * Inherits from Transport.
 *
 * @api public.
 */

Polling.prototype.__proto__ = Transport.prototype;

/**
 * Transport name
 *
 * @api public
 */

Polling.prototype.name = 'polling';

/**
 * Overrides onRequest.
 *
 * @param {http.ServerRequest}
 * @api private
 */

Polling.prototype.onRequest = function (req) {
  var res = req.res;

  if ('GET' == req.method) {
    this.onPollRequest(req, res);
  } else if ('POST' == req.method) {
    this.onDataRequest(req, res);
  } else {
    res.writeHead(500);
    res.end();
  }
};

/**
 * The client sends a request awaiting for us to send data.
 *
 * @api private
 */

Polling.prototype.onPollRequest = function (req, res) {
  if (this.req) {
    debug('poll request overlap');
    // assert: this.res, '.req and .res should be (un)set together'
    this.onError('poll overlap from client');
    res.writeHead(500);
  } else {
    debug('setting poll request');
    this.req = req;
    this.res = res;

    var self = this;

    function onClose () {
      self.onError('poll connection closed prematurely');
    }

    function cleanup () {
      req.removeListener('close', onClose);
      self.req = self.res = null;
    }

    req.cleanup = cleanup;
    req.on('close', onClose);

    this.buffer = false;
    this.flush();
  }
};

/**
 * The client sends a request with data.
 *
 * @api private
 */

Polling.prototype.onDataRequest = function (req, res) {
  if (this.dataReq) {
    // assert: this.dataRes, '.dataReq and .dataRes should be (un)set together'
    this.onError('data request overlap from client');
    res.writeHead(500);
  } else {
    this.dataReq = req;
    this.dataRes = res;

    var chunks = ''
      , self = this

    function cleanup () {
      chunks = '';
      req.removeListener('data', onData);
      req.removeListener('end', onEnd);
      req.removeListener('close', cleanup);
      self.dataReq = self.dataRes = null;
    };

    function onClose () {
      cleanup();
      self.onError('data request connection closed prematurely');
    };

    function onData (data) {
      chunks += data;
    };

    function onEnd () {
      self.onData(chunks);
      res.writeHead(204);
      res.end();
      cleanup();
    };

    req.abort = cleanup;
    req.on('close', onClose);
    req.on('data', onData);
    req.on('end', onEnd);
    req.setEncoding('utf8');
  }
};

/**
 * Processes the incoming data payload.
 */

Polling.prototype.onData = function (data) {
  var packets = parser.decodePayload(data);
  for (var i = 0, l = packets.length; i < l; i++) {
    if ('close' == packets[i].type) {
      debug('got xhr close packet');
      return this.onClose();
    }

    this.onPacket(packets[i]);
  }
};

/**
 * Flushes buffers.
 *
 * @api private
 */

Polling.prototype.flush = function () {
  if (this.writeBuffer) {
    this.write(parser.encodePayload(this.writeBuffer));
    this.writeBuffer = null;
    this.emit('drain');
  }
};

/**
 * Writes a packet.
 *
 * @param {Object} packet
 * @param {Function} called when the packet is dispatched
 * @api private
 */

Polling.prototype.send = function (packet, fn) {
  if (this.buffer) {
    if (!this.writeBuffer) {
      this.writeBuffer = [];
    }

    debug('poll buffering packet: type %s | data %s', packet.type, packet.data);
    this.writeBuffer.push(packet);
    if (fn) this.once('drain', fn);
  } else {
    debug('poll writing packet: type %s | data %s', packet.type, packet.data);
    this.write(parser.encodePayload([packet]));
    if (fn) fn();
  }
};

/**
 * Writes data as response to poll request.
 *
 * @param {String} data
 * @api private
 */

Polling.prototype.write = function (data) {
  this.doWrite(data);
  this.req.cleanup();
  this.buffer = true;
};

/**
 * Closes the transport.
 *
 * @api private
 */

Polling.prototype.doClose = function (fn) {
  if (this.dataReq) {
    // FIXME: should we do this?
    debug('aborting ongoing data request');
    this.dataReq.abort();
  }

  this.send({ type: 'close' }, fn);
};
<commit_msg>Implemented draining and orderly close to polling.<commit_after>
/**
 * Module requirements.
 */

var Transport = require('../transport')
  , parser = require('../parser')
  , debug = require('debug')('engine:transport')

/**
 * Exports the constructor.
 */

module.exports = Polling;

/**
 * HTTP polling constructor.
 *
 * @api public.
 */

function Polling (req) {
  Transport.call(this, req);
};

/**
 * Inherits from Transport.
 *
 * @api public.
 */

Polling.prototype.__proto__ = Transport.prototype;

/**
 * Transport name
 *
 * @api public
 */

Polling.prototype.name = 'polling';

/**
 * Overrides onRequest.
 *
 * @param {http.ServerRequest}
 * @api private
 */

Polling.prototype.onRequest = function (req) {
  var res = req.res;

  if ('GET' == req.method) {
    this.onPollRequest(req, res);
  } else if ('POST' == req.method) {
    this.onDataRequest(req, res);
  } else {
    res.writeHead(500);
    res.end();
  }
};

/**
 * The client sends a request awaiting for us to send data.
 *
 * @api private
 */

Polling.prototype.onPollRequest = function (req, res) {
  if (this.req) {
    debug('poll request overlap');
    // assert: this.res, '.req and .res should be (un)set together'
    this.onError('poll overlap from client');
    res.writeHead(500);
  } else {
    debug('setting poll request');
    this.req = req;
    this.res = res;

    var self = this;

    function onClose () {
      self.onError('poll connection closed prematurely');
    }

    function cleanup () {
      req.removeListener('close', onClose);
      self.req = self.res = null;
    }

    req.cleanup = cleanup;
    req.on('close', onClose);

    this.writable = true;
    this.emit('drain');

    // if we're still writable but had a pending close, trigger an empty send
    if (this.writable && this.shouldClose) {
      debug('triggering empty send to append close packet');
      this.send([]);
    }
  }
};

/**
 * The client sends a request with data.
 *
 * @api private
 */

Polling.prototype.onDataRequest = function (req, res) {
  if (this.dataReq) {
    // assert: this.dataRes, '.dataReq and .dataRes should be (un)set together'
    this.onError('data request overlap from client');
    res.writeHead(500);
  } else {
    this.dataReq = req;
    this.dataRes = res;

    var chunks = ''
      , self = this

    function cleanup () {
      chunks = '';
      req.removeListener('data', onData);
      req.removeListener('end', onEnd);
      req.removeListener('close', cleanup);
      self.dataReq = self.dataRes = null;
    };

    function onClose () {
      cleanup();
      self.onError('data request connection closed prematurely');
    };

    function onData (data) {
      chunks += data;
    };

    function onEnd () {
      self.onData(chunks);
      res.writeHead(204);
      res.end();
      cleanup();
    };

    req.abort = cleanup;
    req.on('close', onClose);
    req.on('data', onData);
    req.on('end', onEnd);
    req.setEncoding('utf8');
  }
};

/**
 * Processes the incoming data payload.
 */

Polling.prototype.onData = function (data) {
  var packets = parser.decodePayload(data);
  for (var i = 0, l = packets.length; i < l; i++) {
    if ('close' == packets[i].type) {
      debug('got xhr close packet');
      return this.onClose();
    }

    this.onPacket(packets[i]);
  }
};

/**
 * Writes a packet payload.
 *
 * @param {Object} packet
 * @api private
 */

Polling.prototype.send = function (packets) {
  debug('polling writing packets', JSON.stringify(packets));
  if (this.shouldClose) {
    debug('appending close packet to payload');
    packets.push({ type: 'close' });
    this.shouldClose();
    this.shouldClose = null;
  }

  this.write(parser.encodePayload(packets));
};

/**
 * Writes data as response to poll request.
 *
 * @param {String} data
 * @api private
 */

Polling.prototype.write = function (data) {
  this.doWrite(data);
  this.req.cleanup();
  this.writable = false;
};

/**
 * Closes the transport.
 *
 * @api private
 */

Polling.prototype.doClose = function (fn) {
  if (this.dataReq) {
    // FIXME: should we do this?
    debug('aborting ongoing data request');
    this.dataReq.abort();
  }

  if (this.writable) {
    debug('polling transport is writable - closing right away');
    this.send([{ type: 'close' }]);
  } else {
    debug('polling transport not writable - marking that we should close');
    this.shouldClose = fn;
  }
};
<|endoftext|>


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

var log = require('util/log');
var config = require('util/config');
var fs = require('fs');
var sys = require('sys');
var crypto = require('crypto');

/**
 * Write a file from an HTTP stream and fire a callback on success or error.
 *
 * @param {String} dest The path to store the file to
 * @param {http.ServerRequest} istream The HTTP stream to read from
 * @param {Array} received  An array of buffers that have already been received
 * @param {Boolean} completed Whether the request has already ended
 * @param {Function} cb A callback that takes a possible error
 */
exports.pumpfilein = function(dest, istream, received, completed, cb) {
  var fstream = fs.createWriteStream(dest, {'flags': 'w', 'encoding': 'binary', 'mode': 0644});
  var sha1 = crypto.createHash('sha1');

  function close_fstream() {
    try {
      fstream.end();
    }
    catch (err) {
      log.err("Unable to close file: " + err.message);
    }
  }

  fstream.on('error', function(err) {
    log.err("Error on file stream: " + err.message);
    close_fstream();
    return cb(err);
  });

  function write_received() {
    for (var i = 0; i < received.length; i++) {
      sha1.update(received[i]);
      fstream.write(received[i]);
    }
  }

  /* If the request has already been completed, we don't need to actually use
   * the pump.
   */
  if (completed) {
    fstream.on('close', function() {
      return cb(null, sha1);
    });

    write_received();

    fstream.end();
    return;
  }

  istream.on('end', function() {
    /* This is not ideal, but sys.pump and the HTTP request don't interact that
     * well together, so this emits a spurious and technically incorrect
     * 'close' event for when the HTTP request body has ended.
     */
    istream.emit('close');
  });

  istream.on('data', function(data) {
    sha1.update(data);
  });

  write_received();

  sys.pump(istream, fstream, function() {
    cb(null, sha1);
  });
};

/**
 * Write a file to an HTTP stream. Does not write the headers.
 *
 * @param {String} source The path to read the file from
 * @param {http.ServerResponse} ostream The HTTP Stream to write the file to
 * @param {Function} cb A callback which takes a possible error
 */
exports.pumpfileout = function(source, ostream, cb) {
  var fstream = fs.createReadStream(source, {'bufferSize': config.get().fileread_buffer_size});

  function close_both() {
    (function() {
      try {
        ostream.end();
      }
      catch (err) {
        log.err("Unable to close outgoing HTTP stream: " + err.message);
      }
    })();

    (function() {
      try {
        fstream.end();
      }
      catch (err) {
        log.err("Unable to close file: " + err.message);
      }
    })();
  }

  fstream.on('error', function(err) {
    close_both();
    return cb(err);
  });

  sys.pump(fstream, ostream, function() {
    cb();
  });
};
<commit_msg>Modify http pumpfile to not operate until the file is open and fire a 'tick' callback during the transfer.<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var log = require('util/log');
var config = require('util/config');
var fs = require('fs');
var sys = require('sys');
var crypto = require('crypto');

/**
 * Write a file from an HTTP stream and fire a callback on success or error.
 *
 * @param {String} dest The path to store the file to
 * @param {http.ServerRequest} istream The HTTP stream to read from
 * @param {Array} received  An array of buffers that have already been received
 * @param {Boolean} completed Whether the request has already ended
 * @param {Function} cb A callback that takes a possible error
 */
exports.pumpfilein = function(dest, istream, received, completed, cb) {
  var fstream = fs.createWriteStream(dest, {'flags': 'w', 'encoding': 'binary', 'mode': 0644});
  var sha1 = crypto.createHash('sha1');

  function close_fstream() {
    try {
      fstream.end();
    }
    catch (err) {
      log.err("Unable to close file: " + err.message);
    }
  }

  fstream.on('error', function(err) {
    log.err("Error on file stream: " + err.message);
    close_fstream();
    return cb(err);
  });

  function write_received() {
    for (var i = 0; i < received.length; i++) {
      sha1.update(received[i]);
      fstream.write(received[i]);
    }
  }

  /* If the request has already been completed, we don't need to actually use
   * the pump.
   */
  if (completed) {
    fstream.on('close', function() {
      return cb(null, sha1);
    });

    write_received();

    fstream.end();
    return;
  }

  istream.on('end', function() {
    /* This is not ideal, but sys.pump and the HTTP request don't interact that
     * well together, so this emits a spurious and technically incorrect
     * 'close' event for when the HTTP request body has ended.
     */
    istream.emit('close');
  });

  istream.on('data', function(data) {
    sha1.update(data);
  });

  write_received();

  sys.pump(istream, fstream, function() {
    cb(null, sha1);
  });
};

/**
 * Write a file to an HTTP stream. Does not write the headers.
 *
 * @param {String} source The path to read the file from
 * @param {http.ServerResponse} ostream The HTTP Stream to write the file to
 * @param {Function} tick An optional callback that is fired each time data is
 *                        written and takes the total number of bytes written.
 * @param {Function} cb A callback which takes a possible error
 */
exports.pumpfileout = function(source, ostream, tick, cb) {
  if (!cb) {
    cb = tick;
    tick = function() {};
  }

  var bytes = 0;
  var fstream = fs.createReadStream(source, {'bufferSize': config.get().fileread_buffer_size});

  function close_both() {
    (function() {
      try {
        ostream.end();
      }
      catch (err) {
        log.err("Unable to close outgoing HTTP stream: " + err.message);
      }
    })();

    (function() {
      try {
        fstream.end();
      }
      catch (err) {
        log.err("Unable to close file: " + err.message);
      }
    })();
  }

  fstream.on('error', function(err) {
    close_both();
    return cb(err);
  });

  fstream.on('data', function(data) {
    bytes += data.length;
    tick(bytes);
  });

  fstream.on('open', function() {
    sys.pump(fstream, ostream, function() {
      cb();
    });
  });
};
<|endoftext|>


<commit_before>
var os = require('os');
var memcached = require('memcached');
var memcachedbin = require('./memcachedbin'); //TODO - move to a single cache
var memjs = require('memjs'); // TODO use this lib only
var path = require('path');

KalturaCache = {
	config : null,
	server : null,
	binserver: null,
	binserverSet: null,
	dataVersion: 0,

	init: function(){
		this.config = KalturaConfig.config.memcache;
		this.server = new memcached(this.config.hostname + ':' + this.config.port, this.config);

		this.binserver = new memcachedbin();
		this.binserver.host = this.config.hostname;
		this.binserver.port = this.config.port;

//		this.binserver.on('connect', function() {
//		TODO: start server async
//		});

		this.binserver.connect();

		this.binserverSet = memjs.Client.create(this.config.hostname + ':' + this.config.port);

		if(this.config.dataVersion){
			this.dataVersion = parseInt(this.config.dataVersion);
		}
	},

	//KEY PREFIXES
	AD_MEDIA_KEY_PREFIX: 'adMedia',
	AD_HANDLED_KEY_PREFIX: 'adHandled',

	FILLER_HANDLED_KEY_PREFIX: 'fillerHandled',
	FILLER_MEDIA_KEY_PREFIX: 'fillerMedia',
	FILLER_ENCODING_PARAMS_KEY_PREFIX: 'fillerEncodingParams',

	CUE_POINT_URL_KEY_PREFIX: 'cuePointUrl',
	CUE_POINT_HANDLED_KEY_PREFIX: 'cuePointHandled',
	CUE_POINT_WATCHER_HANDLED_KEY_PREFIX: 'cuePointWatcherHandled',
	CAN_PLAY_AD_KEY_PREFIX: 'canPlayAd',

	ENTRY_CUE_POINTS_KEY_PREFIX: 'entryCuePoints',
	ENTRY_ELAPSED_TIME_KEY_PREFIX: 'entryElapsedTime',
	ENTRY_REQUIRED_KEY_PREFIX: 'entryRequired',
	ENCODING_PARAMS_KEY_PREFIX: 'encodingParams',

	FILE_DOWNLOADING_KEY_PREFIX: 'fileDownloading',

	MASTER_MANIFEST_REQUIRED_KEY_PREFIX: 'masterRequired',
	MANIFEST_CONTENT_KEY_PREFIX: 'manifestContent',
	METADATA_READY_KEY_PREFIX: 'metadataReady',
	MEDIA_INFO_KEY_PREFIX: 'mediaInfo',

	OLDEST_SEGMENT_TIME_KEY_PREFIX: 'oldestSegmentTime',

	PROCESS_ACTIONS_KEY_PREFIX: 'processActions',
	POST_SEGMENT_STITCHED_KEY_PREFIX: 'postSegmentStitched',

	RENDITION_MANIFEST_HANDLED_KEY_PREFIX: 'renditionManifestHandled',

	SERVER_PROCESSES_KEY_PREFIX: 'serverProcesses',
	SEGMENT_MEDIA_KEY_PREFIX: 'segmentMedia',
	SERVER_AD_ID_KEY_PREFIX: 'serverAdId',

	TRACKING_KEY_PREFIX: 'tracking',

	UI_CONF_CONFIG_KEY_PREFIX: 'uiConfConfig',

	//KEY SUFFIX
	METADATA_KEY_SUFFIX: 'metadata',

	getManifestId : function(manifestUrl) {
		if(KalturaConfig.config.cache.hackWowzaUniqueSession && parseInt(KalturaConfig.config.cache.hackWowzaUniqueSession)){
    		// hack Wowza per session unique key
			manifestUrl = manifestUrl.replace(/\/chunklist_w\d+_(b\d+).m3u8$/, 'chunklist_$1.m3u8');
		}

		return manifestUrl.md5();
	},

	getEncodingId : function(encodingParams){
		return encodingParams.md5();
	},

	getPid : function(pid){
		if(!pid){
			pid = process.pid;
		}
		return pid;
	},

	getSegmentId : function(portion, cuePointId, renditionId) {
		return (portion + '-' + cuePointId + '-' + renditionId).md5();
	},

	getPreSegmentId : function(cuePointId, renditionId) {
		return this.getSegmentId('left', cuePointId, renditionId);
	},

	getPostSegmentId : function(cuePointId, renditionId) {
		return this.getSegmentId('right', cuePointId, renditionId);
	},

	getPostSegmentStitchedId: function(cuePointId, adsSequenceId, segmentIndex){
		return (cuePointId + '-' + segmentIndex + '-' + adsSequenceId).md5();
	},

	getUiConfConfigId : function(uiConfConfig){
		return JSON.stringify(uiConfConfig).md5();
	},

	getStack : function() {
		return new Error();
	},

	getRenditionIdFromMediaInfo: function(mediaInfoKey){
		var keyPrefix = this.getKey(this.MEDIA_INFO_KEY_PREFIX, []) + '-';
		return mediaInfoKey.substring(keyPrefix.length);
	},

	buildEntryRequiredValue: function(renditionId){
		return '\n' + renditionId;
	},

	buildAdsSequenceId: function(serverAdIds){
		sequenceId = [];
		for(var i = 0; i<= serverAdIds.length; i++){
			if(!serverAdIds[i]){
				continue;
			}
			sequenceId.push(this.extractAdIdFromServerAdId(serverAdIds[i]));
		}
		return JSON.stringify(sequenceId).md5();
	},

	extractAdIdFromServerAdId: function(serverAdId){
		return serverAdId.id.split('-')[0];
	},

	extractEntryRequiredValue: function(entryRequired){
		if(!entryRequired){
			return [];
		}
		return entryRequired.split('\n').unique();
	},

	buildSessionServerAdIdValue: function(sessionServerAdId, sequence){
		return '\n' + sequence + ';' + JSON.stringify(sessionServerAdId);
	},

	extractSessionServerAdIdValue: function(sessionServerAdId){
		sessionServerAdId = sessionServerAdId.split('\n');
		var serverAdIds = [];

		for(var i = 0; i<= sessionServerAdId.length; i++){
			if(sessionServerAdId[i]){
				var serverAdId = sessionServerAdId[i].split(';');
				serverAdIds[serverAdId[0]]=JSON.parse(serverAdId[1]);
			}
		}

		return serverAdIds;
	},

	getKey: function(keyPrefix, params, keySuffix){
		var key = keyPrefix;
		for(var i = 0; i< params.length; i++){
			key += '-' + params[i];
		}
		if(keySuffix){
			key += '-' + keySuffix;
		}

		key = 'v' + this.dataVersion + '-' + key;
		return key;
	},

	get : function(key, callback, errorCallback) {
		var stackSource = this.getStack();
		KalturaLogger.debug('Cache.get [' + key + ']...', stackSource);
		this.server.get(key, function(err, data){
			if(err){
				var errMessage = 'Cache.get [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.get [' + key + ']: OK', stackSource);
				if(callback)
					callback(data);
			}
		});
	},

	set : function(key, value, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.set [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		this.server.set(key, value, lifetime, function(err){
			if(err){
				var errMessage = 'Cache.set [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.set [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	touch : function(key, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.touch [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		var cacheTouchCallback = function(err){
			if(err){
				var errMessage = 'Cache.touch [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.touch [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		};

		if(parseInt(this.config.touchEnabled)){
			this.server.touch(key, lifetime, function(err, value){
				if(err){
					cacheTouchCallback(err);
				}
				else if(value){
					cacheTouchCallback();
				}
				else{
					cacheTouchCallback('value is null');
				}
			});
		}
		else{
			var This = this;
			this.server.get(key, function(err, value){
				if(err){
					cacheTouchCallback(err);
				}
				else if(value){
					This.server.set(key, value, lifetime, cacheTouchCallback);
				}
				else{
					cacheTouchCallback('value is null');
				}
			});
		}
	},

	add : function(key, value, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.set [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		this.server.add(key, value, lifetime, function(err){
			if(err){
				var errMessage = 'Cache.add [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.add [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	append : function(key, value, callback, errorCallback) {
		var stackSource = this.getStack();
		this.server.append(key, value, function(err){
			if(err){
				var errMessage = 'Cache.append [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.append [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	getMulti : function(keys, callback, errorCallback) {
		var stackSource = this.getStack();
		var missingAnswers = keys.length;
		var answers = {};

		keys.forEach(function(key, index, array){
			KalturaCache.server.get(key, function(err, data){
    			if(err){
    				var errMessage = 'Cache.getMulti [' + key + ']:' + err;
    				if(errorCallback){
    					errorCallback(errMessage);
    				}
    				else{
    					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
    				}
    			}
    			else{
    				KalturaLogger.debug('Cache.getMulti [' + key + ']: OK', stackSource);
    				answers[key] = data;
        			missingAnswers--;
    				if(!missingAnswers && callback)
    					callback(answers);
    			}
    		});
		});
	},

	del : function(key, callback, errorCallback) {
		var stackSource = this.getStack();
		return this.server.del(key, function(err){
			if(err){
				var errMessage = 'Cache.del [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.del [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	replace : function(key, value, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.set [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		return this.server.replace(key, value, lifetime, function(err){
			if(err){
				var errMessage = 'Cache.replace [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.replace [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	getBinary : function(key, callback, errorCallback) {
		var stackSource = this.getStack();
		KalturaLogger.debug('Cache.getBinary [' + key + ']...', stackSource);
		this.binserver.get(key, function(err, data){
			if(err){
				var errMessage = 'Cache.getBinary [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.getBinary [' + key + ']: OK', stackSource);
				if(callback)
					callback(data);
			}
		});
	},

	getMultiBinary : function(keys, callback, errorCallback) {
		var stackSource = this.getStack();
		var missingAnswers = keys.length;
		var answers = {};

		keys.forEach(function(key, index, array){
			KalturaCache.binserver.get(key, function(err, data){
    			if(err){
    				var errMessage = 'Cache.getMultiBinary [' + key + ']:' + err;
    				if(errorCallback){
    					errorCallback(errMessage);
    				}
    				else{
    					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
    				}
    			}
    			else{
    				KalturaLogger.debug('Cache.getMultiBinary [' + key + ']: OK', stackSource);
    				answers[key] = data;
        			missingAnswers--;
    				if(!missingAnswers && callback)
    					callback(answers);
    			}
    		});
		});
	},
};
KalturaCache.init();
<commit_msg>Add remove rendition manifest key from cache PLAT-5375<commit_after>
var os = require('os');
var memcached = require('memcached');
var memcachedbin = require('./memcachedbin'); //TODO - move to a single cache
var memjs = require('memjs'); // TODO use this lib only
var path = require('path');

KalturaCache = {
	config : null,
	server : null,
	binserver: null,
	binserverSet: null,
	dataVersion: 0,

	init: function(){
		this.config = KalturaConfig.config.memcache;
		this.server = new memcached(this.config.hostname + ':' + this.config.port, this.config);

		this.binserver = new memcachedbin();
		this.binserver.host = this.config.hostname;
		this.binserver.port = this.config.port;

//		this.binserver.on('connect', function() {
//		TODO: start server async
//		});

		this.binserver.connect();

		this.binserverSet = memjs.Client.create(this.config.hostname + ':' + this.config.port);

		if(this.config.dataVersion){
			this.dataVersion = parseInt(this.config.dataVersion);
		}
	},

	//KEY PREFIXES
	AD_MEDIA_KEY_PREFIX: 'adMedia',
	AD_HANDLED_KEY_PREFIX: 'adHandled',

	FILLER_HANDLED_KEY_PREFIX: 'fillerHandled',
	FILLER_MEDIA_KEY_PREFIX: 'fillerMedia',
	FILLER_ENCODING_PARAMS_KEY_PREFIX: 'fillerEncodingParams',

	CUE_POINT_URL_KEY_PREFIX: 'cuePointUrl',
	CUE_POINT_HANDLED_KEY_PREFIX: 'cuePointHandled',
	CUE_POINT_WATCHER_HANDLED_KEY_PREFIX: 'cuePointWatcherHandled',
	CAN_PLAY_AD_KEY_PREFIX: 'canPlayAd',

	ENTRY_CUE_POINTS_KEY_PREFIX: 'entryCuePoints',
	ENTRY_ELAPSED_TIME_KEY_PREFIX: 'entryElapsedTime',
	ENTRY_REQUIRED_KEY_PREFIX: 'entryRequired',
	ENCODING_PARAMS_KEY_PREFIX: 'encodingParams',

	FILE_DOWNLOADING_KEY_PREFIX: 'fileDownloading',

	MASTER_MANIFEST_REQUIRED_KEY_PREFIX: 'masterRequired',
	MANIFEST_CONTENT_KEY_PREFIX: 'manifestContent',
	METADATA_READY_KEY_PREFIX: 'metadataReady',
	MEDIA_INFO_KEY_PREFIX: 'mediaInfo',

	OLDEST_SEGMENT_TIME_KEY_PREFIX: 'oldestSegmentTime',

	PROCESS_ACTIONS_KEY_PREFIX: 'processActions',
	POST_SEGMENT_STITCHED_KEY_PREFIX: 'postSegmentStitched',

	RENDITION_MANIFEST_HANDLED_KEY_PREFIX: 'renditionManifestHandled',

	SERVER_PROCESSES_KEY_PREFIX: 'serverProcesses',
	SEGMENT_MEDIA_KEY_PREFIX: 'segmentMedia',
	SERVER_AD_ID_KEY_PREFIX: 'serverAdId',

	TRACKING_KEY_PREFIX: 'tracking',

	UI_CONF_CONFIG_KEY_PREFIX: 'uiConfConfig',

	//KEY SUFFIX
	METADATA_KEY_SUFFIX: 'metadata',

	getManifestId : function(manifestUrl) {
		if(KalturaConfig.config.cache.hackWowzaUniqueSession && parseInt(KalturaConfig.config.cache.hackWowzaUniqueSession)){
    		// hack Wowza per session unique key
			manifestUrl = manifestUrl.replace(/\/chunklist_w\d+_(b\d+).m3u8$/, 'chunklist_$1.m3u8');
		}

		return manifestUrl.md5();
	},

	getEncodingId : function(encodingParams){
		return encodingParams.md5();
	},

	getPid : function(pid){
		if(!pid){
			pid = process.pid;
		}
		return pid;
	},

	getSegmentId : function(portion, cuePointId, renditionId) {
		return (portion + '-' + cuePointId + '-' + renditionId).md5();
	},

	getPreSegmentId : function(cuePointId, renditionId) {
		return this.getSegmentId('left', cuePointId, renditionId);
	},

	getPostSegmentId : function(cuePointId, renditionId) {
		return this.getSegmentId('right', cuePointId, renditionId);
	},

	getPostSegmentStitchedId: function(cuePointId, adsSequenceId, segmentIndex){
		return (cuePointId + '-' + segmentIndex + '-' + adsSequenceId).md5();
	},

	getUiConfConfigId : function(uiConfConfig){
		return JSON.stringify(uiConfConfig).md5();
	},

	getStack : function() {
		return new Error();
	},

	getRenditionIdFromMediaInfo: function(mediaInfoKey){
		var keyPrefix = this.getKey(this.MEDIA_INFO_KEY_PREFIX, []) + '-';
		return mediaInfoKey.substring(keyPrefix.length);
	},

	buildEntryRequiredValue: function(renditionId){
		return '\n' + renditionId;
	},

	removeRenditionIdFromEntryRequiredValue: function(entryRequired, renditionId){
		var currentRenditions = this.extractEntryRequiredValue(entryRequired);
		var newEntryRequired = "\n";
		var shouldChange = false;
		for(var i = 0; i < currentRenditions.length; i++){
			if(currentRenditions[i].indexOf(renditionId) == -1 ){
				newEntryRequired += "\n" + currentRenditions[i].trim();
			} else {
				shouldChange = true;
			}
		}
		if ( shouldChange ) {
			this.set(entryRequired, newEntryRequired);
		}
	},

	buildAdsSequenceId: function(serverAdIds){
		sequenceId = [];
		for(var i = 0; i<= serverAdIds.length; i++){
			if(!serverAdIds[i]){
				continue;
			}
			sequenceId.push(this.extractAdIdFromServerAdId(serverAdIds[i]));
		}
		return JSON.stringify(sequenceId).md5();
	},

	extractAdIdFromServerAdId: function(serverAdId){
		return serverAdId.id.split('-')[0];
	},

	extractEntryRequiredValue: function(entryRequired){
		if(!entryRequired){
			return [];
		}
		return entryRequired.split('\n').unique();
	},

	buildSessionServerAdIdValue: function(sessionServerAdId, sequence){
		return '\n' + sequence + ';' + JSON.stringify(sessionServerAdId);
	},

	extractSessionServerAdIdValue: function(sessionServerAdId){
		sessionServerAdId = sessionServerAdId.split('\n');
		var serverAdIds = [];

		for(var i = 0; i<= sessionServerAdId.length; i++){
			if(sessionServerAdId[i]){
				var serverAdId = sessionServerAdId[i].split(';');
				serverAdIds[serverAdId[0]]=JSON.parse(serverAdId[1]);
			}
		}

		return serverAdIds;
	},

	getKey: function(keyPrefix, params, keySuffix){
		var key = keyPrefix;
		for(var i = 0; i< params.length; i++){
			key += '-' + params[i];
		}
		if(keySuffix){
			key += '-' + keySuffix;
		}

		key = 'v' + this.dataVersion + '-' + key;
		return key;
	},

	get : function(key, callback, errorCallback) {
		var stackSource = this.getStack();
		KalturaLogger.debug('Cache.get [' + key + ']...', stackSource);
		this.server.get(key, function(err, data){
			if(err){
				var errMessage = 'Cache.get [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.get [' + key + ']: OK', stackSource);
				if(callback)
					callback(data);
			}
		});
	},

	set : function(key, value, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.set [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		this.server.set(key, value, lifetime, function(err){
			if(err){
				var errMessage = 'Cache.set [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.set [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	touch : function(key, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.touch [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		var cacheTouchCallback = function(err){
			if(err){
				var errMessage = 'Cache.touch [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.touch [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		};

		if(parseInt(this.config.touchEnabled)){
			this.server.touch(key, lifetime, function(err, value){
				if(err){
					cacheTouchCallback(err);
				}
				else if(value){
					cacheTouchCallback();
				}
				else{
					cacheTouchCallback('value is null');
				}
			});
		}
		else{
			var This = this;
			this.server.get(key, function(err, value){
				if(err){
					cacheTouchCallback(err);
				}
				else if(value){
					This.server.set(key, value, lifetime, cacheTouchCallback);
				}
				else{
					cacheTouchCallback('value is null');
				}
			});
		}
	},

	add : function(key, value, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.set [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		this.server.add(key, value, lifetime, function(err){
			if(err){
				var errMessage = 'Cache.add [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.add [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	append : function(key, value, callback, errorCallback) {
		var stackSource = this.getStack();
		this.server.append(key, value, function(err){
			if(err){
				var errMessage = 'Cache.append [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.append [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	getMulti : function(keys, callback, errorCallback) {
		var stackSource = this.getStack();
		var missingAnswers = keys.length;
		var answers = {};

		keys.forEach(function(key, index, array){
			KalturaCache.server.get(key, function(err, data){
    			if(err){
    				var errMessage = 'Cache.getMulti [' + key + ']:' + err;
    				if(errorCallback){
    					errorCallback(errMessage);
    				}
    				else{
    					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
    				}
    			}
    			else{
    				KalturaLogger.debug('Cache.getMulti [' + key + ']: OK', stackSource);
    				answers[key] = data;
        			missingAnswers--;
    				if(!missingAnswers && callback)
    					callback(answers);
    			}
    		});
		});
	},

	del : function(key, callback, errorCallback) {
		var stackSource = this.getStack();
		return this.server.del(key, function(err){
			if(err){
				var errMessage = 'Cache.del [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.del [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	replace : function(key, value, lifetime, callback, errorCallback) {
		if(!lifetime || isNaN(lifetime)){
			throw new Error('Cache.set [' + key + ']: lifetime [' + lifetime + '] is not numeric');
		}
		lifetime = parseInt(lifetime);
		var stackSource = this.getStack();
		return this.server.replace(key, value, lifetime, function(err){
			if(err){
				var errMessage = 'Cache.replace [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.replace [' + key + ']: OK', stackSource);
				if(callback)
					callback();
			}
		});
	},

	getBinary : function(key, callback, errorCallback) {
		var stackSource = this.getStack();
		KalturaLogger.debug('Cache.getBinary [' + key + ']...', stackSource);
		this.binserver.get(key, function(err, data){
			if(err){
				var errMessage = 'Cache.getBinary [' + key + ']:' + err;
				if(errorCallback){
					errorCallback(errMessage);
				}
				else{
					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
				}
			}
			else{
				KalturaLogger.debug('Cache.getBinary [' + key + ']: OK', stackSource);
				if(callback)
					callback(data);
			}
		});
	},

	getMultiBinary : function(keys, callback, errorCallback) {
		var stackSource = this.getStack();
		var missingAnswers = keys.length;
		var answers = {};

		keys.forEach(function(key, index, array){
			KalturaCache.binserver.get(key, function(err, data){
    			if(err){
    				var errMessage = 'Cache.getMultiBinary [' + key + ']:' + err;
    				if(errorCallback){
    					errorCallback(errMessage);
    				}
    				else{
    					KalturaLogger.error(errMessage + "\n" + stackSource.stack, stackSource);
    				}
    			}
    			else{
    				KalturaLogger.debug('Cache.getMultiBinary [' + key + ']: OK', stackSource);
    				answers[key] = data;
        			missingAnswers--;
    				if(!missingAnswers && callback)
    					callback(answers);
    			}
    		});
		});
	},
};
KalturaCache.init();
<|endoftext|>


<commit_before>const { resolve, join } = require('path');
const { existsSync } = require('fs');

class GroupHelper {
    constructor(options) {
        this.args = this.arrayToObject(options);
        this.opts = {
            outputOptions: {},
            options: {},
            processingErrors: [],
        };
    }

    hyphenToUpperCase(name) {
        if (!name) {
            return name;
        }
        return name.replace(/-([a-z])/g, function(g) {
            return g[1].toUpperCase();
        });
    }
    mergeRecursive(acc, curr) {
        for (var p in curr) {
            try {
                // Property in destination object set; update its value.
                if (curr[p].constructor == Object) {
                    acc[p] = this.mergeRecursive(acc[p], curr[p]);
                } else {
                    acc[p] = curr[p];
                }
            } catch (e) {
                // Property in destination object not set; create it and set its value.
                acc[p] = curr[p];
            }
        }

        return acc;
    }
    arrayToObject(arr) {
        if (!arr) {
            return;
        }
        var result = {};
        let arrLength = arr.length;
        for (let i = 0; i < arrLength; i++) {
            let key = Object.keys(arr[i])[0];
            const val = arr[i][key];
            result[this.hyphenToUpperCase(key)] = val;
        }
        return result;
    }
    verifyType(key, val) {
        /*  if(!schemaProp.includes(val)) {
            const errMsg = 'Unrecognized Option: ' + val + ' supplied to ' + key;
            this.errors.push(errMsg);
        } */
    }
    mapArgToBoolean(name, optionName) {
        ifArg(name, function(bool) {
            if (bool === true) options[optionName || name] = true;
            else if (bool === false) options[optionName || name] = false;
        });
    }

    loadPlugin(name) {
        const loadUtils = require('loader-utils');
        let args;
        try {
            const p = name && name.indexOf('?');
            if (p > -1) {
                args = loadUtils.parseQuery(name.substring(p));
                name = name.substring(0, p);
            }
        } catch (e) {
            console.error('Invalid plugin arguments ' + name + ' (' + e + ').');
			process.exit(-1); // eslint-disable-line
        }

        let path;
        try {
            const resolve = require('enhanced-resolve');
            path = resolve.sync(process.cwd(), name);
        } catch (e) {
            console.error('Cannot resolve plugin ' + name + '.');
			process.exit(-1); // eslint-disable-line
        }
        let Plugin;
        try {
            Plugin = require(path);
        } catch (e) {
            console.error('Cannot load plugin ' + name + '. (' + path + ')');
            throw e;
        }
        try {
            return new Plugin(args);
        } catch (e) {
            console.error('Cannot instantiate plugin ' + name + '. (' + path + ')');
            throw e;
        }
    }

    ensureArray(parent, name) {
        if (!Array.isArray(parent[name])) {
            parent[name] = [];
        }
    }

    addPlugin(options, plugin) {
        ensureArray(options, 'plugins');
        options.plugins.unshift(plugin);
    }

    resolveFilePath(filename = null, defaultValue) {
        if (filename && Array.isArray(filename)) {
            return filename.map(fp => this.resolveFilePath(fp, defaultValue)).filter(e => e);
        }
        if (filename && filename.indexOf('.js') < 0) {
            filename = filename + '.js';
        }
        if (defaultValue && defaultValue.indexOf('.js') < 0) {
            defaultValue = defaultValue + '.js';
        }
        let configPath;
        const predefinedConfigPath = filename ? resolve(process.cwd(), filename) : null;
        const configPathExists = predefinedConfigPath ? existsSync(predefinedConfigPath) : false;

        if (!configPathExists) {
            let LOOKUP_PATHS = [`${filename}`, `src/${filename}`, defaultValue, `src/${defaultValue}`];
            if (filename) {
                LOOKUP_PATHS.unshift(filename);
            }
            LOOKUP_PATHS.forEach(p => {
                const lookUpPath = join(process.cwd(), ...p.split('/'));
                if (existsSync(lookUpPath) && !configPath) {
                    configPath = lookUpPath;
                }
            });
        }
        return configPathExists ? predefinedConfigPath : configPath;
    }
}

module.exports = GroupHelper;
<commit_msg>feat: drop extraneous block<commit_after>const { resolve, join } = require('path');
const { existsSync } = require('fs');

class GroupHelper {
    constructor(options) {
        this.args = this.arrayToObject(options);
        this.opts = {
            outputOptions: {},
            options: {},
            processingErrors: [],
        };
    }

    hyphenToUpperCase(name) {
        if (!name) {
            return name;
        }
        return name.replace(/-([a-z])/g, function(g) {
            return g[1].toUpperCase();
        });
    }
    mergeRecursive(acc, curr) {
        for (var p in curr) {
            try {
                // Property in destination object set; update its value.
                if (curr[p].constructor == Object) {
                    acc[p] = this.mergeRecursive(acc[p], curr[p]);
                } else {
                    acc[p] = curr[p];
                }
            } catch (e) {
                // Property in destination object not set; create it and set its value.
                acc[p] = curr[p];
            }
        }

        return acc;
    }
    arrayToObject(arr) {
        if (!arr) {
            return;
        }
        var result = {};
        let arrLength = arr.length;
        for (let i = 0; i < arrLength; i++) {
            let key = Object.keys(arr[i])[0];
            const val = arr[i][key];
            result[this.hyphenToUpperCase(key)] = val;
        }
        return result;
    }
    verifyType(key, val) {
        /*  if(!schemaProp.includes(val)) {
            const errMsg = 'Unrecognized Option: ' + val + ' supplied to ' + key;
            this.errors.push(errMsg);
        } */
    }
    mapArgToBoolean(name, optionName) {
        ifArg(name, function(bool) {
            options[optionName || name] = bool;
        });
    }

    loadPlugin(name) {
        const loadUtils = require('loader-utils');
        let args;
        try {
            const p = name && name.indexOf('?');
            if (p > -1) {
                args = loadUtils.parseQuery(name.substring(p));
                name = name.substring(0, p);
            }
        } catch (e) {
            console.error('Invalid plugin arguments ' + name + ' (' + e + ').');
			process.exit(-1); // eslint-disable-line
        }

        let path;
        try {
            const resolve = require('enhanced-resolve');
            path = resolve.sync(process.cwd(), name);
        } catch (e) {
            console.error('Cannot resolve plugin ' + name + '.');
			process.exit(-1); // eslint-disable-line
        }
        let Plugin;
        try {
            Plugin = require(path);
        } catch (e) {
            console.error('Cannot load plugin ' + name + '. (' + path + ')');
            throw e;
        }
        try {
            return new Plugin(args);
        } catch (e) {
            console.error('Cannot instantiate plugin ' + name + '. (' + path + ')');
            throw e;
        }
    }

    ensureArray(parent, name) {
        if (!Array.isArray(parent[name])) {
            parent[name] = [];
        }
    }

    addPlugin(options, plugin) {
        ensureArray(options, 'plugins');
        options.plugins.unshift(plugin);
    }

    resolveFilePath(filename = null, defaultValue) {
        if (filename && Array.isArray(filename)) {
            return filename.map(fp => this.resolveFilePath(fp, defaultValue)).filter(e => e);
        }
        if (filename && filename.indexOf('.js') < 0) {
            filename = filename + '.js';
        }
        if (defaultValue && defaultValue.indexOf('.js') < 0) {
            defaultValue = defaultValue + '.js';
        }
        let configPath;
        const predefinedConfigPath = filename ? resolve(process.cwd(), filename) : null;
        const configPathExists = predefinedConfigPath ? existsSync(predefinedConfigPath) : false;

        if (!configPathExists) {
            let LOOKUP_PATHS = [`${filename}`, `src/${filename}`, defaultValue, `src/${defaultValue}`];
            if (filename) {
                LOOKUP_PATHS.unshift(filename);
            }
            LOOKUP_PATHS.forEach(p => {
                const lookUpPath = join(process.cwd(), ...p.split('/'));
                if (existsSync(lookUpPath) && !configPath) {
                    configPath = lookUpPath;
                }
            });
        }
        return configPathExists ? predefinedConfigPath : configPath;
    }
}

module.exports = GroupHelper;
<|endoftext|>


<commit_before>var path = require('path'),
	events = require('events');

module.exports = function (wrapWidget, randomString, options) {

	return function (widget, params, widgetOptions, renderTemplate, context, callback) {

		if (!callback) {
			callback = context;
			context = {};
		}
		context.widgets = context.widgets || {};

		var cacheKey,
			shouldRender = false,
			eventEmitter,
			that = {},
			identifier = 'widget-' + randomString();

		cacheKey = JSON.stringify({
			type: widget.type,
			params: params,
			options: widgetOptions
		});

		if (context.widgets[cacheKey] && context.widgets[cacheKey].rendered) {
			if (context.widgets[cacheKey].error) return callback(context.widgets[cacheKey].error);
			if (context.widgets[cacheKey].html === '' && !context.widgets[cacheKey].renderOptions) return callback(null, '');
			return callback(null, wrapWidget(widget, params, context.widgets[cacheKey].renderOptions, identifier, context.widgets[cacheKey].html));
		}

		if (!context.widgets[cacheKey]) {
			shouldRender = true;
			context.widgets[cacheKey] = {
				rendered: false,
				emitter: new events.EventEmitter()
			};
			context.widgets[cacheKey].emitter.setMaxListeners(0);
		}
		eventEmitter = context.widgets[cacheKey].emitter;

		eventEmitter.once('done', function (err, html, renderOptions) {
			context.widgets[cacheKey].rendered = true;
			context.widgets[cacheKey].emitter = null;
			if (err) {
				context.widgets[cacheKey].error = err;
				return callback(err);
			}
			context.widgets[cacheKey].html = html;
			context.widgets[cacheKey].renderOptions = renderOptions;
			if (html === '' && !renderOptions) return callback(null, '');
			callback(null, wrapWidget(widget, params, renderOptions, identifier, html));
		});

		if (!shouldRender) return;

		widget.test.bind(that)(params, function (err, result) {
			if (err) return eventEmitter.emit('done', err);
			if (!result) return eventEmitter.emit('done', null, '');
			widget.factory.bind(that)(params, function (err, widgetModel, widgetOptions) {
				if (err) return eventEmitter.emit('done', err);
				widgetModel = widgetModel || {};
				widgetOptions = widgetOptions || {};
				widgetOptions.widgetType = widget.type;
				options.widgetMap(widgetModel, widgetOptions, function (err, mappedModel, mappedOptions) {
					if (err) return eventEmitter.emit('done', err);
					widgetModel = mappedModel || widgetModel;
					widgetOptions = mappedOptions || widgetOptions;
					var templatePath,
						renderOptions = mergeOptions([widgetOptions, widgetOptions, widget.options]);
					if (widgetOptions.template) {
						templatePath = path.join(widget.dir, widgetOptions.template);
					} else {
						templatePath = widget.template;
					}
					if (typeof(widgetModel) === 'string') {
						eventEmitter.emit('done', null, widgetModel, renderOptions);
					} else {
						renderTemplate(templatePath, widgetModel, function (err, widgetHtml) {
							if (err) return eventEmitter.emit('done', err);
							eventEmitter.emit('done', null, widgetHtml, renderOptions);
						});
					}
				});
			});
		});

	}
};

function mergeOptions (optionsToMerge) {
	var result = {};
	optionsToMerge.forEach(function(options) {
		if (!options) return;
		for (var key in options) {
			if (!result.hasOwnProperty(key) && options.hasOwnProperty(key)) {
				result[key] = options[key];
			}
		}
	});
	return result;
}
<commit_msg>Fixed wrap false bug<commit_after>var path = require('path'),
	events = require('events');

module.exports = function (wrapWidget, randomString, options) {

	return function (widget, params, renderOptions, renderTemplate, context, callback) {

		if (!callback) {
			callback = context;
			context = {};
		}
		context.widgets = context.widgets || {};

		var cacheKey,
			shouldRender = false,
			eventEmitter,
			that = {},
			identifier = 'widget-' + randomString();

		cacheKey = JSON.stringify({
			type: widget.type,
			params: params,
			options: renderOptions
		});

		if (context.widgets[cacheKey] && context.widgets[cacheKey].rendered) {
			if (context.widgets[cacheKey].error) return callback(context.widgets[cacheKey].error);
			if (context.widgets[cacheKey].html === '' && !context.widgets[cacheKey].renderOptions) return callback(null, '');
			return callback(null, wrapWidget(widget, params, context.widgets[cacheKey].renderOptions, identifier, context.widgets[cacheKey].html));
		}

		if (!context.widgets[cacheKey]) {
			shouldRender = true;
			context.widgets[cacheKey] = {
				rendered: false,
				emitter: new events.EventEmitter()
			};
			context.widgets[cacheKey].emitter.setMaxListeners(0);
		}
		eventEmitter = context.widgets[cacheKey].emitter;

		eventEmitter.once('done', function (err, html, renderOptions) {
			context.widgets[cacheKey].rendered = true;
			context.widgets[cacheKey].emitter = null;
			if (err) {
				context.widgets[cacheKey].error = err;
				return callback(err);
			}
			context.widgets[cacheKey].html = html;
			context.widgets[cacheKey].renderOptions = renderOptions;
			if (html === '' && !renderOptions) return callback(null, '');
			callback(null, wrapWidget(widget, params, renderOptions, identifier, html));
		});

		if (!shouldRender) return;

		widget.test.bind(that)(params, function (err, result) {
			if (err) return eventEmitter.emit('done', err);
			if (!result) return eventEmitter.emit('done', null, '');
			widget.factory.bind(that)(params, function (err, widgetModel, widgetOptions) {
				if (err) return eventEmitter.emit('done', err);
				widgetModel = widgetModel || {};
				widgetOptions = widgetOptions || {};
				for (var key in renderOptions) {
					if (!widgetOptions.hasOwnProperty(key)) widgetOptions[key] = renderOptions[key];
				}
				widgetOptions.widgetType = widget.type;
				options.widgetMap(widgetModel, widgetOptions, function (err, mappedModel, mappedOptions) {
					if (err) return eventEmitter.emit('done', err);
					widgetModel = mappedModel || widgetModel;
					widgetOptions = mappedOptions || widgetOptions;
					var templatePath,
						renderOptions = mergeOptions([widgetOptions, widgetOptions, widget.options]);
					if (widgetOptions.template) {
						templatePath = path.join(widget.dir, widgetOptions.template);
					} else {
						templatePath = widget.template;
					}

					if (typeof(widgetModel) === 'string') {
						eventEmitter.emit('done', null, widgetModel, renderOptions);
					} else {
						renderTemplate(templatePath, widgetModel, function (err, widgetHtml) {
							if (err) return eventEmitter.emit('done', err);
							eventEmitter.emit('done', null, widgetHtml, renderOptions);
						});
					}
				});
			});
		});

	}
};

function mergeOptions (optionsToMerge) {
	var result = {};
	optionsToMerge.forEach(function(options) {
		if (!options) return;
		for (var key in options) {
			if (!result.hasOwnProperty(key) && options.hasOwnProperty(key)) {
				result[key] = options[key];
			}
		}
	});
	return result;
}
<|endoftext|>


<commit_before><commit_msg>Lock favourite button<commit_after><|endoftext|>