<commit_before>function circularHeatChart() {
    var margin = {top: 20, right: 20, bottom: 20, left: 20},
    innerRadius = 20,
    numSegments = 12,
    segmentHeight = 20,
    domain = null,
    range = ["blue", "red"],
    accessor = function(d) {return d;},
    radialLabels = segmentLabels = [];

    function chart(selection) {
        selection.each(function(data) {
            var svg = d3.select(this);
            var chartSize = Math.min(screen.width, screen.height)/2+40;
            svg.attr("width", chartSize)
               .attr("height", chartSize);

            var offset = innerRadius + Math.ceil(data.length / numSegments) * segmentHeight;
            g = svg.append("g")
                .classed("circular-heat", true)
                .attr("transform", "translate(" + parseInt(margin.left + offset) + "," + parseInt(margin.top + offset) + ")");

            var autoDomain = false;
            if (domain === null) {
                domain = d3.extent(data, accessor);
                autoDomain = true;
            }
            var color = d3.scale.linear().domain(domain).range(range);
            if(autoDomain)
                domain = null;

            g.selectAll("path").data(data)
                .enter().append("path")
                .attr("d", d3.svg.arc().innerRadius(ir).outerRadius(or).startAngle(sa).endAngle(ea))
                .attr("fill", function(d) {return color(accessor(d));});

            // Unique id so that the text path defs are unique - is there a better way to do this?
            var id = d3.selectAll(".circular-heat")[0].length;

            //Radial labels
            var lsa = 0.01; //Label start angle
            var labels = svg.append("g")
                .classed("labels", true)
                .classed("radial", true)
                .attr("transform", "translate(" + parseInt(margin.left + offset) + "," + parseInt(margin.top + offset) + ")");

            labels.selectAll("def")
                .data(radialLabels).enter()
                .append("def")
                .append("path")
                .attr("id", function(d, i) {return "radial-label-path-"+id+"-"+i;})
                .attr("d", function(d, i) {
                    var r = innerRadius + ((i + 0.2) * segmentHeight);
                    return "m" + r * Math.sin(lsa) + " -" + r * Math.cos(lsa) +
                            " a" + r + " " + r + " 0 1 1 -1 0";
                });

            labels.selectAll("text")
                .data(radialLabels).enter()
                .append("text")
                .append("textPath")
                .attr("xlink:href", function(d, i) {return "#radial-label-path-"+id+"-"+i;})
                .style("font-size", 0.6 * segmentHeight + 'px')
                .text(function(d) {return d;});

            //Segment labels
            var segmentLabelOffset = 2;
            var r = innerRadius + Math.ceil(data.length / numSegments) * segmentHeight + segmentLabelOffset;
            labels = svg.append("g")
                .classed("labels", true)
                .classed("segment", true)
                .attr("transform", "translate(" + parseInt(margin.left + offset) + "," + parseInt(margin.top + offset) + ")");

            labels.append("def")
                .append("path")
                .attr("id", "segment-label-path-"+id)
                .attr("d", "m0 -" + r + " a" + r + " " + r + " 0 1 1 -1 0");

            labels.selectAll("text")
                .data(segmentLabels).enter()
                .append("text")
                .append("textPath")
                .attr("xlink:href", "#segment-label-path-"+id)
                .attr("startOffset", function(d, i) {return i * 100 / numSegments + "%";})
                .text(function(d) {return d;});
        });

    }

    /* Arc functions */
    ir = function(d, i) {
        return innerRadius + Math.floor(i/numSegments) * segmentHeight;
    }
    or = function(d, i) {
        return innerRadius + segmentHeight + Math.floor(i/numSegments) * segmentHeight;
    }
    sa = function(d, i) {
        return (i * 2 * Math.PI) / numSegments;
    }
    ea = function(d, i) {
        return ((i + 1) * 2 * Math.PI) / numSegments;
    }

    /* Configuration getters/setters */
    chart.margin = function(_) {
        if (!arguments.length) return margin;
        margin = _;
        return chart;
    };

    chart.innerRadius = function(_) {
        if (!arguments.length) return innerRadius;
        innerRadius = _;
        return chart;
    };

    chart.numSegments = function(_) {
        if (!arguments.length) return numSegments;
        numSegments = _;
        return chart;
    };

    chart.segmentHeight = function(_) {
        if (!arguments.length) return segmentHeight;
        segmentHeight = _;
        return chart;
    };

    chart.domain = function(_) {
        if (!arguments.length) return domain;
        domain = _;
        return chart;
    };

    chart.range = function(_) {
        if (!arguments.length) return range;
        range = _;
        return chart;
    };

    chart.radialLabels = function(_) {
        if (!arguments.length) return radialLabels;
        if (_ == null) _ = [];
        radialLabels = _;
        return chart;
    };

    chart.segmentLabels = function(_) {
        if (!arguments.length) return segmentLabels;
        if (_ == null) _ = [];
        segmentLabels = _;
        return chart;
    };

    chart.accessor = function(_) {
        if (!arguments.length) return accessor;
        accessor = _;
        return chart;
    };

    return chart;
}
<commit_msg>update radial heat map<commit_after>function circularHeatChart() {
    var margin = {top: 20, right: 20, bottom: 20, left: 20},
    innerRadius = 20,
    numSegments = 12,
    segmentHeight = 20,
    domain = null,
    range = ["yellow", "red"],
    accessor = function(d) {return d;},
    radialLabels = segmentLabels = [];

    function chart(selection) {
        selection.each(function(data) {
            var svg = d3.select(this);
            var chartSize = Math.min(screen.width, screen.height)/2+40;
            svg.attr("width", chartSize)
               .attr("height", chartSize);

            var offset = innerRadius + Math.ceil(data.length / numSegments) * segmentHeight;
            g = svg.append("g")
                .classed("circular-heat", true)
                .attr("transform", "translate(" + parseInt(margin.left + offset) + "," + parseInt(margin.top + offset) + ")");

            var autoDomain = false;
            if (domain === null) {
                domain = d3.extent(data, accessor);
                autoDomain = true;
            }
            var color = d3.scale.linear().domain(domain).range(range);
            if(autoDomain)
                domain = null;

            g.selectAll("path").data(data)
                .enter().append("path")
                .attr("d", d3.svg.arc().innerRadius(ir).outerRadius(or).startAngle(sa).endAngle(ea))
                .attr("fill", function(d) {return color(accessor(d));});

            // Unique id so that the text path defs are unique - is there a better way to do this?
            var id = d3.selectAll(".circular-heat")[0].length;

            //Radial labels
            var lsa = 0.01; //Label start angle
            var labels = svg.append("g")
                .classed("labels", true)
                .classed("radial", true)
                .attr("transform", "translate(" + parseInt(margin.left + offset) + "," + parseInt(margin.top + offset) + ")");

            labels.selectAll("def")
                .data(radialLabels).enter()
                .append("def")
                .append("path")
                .attr("id", function(d, i) {return "radial-label-path-"+id+"-"+i;})
                .attr("d", function(d, i) {
                    var r = innerRadius + ((i + 0.2) * segmentHeight);
                    return "m" + r * Math.sin(lsa) + " -" + r * Math.cos(lsa) +
                            " a" + r + " " + r + " 0 1 1 -1 0";
                });

            labels.selectAll("text")
                .data(radialLabels).enter()
                .append("text")
                .append("textPath")
                .attr("xlink:href", function(d, i) {return "#radial-label-path-"+id+"-"+i;})
                .style("font-size", 0.6 * segmentHeight + 'px')
                .text(function(d) {return d;});

            //Segment labels
            var segmentLabelOffset = 2;
            var r = innerRadius + Math.ceil(data.length / numSegments) * segmentHeight + segmentLabelOffset;
            labels = svg.append("g")
                .classed("labels", true)
                .classed("segment", true)
                .attr("transform", "translate(" + parseInt(margin.left + offset) + "," + parseInt(margin.top + offset) + ")");

            labels.append("def")
                .append("path")
                .attr("id", "segment-label-path-"+id)
                .attr("d", "m0 -" + r + " a" + r + " " + r + " 0 1 1 -1 0");

            labels.selectAll("text")
                .data(segmentLabels).enter()
                .append("text")
                .append("textPath")
                .attr("xlink:href", "#segment-label-path-"+id)
                .attr("startOffset", function(d, i) {return i * 100 / numSegments + "%";})
                .text(function(d) {return d;});
        });

    }

    /* Arc functions */
    ir = function(d, i) {
        return innerRadius + Math.floor(i/numSegments) * segmentHeight;
    }
    or = function(d, i) {
        return innerRadius + segmentHeight + Math.floor(i/numSegments) * segmentHeight;
    }
    sa = function(d, i) {
        return (i * 2 * Math.PI) / numSegments;
    }
    ea = function(d, i) {
        return ((i + 1) * 2 * Math.PI) / numSegments;
    }

    /* Configuration getters/setters */
    chart.margin = function(_) {
        if (!arguments.length) return margin;
        margin = _;
        return chart;
    };

    chart.innerRadius = function(_) {
        if (!arguments.length) return innerRadius;
        innerRadius = _;
        return chart;
    };

    chart.numSegments = function(_) {
        if (!arguments.length) return numSegments;
        numSegments = _;
        return chart;
    };

    chart.segmentHeight = function(_) {
        if (!arguments.length) return segmentHeight;
        segmentHeight = _;
        return chart;
    };

    chart.domain = function(_) {
        if (!arguments.length) return domain;
        domain = _;
        return chart;
    };

    chart.range = function(_) {
        if (!arguments.length) return range;
        range = _;
        return chart;
    };

    chart.radialLabels = function(_) {
        if (!arguments.length) return radialLabels;
        if (_ == null) _ = [];
        radialLabels = _;
        return chart;
    };

    chart.segmentLabels = function(_) {
        if (!arguments.length) return segmentLabels;
        if (_ == null) _ = [];
        segmentLabels = _;
        return chart;
    };

    chart.accessor = function(_) {
        if (!arguments.length) return accessor;
        accessor = _;
        return chart;
    };

    return chart;
}
<|endoftext|>


<commit_before>/*
ToDo:
	-Implement photo gallery
	-About me page
	- Filter print gallery by type?
	-Update print details page with pictures
	- ADMIN options - add photos, galleries, pages, etc...
	-RESTful API
*/

/* Need to get these url's from database */
function largeImg(file){
    return "http://mgibsonphotoworks.com/uploads/large/" + file;
}

function thumbImg(file){
    return "http://mgibsonphotoworks.com/uploads/thumbs/" + file;
}

/* Create the ember application registered to a global variable */
window.Photoworks = Ember.Application.create();

/* Using fixture adapter for now, change to RESTful */
Photoworks.ApplicationAdapter = DS.FixtureAdapter.extend();

/* Local storage for the shopping cart */
Photoworks.CartItemSerializer = DS.LSSerializer.extend();
Photoworks.CartItemAdapter = DS.LSAdapter.extend({
	namespace: 'photoworks'
});

/* Pulling galleries from our REST API*/
Photoworks.GalleryAdapter = DS.RESTAdapter.extend();

 	<commit_msg>Modify LinkView with ability to redirect to optional action. Maintains normal link for SEO. Change photo model to use RESTAdapter.<commit_after>/*
ToDo:
	-Implement photo gallery
	-About me page
	- Filter print gallery by type?
	-Update print details page with pictures
	- ADMIN options - add/remove photos, galleries, pages, etc...
	-RESTful API - or just use fixtures
*/

/* Need to get these url's from database */
function largeImg(file){
    return "http://mgibsonphotoworks.com/uploads/large/" + file;
}

function thumbImg(file){
    return "http://mgibsonphotoworks.com/uploads/thumbs/" + file;
}

/* Create the ember application registered to a global variable */
window.Photoworks = Ember.Application.create();

/* Using fixture adapter for now, change to RESTful */
Photoworks.ApplicationAdapter = DS.FixtureAdapter.extend();

/* Local storage for the shopping cart */
Photoworks.CartItemSerializer = DS.LSSerializer.extend();
Photoworks.CartItemAdapter = DS.LSAdapter.extend({
	namespace: 'photoworks'
});

/* Pulling galleries from our REST API*/
Photoworks.GalleryAdapter = DS.RESTAdapter.extend();

Photoworks.PhotoAdapter = DS.RESTAdapter.extend();

/* Modify link-to to be able to add optional action */
Ember.LinkView.reopen({
  action: null,
  _invoke: function(event){
    var action = this.get('action');
    if(action) {
      // There was an action specified (in handlebars) so take custom action
      event.preventDefault(); // prevent the browser from following the link as normal
      if (this.bubbles === false) { event.stopPropagation(); }

      // trigger the action on the controller
      this.get('controller').send(action, this.get('actionParam'));
      return false;
    }

    // no action to take, handle the link-to normally
    return this._super(event);
  }
});

 	<|endoftext|>


<commit_before>/*!
 * Методы и функции для экранирования
 */

var sysEscapeMap = {
	'\\': true,
	[I18N]: true,
	[LEFT_BLOCK]: true,
	[ADV_LEFT_BLOCK]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true,
	[CONCAT_COMMAND]: true,
	[CONCAT_END]: true,
	[IGNORE_COMMAND]: true,
	[INLINE_COMMAND.trim().charAt(0)]: true
};

for (let key in baseShortMap) {
	/* istanbul ignore if */
	if (!baseShortMap.hasOwnProperty(key)) {
		continue;
	}

	sysEscapeMap[key.charAt(0)] = true;
}

var strongSysEscapeMap = {
	'\\': true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true
};

var includeSysEscapeMap = {};
includeSysEscapeMap['\\'] = true;

for (let key in includeDirMap) {
	/* istanbul ignore if */
	if (!includeDirMap.hasOwnProperty(key)) {
		continue;
	}

	includeSysEscapeMap[key.charAt(0)] = true;
}

var escapeMap = {
	'"': true,
	'\'': true,
	'/': true
};

var escapeEndMap = {
	'-': true,
	'+': true,
	'*': true,
	'%': true,
	'~': true,
	'>': true,
	'<': true,
	'^': true,
	',': true,
	';': true,
	'=': true,
	'|': true,
	'&': true,
	'!': true,
	'?': true,
	':': true,
	'(': true,
	'{': true,
	'[': true
};

var escapeEndWordMap = {
	'typeof': true,
	'void': true,
	'instaceof': true,
	'delete': true,
	'in': true,
	'new': true
};

var bMap = {
	'(': true,
	'[': true,
	'{': true
};

var closeBMap = {
	')': true,
	']': true,
	'}': true
};

var pMap = {
	'(': true,
	'[': true
};

var closePMap = {
	')': true,
	']': true
};

function escapeBackslash(str) {
	return String(str).replace(/\\/g, '\\\\');
}

function escapeSingleQuote(str) {
	return String(str)
		.replace(/'/g, '\\\'');
}

function escapeDoubleQuote(str) {
	return String(str)
		.replace(/"/g, '\\\"');
}

function applyDefEscape(str) {
	return escapeNextLine(
		String(str)
			.replace(/\\/g, '\\\\')
			.replace(/'/g, '\\\'')
	);
}

function escapeNextLine(str) {
	return String(str)
		.replace(/\n/g, '\\n')
		.replace(/\r/g, '\\r');
}

if (IS_NODE) {
	global.EscaperIsLocal = true;
}

//#include ../../node_modules/escaper/dist/escaper.js

Escaper.symbols = symbols;
var escaperRgxp = /^__ESCAPER_QUOT__\d+_/;

/**
 * Заметить блоки вида ' ... ', " ... ", / ... /, ` ... `, // ..., /* ... *\/ на
 * __ESCAPER_QUOT__номер_ в указанной строке
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.replaceDangerBlocks = function (str) {
	return Escaper.replace(str, true, this.quotContent, true);
};

/**
 * Заметить __ESCAPER_QUOT__номер_ в указанной строке на реальное содержимое
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.pasteDangerBlocks = function (str) {
	return Escaper.paste(str, this.quotContent);
};

/**
 * Заметить __SNAKESKIN__номер_ в указанной строке на реальное содержимое
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.pasteTplVarBlocks = function (str) {
	return str.replace(/__SNAKESKIN__(\d+)_/g, (sstr, pos) => this.dirContent[pos]);
};
<commit_msg>Рефакторинг<commit_after>/*!
 * Методы и функции для экранирования
 */

var sysEscapeMap = {
	'\\': true,
	[I18N]: true,
	[LEFT_BLOCK]: true,
	[ADV_LEFT_BLOCK]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true,
	[CONCAT_COMMAND]: true,
	[CONCAT_END]: true,
	[IGNORE_COMMAND]: true,
	[INLINE_COMMAND.trim().charAt(0)]: true
};

for (let key in baseShortMap) {
	/* istanbul ignore if */
	if (!baseShortMap.hasOwnProperty(key)) {
		continue;
	}

	sysEscapeMap[key.charAt(0)] = true;
}

var strongSysEscapeMap = {
	'\\': true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true
};

var includeSysEscapeMap = {};
includeSysEscapeMap['\\'] = true;

for (let key in includeDirMap) {
	/* istanbul ignore if */
	if (!includeDirMap.hasOwnProperty(key)) {
		continue;
	}

	includeSysEscapeMap[key.charAt(0)] = true;
}

var escapeMap = {
	'"': true,
	'\'': true,
	'/': true
};

var escapeEndMap = {
	'-': true,
	'+': true,
	'*': true,
	'%': true,
	'~': true,
	'>': true,
	'<': true,
	'^': true,
	',': true,
	';': true,
	'=': true,
	'|': true,
	'&': true,
	'!': true,
	'?': true,
	':': true,
	'(': true,
	'{': true,
	'[': true
};

var escapeEndWordMap = {
	'typeof': true,
	'void': true,
	'instaceof': true,
	'delete': true,
	'in': true,
	'new': true
};

var bMap = {
	'(': true,
	'[': true,
	'{': true
};

var closeBMap = {
	')': true,
	']': true,
	'}': true
};

var pMap = {
	'(': true,
	'[': true
};

var closePMap = {
	')': true,
	']': true
};

function escapeBackslash(str) {
	return String(str).replace(/\\/g, '\\\\');
}

function escapeSingleQuote(str) {
	return String(str)
		.replace(/'/g, '\\\'');
}

function escapeDoubleQuote(str) {
	return String(str)
		.replace(/"/g, '\\\"');
}

function applyDefEscape(str) {
	return escapeNextLine(
		String(str)
			.replace(/\\/g, '\\\\')
			.replace(/'/g, '\\\'')
	);
}

function escapeNextLine(str) {
	return String(str)
		.replace(/\n/g, '\\n')
		.replace(/\r/g, '\\r');
}

if (IS_NODE) {
	global.EscaperIsLocal = true;
}

//#include ../../node_modules/escaper/dist/escaper.js

Escaper.snakeskinRgxp = filterStartRgxp;
var escaperRgxp = /^__ESCAPER_QUOT__\d+_/;

/**
 * Заметить блоки вида ' ... ', " ... ", / ... /, ` ... `, // ..., /* ... *\/ на
 * __ESCAPER_QUOT__номер_ в указанной строке
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.replaceDangerBlocks = function (str) {
	return Escaper.replace(str, true, this.quotContent, true);
};

/**
 * Заметить __ESCAPER_QUOT__номер_ в указанной строке на реальное содержимое
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.pasteDangerBlocks = function (str) {
	return Escaper.paste(str, this.quotContent);
};

/**
 * Заметить __SNAKESKIN__номер_ в указанной строке на реальное содержимое
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.pasteTplVarBlocks = function (str) {
	return str.replace(/__SNAKESKIN__(\d+)_/g, (sstr, pos) => this.dirContent[pos]);
};
<|endoftext|>


<commit_before>(function(exports) {
  var LexemeFrequency = require('./LexemeFrequency').LexemeFrequency;

  var defaults = {
    // From Jonathan Feinberg's cue.language, see https://github.com/jdf/cue.language/blob/master/license.txt.
    maxLength: 30,
    punctuation: /[!"'&()*+,-\.\/:;<=>?\[\\\]^`\{|\}~]+/g,
    wordSeparators: /[\s\u3031-\u3035\u309b\u309c\u30a0\u30fc\uff70]+/g,
    english: /^(i|me|my|myself|we|us|our|ours|ourselves|you|your|yours|yourself|yourselves|he|him|his|himself|she|her|hers|herself|it|its|itself|they|them|their|theirs|themselves|what|which|who|whom|whose|this|that|these|those|am|is|are|was|were|be|been|being|have|has|had|having|do|does|did|doing|will|would|should|can|could|ought|i'm|you're|he's|she's|it's|we're|they're|i've|you've|we've|they've|i'd|you'd|he'd|she'd|we'd|they'd|i'll|you'll|he'll|she'll|we'll|they'll|isn't|aren't|wasn't|weren't|hasn't|haven't|hadn't|doesn't|don't|didn't|won't|wouldn't|shan't|shouldn't|can't|cannot|couldn't|mustn't|let's|that's|who's|what's|here's|there's|when's|where's|why's|how's|a|an|the|and|but|if|or|because|as|until|while|of|at|by|for|with|about|against|between|into|through|during|before|after|above|below|to|from|up|upon|down|in|out|on|off|over|under|again|further|then|once|here|there|when|where|why|how|all|any|both|each|few|more|most|other|some|such|no|nor|not|only|own|same|so|than|too|very|say|says|said|shall)$/
  };

  var getUnique = function(arrayObj) {
    var u = {}, a = [];
    for (var i = 0, l = arrayObj.length; i < l; ++i) {
      if (u.hasOwnProperty(arrayObj[i])) {
        continue;
      }
      if (arrayObj[i]) {
        if (arrayObj[i].trim) {
          arrayObj[i] = arrayObj[i].trim();
        }
        a.push(arrayObj[i]);
        u[arrayObj[i]] = 1;
      }
    }
    return a;
  };

  var processNonContentMorphemes = function(userCloud) {
    var processed = false,
      stringCheck,
      commasOrSpaces = /[,\s]+/g;

    if (userCloud.prefixesArray) {
      stringCheck = userCloud.prefixesArray.toString().substring(0, 20);

      if (stringCheck.indexOf('/') === 0) {
        // user most likely provided regex of prefixes
        userCloud.prefixesArray = userCloud.prefixesArray.toString().replace('/^(', '').replace(')$/', '').split('|');
      } else if (Object.prototype.toString.call(userCloud.prefixesArray) === '[object Array]') {
        // user most likely provided an array of prefixes
      } else if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
        // user most likely provided comma-separated or space-separated list of prefixes
        userCloud.prefixesArray = userCloud.prefixesArray.split(commasOrSpaces);
      }
    } else {
      userCloud.prefixesArray = [];
    }

    if (userCloud.suffixesArray) {
      stringCheck = userCloud.suffixesArray.toString().substring(0, 20);

      if (stringCheck.indexOf('/') === 0) {
        // user most likely provided regex of prefixes
        userCloud.suffixesArray = userCloud.suffixesArray.toString().replace('/^(', '').replace(')$/', '').split('|');
      } else if (Object.prototype.toString.call(userCloud.suffixesArray) === '[object Array]') {
        // user most likely provided an array of prefixes
      } else if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
        // user most likely provided comma-separated or space-separated list of prefixes
        userCloud.suffixesArray = userCloud.suffixesArray.split(commasOrSpaces);
      }
    } else {
      userCloud.suffixesArray = [];
    }

    if (userCloud.morphemesArray) {
      stringCheck = userCloud.morphemesArray.toString().substring(0, 20);

      if (stringCheck.indexOf('/') === 0) {
        // user most likely provided regex of stop words
        userCloud.morphemesArray = userCloud.morphemesArray.toString().replace('/^(', '').replace(')$/', '').split('|');
      } else if (Object.prototype.toString.call(userCloud.morphemesArray) === '[object Array]') {
        // user most likely provided an array of stop words
      } else if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
        // user most likely provided comma-separated or space-separated list of stop words
        userCloud.morphemesArray = userCloud.morphemesArray.split(commasOrSpaces);
      }
    } else {
      userCloud.morphemesArray = [];
    }

    userCloud.morphemesArray = userCloud.morphemesArray.concat(userCloud.prefixesArray).concat(userCloud.suffixesArray);

    userCloud.morphemesArray = getUnique(userCloud.morphemesArray).sort(function(a, b) {
      return b.length - a.length;
    });
    console.log(userCloud.morphemesArray);
    userCloud.morphemesRegExp = userCloud.morphemesArray.map(function(morpheme) {
      console.log('morpheme' + morpheme);
      if (morpheme.indexOf('-') === 0) {
        return morpheme.replace('-', '') + '$';
      }
      if (morpheme.indexOf('-') === morpheme.length - 1) {
        return '^' + morpheme.replace('-', '');
      }
    }).join('|');
    userCloud.morphemesRegExp = new RegExp('(' + userCloud.morphemesRegExp + ')');

  };

  var processNonContentWords = function(userCloud) {
    var providedNonContentWords = userCloud.nonContentWordsArray;
    // console.log('userCloud.nonContentWords', userCloud.nonContentWords);
    var processed = false;
    // console.log('providedNonContentWords', providedNonContentWords);

    processNonContentMorphemes(userCloud);

    if (!userCloud.userSpecifiedNonContentWords) {
      userCloud.wordFrequencies = null;
      var autoCalculatedNonContentWords = LexemeFrequency.calculateNonContentWords(userCloud).nonContentWordsArray;
      console.log('autoCalculatedNonContentWords', autoCalculatedNonContentWords.join(','));
      processed = true;
      userCloud.nonContentWordsArray = autoCalculatedNonContentWords;
      userCloud.nonContentWordsRegExp = new RegExp('^(' + autoCalculatedNonContentWords.join('|') + ')$');
      return userCloud;
    }
    // console.log('not autogen userCloud.nonContentWords ', userCloud.nonContentWords);

    var stringCheck = providedNonContentWords.toString().substring(0, 20),
      commasOrSpaces = /[,\s]+/g;

    if (stringCheck.indexOf('/') === 0) {
      // user most likely provided regex of stop words
      processed = true;
      userCloud.nonContentWordsArray = providedNonContentWords.toString().replace('/^(', '').replace(')$/', '').split('|');
      userCloud.nonContentWordsRegExp = new RegExp(providedNonContentWords);
      return userCloud;
    }

    if (Object.prototype.toString.call(providedNonContentWords) === '[object Array]') {
      // user most likely provided an array of stop words
      processed = true;
      userCloud.nonContentWordsArray = providedNonContentWords;
      userCloud.nonContentWordsRegExp = new RegExp('^(' + providedNonContentWords.join('|') + ')$');
      return userCloud;
    }

    if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
      // user most likely provided comma-separated or space-separated list of stop words
      processed = true;
      userCloud.nonContentWordsArray = providedNonContentWords.split(commasOrSpaces);
      userCloud.nonContentWordsRegExp = new RegExp('^(' + providedNonContentWords.replace(commasOrSpaces, '|') + ')$');
      return userCloud;
    }

    if (!processed) {
      // user did not provide a parsable regex, throw error
      throw 'Invalid RegExp ' + providedNonContentWords;
    }

  };

  var filterText = function(userCloud) {
    userCloud.punctuation = userCloud.punctuation || defaults.punctuation;
    var text = userCloud.orthography.replace(userCloud.punctuation, ' ');

    if (userCloud.caseInsensitive) {
      text = text.toLocaleLowerCase();
    }
    var filteredText = text.split(defaults.wordSeparators).map(function(word) {
      if (!userCloud.nonContentWordsRegExp.test(word)) {
        if (userCloud.morphemesRegExp) {
          word = word.replace(userCloud.morphemesRegExp, '');
        }
        return word;
      } else {
        return '';
      }
    });
    userCloud.filteredText = filteredText.join(' ');
    return userCloud;
  };

  exports.NonContentWords = {
    processNonContentWords: processNonContentWords,
    defaults: defaults,
    LexemeFrequency: LexemeFrequency,
    filterText: filterText
  };

})(typeof exports === 'undefined' ? this['NonContentWords'] = {} : exports);
<commit_msg>making stop words regex null if array is empty<commit_after>(function(exports) {
  var LexemeFrequency = require('./LexemeFrequency').LexemeFrequency;

  var defaults = {
    // From Jonathan Feinberg's cue.language, see https://github.com/jdf/cue.language/blob/master/license.txt.
    maxLength: 30,
    punctuation: /[!"'&()*+,-\.\/:;<=>?\[\\\]^`\{|\}~]+/g,
    wordSeparators: /[\s\u3031-\u3035\u309b\u309c\u30a0\u30fc\uff70]+/g,
    english: /^(i|me|my|myself|we|us|our|ours|ourselves|you|your|yours|yourself|yourselves|he|him|his|himself|she|her|hers|herself|it|its|itself|they|them|their|theirs|themselves|what|which|who|whom|whose|this|that|these|those|am|is|are|was|were|be|been|being|have|has|had|having|do|does|did|doing|will|would|should|can|could|ought|i'm|you're|he's|she's|it's|we're|they're|i've|you've|we've|they've|i'd|you'd|he'd|she'd|we'd|they'd|i'll|you'll|he'll|she'll|we'll|they'll|isn't|aren't|wasn't|weren't|hasn't|haven't|hadn't|doesn't|don't|didn't|won't|wouldn't|shan't|shouldn't|can't|cannot|couldn't|mustn't|let's|that's|who's|what's|here's|there's|when's|where's|why's|how's|a|an|the|and|but|if|or|because|as|until|while|of|at|by|for|with|about|against|between|into|through|during|before|after|above|below|to|from|up|upon|down|in|out|on|off|over|under|again|further|then|once|here|there|when|where|why|how|all|any|both|each|few|more|most|other|some|such|no|nor|not|only|own|same|so|than|too|very|say|says|said|shall)$/
  };

  var getUnique = function(arrayObj) {
    var u = {}, a = [];
    for (var i = 0, l = arrayObj.length; i < l; ++i) {
      if (u.hasOwnProperty(arrayObj[i])) {
        continue;
      }
      if (arrayObj[i]) {
        if (arrayObj[i].trim) {
          arrayObj[i] = arrayObj[i].trim();
        }
        a.push(arrayObj[i]);
        u[arrayObj[i]] = 1;
      }
    }
    return a;
  };

  var processNonContentMorphemes = function(userCloud) {
    var processed = false,
      stringCheck,
      commasOrSpaces = /[,\s]+/g;

    if (userCloud.prefixesArray) {
      stringCheck = userCloud.prefixesArray.toString().substring(0, 20);

      if (stringCheck.indexOf('/') === 0) {
        // user most likely provided regex of prefixes
        userCloud.prefixesArray = userCloud.prefixesArray.toString().replace('/^(', '').replace(')$/', '').split('|');
      } else if (Object.prototype.toString.call(userCloud.prefixesArray) === '[object Array]') {
        // user most likely provided an array of prefixes
      } else if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
        // user most likely provided comma-separated or space-separated list of prefixes
        userCloud.prefixesArray = userCloud.prefixesArray.split(commasOrSpaces);
      }
    } else {
      userCloud.prefixesArray = [];
    }

    if (userCloud.suffixesArray) {
      stringCheck = userCloud.suffixesArray.toString().substring(0, 20);

      if (stringCheck.indexOf('/') === 0) {
        // user most likely provided regex of prefixes
        userCloud.suffixesArray = userCloud.suffixesArray.toString().replace('/^(', '').replace(')$/', '').split('|');
      } else if (Object.prototype.toString.call(userCloud.suffixesArray) === '[object Array]') {
        // user most likely provided an array of prefixes
      } else if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
        // user most likely provided comma-separated or space-separated list of prefixes
        userCloud.suffixesArray = userCloud.suffixesArray.split(commasOrSpaces);
      }
    } else {
      userCloud.suffixesArray = [];
    }

    if (userCloud.morphemesArray) {
      stringCheck = userCloud.morphemesArray.toString().substring(0, 20);

      if (stringCheck.indexOf('/') === 0) {
        // user most likely provided regex of stop words
        userCloud.morphemesArray = userCloud.morphemesArray.toString().replace('/^(', '').replace(')$/', '').split('|');
      } else if (Object.prototype.toString.call(userCloud.morphemesArray) === '[object Array]') {
        // user most likely provided an array of stop words
      } else if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
        // user most likely provided comma-separated or space-separated list of stop words
        userCloud.morphemesArray = userCloud.morphemesArray.split(commasOrSpaces);
      }
    } else {
      userCloud.morphemesArray = [];
    }

    userCloud.morphemesArray = userCloud.morphemesArray.concat(userCloud.prefixesArray).concat(userCloud.suffixesArray);
    userCloud.morphemesArray = getUnique(userCloud.morphemesArray).sort(function(a, b) {
      return b.length - a.length;
    });
    if (userCloud.morphemesArray.length > 0) {
      console.log(userCloud.morphemesArray);
      userCloud.morphemesRegExp = userCloud.morphemesArray.map(function(morpheme) {
        console.log('morpheme' + morpheme);
        if (morpheme.indexOf('-') === 0) {
          return morpheme.replace('-', '') + '$';
        }
        if (morpheme.indexOf('-') === morpheme.length - 1) {
          return '^' + morpheme.replace('-', '');
        }
      }).join('|');
      userCloud.morphemesRegExp = new RegExp('(' + userCloud.morphemesRegExp + ')');
    } else {
      userCloud.morphemesRegExp = null;
    }

  };

  var processNonContentWords = function(userCloud) {
    var processed = false,
      stringCheck;

    processNonContentMorphemes(userCloud);

    if (!userCloud.userSpecifiedNonContentWords) {
      userCloud.wordFrequencies = null;
      userCloud.nonContentWordsArray = LexemeFrequency.calculateNonContentWords(userCloud).nonContentWordsArray;
    } else {
      stringCheck = userCloud.nonContentWordsArray.toString().substring(0, 20),
      commasOrSpaces = /[,\s]+/g;

      if (stringCheck.indexOf('/') === 0) {
        // user most likely provided regex of stop words
        processed = true;
        userCloud.nonContentWordsArray = userCloud.nonContentWordsArray.toString().replace('/^(', '').replace(')$/', '').split('|');
      } else if (Object.prototype.toString.call(userCloud.nonContentWordsArray) === '[object Array]') {
        // user most likely provided an array of stop words
        processed = true;
        userCloud.nonContentWordsArray = userCloud.nonContentWordsArray;
      } else if ((stringCheck.indexOf(',') !== -1) || (stringCheck.indexOf(',') === -1 && stringCheck.indexOf(' ') !== -1)) {
        // user most likely provided comma-separated or space-separated list of stop words
        processed = true;
        userCloud.nonContentWordsArray = userCloud.nonContentWordsArray.split(commasOrSpaces);
      } else if (!processed) {
        // user did not provide a parsable regex, throw error
        throw 'Invalid RegExp ' + userCloud.nonContentWordsArray;
      }
    }

    if (userCloud.nonContentWordsArray.length > 0) {
      userCloud.nonContentWordsRegExp = new RegExp('^(' + userCloud.nonContentWordsArray.join('|') + ')$');
    } else {
      userCloud.nonContentWordsRegExp = null;
    }
  };

  var filterText = function(userCloud) {
    userCloud.punctuation = userCloud.punctuation || defaults.punctuation;
    var text = userCloud.orthography.replace(userCloud.punctuation, ' ');

    if (userCloud.caseInsensitive) {
      text = text.toLocaleLowerCase();
    }
    var filteredText = text.split(defaults.wordSeparators).map(function(word) {
      if (!userCloud.nonContentWordsRegExp.test(word)) {
        if (userCloud.morphemesRegExp) {
          word = word.replace(userCloud.morphemesRegExp, '');
        }
        return word;
      } else {
        return '';
      }
    });
    userCloud.filteredText = filteredText.join(' ');
    return userCloud;
  };

  exports.NonContentWords = {
    processNonContentWords: processNonContentWords,
    defaults: defaults,
    LexemeFrequency: LexemeFrequency,
    filterText: filterText
  };

})(typeof exports === 'undefined' ? this['NonContentWords'] = {} : exports);
<|endoftext|>


<commit_before>// Copyright 2021, University of Colorado Boulder

/**
 * Transpiles *.ts and copies all *.js files to chipper/dist. Does not do type checking. Filters based on active-repos
 * and subsets of directories within repos (such as js/, images/, and sounds/)
 *
 * See transpile.js for the CLI usage
 *
 *  @author Sam Reid (PhET Interactive Simulations)
 */

// imports
const fs = require( 'fs' );
const path = require( 'path' );
const crypto = require( 'crypto' );
const core = require( '@babel/core' );
const assert = require( 'assert' );
const getActiveRepos = require( '../../../perennial-alias/js/common/getActiveRepos' );

// constants

// Cache status is stored in chipper/dist so if you wipe chipper/dist you also wipe the cache
const statusPath = '../chipper/dist/js-cache-status.json';
const root = '../';

// Directories in a sim repo that may contain things for transpilation
// This is used for a top-down search in the initial transpilation and for filtering relevant files in the watch process
const subdirs = [ 'js', 'images', 'mipmaps', 'sounds' ];

class Transpiler {
  constructor( options ) {

    options = options || {
      clean: false,
      verbose: false
    };

    // @private
    this.verbose = options.verbose;

    // Track the status of each repo. Key= repo, value=md5 hash of contents
    this.status = {};

    // Make sure a directory exists for the cached status file
    fs.mkdirSync( path.dirname( statusPath ), { recursive: true } );

    if ( options.clean ) {
      console.log( 'cleaning...' );
      fs.writeFileSync( statusPath, JSON.stringify( {}, null, 2 ) );
    }

    // Load cached status
    try {
      this.status = JSON.parse( fs.readFileSync( statusPath, 'utf-8' ) );
    }
    catch( e ) {
      console.log( 'couldnt parse status cache, making a clean one' );
      this.status = {};
      fs.writeFileSync( statusPath, JSON.stringify( this.status, null, 2 ) );
    }

    this.activeRepos = getActiveRepos();
  }

  /**
   * Returns the path in chipper/dist that corresponds to a source file.
   * @param filename
   * @returns {string}
   * @public
   */
  static getTargetPath( filename ) {
    const relativePath = path.relative( root, filename );
    const targetPath = path.join( root, 'chipper', 'dist', 'js', ...relativePath.split( path.sep ) ).split( '.ts' ).join( '.js' );
    return targetPath;
  }

  /**
   * Transpile the file using babel, and write it to the corresponding location in chipper/dist
   * @param {string} sourceFile
   * @param {string} targetPath
   * @param {string} text - file text
   * @private
   */
  static transpileFunction( sourceFile, targetPath, text ) {
    const x = core.transformSync( text, {
      filename: sourceFile,

      // Load directly from node_modules so we do not have to npm install this dependency
      // in every sim repo.  This strategy is also used in transpile.js
      presets: [ '../chipper/node_modules/@babel/preset-typescript' ],
      sourceMaps: 'inline'
    } );

    fs.mkdirSync( path.dirname( targetPath ), { recursive: true } );
    fs.writeFileSync( targetPath, x.code );
  }

  // @public
  static modifiedTimeMilliseconds( file ) {
    return fs.statSync( file ).mtime.getTime();
  }

  /**
   * For *.ts and *.js files, checks if they have changed file contents since last transpile.  If so, the
   * file is transpiled.
   * @param {string} path
   * @private
   */
  visitFile( path ) {
    if ( path.endsWith( '.js' ) || path.endsWith( '.ts' ) ) {
      const changeDetectedTime = Date.now();
      const text = fs.readFileSync( path, 'utf-8' );
      const hash = crypto.createHash( 'md5' ).update( text ).digest( 'hex' );

      // If the file has changed, transpile and update the cache.  We have to choose on the spectrum between safety
      // and performance.  In order to maintain high performance with a low error rate, we only write the transpiled file
      // if (a) the cache is out of date (b) there is no target file at all or (c) if the target file has been modified.
      const targetPath = Transpiler.getTargetPath( path );

      if (
        !this.status[ path ] ||
        this.status[ path ].sourceMD5 !== hash ||
        !fs.existsSync( targetPath ) ||
        this.status[ path ].targetMilliseconds !== Transpiler.modifiedTimeMilliseconds( targetPath )
      ) {
        try {
          let reason = '';
          if ( this.verbose ) {
            reason = ( !this.status[ path ] ) ? ' (not cached)' :
                     ( this.status[ path ].sourceMD5 !== hash ) ? ' (changed)' :
                     ( !fs.existsSync( targetPath ) ) ? ' (no target)' :
                     ( this.status[ path ].targetMilliseconds !== Transpiler.modifiedTimeMilliseconds( targetPath ) ) ? ' (target modified)' :
                     '???';
          }
          Transpiler.transpileFunction( path, targetPath, text );

          this.status[ path ] = {
            sourceMD5: hash,
            targetMilliseconds: Transpiler.modifiedTimeMilliseconds( targetPath )
          };
          fs.writeFileSync( statusPath, JSON.stringify( this.status, null, 2 ) );
          const now = Date.now();
          const nowTimeString = new Date( now ).toLocaleTimeString();

          console.log( `${nowTimeString}, ${( now - changeDetectedTime )} ms: ${path}${reason}` );
        }
        catch( e ) {
          console.log( e );
          console.log( 'ERROR' );
        }
      }
    }
  }

  // @private - Recursively visit a directory for files to transpile
  visitDirectory( dir ) {
    if ( fs.existsSync( dir ) ) {
      const files = fs.readdirSync( dir );
      files.forEach( file => {
        const child = path.join( dir, file );
        if ( fs.lstatSync( child ).isDirectory() ) {
          this.visitDirectory( child );
        }
        else {
          this.visitFile( child );
        }
      } );
    }
  }

  /**
   * Transpile the specified repos
   * @param {string[]} repos
   * @public
   */
  transpileRepos( repos ) {
    assert( Array.isArray( repos ), 'repos should be an array' );
    repos.forEach( repo => this.transpileRepo( repo ) );
  }

  // @public - Visit all the subdirectories in a repo that need transpilation
  transpileRepo( repo ) {
    subdirs.forEach( subdir => this.visitDirectory( path.join( '..', repo, subdir ) ) );
    if ( repo === 'sherpa' ) {

      // Our sims load this as a module rather than a preload, so we must transpile it
      this.visitFile( path.join( '..', repo, 'lib', 'game-up-camera-1.0.0.js' ) );
    }
    else if ( repo === 'brand' ) {
      this.visitDirectory( path.join( '..', repo, 'phet' ) );
      this.visitDirectory( path.join( '..', repo, 'phet-io' ) );
      this.visitDirectory( path.join( '..', repo, 'adapted-from-phet' ) );
    }
  }

  // @public
  transpileAll() {
    this.transpileRepos( this.activeRepos );
  }

  // @public
  watch() {
    fs.watch( '../', { recursive: true }, ( eventType, filename ) => {

      if ( !filename || !fs.existsSync( '../' + filename ) ) {
        return;
      }
      if ( filename.includes( '/node_modules/' ) ||
           filename.includes( '.git/' ) ||
           filename.includes( 'chipper/dist/' ) ||
           filename.includes( 'transpile/cache/status.json' ) ||

           // Temporary files sometimes saved by the IDE
           filename.endsWith( '~' ) ) {

        // ignore
      }
      else if ( filename === 'perennial/data/active-repos' ) {
        const newActiveRepos = fs.readFileSync( '../perennial/data/active-repos', 'utf-8' ).trim().split( '\n' );
        console.log( 'reloaded active repos' );
        const newRepos = newActiveRepos.filter( repo => !this.activeRepos.includes( repo ) );

        // Run an initial scan on newly added repos
        newRepos.forEach( repo => {
          console.log( 'New repo detected in active-repos, transpiling: ' + repo );
          this.transpileRepo( repo );
        } );
        this.activeRepos = newActiveRepos;
      }
      else {
        const terms = filename.split( path.sep );
        if ( this.activeRepos.includes( terms[ 0 ] ) && subdirs.includes( terms[ 1 ] ) ) {
          this.visitFile( '../' + filename );
        }
      }
    } );
  }
}

module.exports = Transpiler;<commit_msg>Make sure file exists, see https://github.com/phetsims/chipper/issues/1161<commit_after>// Copyright 2021, University of Colorado Boulder

/**
 * Transpiles *.ts and copies all *.js files to chipper/dist. Does not do type checking. Filters based on active-repos
 * and subsets of directories within repos (such as js/, images/, and sounds/)
 *
 * See transpile.js for the CLI usage
 *
 *  @author Sam Reid (PhET Interactive Simulations)
 */

// imports
const fs = require( 'fs' );
const path = require( 'path' );
const crypto = require( 'crypto' );
const core = require( '@babel/core' );
const assert = require( 'assert' );
const getActiveRepos = require( '../../../perennial-alias/js/common/getActiveRepos' );

// constants

// Cache status is stored in chipper/dist so if you wipe chipper/dist you also wipe the cache
const statusPath = '../chipper/dist/js-cache-status.json';
const root = '../';

// Directories in a sim repo that may contain things for transpilation
// This is used for a top-down search in the initial transpilation and for filtering relevant files in the watch process
const subdirs = [ 'js', 'images', 'mipmaps', 'sounds' ];

class Transpiler {
  constructor( options ) {

    options = options || {
      clean: false,
      verbose: false
    };

    // @private
    this.verbose = options.verbose;

    // Track the status of each repo. Key= repo, value=md5 hash of contents
    this.status = {};

    // Make sure a directory exists for the cached status file
    fs.mkdirSync( path.dirname( statusPath ), { recursive: true } );

    if ( options.clean ) {
      console.log( 'cleaning...' );
      fs.writeFileSync( statusPath, JSON.stringify( {}, null, 2 ) );
    }

    // Load cached status
    try {
      this.status = JSON.parse( fs.readFileSync( statusPath, 'utf-8' ) );
    }
    catch( e ) {
      console.log( 'couldnt parse status cache, making a clean one' );
      this.status = {};
      fs.writeFileSync( statusPath, JSON.stringify( this.status, null, 2 ) );
    }

    this.activeRepos = getActiveRepos();
  }

  /**
   * Returns the path in chipper/dist that corresponds to a source file.
   * @param filename
   * @returns {string}
   * @public
   */
  static getTargetPath( filename ) {
    const relativePath = path.relative( root, filename );
    const targetPath = path.join( root, 'chipper', 'dist', 'js', ...relativePath.split( path.sep ) ).split( '.ts' ).join( '.js' );
    return targetPath;
  }

  /**
   * Transpile the file using babel, and write it to the corresponding location in chipper/dist
   * @param {string} sourceFile
   * @param {string} targetPath
   * @param {string} text - file text
   * @private
   */
  static transpileFunction( sourceFile, targetPath, text ) {
    const x = core.transformSync( text, {
      filename: sourceFile,

      // Load directly from node_modules so we do not have to npm install this dependency
      // in every sim repo.  This strategy is also used in transpile.js
      presets: [ '../chipper/node_modules/@babel/preset-typescript' ],
      sourceMaps: 'inline'
    } );

    fs.mkdirSync( path.dirname( targetPath ), { recursive: true } );
    fs.writeFileSync( targetPath, x.code );
  }

  // @public
  static modifiedTimeMilliseconds( file ) {
    return fs.statSync( file ).mtime.getTime();
  }

  /**
   * For *.ts and *.js files, checks if they have changed file contents since last transpile.  If so, the
   * file is transpiled.
   * @param {string} path
   * @private
   */
  visitFile( path ) {
    if ( path.endsWith( '.js' ) || path.endsWith( '.ts' ) ) {
      const changeDetectedTime = Date.now();
      const text = fs.readFileSync( path, 'utf-8' );
      const hash = crypto.createHash( 'md5' ).update( text ).digest( 'hex' );

      // If the file has changed, transpile and update the cache.  We have to choose on the spectrum between safety
      // and performance.  In order to maintain high performance with a low error rate, we only write the transpiled file
      // if (a) the cache is out of date (b) there is no target file at all or (c) if the target file has been modified.
      const targetPath = Transpiler.getTargetPath( path );

      if (
        !this.status[ path ] ||
        this.status[ path ].sourceMD5 !== hash ||
        !fs.existsSync( targetPath ) ||
        this.status[ path ].targetMilliseconds !== Transpiler.modifiedTimeMilliseconds( targetPath )
      ) {
        try {
          let reason = '';
          if ( this.verbose ) {
            reason = ( !this.status[ path ] ) ? ' (not cached)' :
                     ( this.status[ path ].sourceMD5 !== hash ) ? ' (changed)' :
                     ( !fs.existsSync( targetPath ) ) ? ' (no target)' :
                     ( this.status[ path ].targetMilliseconds !== Transpiler.modifiedTimeMilliseconds( targetPath ) ) ? ' (target modified)' :
                     '???';
          }
          Transpiler.transpileFunction( path, targetPath, text );

          this.status[ path ] = {
            sourceMD5: hash,
            targetMilliseconds: Transpiler.modifiedTimeMilliseconds( targetPath )
          };
          fs.writeFileSync( statusPath, JSON.stringify( this.status, null, 2 ) );
          const now = Date.now();
          const nowTimeString = new Date( now ).toLocaleTimeString();

          console.log( `${nowTimeString}, ${( now - changeDetectedTime )} ms: ${path}${reason}` );
        }
        catch( e ) {
          console.log( e );
          console.log( 'ERROR' );
        }
      }
    }
  }

  // @private - Recursively visit a directory for files to transpile
  visitDirectory( dir ) {
    if ( fs.existsSync( dir ) ) {
      const files = fs.readdirSync( dir );
      files.forEach( file => {
        const child = path.join( dir, file );
        if ( fs.lstatSync( child ).isDirectory() ) {
          this.visitDirectory( child );
        }
        else {
          this.visitFile( child );
        }
      } );
    }
  }

  /**
   * Transpile the specified repos
   * @param {string[]} repos
   * @public
   */
  transpileRepos( repos ) {
    assert( Array.isArray( repos ), 'repos should be an array' );
    repos.forEach( repo => this.transpileRepo( repo ) );
  }

  // @public - Visit all the subdirectories in a repo that need transpilation
  transpileRepo( repo ) {
    subdirs.forEach( subdir => this.visitDirectory( path.join( '..', repo, subdir ) ) );
    if ( repo === 'sherpa' ) {

      // Our sims load this as a module rather than a preload, so we must transpile it
      this.visitFile( path.join( '..', repo, 'lib', 'game-up-camera-1.0.0.js' ) );
    }
    else if ( repo === 'brand' ) {
      this.visitDirectory( path.join( '..', repo, 'phet' ) );
      this.visitDirectory( path.join( '..', repo, 'phet-io' ) );
      this.visitDirectory( path.join( '..', repo, 'adapted-from-phet' ) );
    }
  }

  // @public
  transpileAll() {
    this.transpileRepos( this.activeRepos );
  }

  // @public
  watch() {
    fs.watch( '../', { recursive: true }, ( eventType, filename ) => {

      if ( !filename || !fs.existsSync( '../' + filename ) ) {
        return;
      }
      if ( filename.includes( '/node_modules/' ) ||
           filename.includes( '.git/' ) ||
           filename.includes( 'chipper/dist/' ) ||
           filename.includes( 'transpile/cache/status.json' ) ||

           // Temporary files sometimes saved by the IDE
           filename.endsWith( '~' ) ) {

        // ignore
      }
      else if ( filename === 'perennial/data/active-repos' ) {
        const newActiveRepos = fs.readFileSync( '../perennial/data/active-repos', 'utf-8' ).trim().split( '\n' );
        console.log( 'reloaded active repos' );
        const newRepos = newActiveRepos.filter( repo => !this.activeRepos.includes( repo ) );

        // Run an initial scan on newly added repos
        newRepos.forEach( repo => {
          console.log( 'New repo detected in active-repos, transpiling: ' + repo );
          this.transpileRepo( repo );
        } );
        this.activeRepos = newActiveRepos;
      }
      else {
        const terms = filename.split( path.sep );
        if ( this.activeRepos.includes( terms[ 0 ] ) && subdirs.includes( terms[ 1 ] ) &&
             fs.existsSync( '../' + filename ) ) {
          this.visitFile( '../' + filename );
        }
      }
    } );
  }
}

module.exports = Transpiler;<|endoftext|>


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

  var dom = app.dom || require('../dom.js');
  var Component = app.Component || require('./component.js');

  var Button = Component.inherits(function(props) {
    this.isActive = this.prop(false);
    this.disabled = this.prop(false);

    this.registerTapListener();
  });

  Button.prototype.registerTapListener = function() {
    new dom.Draggable({
      element: this.element(),
      onstart: Button.prototype.onstart.bind(this),
      onmove: Button.prototype.onmove.bind(this),
      onend: Button.prototype.onend.bind(this),
    });
  };

  Button.prototype.redraw = function() {
    this.redrawDOMToggleClassBy('isActive', 'active');
    this.redrawDOMToggleClassBy('disabled', 'disabled');
    this.onredraw();
  };

  Button.prototype.onstart = function(x, y, event, context) {
    context.target = dom.target(event);
    dom.cancel(event);
    dom.removeFocus();
    this.isActive(true);
  };

  Button.prototype.onmove = function(dx, dy, event, context) {
    this.isActive(dom.target(event) === context.target);
  };

  Button.prototype.onend = function(dx, dy, event, context) {
    this.isActive(false);
    if (dom.target(event) === context.target) {
      this.ontap();
    }
  };

  Button.prototype.ontap = function() {};

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = Button;
  } else {
    app.Button = Button;
  }
})(this.app || (this.app = {}));
<commit_msg>Register event listeners for button component on init event<commit_after>(function(app) {
  'use strict';

  var dom = app.dom || require('../dom.js');
  var Component = app.Component || require('./component.js');

  var Button = Component.inherits(function(props) {
    this.isActive = this.prop(false);
    this.disabled = this.prop(false);
  });

  Button.prototype.redraw = function() {
    this.redrawDOMToggleClassBy('isActive', 'active');
    this.redrawDOMToggleClassBy('disabled', 'disabled');
    this.onredraw();
  };

  Button.prototype.oninit = function() {
    new dom.Draggable({
      element: this.element(),
      onstart: Button.prototype.onstart.bind(this),
      onmove: Button.prototype.onmove.bind(this),
      onend: Button.prototype.onend.bind(this),
    });
  };

  Button.prototype.onstart = function(x, y, event, context) {
    context.target = dom.target(event);
    dom.cancel(event);
    dom.removeFocus();
    this.isActive(true);
  };

  Button.prototype.onmove = function(dx, dy, event, context) {
    this.isActive(dom.target(event) === context.target);
  };

  Button.prototype.onend = function(dx, dy, event, context) {
    this.isActive(false);
    if (dom.target(event) === context.target) {
      this.ontap();
    }
  };

  Button.prototype.ontap = function() {};

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = Button;
  } else {
    app.Button = Button;
  }
})(this.app || (this.app = {}));
<|endoftext|>


<commit_before>Template.WidgetShow.helpers({
  widgetTemplate: function() {
    return this.package.templateFor('Widget');
  },
  providesInfo: function() {
    return this.package.providesTemplate('Info');
  },
  providesSettings: function() {
    return this.package.providesTemplate('Settings');
  },
  componentId: function(component) {
    return this.componentId(component);
  },
  widgetClass: function() {
    return this.packageName;
  },
  widgetMetadata: function() {
    return this.package.metadata();
  },
  titleBar: function() {
    return Widget.Settings.titleBar;
  },
  gridAttrs: function() {
    var resizeConstraints = this.package.widget.resize.constraints;
    var attrs = {
      'data-sizex': this.width,
      'data-sizey': this.height,
      'data-min-sizex': resizeConstraints.width.min,
      'data-max-sizex': resizeConstraints.width.max,
      'data-min-sizey': resizeConstraints.height.min,
      'data-max-sizey': resizeConstraints.height.max
    };
    if (this.position) {
      attrs['data-row'] = this.position.x;
      attrs['data-col'] = this.position.y;
    }
    return attrs;
  }
});

Template.WidgetShow.onCreated(function() {
  var self = this;

  _.extend(self, {
    gridUnitsToPixels: function(dims) {
      var dashboard = self.data.dashboard();
      var currentDims = {
        width: self.$('.widget').attr('data-sizex'),
        height: self.$('.widget').attr('data-sizey')
      };
      dims = dims || currentDims;
      _.defaults(dims, currentDims);
      return {
        width: dims.width * dashboard.columnWidth +
          dashboard.gutter * (dims.width - 1),
        height: dims.height * dashboard.rowHeight +
          dashboard.gutter * (dims.height - 1)
      };
    },

    scaleBody: function(newDims) {
      var widget = self.data;
      var $widgetBody = self.$('.widget-body');

      var newPixelDims = self.gridUnitsToPixels(newDims);
      var originalGridDims = widget.package.widget.dimensions;
      var originalPixelDims = self.gridUnitsToPixels(originalGridDims);

      // We're just scaling the body, so don't count the title bar.
      newPixelDims.height -= Widget.Settings.titleBar.height;
      originalPixelDims.height -= Widget.Settings.titleBar.height;

      $widgetBody.css({
        transform: 'scaleX(' + newPixelDims.width / originalPixelDims.width + ') ' +
                   'scaleY(' + newPixelDims.height / originalPixelDims.height + ')'
      });
    }
  });
});

Template.WidgetShow.onRendered(function() {
  var dashboardTemplate = Dashboards.templateFromChild(this);
  var widgetNode = this.firstNode;
  var self = this;

  if (dashboardTemplate.gridster) {
    dashboardTemplate.gridster.add_widget(
      widgetNode, $(widgetNode).data('sizex'), $(widgetNode).data('sizey'));
    Widgets.updatePositions(dashboardTemplate.gridster.serialize());
  } else {
    dashboardTemplate.widgetNodes.push(widgetNode);
  }

  if (self.data.package.widget.resize.mode === 'scale') {
    var originalGridDims = self.data.package.widget.dimensions;
    var originalPixelDims = self.gridUnitsToPixels(originalGridDims);
    originalPixelDims.height -= Widget.Settings.titleBar.height;

    // Pin the width and height so we don't get both reflows and transforms.
    self.$('.widget-body').css(originalPixelDims);
    self.scaleBody();
  }

  // When other clients resize widgets
  self.autorun(function() {
    Widgets.find(self.data._id).observeChanges({
      changed: function(id, fields) {
        if (_(fields).has('width') || _(fields).has('height')) {
          self.scaleBody(fields);
        }
      }
    });
  });

  self.$infoContent = self.$('.widget-info').detach();
  self.$settingsContent = self.$('.widget-settings').detach();

  $(widgetNode).popover({
    selector: '[data-toggle="popover"]',
    content: function() {
      var isSettings = $(this).attr('class').indexOf('settings') >= 0;
      return isSettings ? self.$settingsContent.get(0) : self.$infoContent.get(0);
    }
  });

  $(widgetNode).removeClass('hidden');
});

Template.WidgetShow.events({
  'click .remove-widget': function(ev, template) {
    var dashboardTemplate = Dashboards.templateFromChild(template);
    var dashboard = dashboardTemplate.data;

    Template.WidgetShow.closePopover(this, 'Settings');
    Template.WidgetShow.closePopover(this, 'Info');

    dashboardTemplate.gridster.remove_widget(template.firstNode);
    Widgets.updatePositions(dashboardTemplate.gridster.serialize());
    dashboard.removeWidget(this);
  },
  'gridster:resizestart': function(ev, template) {
    if (this.package.widget.resize.mode === 'scale') {
      template.$('.widget-body').append('
');
    }
    // This was passed down from the dashboard - don't bubble it back up.
    ev.stopPropagation();
  },
  'gridster:resizestop': function(ev, template) {
    if (this.package.widget.resize.mode === 'scale') {
      template.scaleBody();
      template.$('.resizing-cover').remove();
    }
    ev.stopPropagation();
  },
});

Template.registerHelper('widgetLoading', function() {
  return 'Loading...';
});

Template.WidgetShow.closePopover = function(widget, component) {
  $('#' + widget.componentId(component)).popover('hide');
};

var addPopoverCloserToTemplate = function(template, popoverName) {
  var closeForTemplate = function() {
    var widget;
    if (this.data.constructor === WidgetData) {
      widget = this.data.widget;
    } else {
      widget = this.data;
    }
    Template.WidgetShow.closePopover(widget, popoverName);
  };
  template.onCreated(function() {
    this['close' + popoverName] = closeForTemplate;
  });
};

var addPopoverCloser = function(popoverName) {
  addPopoverCloserToTemplate(Template['Widget' + popoverName], popoverName);

  WidgetPackages.find().observe({
    added: function(package) {
      if (!package.providesTemplate(popoverName)) { return; }
      addPopoverCloserToTemplate(
          Template[package.templateFor(popoverName)], popoverName);
    }
  });
};

addPopoverCloser('Settings');
addPopoverCloser('Info');
<commit_msg>do not scale when mode is not scale<commit_after>Template.WidgetShow.helpers({
  widgetTemplate: function() {
    return this.package.templateFor('Widget');
  },
  providesInfo: function() {
    return this.package.providesTemplate('Info');
  },
  providesSettings: function() {
    return this.package.providesTemplate('Settings');
  },
  componentId: function(component) {
    return this.componentId(component);
  },
  widgetClass: function() {
    return this.packageName;
  },
  widgetMetadata: function() {
    return this.package.metadata();
  },
  titleBar: function() {
    return Widget.Settings.titleBar;
  },
  gridAttrs: function() {
    var resizeConstraints = this.package.widget.resize.constraints;
    var attrs = {
      'data-sizex': this.width,
      'data-sizey': this.height,
      'data-min-sizex': resizeConstraints.width.min,
      'data-max-sizex': resizeConstraints.width.max,
      'data-min-sizey': resizeConstraints.height.min,
      'data-max-sizey': resizeConstraints.height.max
    };
    if (this.position) {
      attrs['data-row'] = this.position.x;
      attrs['data-col'] = this.position.y;
    }
    return attrs;
  }
});

Template.WidgetShow.onCreated(function() {
  var self = this;

  _.extend(self, {
    gridUnitsToPixels: function(dims) {
      var dashboard = self.data.dashboard();
      var currentDims = {
        width: self.$('.widget').attr('data-sizex'),
        height: self.$('.widget').attr('data-sizey')
      };
      dims = dims || currentDims;
      _.defaults(dims, currentDims);
      return {
        width: dims.width * dashboard.columnWidth +
          dashboard.gutter * (dims.width - 1),
        height: dims.height * dashboard.rowHeight +
          dashboard.gutter * (dims.height - 1)
      };
    },

    scaleBody: function(newDims) {
      var widget = self.data;
      var $widgetBody = self.$('.widget-body');

      var newPixelDims = self.gridUnitsToPixels(newDims);
      var originalGridDims = widget.package.widget.dimensions;
      var originalPixelDims = self.gridUnitsToPixels(originalGridDims);

      // We're just scaling the body, so don't count the title bar.
      newPixelDims.height -= Widget.Settings.titleBar.height;
      originalPixelDims.height -= Widget.Settings.titleBar.height;

      $widgetBody.css({
        transform: 'scaleX(' + newPixelDims.width / originalPixelDims.width + ') ' +
                   'scaleY(' + newPixelDims.height / originalPixelDims.height + ')'
      });
    }
  });
});

Template.WidgetShow.onRendered(function() {
  var dashboardTemplate = Dashboards.templateFromChild(this);
  var widgetNode = this.firstNode;
  var self = this;
  var resizeMode = self.data.package.widget.resize.mode;

  if (dashboardTemplate.gridster) {
    dashboardTemplate.gridster.add_widget(
      widgetNode, $(widgetNode).data('sizex'), $(widgetNode).data('sizey'));
    Widgets.updatePositions(dashboardTemplate.gridster.serialize());
  } else {
    dashboardTemplate.widgetNodes.push(widgetNode);
  }

  if (resizeMode === 'scale') {
    var originalGridDims = self.data.package.widget.dimensions;
    var originalPixelDims = self.gridUnitsToPixels(originalGridDims);
    originalPixelDims.height -= Widget.Settings.titleBar.height;

    // Pin the width and height so we don't get both reflows and transforms.
    self.$('.widget-body').css(originalPixelDims);
    self.scaleBody();
  }

  // When other clients resize widgets
  self.autorun(function() {
    Widgets.find(self.data._id).observeChanges({
      changed: function(id, fields) {
        if (resizeMode === 'scale' &&
            (_(fields).has('width') || _(fields).has('height'))) {
          self.scaleBody(fields);
        }
      }
    });
  });

  self.$infoContent = self.$('.widget-info').detach();
  self.$settingsContent = self.$('.widget-settings').detach();

  $(widgetNode).popover({
    selector: '[data-toggle="popover"]',
    content: function() {
      var isSettings = $(this).attr('class').indexOf('settings') >= 0;
      return isSettings ? self.$settingsContent.get(0) : self.$infoContent.get(0);
    }
  });

  $(widgetNode).removeClass('hidden');
});

Template.WidgetShow.events({
  'click .remove-widget': function(ev, template) {
    var dashboardTemplate = Dashboards.templateFromChild(template);
    var dashboard = dashboardTemplate.data;

    Template.WidgetShow.closePopover(this, 'Settings');
    Template.WidgetShow.closePopover(this, 'Info');

    dashboardTemplate.gridster.remove_widget(template.firstNode);
    Widgets.updatePositions(dashboardTemplate.gridster.serialize());
    dashboard.removeWidget(this);
  },
  'gridster:resizestart': function(ev, template) {
    if (this.package.widget.resize.mode === 'scale') {
      template.$('.widget-body').append('
');
    }
    // This was passed down from the dashboard - don't bubble it back up.
    ev.stopPropagation();
  },
  'gridster:resizestop': function(ev, template) {
    if (this.package.widget.resize.mode === 'scale') {
      template.scaleBody();
      template.$('.resizing-cover').remove();
    }
    ev.stopPropagation();
  },
});

Template.registerHelper('widgetLoading', function() {
  return 'Loading...';
});

Template.WidgetShow.closePopover = function(widget, component) {
  $('#' + widget.componentId(component)).popover('hide');
};

var addPopoverCloserToTemplate = function(template, popoverName) {
  var closeForTemplate = function() {
    var widget;
    if (this.data.constructor === WidgetData) {
      widget = this.data.widget;
    } else {
      widget = this.data;
    }
    Template.WidgetShow.closePopover(widget, popoverName);
  };
  template.onCreated(function() {
    this['close' + popoverName] = closeForTemplate;
  });
};

var addPopoverCloser = function(popoverName) {
  addPopoverCloserToTemplate(Template['Widget' + popoverName], popoverName);

  WidgetPackages.find().observe({
    added: function(package) {
      if (!package.providesTemplate(popoverName)) { return; }
      addPopoverCloserToTemplate(
          Template[package.templateFor(popoverName)], popoverName);
    }
  });
};

addPopoverCloser('Settings');
addPopoverCloser('Info');
<|endoftext|>


<commit_before>(function()
{
  angular
    .module('settings')
    .controller('SettingsController', SettingsController);

  SettingsController.$inject = ['$scope', '$state', '$ionicModal', '$ionicViewService', '$ionicPopup', 'FooseyService', 'SettingsService'];

  function SettingsController($scope, $state, $ionicModal, $ionicViewService, $ionicPopup, FooseyService, SettingsService)
  {
    // send to login screen if they haven't logged in yet
    if (!SettingsService.loggedIn) SettingsService.logOut();

  	$scope.settings = SettingsService;
    $scope.players = [];
    $scope.playerSelections = [];
    $scope.player = {};
    $scope.player.selected = SettingsService.playerID;
  	$scope.tapped = 0;

  	$scope.tap = tap;

    loadPlayers();

    $scope.$watch('player.selected', function(player)
    {
      if (_.isUndefined(player)) return;
      SettingsService.setPlayer(player);
    });

    function loadPlayers()
    {
      // load from server
      FooseyService.getAllPlayers(false).then(
        function (players)
        {
          $scope.players = players.sort(function(a, b){
            return a.displayName.localeCompare(b.displayName);
          });
          // filter the player selections that you can choose to just the active players
          $scope.playerSelections = _.filter($scope.players, function(player){ return player.active });
        });
    }

  	function tap()
  	{
  		$scope.tapped++;
  	}
  }
})();<commit_msg>Removed unused and deprecated dependencies<commit_after>(function()
{
  angular
    .module('settings')
    .controller('SettingsController', SettingsController);

  SettingsController.$inject = ['$scope', 'FooseyService', 'SettingsService'];

  function SettingsController($scope, FooseyService, SettingsService)
  {
    // send to login screen if they haven't logged in yet
    if (!SettingsService.loggedIn) SettingsService.logOut();

  	$scope.settings = SettingsService;
    $scope.players = [];
    $scope.playerSelections = [];
    $scope.player = {};
    $scope.player.selected = SettingsService.playerID;
  	$scope.tapped = 0;

  	$scope.tap = tap;

    loadPlayers();

    $scope.$watch('player.selected', function(player)
    {
      if (_.isUndefined(player)) return;
      SettingsService.setPlayer(player);
    });

    function loadPlayers()
    {
      // load from server
      FooseyService.getAllPlayers(false).then(
        function (players)
        {
          $scope.players = players.sort(function(a, b){
            return a.displayName.localeCompare(b.displayName);
          });
          // filter the player selections that you can choose to just the active players
          $scope.playerSelections = _.filter($scope.players, function(player){ return player.active });
        });
    }

  	function tap()
  	{
  		$scope.tapped++;
  	}
  }
})();<|endoftext|>


<commit_before>'use strict';

const cluster = require('./');
const utils = require('./utils');
const Base = require('sdk-base');

class APIClientBase extends Base {
  constructor(options) {
    options = options || {};
    super(options);

    const wrapper = (options.cluster || cluster)(
      this.DataClient, this.clusterOptions
    );
    for (const from in this.delegates) {
      const to = this.delegates[from];
      wrapper.delegate(from, to);
    }
    this._client = wrapper.create(options);
    utils.delegateEvents(this._client, this);
    this._client.ready(err => {
      this.ready(err ? err : true);
    });
  }

  get DataClient() {
    /* istanbul ignore  next */
    throw new Error('[APIClient] DataClient is required');
  }

  /**
   * the cluster options
   *
   * @property {Object} APIClientBase#clusterOptions
   */
  get clusterOptions() {
    /* istanbul ignore  next */
    return {};
  }

  /**
   * the delegates map
   *
   * @example
   * ---------------------------
   * delegates => {
   *    subscribe: 'subscribe',
   *    foo: 'invoke',
   * }
   *
   * @property {Object} APIClientBase#delegates
   */
  get delegates() {
    /* istanbul ignore  next */
    return {};
  }
}

module.exports = APIClientBase;
<commit_msg>fix: don't auto ready when initMethod exists (#17)<commit_after>'use strict';

const cluster = require('./');
const utils = require('./utils');
const Base = require('sdk-base');

class APIClientBase extends Base {
  constructor(options) {
    options = options || {};
    super(options);

    const wrapper = (options.cluster || cluster)(
      this.DataClient, this.clusterOptions
    );
    for (const from in this.delegates) {
      const to = this.delegates[from];
      wrapper.delegate(from, to);
    }
    this._client = wrapper.create(options);
    utils.delegateEvents(this._client, this);

    if (!options.initMethod) {
      this._client.ready(err => {
        this.ready(err ? err : true);
      });
    }
  }

  get DataClient() {
    /* istanbul ignore  next */
    throw new Error('[APIClient] DataClient is required');
  }

  /**
   * the cluster options
   *
   * @property {Object} APIClientBase#clusterOptions
   */
  get clusterOptions() {
    /* istanbul ignore  next */
    return {};
  }

  /**
   * the delegates map
   *
   * @example
   * ---------------------------
   * delegates => {
   *    subscribe: 'subscribe',
   *    foo: 'invoke',
   * }
   *
   * @property {Object} APIClientBase#delegates
   */
  get delegates() {
    /* istanbul ignore  next */
    return {};
  }
}

module.exports = APIClientBase;
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import reactDOM from 'react-dom';
import withStyles from '../../decorators/withStyles';
import styles from './Character.css';
import TweenMax from '../../vendor/gsap';
import { get as getLine } from '../../constants/ABTest';

@withStyles(styles)
class Character extends Component {
  constructor(){
    super();
    this.handleClick = this.handleClick.bind(this);
    this.handleTouchEnd = this.handleTouchEnd.bind(this);
  }
  componentWillUpdate(nextProps, nextState) {
    if (nextProps.active) {
      this.tl.to(this.character, 0.4, {WebkitTransform: 'translateY(0)'})
             .to(this.bubble, 0.4, {WebkitTransform: 'translateY(0) scale(1)'}, '-=0.4');
    } else {
      this.tl.to(this.character, 0, {WebkitTransform: 'translateY(100%)'})
             .to(this.bubble, 0, {WebkitTransform: 'translateY(200%) scale(0.7)'});
    }
  }
  componentDidMount() {
    this.character = reactDOM.findDOMNode(this.refs.character);
    this.bubble = reactDOM.findDOMNode(this.refs.bubble);
    this.tl = new TimelineMax();
  }
  handleClick(e){
    e.preventDefault();
    TweenMax.to(this.character, 0, {WebkitTransform: 'scale(1.2)'});
  }
  handleTouchEnd(e){
    e.preventDefault();
    TweenMax.to(this.character, 0, {WebkitTransform: 'scale(1)'})
  }
  render(){
    let line;
    switch (this.props.line) {
      case 1:
        line = getLine(this.props.version).scene2.dialogue;
        break;
      case 2:
        line = getLine(this.props.version).scene3.dialogue;
        break;
      case 3:
        line = getLine(this.props.version).scene4.dialogue;
        break;
      case 4:
        line = getLine(this.props.version).scene5.dialogue;
        break;
      default:
    }
    let styles = {
      display: 'block'
    };
    let characterVersion = 1;
    //if version 3 it will hide all the bubbles
    if(this.props.version === 3 || this.props.version === 4) {
      styles.display = 'none';
      characterVersion = 2;
    }
    return(

{line}

    )
  }
}

export default Character;
<commit_msg>ab test for tw finished<commit_after>import React, {Component} from 'react';
import reactDOM from 'react-dom';
import withStyles from '../../decorators/withStyles';
import styles from './Character.css';
import TweenMax from '../../vendor/gsap';
import { get as getLine } from '../../constants/ABTest';

@withStyles(styles)
class Character extends Component {
  constructor(){
    super();
    this.handleClick = this.handleClick.bind(this);
    this.handleTouchEnd = this.handleTouchEnd.bind(this);
  }
  componentWillUpdate(nextProps, nextState) {
    if (nextProps.active) {
      this.tl.to(this.character, 0.4, {WebkitTransform: 'translateY(0)'})
             .to(this.bubble, 0.4, {WebkitTransform: 'translateY(0) scale(1)'}, '-=0.4');
    } else {
      this.tl.to(this.character, 0, {WebkitTransform: 'translateY(100%)'})
             .to(this.bubble, 0, {WebkitTransform: 'translateY(200%) scale(0.7)'});
    }
  }
  componentDidMount() {
    this.character = reactDOM.findDOMNode(this.refs.character);
    this.bubble = reactDOM.findDOMNode(this.refs.bubble);
    this.tl = new TimelineMax();
  }
  handleClick(e){
    e.preventDefault();
    TweenMax.to(this.character, 0, {WebkitTransform: 'scale(1.2)'});
  }
  handleTouchEnd(e){
    e.preventDefault();
    TweenMax.to(this.character, 0, {WebkitTransform: 'scale(1)'})
  }
  render(){
    let line;
    switch (this.props.line) {
      case 1:
        line = getLine(this.props.version).scene2.dialogue;
        break;
      case 2:
        line = getLine(this.props.version).scene3.dialogue;
        break;
      case 3:
        line = getLine(this.props.version).scene4.dialogue;
        break;
      case 4:
        line = getLine(this.props.version).scene5.dialogue;
        break;
      default:
    }
    let styles = {
      display: 'block'
    };
    let characterVersion = 1;
    //if version 3 it will hide all the bubbles
    if(this.props.version === 3) {
      styles.display = 'none';
      characterVersion = 1;
    } else if (this.props.version === 4) {
      styles.display = 'none';
      characterVersion = 2;
    }
    return(

{line}

    )
  }
}

export default Character;
<|endoftext|>


<commit_before>var context = new window.AudioContext(); // Set up audio system
var osc = context.createOscillator();
osc.connect(context.destination);
osc.start(); context.suspend();
function playSound(freq,type='square') {
	osc.type = type; // Sine, square, sawtooth, triangle
	osc.frequency.value = freq; // Hz
	context.resume();
	setTimeout(()=>context.suspend(),100);
}
var over = 0;
cellColor = '#55F';
colors = ['blue','green','red','orange','purple','brown','gray','pink'];
gridW = 20; boxW = 25; // Set box dimensions and grid size
gridH = 20; boxH = 25;
sp = 2;
covered = gridW * gridH;
bombChance = .1;
bombs = Array(gridW*gridH).fill(0);
bombCount = 0;
while (bombCount < gridW * gridH * bombChance) {
	var select = Math.ceil(gridW * gridH * Math.random());
	if (bombs[select] == 0) {
		bombs[select] = 1;
		bombCount++;
	}
}
zones = new Array(gridW); // Create array of boxes
for (i=0; i<gridW; i++) {
	zones[i] = new Array(gridH);
}
var c = document.getElementById("game"); // Adjust canvas dimensions
c.width = gridW * boxW + (sp * (gridW - 1));
c.height = gridH * boxH + (sp * (gridH - 1));
var ctx = c.getContext("2d");

function getNearbyBombs(x) { // Find number of nearby bombs
	var a = x % gridW;
	var b = Math.floor(x / gridW);
	var near = (a>0?bombs[x-1]+(b>0?bombs[x-1-gridW]:0)+(b<gridH-1?bombs[x-1+gridW]:0):0) +
			(a<(gridW-1)?bombs[x+1]+(b>0?bombs[x+1-gridW]:0)+(b<gridH-1?bombs[x+1+gridW]:0):0) +
			(b>0?bombs[x-gridW]:0) +
			(b<gridH-1?bombs[x+gridW]:0);
	return near;
}

function component(a, b, color, x, y, bomb) { // Create and handle individual boxes
    this.x = x;
    this.y = y;
	this.a = a;
	this.b = b;
	this.bomb = bombs[a+(b*gridW)];
	this.bCN = getNearbyBombs(a+(b*gridW)); // Find bomb count nearby
	this.color = color;
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, boxW, boxH);
	this.unclicked = true;
	this.flagDown = false;
	this.flag = function () {
		if (this.unclicked && !over) {
			playSound(400,'sine');
			ctx.fillStyle = this.flagDown ? this.color : "yellow";
			ctx.fillRect(this.x, this.y, boxW, boxH);
			this.flagDown ^= 1;
		}
	};
	this.clicked = function() {
		if (this.unclicked && !this.flagDown && !over) {
			this.unclicked = false;
			if (this.bomb) {
				playSound(1000);
				ctx.fillStyle = "red";
				ctx.fillRect(this.x, this.y, boxW, boxH);
				setTimeout(()=>{
					if (!over) {
					zones.forEach(a=>a.forEach(b=>{if(b.bomb)b.clicked()})); // Click all bombs
					over = 1;
					ctx.font = "bold "+Math.min(boxW*3,boxH*3)+"px Arial";
					playSound(800);
					ctx.fillStyle = "black";
					ctx.fillText('GAME OVER', (sp+boxW)*gridW/16, (sp+boxH)*gridH/2);
					}}, 500);
			}
			else {
				playSound(256);
				ctx.fillStyle = "#FFF";
				ctx.fillRect(this.x, this.y, boxW, boxH);
				ctx.fillStyle = colors[this.bCN-1];
				ctx.font = Math.min(boxW, boxH)+"px Arial";
				if (this.bCN) ctx.fillText(this.bCN, this.x+(boxW)/4, this.y+boxH*7/8);
				else { // If empty, click all nearby boxes
					if (a > 0) {
						zones[a-1][b].clicked();
						if (b > 0) zones[a-1][b-1].clicked();
						if (b < gridH-1) zones[a-1][b+1].clicked();
					}
					if (a < gridW-1) {
						zones[a+1][b].clicked();
						if (b > 0) zones[a+1][b-1].clicked();
						if (b < gridH-1) zones[a+1][b+1].clicked();
					}
					if (b > 0) zones[a][b-1].clicked();
					if (b < gridH-1) zones[a][b+1].clicked();
				}
				if (bombs.every((val,i) => { // Check if game complete
					var a = i % gridW;
					var b = Math.floor(i / gridW);
					return val || !zones[a][b].unclicked;
				})) {
					over = 2;
					setTimeout(()=>{
						ctx.font = "bold "+Math.min(boxW*3,boxH*3)+"px Arial";
						playSound(800);
						ctx.fillStyle = "black";
						ctx.fillText('VICTORY!', (sp+boxW)*gridW/6, (sp+boxH)*gridH/2);
						}, 500);
				}
			}
		}
	}
};

for (var a=0; a<gridW; a++) { // Create all boxes at once
	for (var b=0; b<gridH; b++) {
		zones[a][b] = new component(a,b,cellColor,(sp+boxW)*a,(sp+boxH)*b,Math.random()<=bombChance);
	}
}
console.log("Boxes prepared.");

c.onclick = function(e) { // Handle clicks on boxes
	a = Math.floor(e.layerX/(boxW+sp));
	b = Math.floor(e.layerY/(boxH+sp));
	zones[a][b].clicked();
}

c.oncontextmenu = function(e) { // Handle right-clicks on boxes
	a = Math.floor(e.layerX/(boxW+sp));
	b = Math.floor(e.layerY/(boxH+sp));
	zones[a][b].flag();
	return false;
}

//zones.forEach(a=>a.forEach(b=>b.clicked())); // Click all boxes
// zones.forEach(a=>a.forEach(b=>{if(!b.bomb)b.clicked()})); // Click all correct boxes
<commit_msg>Fix basic JS errors<commit_after>var context = new window.AudioContext(); // Set up audio system
var osc = context.createOscillator();
osc.connect(context.destination);
osc.start(); context.suspend();

g = context.createGain();
g.gain.value = 0.01; // This should theoretically make the sound quieter

function playSound(freq,type='square') {
	osc.type = type; // Sine, square, sawtooth, triangle
	osc.frequency.value = freq; // Hz
	context.resume();
	setTimeout(()=>context.suspend(),100);
}
var over = 0;
cellColor = '#55F';
colors = ['blue','green','red','orange','purple','brown','gray','pink'];
gridW = 20; boxW = 25; // Set box dimensions and grid size
gridH = 20; boxH = 25;
sp = 2;
covered = gridW * gridH;
bombChance = .1;
bombs = Array(gridW*gridH).fill(0);
bombCount = 0;
while (bombCount < gridW * gridH * bombChance) {
	var select = Math.ceil(gridW * gridH * Math.random());
	if (bombs[select] == 0) {
		bombs[select] = 1;
		bombCount++;
	}
}
zones = new Array(gridW); // Create array of boxes
for (i=0; i<gridW; i++) {
	zones[i] = new Array(gridH);
}
var c = document.getElementById("game"); // Adjust canvas dimensions
c.width = gridW * boxW + (sp * (gridW - 1));
c.height = gridH * boxH + (sp * (gridH - 1));
var ctx = c.getContext("2d");

function getNearbyBombs(x) { // Find number of nearby bombs
	var a = x % gridW;
	var b = Math.floor(x / gridW);
	var near = (a>0?bombs[x-1]+(b>0?bombs[x-1-gridW]:0)+(b<gridH-1?bombs[x-1+gridW]:0):0) +
			(a<(gridW-1)?bombs[x+1]+(b>0?bombs[x+1-gridW]:0)+(b<gridH-1?bombs[x+1+gridW]:0):0) +
			(b>0?bombs[x-gridW]:0) +
			(b<gridH-1?bombs[x+gridW]:0);
	return near;
}

function component(a, b, color, x, y) { // Create and handle individual boxes
    this.x = x;
    this.y = y;
	this.a = a;
	this.b = b;
	this.bomb = bombs[a+(b*gridW)];
	this.bCN = getNearbyBombs(a+(b*gridW)); // Find bomb count nearby
	this.color = color;
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, boxW, boxH);
	this.unclicked = true;
	this.flagDown = false;
	this.flag = function () {
		if (this.unclicked && !over) {
			playSound(400,'sine');
			ctx.fillStyle = this.flagDown ? this.color : "yellow";
			ctx.fillRect(this.x, this.y, boxW, boxH);
			this.flagDown ^= 1;
		}
	};
	this.clicked = function() {
		if (this.unclicked && !this.flagDown && !over) {
			this.unclicked = false;
			if (this.bomb) {
				playSound(1000);
				ctx.fillStyle = "red";
				ctx.fillRect(this.x, this.y, boxW, boxH);
				setTimeout(()=>{
					if (!over) {
					zones.forEach(a=>a.forEach(b=>{if(b.bomb)b.clicked()})); // Click all bombs
					over = 1;
					ctx.font = "bold "+Math.min(boxW*3,boxH*3)+"px Arial";
					playSound(800);
					ctx.fillStyle = "black";
					ctx.fillText('GAME OVER', (sp+boxW)*gridW/16, (sp+boxH)*gridH/2);
					}}, 500);
			}
			else {
				playSound(256);
				ctx.fillStyle = "#FFF";
				ctx.fillRect(this.x, this.y, boxW, boxH);
				ctx.fillStyle = colors[this.bCN-1];
				ctx.font = Math.min(boxW, boxH)+"px Arial";
				if (this.bCN) ctx.fillText(this.bCN, this.x+(boxW)/4, this.y+boxH*7/8);
				else { // If empty, click all nearby boxes
					if (a > 0) {
						zones[a-1][b].clicked();
						if (b > 0) zones[a-1][b-1].clicked();
						if (b < gridH-1) zones[a-1][b+1].clicked();
					}
					if (a < gridW-1) {
						zones[a+1][b].clicked();
						if (b > 0) zones[a+1][b-1].clicked();
						if (b < gridH-1) zones[a+1][b+1].clicked();
					}
					if (b > 0) zones[a][b-1].clicked();
					if (b < gridH-1) zones[a][b+1].clicked();
				}
				if (bombs.every((val,i) => { // Check if game complete
					var a = i % gridW;
					var b = Math.floor(i / gridW);
					return val || !zones[a][b].unclicked;
				})) {
					over = 2;
					setTimeout(()=>{
						ctx.font = "bold "+Math.min(boxW*3,boxH*3)+"px Arial";
						playSound(800);
						ctx.fillStyle = "black";
						ctx.fillText('VICTORY!', (sp+boxW)*gridW/6, (sp+boxH)*gridH/2);
						}, 500);
				}
			}
		}
	}
};

for (var a=0; a<gridW; a++) { // Create all boxes at once
	for (var b=0; b<gridH; b++) {
		zones[a][b] = new component(a,b,cellColor,(sp+boxW)*a,(sp+boxH)*b,Math.random()<=bombChance);
	}
}
console.log("Boxes prepared.");

c.onclick = function(e) { // Handle clicks on boxes
	a = Math.floor(e.offsetX/(boxW+sp));
	b = Math.floor(e.offsetY/(boxH+sp));
	zones[a][b].clicked();
}

c.oncontextmenu = function(e) { // Handle right-clicks on boxes
	a = Math.floor(e.offsetX/(boxW+sp));
	b = Math.floor(e.offsetY/(boxH+sp));
	zones[a][b].flag();
	return false;
}

//zones.forEach(a=>a.forEach(b=>b.clicked())); // Click all boxes
// zones.forEach(a=>a.forEach(b=>{if(!b.bomb)b.clicked()})); // Click all correct boxes
<|endoftext|>


<commit_before>angular.module("adminPanel",["myTable","ngResource","jqDialog","addButton","ui"]);

function actButtons(_mData) {
      this.aTargets=[-1];
      this.mData=_mData;
      this.fnCreatedCell=function (nTd, sData, oData, iRow, iCol) {
		butDel = $("<button>delete</button>").button({
        	    text:false,
	            icons: {
	                primary: "ui-icon-trash"
	            }
	        })
	        .on("click",function() {
                            myscope = angular.element(nTd).scope().doDel(oData);
        	});

                butEdit = $("<button>edit</button>").button({
        	    text:false,
	            icons: {
	                primary: "ui-icon-wrench"
	            }
	        })
	        .on("click",function() {
                            myscope = angular.element(nTd).scope().doEdit(oData);
        	});

        	$(nTd).empty().prepend(butDel).prepend(butEdit);
      }
}

function userAdmin($scope,$window,$resource) {
	var User = $resource('/admin/users/:userId',{userId:'@id'});

        $scope.userColumnDefs = [
            { "mData": "name", "aTargets":[0] },
            { "mData": "email", "aTargets":[1] },
            new actButtons("id")
        ];

        $scope.showDlg = function() {
            $scope.curUsr = new User();
            $scope.dlgState=true;
        }

        $scope.hideDlg = function() {
            $scope.dlgState=false;
            $scope.$digest();
        }

        $scope.refresh =function() {
            User.query(function(data) {$scope.users=data; });
          //  $scope.$apply();
        }

        $scope.doDel = function(usr) {
            if($window.confirm(usr.name + " wirklich löschen?")) {
                User.remove({userId:usr.id});
            }
            $scope.refresh();
        }

        $scope.doEdit = function(usr) {
            $scope.curUsr = User.get({userId:usr.id});
            $scope.dlgState=true;
        }

        $scope.submitDialog = function() {
            $scope.curUsr.$save();
            $scope.dlgState=false;
            $scope.refresh();
        }

        //initialization code
        $scope.dlgState = false;
        $scope.refresh();
        $scope.curUsr=new User();

}

function eventAdmin($scope,$resource,$window) {
	$scope.eventColumnDefs = [
            { "mDataProp": "what", "aTargets":[0] },
            { "mDataProp": "where", "aTargets":[1] },
            { "mDataProp": "when", "aTargets":[2] },
            new actButtons("tid")
        ];

	var Event = $resource('/admin/trainings/:evtId',{evtId:'@tid'});

	function refresh() {
            Event.query(function(data) {$scope.events=data;});
       }

        $scope.doDel = function(evt) {
            if($window.confirm(evt.what + " (" + evt.where +") wirklich löschen?")) {
               Event.remove({evtId:evt.tid});
            }
            refresh();
        };

        $scope.doEdit = function(evt) {
            $scope.curEvt = Event.get({evtId:evt.tid});
            $scope.curEvt.when = Date.parse($scope.curEvt.when);
            $scope.dlgState=true;
        };

       $scope.showDlg = function() {
           $scope.curEvt=new Event();
           $scope.curEvt.when = new Date();
           $scope.dlgState = true;
       }

       $scope.submitDlg = function() {
           $scope.curEvt.$save();
           $scope.dlgState=false;
           refresh();
       }

        //init
        $scope.dlgState = false;
        refresh();
        $scope.curEvt = new Event();
        $scope.curEvt.when = new Date();
}

function commentAdmin($scope,$resource,$window) {
	$scope.commentColumnDefs = [
            { "mDataProp": "tid", "aTargets":[0] },
            { "mDataProp": "autor", "aTargets":[1] },
            { "mDataProp": "time", "aTargets":[2] },
            { "mDataProp": "msg", "aTargets":[3] },
             new actButtons("id")
        ];

        var Comment = $resource('/admin/comments/:cmtId',{cmtId:'@id'});

        function refresh() {
            Comment.query(function(data) {$scope.comments=data;});
        }

        $scope.doDel = function(cmt) {
            if($window.confirm("Kommentar wirklich löschen?")) {
               Comment.remove({cmtId:cmt.id});
            }
            refresh();
        };

        $scope.doEdit = function(cmt) {
            $scope.curCmt = Comment.get({cmtId:cmt.id});
            $scope.dlgState=true;
        };

        $scope.submitDlg = function() {
           $scope.curCmt.$save();
           $scope.dlgState=false;
           refresh();
       }

        //init
        $scope.dlgState = false;
        refresh();
        $scope.curCmt = new Comment();
}
<commit_msg>fixed  saving and updating Signed-off-by:h0ru5 <johannes.hund@gmail.com><commit_after>angular.module("adminPanel",["myTable","ngResource","jqDialog","addButton","ui"]);

function actButtons(_mData) {
      this.aTargets=[-1];
      this.mData=_mData;
      this.fnCreatedCell=function (nTd, sData, oData, iRow, iCol) {
		butDel = $("<button>delete</button>").button({
        	    text:false,
	            icons: {
	                primary: "ui-icon-trash"
	            }
	        })
	        .on("click",function() {
                            myscope = angular.element(nTd).scope().doDel(oData);
        	});

                butEdit = $("<button>edit</button>").button({
        	    text:false,
	            icons: {
	                primary: "ui-icon-wrench"
	            }
	        })
	        .on("click",function() {
                            myscope = angular.element(nTd).scope().doEdit(oData);
        	});

        	$(nTd).empty().prepend(butDel).prepend(butEdit);
      }
}

function userAdmin($scope,$window,$resource) {
	var User = $resource('/admin/users/:userId',{userId:'@id'});

        $scope.userColumnDefs = [
            { "mData": "name", "aTargets":[0] },
            { "mData": "email", "aTargets":[1] },
            new actButtons("id")
        ];

        $scope.showDlg = function() {
            $scope.curUsr = new User();
            $scope.dlgState=true;
        }

        $scope.hideDlg = function() {
            $scope.dlgState=false;
            $scope.refresh();
        }

        $scope.refresh =function() {
            User.query(function(data) {$scope.users=data; });
          if(!$scope.$$phase) {
                $scope.$digest();
            }
        }

        $scope.doDel = function(usr) {
            if($window.confirm(usr.name + " wirklich löschen?")) {
                User.remove({userId:usr.id});
            }
            $scope.refresh();
        }

        $scope.doEdit = function(usr) {
            $scope.curUsr = User.get({userId:usr.id});
            $scope.dlgState=true;
        }

        $scope.submitDlg = function() {
            $scope.curUsr.$save();
            $scope.dlgState=false;
            $scope.refresh();
        }

        //initialization code
        $scope.dlgState = false;
        $scope.refresh();
        $scope.curUsr=new User();

}

function eventAdmin($scope,$resource,$window) {
	$scope.eventColumnDefs = [
            { "mDataProp": "what", "aTargets":[0] },
            { "mDataProp": "where", "aTargets":[1] },
            { "mDataProp": "when", "aTargets":[2] },
            new actButtons("tid")
        ];

	var Event = $resource('/admin/trainings/:evtId',{evtId:'@tid'});

	function refresh() {
            Event.query(function(data) {$scope.events=data;});
       }

        $scope.doDel = function(evt) {
            if($window.confirm(evt.what + " (" + evt.where +") wirklich löschen?")) {
               Event.remove({evtId:evt.tid});
            }
            refresh();
        };

        $scope.doEdit = function(evt) {
            $scope.curEvt = Event.get({evtId:evt.tid});
            $scope.curEvt.when = Date.parse($scope.curEvt.when);
            $scope.dlgState=true;
        };

       $scope.showDlg = function() {
           $scope.curEvt=new Event();
           $scope.curEvt.when = new Date();
           $scope.dlgState = true;
       }

       $scope.submitDlg = function() {
           $scope.curEvt.$save();
           $scope.dlgState=false;
           refresh();
       }

        //init
        $scope.dlgState = false;
        refresh();
        $scope.curEvt = new Event();
        $scope.curEvt.when = new Date();
}

function commentAdmin($scope,$resource,$window) {
	$scope.commentColumnDefs = [
            { "mDataProp": "tid", "aTargets":[0] },
            { "mDataProp": "autor", "aTargets":[1] },
            { "mDataProp": "time", "aTargets":[2] },
            { "mDataProp": "msg", "aTargets":[3] },
             new actButtons("id")
        ];

        var Comment = $resource('/admin/comments/:cmtId',{cmtId:'@id'});

        function refresh() {
            Comment.query(function(data) {$scope.comments=data;});
        }

        $scope.doDel = function(cmt) {
            if($window.confirm("Kommentar wirklich löschen?")) {
               Comment.remove({cmtId:cmt.id});
            }
            refresh();
        };

        $scope.doEdit = function(cmt) {
            $scope.curCmt = Comment.get({cmtId:cmt.id});
            $scope.dlgState=true;
        };

        $scope.submitDlg = function() {
           $scope.curCmt.$save();
           $scope.dlgState=false;
           refresh();
       }

        //init
        $scope.dlgState = false;
        refresh();
        $scope.curCmt = new Comment();
}
<|endoftext|>


<commit_before>import { test, module } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, click, currentURL } from '@ember/test-helpers';
import { find } from '@ember/test-helpers';

module('Acceptance | All Public Pages', function(hooks) {
  setupApplicationTest(hooks);

  // test('visit every Docs page in order', async function(assert) {
  //   let urls = await keepClickingNext('/docs', '.doc-page-nav-link-next');
  //   assert.equal(urls.length, 15);
  // });

  // test('visit every Cookbook page in order', async function(assert) {
  //   let urls = await keepClickingNext('/cookbook', '.doc-page-nav-link-next');
  //   assert.equal(urls.length, 6);
  // });

  test('visit /addons', async function(assert) {
    await visit('/addons');
    assert.equal('/addons', currentURL());
  });
});

async function keepClickingNext(initialUrl, nextLinkSelector) {
  let seenURLs = Object.create(null);
  await visit(initialUrl);
  let nextLink;
  do {
    let url = currentURL();
    if (seenURLs[url]) {
      throw new Error('page visitor detected a loop');
    }
    seenURLs[currentURL()] = true;
    nextLink = find(nextLinkSelector);
    if (nextLink) {
      await click(nextLink);
    }
  } while (nextLink);
  return Object.keys(seenURLs);
}
<commit_msg>Remove unused stuff<commit_after>import { test, module } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, currentURL } from '@ember/test-helpers';

module('Acceptance | All Public Pages', function(hooks) {
  setupApplicationTest(hooks);

  // test('visit every Docs page in order', async function(assert) {
  //   let urls = await keepClickingNext('/docs', '.doc-page-nav-link-next');
  //   assert.equal(urls.length, 15);
  // });

  // test('visit every Cookbook page in order', async function(assert) {
  //   let urls = await keepClickingNext('/cookbook', '.doc-page-nav-link-next');
  //   assert.equal(urls.length, 6);
  // });

  test('visit /addons', async function(assert) {
    await visit('/addons');
    assert.equal('/addons', currentURL());
  });
});

// async function keepClickingNext(initialUrl, nextLinkSelector) {
//   let seenURLs = Object.create(null);
//   await visit(initialUrl);
//   let nextLink;
//   do {
//     let url = currentURL();
//     if (seenURLs[url]) {
//       throw new Error('page visitor detected a loop');
//     }
//     seenURLs[currentURL()] = true;
//     nextLink = find(nextLinkSelector);
//     if (nextLink) {
//       await click(nextLink);
//     }
//   } while (nextLink);
//   return Object.keys(seenURLs);
// }
<|endoftext|>