<commit_before>var LABEL_WIDTH = 245,
	VTX_DIST = 40, // Distance between centers of two consecutive vertices
	VTX_RAD = 4,
	LABEL_OFFSET = 10; // Distance between label and center of vertex

// Translate every vertex (hence entire graphic) by this much
var VTX_TRANS = {x: 0, y: 20};

var canvas = d3.select("#canvas");
var sidePanel = d3.select("#side-panel");

// Overall width of canvas
var WIDTH = canvas.style("width");
WIDTH = +(WIDTH.substring(0, WIDTH.length - 2));

// Set height based on the number of vertices
var HEIGHT = VTX_DIST * Math.max(asoiaf_chars.length, tac_chars.length);
canvas.style("height", HEIGHT);

////////////////// Helper functions //////////////////

// Return absolute coordinates of center of vertex
// Accepts either a vertex object or an ID string
function vertexPos(v) {

	// If v is an ID string, use it to retrieve vertex
	if(v.name == undefined)
		v = canvas.select("#" + v).datum();

	var pos = {
		x: (v.series == "asoiaf" ? LABEL_WIDTH : WIDTH - LABEL_WIDTH) + VTX_TRANS.x,
		y: v.index * VTX_DIST + VTX_TRANS.y
	};
	return pos;
}

// Callback for when a vertex is clicked
function vertexClicked(v) {

	// Hide all edges first
	edges.classed("active", false)
		.html("");

	// Select current vertex & deselect all others
	vertices.classed("selected", function(w) {return w.id == v.id;});

	// Show edges incident to the clicked vertex
	edges.classed("active", function(e) {
			return e.tac == v.id || e.asoiaf == v.id;
		})
		.classed("selected", false);

	// Set mouseover text to name of connected character
	canvas.selectAll(".edge.active")
	  .append("title")
        .html(function(e) {
			var otherV = (v.series == "tac" ? e.asoiaf : e.tac); // ID
			console.log(otherV);
			return canvas.select("#" + otherV).datum().name;
		});

	// Clear the side panel
	sidePanel.select("#instructions").remove();
	sidePanel.selectAll("div").html("");

	showInfo(v, sidePanel.select("#selected-char"));
}

// Fill selection with info from vertex v
function showInfo(v, selection) {

	selection.html("");

	// We will add text whether the image loads or not
	function addText() {
		selection.append("h2")
		    .html(v.name);

		// First look for text in blurbs folder; if not found, use wiki
		d3.text("blurbs/" + v.id, function(error, blurb) {
			if(error == null) {
				selection.append("p").text(blurb.trim());
			}
			else {

				// No blurb found; pull text from wiki

				/* Assume v.wiki_handle is a correctly encoded URL if defined,
				 * e.g. %20 instead of ' '.
				 */
				var wiki_handle = v.wiki_handle;
				if(wiki_handle == undefined)
					wiki_handle = encodeURI(v.name);

				var domain = null;
				var link_url = "http://";
				if(v.series == "tac") {
					domain = "en%2Ewikipedia%2Eorg%2Fw";
					link_url += "en.wikipedia.org/wiki/";
				}
				else {
					domain = "awoiaf%2Ewesteros%2Eorg";
					link_url += "awoiaf.westeros.org/index.php/";
				}
				link_url += wiki_handle;

				url = "wikis.php?domain=" + domain + "&handle=" + wiki_handle;
				var req = new XMLHttpRequest();
				req.open("GET", url, true);

				req.onload = function() {
					var pages = JSON.parse(this.response).query.pages;
					for(var pageid in pages) {
						selection.append("p").html(pages[pageid].extract);
						break; // Only want one page
					}
					selection.append("a")
						.attr("href", link_url)
					    .html("From " + (v.series == "tac" ? "Wikipedia" : "A Wiki of Ice and Fire"));
				};

				req.onerror = function() {
					console.log("Error opening " + url);
				};

				req.send();
			}
		});

	};

	// Check for image file first
	var img_url = "pics/" + v.id + ".jpg";
	var img_req = new XMLHttpRequest();
	img_req.open("HEAD", img_url, true);
	img_req.onload = function() {
        if(this.status == 200 || this.status == 0) // File exists; add the image
		    selection.append("img")
		        .attr("src", img_url);
		addText();
	};
	img_req.onerror = addText;

	img_req.send();
}

function edgeClicked(e) {

	// Deselect other edges and select this one
	edges.classed("selected", function(f) {
			return f.tac == e.tac && f.asoiaf == e.asoiaf;
		});

	// Get the endpoint of e that is NOT the selected vertex
	var otherV = (canvas.select(".vertex.selected").classed("tac") ? e.asoiaf : e.tac); // ID
	otherV = canvas.select("#" + otherV).datum(); // Vertex object

	showInfo(otherV, sidePanel.select("#connected-char"));

	// Show connections between characters in a bulleted list
	var connections = d3.select("#connections").html("");
	connections.append("h2")
		.html("Connections");
	var ul = connections.append("ul");
	d3.text("blurbs/" + e.tac + "-" + e.asoiaf, function(error, blurb) {
			if(error == null) {
				blurb = blurb.split("\n"); // Each newline marks a new bullet
				for(var i = 0; i < blurb.length; i++) {
					blurb[i] = blurb[i].trim();
					if(blurb[i].length == 0) // Skip empty lines
						continue;
					ul.append("li").html(blurb[i]);
				}
			}
			else
				console.log(error);
		});

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Draw vertices
var vertices = canvas.selectAll(".vertex") // Should be empty
	.data(vertexList)
  .enter().append("g")
	.classed("vertex", true)
	.classed("tac", function(v) {return v.series == "tac";})
	.classed("asoiaf", function(v) {return v.series == "asoiaf";})
	.attr("id", function(v) {return v.id;})
	.attr("transform", function(v) {
			var pos = vertexPos(v);
			return "translate(" + pos.x + "," + pos.y + ")";
		});

vertices.append("circle")
	.attr("r", VTX_RAD);

vertices.append("text")
	.text(function(v) {return v.name;})
	.attr("x", function(v) {return v.series == "asoiaf" ? -LABEL_OFFSET : LABEL_OFFSET;})
	.attr("y", 4);

console.log(vertices);
console.log(canvas.style("height"));

// Draw edges

var edges = canvas.selectAll(".edge"); // Should be empty

// Get edge list from the server
var req = new XMLHttpRequest();
req.open("GET", "edges.php", true);
req.onload = function() {
	if(this.status == 200 || this.status == 0) {
		edgeList = JSON.parse(this.response);
		edges = edges.data(edgeList)
		  .enter().append("line")
			.attr("x1", vertexPos("clemence").x) // Use any TAC character
			.attr("y1", function(e) {return vertexPos(e.tac).y;})
			.attr("x2", vertexPos("sansa").x) // Use any ASOIAF character
			.attr("y2", function(e) {return vertexPos(e.asoiaf).y;})
			.on("click", edgeClicked)
			.classed("edge", true);

		vertices.on("click", vertexClicked);
	}
};
req.send();
<commit_msg>Move code to show connections to helper function<commit_after>var LABEL_WIDTH = 245,
	VTX_DIST = 40, // Distance between centers of two consecutive vertices
	VTX_RAD = 4,
	LABEL_OFFSET = 10; // Distance between label and center of vertex

// Translate every vertex (hence entire graphic) by this much
var VTX_TRANS = {x: 0, y: 20};

var canvas = d3.select("#canvas");
var sidePanel = d3.select("#side-panel");

// Overall width of canvas
var WIDTH = canvas.style("width");
WIDTH = +(WIDTH.substring(0, WIDTH.length - 2));

// Set height based on the number of vertices
var HEIGHT = VTX_DIST * Math.max(asoiaf_chars.length, tac_chars.length);
canvas.style("height", HEIGHT);

////////////////// Helper functions //////////////////

// Return absolute coordinates of center of vertex
// Accepts either a vertex object or an ID string
function vertexPos(v) {

	// If v is an ID string, use it to retrieve vertex
	if(v.name == undefined)
		v = canvas.select("#" + v).datum();

	var pos = {
		x: (v.series == "asoiaf" ? LABEL_WIDTH : WIDTH - LABEL_WIDTH) + VTX_TRANS.x,
		y: v.index * VTX_DIST + VTX_TRANS.y
	};
	return pos;
}

// Callback for when a vertex is clicked
function vertexClicked(v) {

	// Hide all edges first
	edges.classed("active", false)
		.html("");

	// Select current vertex & deselect all others
	vertices.classed("selected", function(w) {return w.id == v.id;});

	// Show edges incident to the clicked vertex
	edges.classed("active", function(e) {
			return e.tac == v.id || e.asoiaf == v.id;
		})
		.classed("selected", false);

	// Set mouseover text to name of connected character
	canvas.selectAll(".edge.active")
	  .append("title")
        .html(function(e) {
			var otherV = (v.series == "tac" ? e.asoiaf : e.tac); // ID
			console.log(otherV);
			return canvas.select("#" + otherV).datum().name;
		});

	// Clear the side panel
	sidePanel.select("#instructions").remove();
	sidePanel.selectAll("div").html("");

	showInfo(v, sidePanel.select("#selected-char"));
}

// Fill selection with info from vertex v
function showInfo(v, selection) {

	selection.html("");

	// We will add text whether the image loads or not
	function addText() {
		selection.append("h2")
		    .html(v.name);

		// First look for text in blurbs folder; if not found, use wiki
		d3.text("blurbs/" + v.id, function(error, blurb) {
			if(error == null) {
				selection.append("p").text(blurb.trim());
			}
			else {

				// No blurb found; pull text from wiki

				/* Assume v.wiki_handle is a correctly encoded URL if defined,
				 * e.g. %20 instead of ' '.
				 */
				var wiki_handle = v.wiki_handle;
				if(wiki_handle == undefined)
					wiki_handle = encodeURI(v.name);

				var domain = null;
				var link_url = "http://";
				if(v.series == "tac") {
					domain = "en%2Ewikipedia%2Eorg%2Fw";
					link_url += "en.wikipedia.org/wiki/";
				}
				else {
					domain = "awoiaf%2Ewesteros%2Eorg";
					link_url += "awoiaf.westeros.org/index.php/";
				}
				link_url += wiki_handle;

				url = "wikis.php?domain=" + domain + "&handle=" + wiki_handle;
				var req = new XMLHttpRequest();
				req.open("GET", url, true);

				req.onload = function() {
					var pages = JSON.parse(this.response).query.pages;
					for(var pageid in pages) {
						selection.append("p").html(pages[pageid].extract);
						break; // Only want one page
					}
					selection.append("a")
						.attr("href", link_url)
					    .html("From " + (v.series == "tac" ? "Wikipedia" : "A Wiki of Ice and Fire"));
				};

				req.onerror = function() {
					console.log("Error opening " + url);
				};

				req.send();
			}
		});

	};

	// Check for image file first
	var img_url = "pics/" + v.id + ".jpg";
	var img_req = new XMLHttpRequest();
	img_req.open("HEAD", img_url, true);
	img_req.onload = function() {
        if(this.status == 200 || this.status == 0) // File exists; add the image
		    selection.append("img")
		        .attr("src", img_url);
		addText();
	};
	img_req.onerror = addText;

	img_req.send();
}

function edgeClicked(e) {

	// Deselect other edges and select this one
	edges.classed("selected", function(f) {
			return f.tac == e.tac && f.asoiaf == e.asoiaf;
		});

	// Get the endpoint of e that is NOT the selected vertex
	var otherV = (canvas.select(".vertex.selected").classed("tac") ? e.asoiaf : e.tac); // ID
	otherV = canvas.select("#" + otherV).datum(); // Vertex object

	showInfo(otherV, sidePanel.select("#connected-char"));
	showConnections(e);
}

function showConnections(e) {

	// Show connections between characters in a bulleted list
	var connections = d3.select("#connections").html("");
	connections.append("h2")
		.html("Connections");
	var ul = connections.append("ul");
	d3.text("blurbs/" + e.tac + "-" + e.asoiaf, function(error, blurb) {
			if(error == null) {
				blurb = blurb.split("\n"); // Each newline marks a new bullet
				for(var i = 0; i < blurb.length; i++) {
					blurb[i] = blurb[i].trim();
					if(blurb[i].length == 0) // Skip empty lines
						continue;
					ul.append("li").html(blurb[i]);
				}
			}
			else
				console.log(error);
	});

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Draw vertices
var vertices = canvas.selectAll(".vertex") // Should be empty
	.data(vertexList)
  .enter().append("g")
	.classed("vertex", true)
	.classed("tac", function(v) {return v.series == "tac";})
	.classed("asoiaf", function(v) {return v.series == "asoiaf";})
	.attr("id", function(v) {return v.id;})
	.attr("transform", function(v) {
			var pos = vertexPos(v);
			return "translate(" + pos.x + "," + pos.y + ")";
		});

vertices.append("circle")
	.attr("r", VTX_RAD);

vertices.append("text")
	.text(function(v) {return v.name;})
	.attr("x", function(v) {return v.series == "asoiaf" ? -LABEL_OFFSET : LABEL_OFFSET;})
	.attr("y", 4);

console.log(vertices);
console.log(canvas.style("height"));

// Draw edges

var edges = canvas.selectAll(".edge"); // Should be empty

// Get edge list from the server
var req = new XMLHttpRequest();
req.open("GET", "edges.php", true);
req.onload = function() {
	if(this.status == 200 || this.status == 0) {
		edgeList = JSON.parse(this.response);
		edges = edges.data(edgeList)
		  .enter().append("line")
			.attr("x1", vertexPos("clemence").x) // Use any TAC character
			.attr("y1", function(e) {return vertexPos(e.tac).y;})
			.attr("x2", vertexPos("sansa").x) // Use any ASOIAF character
			.attr("y2", function(e) {return vertexPos(e.asoiaf).y;})
			.on("click", edgeClicked)
			.classed("edge", true);

		vertices.on("click", vertexClicked);
	}
};
req.send();
<|endoftext|>


<commit_before>// Meyda Javascript DSP library
var featureExtractors = {
	"rms": function(input,bufferSize){
		return Math.sqrt(input.reduce(function(last,current){
			return Math.pow(current,2);
		},0)/bufferSize)
	}
}

var Meyda = function(audioContext,callback,feature,bufferSize=256){
	var node = audioContext.createScriptProcessor(bufferSize, 1, 1);
	node.onaudioprocess = function(e) {
		// type float32Array
		var input = e.inputBuffer.getChannelData(0);

		// Convert from float32Array to Array
		input = Array.prototype.slice.call(input);
		callback(featureExtractors[feature](input,bufferSize));
	}
	return node;
}<commit_msg>supports lists of features<commit_after>// Meyda Javascript DSP library
var featureExtractors = {
	"rms": function(input,bufferSize){
		return Math.sqrt(input.reduce(function(last,current){
			return Math.pow(current,2);
		},0)/bufferSize)
	}
}

var Meyda = function(audioContext,callback,feature,bufferSize=256){
	var node = audioContext.createScriptProcessor(bufferSize, 1, 1);
	node.onaudioprocess = function(e) {
		// type float32Array
		var input = e.inputBuffer.getChannelData(0);

		// Convert from float32Array to Array
		input = Array.prototype.slice.call(input);
		if(typeof feature === "object"){
			for (var x = 0; x < feature.length; x++){
				callback(featureExtractors[feature[x]](input,bufferSize));
			}
		}
		else if (typeof feature === "string"){
			callback(featureExtractors[feature](input,bufferSize));
		}
		else{
			throw "Invalid Feature Format";
		}
	}
	return node;
}
<|endoftext|>


<commit_before>/* eslint strict: 0 */
'use strict';

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const Menu = electron.Menu;
const crashReporter = electron.crashReporter;
const shell = electron.shell;
let menu;
let template;
let mainWindow = null;

require('electron-debug')();
crashReporter.start();

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  } else {
    app.quit();
  }
});

app.on('ready', () => {
  var size = electron.screen.getPrimaryDisplay().workAreaSize;
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 900,
    minWidth: 800,
    minHeight: 400,
    frame: true,
    titleBarStyle: 'hidden'
  });

  if (process.env.HOT) {
    mainWindow.loadURL(`file://${__dirname}/app/dev-app.html`);
  } else {
    mainWindow.loadURL(`file://${__dirname}/app/app.html`);
  }

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  if (process.env.NODE_ENV === 'development') {
    mainWindow.openDevTools();
  }

  if (process.platform === 'darwin') {
    template = [];
    menu = Menu.buildFromTemplate(template);
    mainWindow.setMenu(menu);
  }
});
<commit_msg>update the minimum window dimensions to 900 x 450<commit_after>/* eslint strict: 0 */
'use strict';

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const Menu = electron.Menu;
const crashReporter = electron.crashReporter;
const shell = electron.shell;
let menu;
let template;
let mainWindow = null;

require('electron-debug')();
crashReporter.start();

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  } else {
    app.quit();
  }
});

app.on('ready', () => {
  var size = electron.screen.getPrimaryDisplay().workAreaSize;
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 900,
    minWidth: 900,
    minHeight: 450,
    frame: true,
    titleBarStyle: 'hidden'
  });

  if (process.env.HOT) {
    mainWindow.loadURL(`file://${__dirname}/app/dev-app.html`);
  } else {
    mainWindow.loadURL(`file://${__dirname}/app/app.html`);
  }

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  if (process.env.NODE_ENV === 'development') {
    mainWindow.openDevTools();
  }

  if (process.platform === 'darwin') {
    template = [];
    menu = Menu.buildFromTemplate(template);
    mainWindow.setMenu(menu);
  }
});
<|endoftext|>


<commit_before>const svgNamespace = 'http://www.w3.org/2000/svg'

const weakMap = new WeakMap()

const createQuoteError = (problem) => Error(`Quote ${problem}`)
const createAssertionError = (actual, expected) =>
  Error(`Expected ${expected}. Found ${actual}.`)

const resolve = (obj) => {
  if (typeof obj === 'function') {
    let afterUpdate

    obj = obj((cb) => {
      afterUpdate = cb
    })

    obj.afterUpdate = afterUpdate
  }

  return obj
}

const readMeta = (target, meta = {}) => {
  if (!meta._read) {
    Object.assign(meta, weakMap.get(target) ?? {})

    meta._read = true
  }

  return meta
}

const getNextSibling = (current) => current?.nextSibling

const getListener = (key) => (e) => {
  const map = weakMap.get(e.target)

  if (map && map[key]) {
    map[key](e)
  }
}

const morphAttribute = (target, key, value, meta, listeners) => {
  const document = target.ownerDocument
  const remove = value == null || value === false

  if (key.indexOf('on') === 0) {
    readMeta(target, meta)

    if (remove) {
      if (meta[key]) {
        meta[key] = null
      }
    } else {
      meta[key] = value

      if (!listeners.includes(key)) {
        listeners.push(key)

        const type = key.substring(2)

        document.addEventListener(type, getListener(key))
      }
    }
  } else {
    if (remove) {
      target.removeAttribute(key)
    } else {
      const stringified = value === true ? '' : value

      if (target.getAttribute(key) !== stringified) {
        target.setAttribute(key, stringified)
      }
    }

    if (key === 'value' || value === true || value === false) {
      if (target[key] !== value) {
        target[key] = value
      }
    }
  }
}

const morphChild = (
  target,
  childNode,
  next,
  variables,
  isSameView,
  forceAppend,
  listeners
) => {
  const document = target.ownerDocument

  const append = forceAppend || childNode == null

  let replace = false

  let currentChild = childNode

  if (next.type === 'text') {
    if (!append && childNode.nodeType !== 3) {
      replace = true
    }

    if (append || replace) {
      currentChild = document.createTextNode(next.value)
    } else if (childNode.data !== next.value) {
      childNode.data = next.value
    }
  } else {
    const tag = next.tag

    if (
      !append &&
      (childNode.nodeType !== 1 || childNode.nodeName.toLowerCase() !== tag)
    ) {
      replace = true
    }

    if (append || replace) {
      const isSvg = tag === 'svg' || target.namespaceURI === svgNamespace

      currentChild = isSvg
        ? document.createElementNS(svgNamespace, tag)
        : document.createElement(tag)
    }

    if (next.view != null) {
      morphRoot(currentChild, next, listeners)
    } else if (!isSameView || next.dynamic) {
      morph(currentChild, next, variables, isSameView, {}, listeners)
    }
  }

  if (forceAppend && childNode) {
    childNode.before(currentChild)
  } else if (append) {
    target.append(currentChild)
  } else if (replace) {
    childNode.replaceWith(currentChild)
  }

  if (currentChild != null && next.afterUpdate) {
    next.afterUpdate(currentChild)
  }

  return getNextSibling(currentChild)
}

const morph = (target, next, variables, isSameView, meta, listeners) => {
  const attributesLength = next.attributes.length

  if (attributesLength) {
    for (let i = 0, length = attributesLength; i < length; i++) {
      const attribute = next.attributes[i]

      if (!isSameView || attribute.variable) {
        let value = attribute.value

        if (attribute.variable) {
          value = variables[value]
        }

        if (attribute.key) {
          morphAttribute(target, attribute.key, value, meta, listeners)
        } else {
          for (const key of Object.keys(value)) {
            morphAttribute(target, key, value[key], meta, listeners)
          }
        }
      }
    }
  }

  const childrenLength = next.children.length
  let childNode = target.firstChild

  let keys

  let prevKeys

  if (childrenLength) {
    let deopt = !isSameView

    for (let childIndex = 0; childIndex < childrenLength; childIndex++) {
      let child = next.children[childIndex]

      if (!deopt && !child.dynamic && !child.variable) {
        childNode = getNextSibling(childNode)
      } else {
        deopt = true

        if (child.variable) {
          const variableValue = child.value

          child = variables[variableValue]

          if (child?.[Symbol.iterator] == null || typeof child === 'string') {
            child = [child]
          }

          let keyIndex = 0
          let lengthDifference

          for (let grand of child) {
            grand = resolve(grand)

            if (grand == null) grand = ''

            let keysMatch = true

            if (grand.key != null) {
              if (!keys) {
                keys = {}

                readMeta(target, meta)

                prevKeys = meta.keys?.[variableValue] ?? {}
              }

              if (!keys[variableValue]) {
                keys[variableValue] = []
              }

              keys[variableValue].push(grand.key)

              keysMatch = prevKeys[keyIndex] === grand.key

              grand = grand.value

              lengthDifference = child.length - prevKeys.length
            }

            keyIndex++

            if (grand.type == null) {
              grand = {type: 'text', value: grand}
            }

            if (!keysMatch && lengthDifference < 0 && childNode != null) {
              lengthDifference++

              const extraNode = childNode

              childNode = childNode.nextSibling

              extraNode.remove()
            }

            if (isSameView && grand.view != null && !grand.dynamic) {
              childNode = getNextSibling(childNode)
            } else {
              const forceAppend =
                !keysMatch && lengthDifference > 0 && childNode

              if (forceAppend) {
                lengthDifference--

                keyIndex--
              }

              childNode = morphChild(
                target,
                childNode,
                grand,
                variables,
                isSameView,
                forceAppend,
                listeners
              )
            }
          }
        } else {
          childNode = morphChild(
            target,
            childNode,
            child,
            variables,
            isSameView,
            false,
            listeners
          )
        }
      }
    }
  }

  if (keys) {
    meta.keys = keys
  }

  if (childNode) {
    while (childNode.nextSibling) {
      childNode.nextSibling.remove()
    }

    childNode.remove()
  }

  if (meta._read) weakMap.set(target, meta)
}

const morphRoot = (target, next, listeners) => {
  const meta = readMeta(target)

  const isSameView = next.view === 0 || next.view === meta.view

  if (isSameView && next.view != null && !next.dynamic) {
    return
  }

  if (!isSameView) {
    meta.view = next.view
  }

  if (!isSameView || next.dynamic) {
    morph(target, next, next.variables, isSameView, meta, listeners)
  }
}

export const createDomView = (target, view) => {
  const listeners = []

  return (state) => {
    const current = resolve(view(state))

    morphRoot(target, current, listeners)

    if (current.afterUpdate) {
      current.afterUpdate(target)
    }
  }
}

const viewZero = {
  type: 'node',
  view: 0,
  dynamic: false
}

export const skipUpdate = () => viewZero

const valueTrue = {
  type: 'value',
  value: true
}

const END = Symbol('end')

const isSpaceChar = (char) => /\s/.test(char)
const isOfClose = (char) => char === '/' || char === '>' || isSpaceChar(char)
const isOfTag = (char) => !isOfClose(char)
const isOfKey = (char) => char !== '=' && !isOfClose(char)
const isQuoteChar = (char) => char === '"' || char === "'"

const tokenizer = {
  *get(acc, strs, vlength) {
    for (let index = 0, length = strs.length; index < length; index++) {
      const str = strs[index]
      let first = index > 0

      let tag = acc.tag
      let i = 0

      const current = () => str.charAt(i)
      const next = () => str.charAt(i + 1)

      while (current()) {
        if (!tag && current() === '<') {
          let value = ''
          let end = false

          if (next() === '/') {
            end = true

            i++
          }

          while (next() && isOfTag(next())) {
            i++

            value += current()
          }

          yield {
            type: !end ? 'tag' : 'endtag',
            value
          }

          first = false

          tag = value

          i++
        } else if (tag && isSpaceChar(current())) {
          i++
        } else if (tag && current() === '/' && next() === '>') {
          yield* [
            END,
            {
              type: 'endtag',
              value: tag
            },
            END
          ]

          first = false

          tag = false

          i += 2
        } else if (tag && current() === '>') {
          yield END

          first = false

          tag = false

          i++
        } else if (tag && isOfKey(current())) {
          let value = ''

          i--

          while (next() && isOfKey(next())) {
            i++

            value += current()
          }

          yield {
            type: 'key',
            value
          }

          first = false

          if (next() === '=') {
            i++

            let quote = ''
            let value = ''

            if (next() && isQuoteChar(next())) {
              i++

              quote = current()

              while (next() !== quote) {
                if (next()) {
                  i++

                  value += current()
                } else {
                  throw createQuoteError('mismatch')
                }
              }

              i++

              yield {
                type: 'value',
                value
              }
            } else if (next()) {
              throw createQuoteError('expected')
            }
          } else {
            yield valueTrue
          }

          i++
        } else if (!tag) {
          let value = ''

          while (current() && current() !== '<') {
            value += current()

            i++
          }

          let trim = true

          if (!current() && first) {
            trim = false
          }

          if ((!trim && value) || (trim && value.trim())) {
            yield {
              type: 'text',
              value
            }
          }
        }
      }

      acc.tag = tag

      if (index < vlength) {
        yield {
          type: 'variable',
          value: index
        }
      }
    }
  }
}

const parse = (tokens, parent, tag) => {
  const child = {
    tag,
    type: 'node',
    dynamic: false,
    attributes: [],
    children: []
  }

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token === END) {
      break
    } else if (token.type === 'key') {
      const next = tokens.next()?.value

      if (next.type === 'value') {
        child.attributes.push({key: token.value, value: next.value})
      } else {
        const value = next.value

        child.dynamic = true

        child.attributes.push({
          key: token.value,
          variable: true,
          value
        })
      }
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.attributes.push({
        key: false,
        variable: true,
        value: token.value
      })
    }
  }

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'endtag' && token.value === child.tag) {
      break
    } else if (token.type === 'tag') {
      const dynamic = parse(tokens, child, token.value)

      child.dynamic = child.dynamic || dynamic
    } else if (token.type === 'text') {
      child.children.push({
        type: 'text',
        value: token.value
      })
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.children.push({
        type: 'variable',
        variable: true,
        value: token.value
      })
    }
  }

  parent.children.push(child)

  return child.dynamic
}

let view = 1

const toTemplate = (strs, vlength) => {
  const acc = {
    tag: false
  }

  const tokens = tokenizer.get(acc, strs, vlength)

  const children = []

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'tag') {
      parse(tokens, {children}, token.value)
    } else if (token.type === 'text') {
      children.push({value: token.value})
    }
  }

  if (children.length !== 1) {
    throw createAssertionError(children.length, 1)
  } else if (children[0].type !== 'node') {
    throw createAssertionError(children[0].type, "'node'")
  }

  children[0].view = view++

  return children[0]
}

export const html = (strs, ...variables) => {
  let result = weakMap.get(strs)

  if (!result) {
    result = toTemplate(strs, variables.length)

    weakMap.set(strs, result)
  }

  return Object.assign({variables}, result)
}

export const createApp = (state) => {
  let viewCalled = false
  let view

  const app = {
    render(v) {
      view = v

      viewCalled = false

      return Promise.resolve().then(() => {
        if (!viewCalled) {
          viewCalled = true

          view(state)
        }
      })
    },
    commit(arg) {
      if (typeof arg === 'function') {
        state = arg(state) ?? state
      } else {
        state = arg
      }

      viewCalled = true

      if (view != null) {
        view(state)
      }
    }
  }

  return app
}
<commit_msg>Fix null return<commit_after>const svgNamespace = 'http://www.w3.org/2000/svg'

const weakMap = new WeakMap()

const createQuoteError = (problem) => Error(`Quote ${problem}`)
const createAssertionError = (actual, expected) =>
  Error(`Expected ${expected}. Found ${actual}.`)

const resolve = (obj) => {
  if (typeof obj === 'function') {
    let afterUpdate

    obj = obj((cb) => {
      afterUpdate = cb
    })

    if (obj) obj.afterUpdate = afterUpdate
  }

  return obj
}

const readMeta = (target, meta = {}) => {
  if (!meta._read) {
    Object.assign(meta, weakMap.get(target) ?? {})

    meta._read = true
  }

  return meta
}

const getNextSibling = (current) => current?.nextSibling

const getListener = (key) => (e) => {
  const map = weakMap.get(e.target)

  if (map && map[key]) {
    map[key](e)
  }
}

const morphAttribute = (target, key, value, meta, listeners) => {
  const document = target.ownerDocument
  const remove = value == null || value === false

  if (key.indexOf('on') === 0) {
    readMeta(target, meta)

    if (remove) {
      if (meta[key]) {
        meta[key] = null
      }
    } else {
      meta[key] = value

      if (!listeners.includes(key)) {
        listeners.push(key)

        const type = key.substring(2)

        document.addEventListener(type, getListener(key))
      }
    }
  } else {
    if (remove) {
      target.removeAttribute(key)
    } else {
      const stringified = value === true ? '' : value

      if (target.getAttribute(key) !== stringified) {
        target.setAttribute(key, stringified)
      }
    }

    if (key === 'value' || value === true || value === false) {
      if (target[key] !== value) {
        target[key] = value
      }
    }
  }
}

const morphChild = (
  target,
  childNode,
  next,
  variables,
  isSameView,
  forceAppend,
  listeners
) => {
  const document = target.ownerDocument

  const append = forceAppend || childNode == null

  let replace = false

  let currentChild = childNode

  if (next.type === 'text') {
    if (!append && childNode.nodeType !== 3) {
      replace = true
    }

    if (append || replace) {
      currentChild = document.createTextNode(next.value)
    } else if (childNode.data !== next.value) {
      childNode.data = next.value
    }
  } else {
    const tag = next.tag

    if (
      !append &&
      (childNode.nodeType !== 1 || childNode.nodeName.toLowerCase() !== tag)
    ) {
      replace = true
    }

    if (append || replace) {
      const isSvg = tag === 'svg' || target.namespaceURI === svgNamespace

      currentChild = isSvg
        ? document.createElementNS(svgNamespace, tag)
        : document.createElement(tag)
    }

    if (next.view != null) {
      morphRoot(currentChild, next, listeners)
    } else if (!isSameView || next.dynamic) {
      morph(currentChild, next, variables, isSameView, {}, listeners)
    }
  }

  if (forceAppend && childNode) {
    childNode.before(currentChild)
  } else if (append) {
    target.append(currentChild)
  } else if (replace) {
    childNode.replaceWith(currentChild)
  }

  if (currentChild != null && next.afterUpdate) {
    next.afterUpdate(currentChild)
  }

  return getNextSibling(currentChild)
}

const morph = (target, next, variables, isSameView, meta, listeners) => {
  const attributesLength = next.attributes.length

  if (attributesLength) {
    for (let i = 0, length = attributesLength; i < length; i++) {
      const attribute = next.attributes[i]

      if (!isSameView || attribute.variable) {
        let value = attribute.value

        if (attribute.variable) {
          value = variables[value]
        }

        if (attribute.key) {
          morphAttribute(target, attribute.key, value, meta, listeners)
        } else {
          for (const key of Object.keys(value)) {
            morphAttribute(target, key, value[key], meta, listeners)
          }
        }
      }
    }
  }

  const childrenLength = next.children.length
  let childNode = target.firstChild

  let keys

  let prevKeys

  if (childrenLength) {
    let deopt = !isSameView

    for (let childIndex = 0; childIndex < childrenLength; childIndex++) {
      let child = next.children[childIndex]

      if (!deopt && !child.dynamic && !child.variable) {
        childNode = getNextSibling(childNode)
      } else {
        deopt = true

        if (child.variable) {
          const variableValue = child.value

          child = variables[variableValue]

          if (child?.[Symbol.iterator] == null || typeof child === 'string') {
            child = [child]
          }

          let keyIndex = 0
          let lengthDifference

          for (let grand of child) {
            grand = resolve(grand)

            if (grand == null) grand = ''

            let keysMatch = true

            if (grand.key != null) {
              if (!keys) {
                keys = {}

                readMeta(target, meta)

                prevKeys = meta.keys?.[variableValue] ?? {}
              }

              if (!keys[variableValue]) {
                keys[variableValue] = []
              }

              keys[variableValue].push(grand.key)

              keysMatch = prevKeys[keyIndex] === grand.key

              grand = grand.value

              lengthDifference = child.length - prevKeys.length
            }

            keyIndex++

            if (grand.type == null) {
              grand = {type: 'text', value: grand}
            }

            if (!keysMatch && lengthDifference < 0 && childNode != null) {
              lengthDifference++

              const extraNode = childNode

              childNode = childNode.nextSibling

              extraNode.remove()
            }

            if (isSameView && grand.view != null && !grand.dynamic) {
              childNode = getNextSibling(childNode)
            } else {
              const forceAppend =
                !keysMatch && lengthDifference > 0 && childNode

              if (forceAppend) {
                lengthDifference--

                keyIndex--
              }

              childNode = morphChild(
                target,
                childNode,
                grand,
                variables,
                isSameView,
                forceAppend,
                listeners
              )
            }
          }
        } else {
          childNode = morphChild(
            target,
            childNode,
            child,
            variables,
            isSameView,
            false,
            listeners
          )
        }
      }
    }
  }

  if (keys) {
    meta.keys = keys
  }

  if (childNode) {
    while (childNode.nextSibling) {
      childNode.nextSibling.remove()
    }

    childNode.remove()
  }

  if (meta._read) weakMap.set(target, meta)
}

const morphRoot = (target, next, listeners) => {
  const meta = readMeta(target)

  const isSameView = next.view === 0 || next.view === meta.view

  if (isSameView && next.view != null && !next.dynamic) {
    return
  }

  if (!isSameView) {
    meta.view = next.view
  }

  if (!isSameView || next.dynamic) {
    morph(target, next, next.variables, isSameView, meta, listeners)
  }
}

export const createDomView = (target, view) => {
  const listeners = []

  return (state) => {
    const current = resolve(view(state))

    morphRoot(target, current, listeners)

    if (current.afterUpdate) {
      current.afterUpdate(target)
    }
  }
}

const viewZero = {
  type: 'node',
  view: 0,
  dynamic: false
}

export const skipUpdate = () => viewZero

const valueTrue = {
  type: 'value',
  value: true
}

const END = Symbol('end')

const isSpaceChar = (char) => /\s/.test(char)
const isOfClose = (char) => char === '/' || char === '>' || isSpaceChar(char)
const isOfTag = (char) => !isOfClose(char)
const isOfKey = (char) => char !== '=' && !isOfClose(char)
const isQuoteChar = (char) => char === '"' || char === "'"

const tokenizer = {
  *get(acc, strs, vlength) {
    for (let index = 0, length = strs.length; index < length; index++) {
      const str = strs[index]
      let first = index > 0

      let tag = acc.tag
      let i = 0

      const current = () => str.charAt(i)
      const next = () => str.charAt(i + 1)

      while (current()) {
        if (!tag && current() === '<') {
          let value = ''
          let end = false

          if (next() === '/') {
            end = true

            i++
          }

          while (next() && isOfTag(next())) {
            i++

            value += current()
          }

          yield {
            type: !end ? 'tag' : 'endtag',
            value
          }

          first = false

          tag = value

          i++
        } else if (tag && isSpaceChar(current())) {
          i++
        } else if (tag && current() === '/' && next() === '>') {
          yield* [
            END,
            {
              type: 'endtag',
              value: tag
            },
            END
          ]

          first = false

          tag = false

          i += 2
        } else if (tag && current() === '>') {
          yield END

          first = false

          tag = false

          i++
        } else if (tag && isOfKey(current())) {
          let value = ''

          i--

          while (next() && isOfKey(next())) {
            i++

            value += current()
          }

          yield {
            type: 'key',
            value
          }

          first = false

          if (next() === '=') {
            i++

            let quote = ''
            let value = ''

            if (next() && isQuoteChar(next())) {
              i++

              quote = current()

              while (next() !== quote) {
                if (next()) {
                  i++

                  value += current()
                } else {
                  throw createQuoteError('mismatch')
                }
              }

              i++

              yield {
                type: 'value',
                value
              }
            } else if (next()) {
              throw createQuoteError('expected')
            }
          } else {
            yield valueTrue
          }

          i++
        } else if (!tag) {
          let value = ''

          while (current() && current() !== '<') {
            value += current()

            i++
          }

          let trim = true

          if (!current() && first) {
            trim = false
          }

          if ((!trim && value) || (trim && value.trim())) {
            yield {
              type: 'text',
              value
            }
          }
        }
      }

      acc.tag = tag

      if (index < vlength) {
        yield {
          type: 'variable',
          value: index
        }
      }
    }
  }
}

const parse = (tokens, parent, tag) => {
  const child = {
    tag,
    type: 'node',
    dynamic: false,
    attributes: [],
    children: []
  }

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token === END) {
      break
    } else if (token.type === 'key') {
      const next = tokens.next()?.value

      if (next.type === 'value') {
        child.attributes.push({key: token.value, value: next.value})
      } else {
        const value = next.value

        child.dynamic = true

        child.attributes.push({
          key: token.value,
          variable: true,
          value
        })
      }
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.attributes.push({
        key: false,
        variable: true,
        value: token.value
      })
    }
  }

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'endtag' && token.value === child.tag) {
      break
    } else if (token.type === 'tag') {
      const dynamic = parse(tokens, child, token.value)

      child.dynamic = child.dynamic || dynamic
    } else if (token.type === 'text') {
      child.children.push({
        type: 'text',
        value: token.value
      })
    } else if (token.type === 'variable') {
      child.dynamic = true

      child.children.push({
        type: 'variable',
        variable: true,
        value: token.value
      })
    }
  }

  parent.children.push(child)

  return child.dynamic
}

let view = 1

const toTemplate = (strs, vlength) => {
  const acc = {
    tag: false
  }

  const tokens = tokenizer.get(acc, strs, vlength)

  const children = []

  let current

  for (;;) {
    current = tokens.next()

    if (current.done) break

    const token = current.value

    if (token.type === 'tag') {
      parse(tokens, {children}, token.value)
    } else if (token.type === 'text') {
      children.push({value: token.value})
    }
  }

  if (children.length !== 1) {
    throw createAssertionError(children.length, 1)
  } else if (children[0].type !== 'node') {
    throw createAssertionError(children[0].type, "'node'")
  }

  children[0].view = view++

  return children[0]
}

export const html = (strs, ...variables) => {
  let result = weakMap.get(strs)

  if (!result) {
    result = toTemplate(strs, variables.length)

    weakMap.set(strs, result)
  }

  return Object.assign({variables}, result)
}

export const createApp = (state) => {
  let viewCalled = false
  let view

  const app = {
    render(v) {
      view = v

      viewCalled = false

      return Promise.resolve().then(() => {
        if (!viewCalled) {
          viewCalled = true

          view(state)
        }
      })
    },
    commit(arg) {
      if (typeof arg === 'function') {
        state = arg(state) ?? state
      } else {
        state = arg
      }

      viewCalled = true

      if (view != null) {
        view(state)
      }
    }
  }

  return app
}
<|endoftext|>


<commit_before>//Import Modules
require('prototype.spawn')();
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepairer = require('role.repairer');
var roleWallRepairer = require('role.wallrepairer');

module.exports.loop = function () {
        var tower = Game.getObjectById('577c54de60a6481721b4c1ba');
        if(tower) {
        //var closestDamagedStructure = tower.pos.findClosestByRange(FIND_STRUCTURES, {
        //    filter: (structure) => structure.hits < structure.hitsMax
        //});
        //if(closestDamagedStructure) {
        //    tower.repair(closestDamagedStructure);
        //}
        var closestHostile = tower.pos.findClosestByRange(FIND_HOSTILE_CREEPS);
        if(closestHostile) {
            tower.attack(closestHostile);
        }
    }
    // clear memory
    for (let name in Memory.creeps) {
        if (Game.creeps[name] == undefined) {
            delete Memory.creeps[name];
        }
    }
    //for every creep name in game.creeps
    for (let name in Game.creeps) {
        // get the creep object
        var creep = Game.creeps[name];

        //if creep is harvester, call harvester script
        if (creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        // if creep is upgrader, call upgrader script
        else if (creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        // if creep is builder, call builder script
        else if (creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
        // if creep is repairer, call repairer script
        else if (creep.memory.role == 'repairer') {
            roleRepairer.run(creep);
        }
                // if creep is wallrepairer, call repairer script
        else if (creep.memory.role == 'wallrepairer') {
            roleWallRepairer.run(creep);
        }
    }

    var minimumNumberOfHarvesters = 5;
    var minimumNumberOfUpgraders = 1;
    var minimumNumberOfBuilders = 1;
    var minimumNumberOfRepairers = 2;
    var minimumNumberOfWallRepairers = 1;

    var maximumNumberOfBuilders = 10;

    var numberOfHarvesters = _.sum(Game.creeps, (c) => c.memory.role == 'harvester');
    var numberOfUpgraders = _.sum(Game.creeps, (c) => c.memory.role == 'upgrader');
    var numberOfBuilders = _.sum(Game.creeps, (c) => c.memory.role == 'builder');
    var numberOfRepairers = _.sum(Game.creeps, (c) => c.memory.role == 'repairer');
    var numberOfWallRepairers = _.sum(Game.creeps, (c) => c.memory.role == 'wallrepairer');

    var energy = Game.spawns.Spawn1.room.energyCapacityAvailable;
    var name = undefined;

    if (numberOfHarvesters < minimumNumberOfHarvesters) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'harvester');
            if (name == ERR_NOT_ENOUGH_ENERGY && numberOfHarvesters == 0) {
                name = Game.spawns.Spawn1.createCustomCreep(
                    Game.spawns.Spawn1.room.energyAvailable, 'harvester');
        }
    }
    else if (numberOfUpgraders < minimumNumberOfUpgraders) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'upgrader');
    }
    else if (numberOfRepairers < minimumNumberOfRepairers) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'repairer');
    }
    else if (numberOfWallRepairers < minimumNumberOfWallRepairers) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'wallrepairer');
    }
    else if (numberOfBuilders < minimumNumberOfBuilders) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'builder');
    }
    else if (numberOfBuilders < maximumNumberOfBuilders){
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'builder');
    }
    if (!(name < 0)) {
        console.log("Spawned new creep: " + name );
    }
};
<commit_msg>Turned on tower repair for ramparts that have less than 500k hp<commit_after>//Import Modules
require('prototype.spawn')();
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepairer = require('role.repairer');
var roleWallRepairer = require('role.wallrepairer');

module.exports.loop = function () {
        var tower = Game.getObjectById('577c54de60a6481721b4c1ba');
        if(tower) {
        var closestDamagedStructure = tower.pos.findClosestByRange(FIND_STRUCTURES, {
            filter: (structure) => structure.hits < 500000 && (structure).structureType == STRUCTURE_RAMPART
        });
        if(closestDamagedStructure) {
            tower.repair(closestDamagedStructure);
        }
        var closestHostile = tower.pos.findClosestByRange(FIND_HOSTILE_CREEPS);
        if(closestHostile) {
            tower.attack(closestHostile);
        }
    }
    // clear memory
    for (let name in Memory.creeps) {
        if (Game.creeps[name] == undefined) {
            delete Memory.creeps[name];
        }
    }
    //for every creep name in game.creeps
    for (let name in Game.creeps) {
        // get the creep object
        var creep = Game.creeps[name];

        //if creep is harvester, call harvester script
        if (creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        // if creep is upgrader, call upgrader script
        else if (creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        // if creep is builder, call builder script
        else if (creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
        // if creep is repairer, call repairer script
        else if (creep.memory.role == 'repairer') {
            roleRepairer.run(creep);
        }
                // if creep is wallrepairer, call repairer script
        else if (creep.memory.role == 'wallrepairer') {
            roleWallRepairer.run(creep);
        }
    }

    var minimumNumberOfHarvesters = 5;
    var minimumNumberOfUpgraders = 1;
    var minimumNumberOfBuilders = 1;
    var minimumNumberOfRepairers = 2;
    var minimumNumberOfWallRepairers = 1;

    var maximumNumberOfBuilders = 10;

    var numberOfHarvesters = _.sum(Game.creeps, (c) => c.memory.role == 'harvester');
    var numberOfUpgraders = _.sum(Game.creeps, (c) => c.memory.role == 'upgrader');
    var numberOfBuilders = _.sum(Game.creeps, (c) => c.memory.role == 'builder');
    var numberOfRepairers = _.sum(Game.creeps, (c) => c.memory.role == 'repairer');
    var numberOfWallRepairers = _.sum(Game.creeps, (c) => c.memory.role == 'wallrepairer');

    var energy = Game.spawns.Spawn1.room.energyCapacityAvailable;
    var name = undefined;

    if (numberOfHarvesters < minimumNumberOfHarvesters) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'harvester');
            if (name == ERR_NOT_ENOUGH_ENERGY && numberOfHarvesters == 0) {
                name = Game.spawns.Spawn1.createCustomCreep(
                    Game.spawns.Spawn1.room.energyAvailable, 'harvester');
        }
    }
    else if (numberOfUpgraders < minimumNumberOfUpgraders) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'upgrader');
    }
    else if (numberOfRepairers < minimumNumberOfRepairers) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'repairer');
    }
    else if (numberOfWallRepairers < minimumNumberOfWallRepairers) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'wallrepairer');
    }
    else if (numberOfBuilders < minimumNumberOfBuilders) {
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'builder');
    }
    else if (numberOfBuilders < maximumNumberOfBuilders){
        name = Game.spawns.Spawn1.createCustomCreep(energy, 'builder');
    }
    if (!(name < 0)) {
        console.log("Spawned new creep: " + name );
    }
};
<|endoftext|>


<commit_before>'use strict';

const doc = window.document;

/**
 * Class for building elements and mounting them in the document
 */
class DOM {
  /**
   * Mount an element as a child of target element
   * @param el The element to mount
   * @param [target] The target element to mount an element to. Defaults. to document.body
   * @param [replace] If true, replace the content of target with el. Otherwise,
   * append el to the existing content of target. Defaults to false.
   */
  static mount(el, target = document.body, replace = false) {
    if (replace) {
      target.innerHTML = '';
    }
    target.appendChild(el);
  }

  static render(tagName, attrs) {
    const elem = this.build(tagName).render();
    if (attrs) {
      for (let attr in attrs) {
        elem.setAttribute(attr, attrs[attr]);
      }
    }
    return elem;
  }

  static build(tagName) {
    let id, classes = [], dividers = [], targets = ['#', '.'];

    let idx = 0;
    for (let char of tagName) {
      if (targets.indexOf(char) > -1) {
        dividers.push(idx);
      }
      idx++;
    }

    dividers.sort((a, b) => a - b);

    for (let [idx, d] of dividers.entries()) {
      let symbol = tagName[d];
      if (DOM.isClass(symbol)) {
        if (dividers.length > idx + 1) {
          classes.push(tagName.substring(d + 1, dividers[idx + 1]));
        } else {
          classes.push(tagName.substring(d + 1));
        }
      } else if (DOM.isId(symbol)) {
        if (dividers.length > idx + 1) {
          id = tagName.substring(d + 1, dividers[idx + 1]);
        } else {
          id = tagName.substring(d + 1);
        }
      }
    }

    // Determine actual plain tag name
    if (dividers.length) {
      tagName = tagName.substring(0, dividers[0]);
    }

    let elem = doc.createElement(tagName);

    if (classes.length) {
      for (let c of classes) {
        elem.classList.add(c);
      }
    }

    if (id) {
      elem.id = id;
    }

    return this.builder(elem);
  }

  static isClass(divider) {
    return divider === '.';
  }

  static isId(divider) {
    return divider === '#';
  }

  static builder(elem) {
    return {
      render: () => elem,
      click: this.click.bind(this, elem),
      on: this.on.bind(this, elem),
      withAttrs: this.withAttrs.bind(this, elem),
      withStyle: this.withStyle.bind(this, elem),
      withText: this.withText.bind(this, elem)
    };
  }

  static click(elem, cb) {
    elem.addEventListener('click', cb);
    return this.builder(elem);
  }

  static on(elem, event, cb) {
    elem.addEventListener(event, cb);
    return this.builder(elem);
  }

  static withAttrs(elem, attrs) {
    Object.assign(elem, attrs);
    return this.builder(elem);
  }

  static withStyle(elem, style) {
    Object.assign(elem.style, style);
    return this.builder(elem);
  }

  static withText(elem, text) {
    elem.textContent = text;
    return this.builder(elem);
  }
}

const blue = {
  background: 'navy'
};
const green = {
  background: 'darkgreen'
};
const red = {
  background: 'darkred'
};
const yellow = {
  background: 'yellow'
};
const gray = {
  background: 'gray'
};

const transition = {
  transition: 'background-color .25s ease-in',
  '-webkit-transition': 'background-color .25s ease-in'
};
const tall = {
  height: '200px',
  width: '100px',
  display: 'inline-block',
  margin: '2px'
};
const wide = {
  height: '100px',
  width: '200px',
  display: 'inline-block',
  margin: '2px'
};
const square = {
  height: '150px',
  width: '150px',
  display: 'inline-block',
  margin: 0,
  padding: 0
};

const app = DOM.render('div#app');

const header = DOM.build('div.header')
  .withStyle({ backgroundColor: 'lightgray' })
  .render();

const attrs = {
  href: 'http://google.com',
  target: '_blank'
};

const linkStyle = {
  margin: '5px',
  display: 'inline-block'
};

const links = ['Home', 'About', 'Archive'].map(function(text) {
  const linkContainer = DOM.build('div.link').withStyle(linkStyle).render();
  DOM.mount(
    DOM.build('a').withText(text).withAttrs(attrs).render(),
    linkContainer
  );
  return linkContainer;
});

links.forEach(function(link) {
  DOM.mount(link, header);
});

DOM.mount(header, app);

const spaced = {
  margin: '5px'
};

const container = DOM.render('div#container');
const colors = [blue, green, red, yellow, gray];
for (let i = 0; i < 5; i++) {
  const box = DOM.build('div')
    .withStyle(colors[i])
    .withStyle(square)
    .withStyle(spaced)
    .on('mouseenter', function() {
      this.style.opacity = 0.3;
    })
    .on('mouseleave', function() {
      this.style.opacity = 1;
    })
    .render();

  DOM.mount(box, container);
}

DOM.mount(container, app);

// const els = []
// for (let i = 0; i < 40; i++) {
//   els.push(
//     DOM.build('div.disco')
//       .withStyle(square)
//       .withStyle(transition)
//       .withStyle(red)
//       // .withText('Reed')
//       .render()
//   )
// }
// els.forEach(el => app.appendChild(el))

DOM.mount(app);

// const styles = [red, blue, green, yellow, gray]

// window.setInterval(() => {
//   const divs = document.querySelectorAll('div.disco')
//   for (let d of divs) {
//     Object.assign(
//       d.style,
//       styles[Math.floor(Math.random() * styles.length)],
//       transition
//     )
//   }
// }, 250)
<commit_msg>Rewrite parsing of element creation strings<commit_after>'use strict';

const doc = window.document;

/**
 * Class for building elements and mounting them in the document
 */
class DOM {
  /**
   * Mount an element as a child of target element
   * @param el The element to mount
   * @param [target] The target element to mount an element to. Defaults. to document.body
   * @param [replace] If true, replace the content of target with el. Otherwise,
   * append el to the existing content of target. Defaults to false.
   */
  static mount(el, target = document.body, replace = false) {
    if (replace) {
      target.innerHTML = '';
    }
    target.appendChild(el);
  }

  static render(elemStr, attrs) {
    const elem = DOM.build(elemStr).render();
    if (attrs) {
      for (let attr in attrs) {
        elem.setAttribute(attr, attrs[attr]);
      }
    }
    return elem;
  }

  static parse(elemStr) {
    if (!elemStr.length) {
      throw new Error('Invalid element string: Empty input');
    }

    let parts = elemStr.split(/([#\.][_a-zA-Z0-9-]+)/).filter(p => !!p);
    // console.log('raw parts:', parts);

    if (parts[0].match(/[a-zA-Z]/).index !== 0) {
      throw new Error('Invalid element string: Must start with tag name');
    }

    const tagName = parts.shift().match(/[a-zA-Z]+/)[0];
    let id = parts.find(p => p.startsWith('#'));
    if (id) {
      id = id.substring(1);
    }
    const classes = parts
      .filter(p => p.startsWith('.') && p.substring(1).match(/[_a-zA-Z0-9-]/))
      .map(p => p.substring(1));

    return {
      tagName,
      classes,
      id
    };
  }

  static construct(elemDef) {
    let elem = doc.createElement(elemDef.tagName);

    if (elemDef.classes.length) {
      for (let c of elemDef.classes) {
        elem.classList.add(c);
      }
    }

    if (elemDef.id) {
      elem.id = elemDef.id;
    }

    return elem;
  }

  static build(elemStr) {
    return DOM.builder(DOM.construct(DOM.parse(elemStr)));
  }

  static isClass(divider) {
    return divider === '.';
  }

  static isId(divider) {
    return divider === '#';
  }

  static builder(elem) {
    return {
      render: () => elem,
      click: DOM.click.bind(DOM, elem),
      on: DOM.on.bind(DOM, elem),
      withAttrs: DOM.withAttrs.bind(DOM, elem),
      withStyle: DOM.withStyle.bind(DOM, elem),
      withText: DOM.withText.bind(DOM, elem)
    };
  }

  static click(elem, cb) {
    elem.addEventListener('click', cb);
    return DOM.builder(elem);
  }

  static on(elem, event, cb) {
    elem.addEventListener(event, cb);
    return DOM.builder(elem);
  }

  static withAttrs(elem, attrs) {
    Object.assign(elem, attrs);
    return DOM.builder(elem);
  }

  static withStyle(elem, style) {
    Object.assign(elem.style, style);
    return DOM.builder(elem);
  }

  static withText(elem, text) {
    elem.textContent = text;
    return DOM.builder(elem);
  }
}

const blue = {
  background: 'navy'
};
const green = {
  background: 'darkgreen'
};
const red = {
  background: 'darkred'
};
const yellow = {
  background: 'yellow'
};
const gray = {
  background: 'gray'
};

const transition = {
  transition: 'background-color .25s ease-in',
  '-webkit-transition': 'background-color .25s ease-in'
};
const tall = {
  height: '200px',
  width: '100px',
  display: 'inline-block',
  margin: '2px'
};
const wide = {
  height: '100px',
  width: '200px',
  display: 'inline-block',
  margin: '2px'
};
const square = {
  height: '150px',
  width: '150px',
  display: 'inline-block',
  margin: 0,
  padding: 0
};

const app = DOM.render('div#app');

const header = DOM.build('div.header')
  .withStyle({ backgroundColor: 'lightgray' })
  .render();

const attrs = {
  href: 'http://google.com',
  target: '_blank'
};

const linkStyle = {
  margin: '5px',
  display: 'inline-block'
};

const links = ['Home', 'About', 'Archive'].map(function(text) {
  const linkContainer = DOM.build('div.link').withStyle(linkStyle).render();
  DOM.mount(
    DOM.build('a').withText(text).withAttrs(attrs).render(),
    linkContainer
  );
  return linkContainer;
});

links.forEach(function(link) {
  DOM.mount(link, header);
});

DOM.mount(header, app);

const spaced = {
  margin: '5px'
};

const container = DOM.render('div#container');
const colors = [blue, green, red, yellow, gray];
for (let i = 0; i < 5; i++) {
  const box = DOM.build('div')
    .withStyle(colors[i])
    .withStyle(square)
    .withStyle(spaced)
    .on('mouseenter', function() {
      this.style.opacity = 0.3;
    })
    .on('mouseleave', function() {
      this.style.opacity = 1;
    })
    .render();

  DOM.mount(box, container);
}

DOM.mount(container, app);

// const els = []
// for (let i = 0; i < 40; i++) {
//   els.push(
//     DOM.build('div.disco')
//       .withStyle(square)
//       .withStyle(transition)
//       .withStyle(red)
//       // .withText('Reed')
//       .render()
//   )
// }
// els.forEach(el => app.appendChild(el))

DOM.mount(app);

// const styles = [red, blue, green, yellow, gray]

// window.setInterval(() => {
//   const divs = document.querySelectorAll('div.disco')
//   for (let d of divs) {
//     Object.assign(
//       d.style,
//       styles[Math.floor(Math.random() * styles.length)],
//       transition
//     )
//   }
// }, 250)
<|endoftext|>


<commit_before>/**
 * Created by asher on 2/07/16.
 */
console.log("Starting up...");
var express = require('express'),
    http = require('http'),
    https = require('https'),
    app = express(),
    port = process.env.PORT || process.argv[2] || 8060,
    base = ".proxy.asherfoster.com";

app.get('/', function(req, res){
    var url = req.query.url,
        host = req.headers.host.split(base).join();
    console.log(host);
    // if(url){
    //     var protocol = url.split(':')[0];
    //     if(protocol === 'http' || protocol === 'https'){
    //         var body = "";
    //         (protocol === 'https' ? https : http).get(url, function(resp){
    //             resp.on('data', function(chunk) {
    //                 body += chunk;
    //             });
    //             resp.on('end', function() {
    //                 res.send(body);
    //             });
    //         });
    //     }else res.send(400).send("Must be a HTTP or HTTPS URL");
    // }else res.status(400).send("Must have URL query field");
});
app.listen(port);
console.log("Ready on port "+port);<commit_msg>This is getting really complicated<commit_after>/**
 * Created by asher on 2/07/16.
 */
console.log("Starting up...");
var express = require('express'),
    http = require('http'),
    https = require('https'),
    app = express(),
    port = process.env.PORT || process.argv[2] || 8060,
    base = ".proxy.asherfoster.com";

app.use(function(req, res){
    var host = req.headers.host.split(base)[0];
    console.log(host + "/" + req.url);
    // if(url){
    //     var protocol = url.split(':')[0];
    //     if(protocol === 'http' || protocol === 'https'){
    //         var body = "";
    //         (protocol === 'https' ? https : http).get(url, function(resp){
    //             resp.on('data', function(chunk) {
    //                 body += chunk;
    //             });
    //             resp.on('end', function() {
    //                 res.send(body);
    //             });
    //         });
    //     }else res.send(400).send("Must be a HTTP or HTTPS URL");
    // }else res.status(400).send("Must have URL query field");
});
app.listen(port);
console.log("Ready on port "+port);<|endoftext|>


<commit_before>/*
 Copyright 2018-present the GitHub PR Descriptions in Squash and Merge authors. All Rights Reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 GitHub loads its webpages using pjax, meaning we never really get a full document-did-load
 event firing after the initial load. This means if you open the pull requests page and then
 click a pull request, this js file is only executed when you load the initial pull requests page.
 Because the DOM is changing dynamically and we don't have a way to register live events to DOM
 elements as they're created, we need to poll the page for any squash-and-merge buttons.
 */
(function() {
  /*
   On PR pages, finds a "Squash and Merge" button and adds a click event listener that replaces
   the commit description with the PR description.
   */
  function scanForSquashAndMergeButtons() {
    if (document.location.href.indexOf('/pull/') === -1) {
      return;
    }
    var squashContainer = document.getElementsByClassName('btn-group-squash')[0];
    if (!squashContainer) {
      return;
    }
    var squashButton = squashContainer.querySelector('button[type="submit"]');

    if (squashButton.getAttribute('squashmerge')) {
      return;
    }

    squashButton.addEventListener('click', function() {
      // GitHub populates the commit message with a bit of a delay, so we also need to delay our
      // population of the message.
      setTimeout(function() {
        var mergeMessageField = document.getElementById('merge_message_field');
        var prTextarea = document.getElementsByClassName('comment-form-textarea')[0];
        mergeMessageField.value = prTextarea.value;
      }, 50);
    });
    squashButton.setAttribute('squashmerge', 'true');
  }

  const pollInterval = 1000; // Milliseconds

  /*
   Polls the current page for a squash and merge button.
   */
  function poll() {
    scanForSquashAndMergeButtons();

    setTimeout(poll, pollInterval);
  }

  setTimeout(poll, pollInterval);
})();
<commit_msg>Update main.js (#3)<commit_after>/*
 Copyright 2018-present the GitHub PR Descriptions in Squash and Merge authors. All Rights Reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 GitHub loads its webpages using pjax, meaning we never really get a full document-did-load
 event firing after the initial load. This means if you open the pull requests page and then
 click a pull request, this js file is only executed when you load the initial pull requests page.
 Because the DOM is changing dynamically and we don't have a way to register live events to DOM
 elements as they're created, we need to poll the page for any squash-and-merge buttons.
 */
(function() {
  /*
   On PR pages, finds a "Squash and Merge" button and adds a click event listener that replaces
   the commit description with the PR description.
   */
  function scanForSquashAndMergeButtons() {
    if (document.location.href.indexOf('/pull/') === -1) {
      return;
    }
    var squashContainer = document.getElementsByClassName('btn-group-squash')[0];
    if (!squashContainer) {
      return;
    }
    var squashButton = squashContainer.querySelector('button[data-details-container=".js-merge-pr"]');

    if (squashButton.getAttribute('squashmerge')) {
      return;
    }

    squashButton.addEventListener('click', function() {
      // GitHub populates the commit message with a bit of a delay, so we also need to delay our
      // population of the message.
      setTimeout(function() {
        var mergeMessageField = document.getElementById('merge_message_field');
        var prTextarea = document.getElementsByClassName('comment-form-textarea')[0];
        mergeMessageField.value = prTextarea.value;
      }, 50);
    });
    squashButton.setAttribute('squashmerge', 'true');
  }

  const pollInterval = 1000; // Milliseconds

  /*
   Polls the current page for a squash and merge button.
   */
  function poll() {
    scanForSquashAndMergeButtons();

    setTimeout(poll, pollInterval);
  }

  setTimeout(poll, pollInterval);
})();
<|endoftext|>


<commit_before>var DEBUG = false;

if (DEBUG) {
    console.log('inside of the aminogfx main.js');
}

var binary = require('node-pre-gyp');
var path = require('path');
var binding_path = binary.find(path.resolve(path.join(__dirname,'./package.json')));
var sgtest = require(binding_path);

//detect platform
var OS = 'KLAATU';

if (process.arch == 'arm') {
    OS = 'RPI';
}
if (process.platform == 'darwin') {
    OS ='MAC';
}

var amino_core = require('aminogfx');
var Core = amino_core.Core;
var Shaders = require('./src/shaders.js');
var fs = require('fs');

//Fonts

var fontmap = {};
var defaultFonts = {
    'source': {
        name:'source',
        weights: {
            200: {
                normal: "SourceSansPro-ExtraLight.ttf",
                italic: "SourceSansPro-ExtraLightItalic.ttf"
            },
            300: {
                normal: "SourceSansPro-Light.ttf",
                italic: "SourceSansPro-LightItalic.ttf"
            },
            400: {
                normal: "SourceSansPro-Regular.ttf",
                italic: "SourceSansPro-Italic.ttf"
            },

            600: {
                normal: "SourceSansPro-Semibold.ttf",
                italic: "SourceSansPro-SemiboldItalic.ttf"
            },
            700: {
                normal: "SourceSansPro-Bold.ttf",
                italic: "SourceSansPro-BoldItalic.ttf"
            },
            900: {
                normal: "SourceSansPro-Black.ttf",
                italic: "SourceSansPro-BlackItalic.ttf"
            }
        }
    },
    'awesome': {
        name:'awesome',
        weights: {
            400: {
                normal: "fontawesome-webfont.ttf"
            }
        }
    }
}

var propsHash = {

    //general
    "visible":18,
    "opacity":27,
    "r":5,
    "g":6,
    "b":7,
    "texid":8,
    "w":10,
    "h":11,
    "x":21,
    "y":22,

    //transforms  (use x and y for translate in X and Y)
    "sx":2,
    "sy":3,
    "rz":4,
    "rx":19,
    "ry":20,

    //text
    "text":9,
    "fontSize":12,
    "fontId":28,

    //animation
    "count":29,
    "lerplinear":13,
    "lerpcubicin":14,
    "lerpcubicout":15,
    "lerpprop":16,
    "lerpcubicinout":17,
    "autoreverse":35,

    //geometry
    "geometry":24,
    "filled":25,
    "closed":26,
    "dimension": 36,

    //rectangle texture
    "textureLeft":  30,
    "textureRight": 31,
    "textureTop":   32,
    "textureBottom":33,

    //clipping
    "cliprect": 34

};

function JSFont(desc) {
    this.name = desc.name;
    var reg = desc.weights[400];
    this.desc = desc;
    this.weights = {};
    this.filepaths = {};

    var dir = process.cwd();
    process.chdir(__dirname+'/..'); // chdir such that fonts (and internal shaders) may be found
    var aminodir = __dirname+'/resources/';
    if(desc.path) {
        aminodir = desc.path;
    }
    for(var weight in desc.weights) {
        var filepath = aminodir+desc.weights[weight].normal;
        if(!fs.existsSync(filepath)) {
            console.log("WARNING. File not found",filepath);
            throw new Error();
        }
        this.weights[weight] = Core.getCore().getNative().createNativeFont(filepath);
        this.filepaths[weight] = filepath;
    }
    process.chdir(dir);

    this.getNative = function(size, weight, style) {
        if(this.weights[weight] != undefined) {
            return this.weights[weight];
        }
        console.log("ERROR. COULDN'T find the native for " + size + " " + weight + " " + style);
        return this.weights[400];
    }

    /** @func calcStringWidth(string, size)  returns the width of the specified string rendered at the specified size */
    this.calcStringWidth = function(str, size, weight, style) {
        amino.GETCHARWIDTHCOUNT++;
        return amino.sgtest.getCharWidth(str,size,this.getNative(size,weight,style));
    }
    this.getHeight = function(size, weight, style) {
        amino.GETCHARHEIGHTCOUNT++;
        if(size == undefined) {
            throw new Error("SIZE IS UNDEFINED");
        }
        return amino.sgtest.getFontHeight(size, this.getNative(size, weight, style));
    }
    this.getHeightMetrics = function(size, weight, style) {
        if(size == undefined) {
            throw new Error("SIZE IS UNDEFINED");
        }
        return {
            ascender: amino.sgtest.getFontAscender(size, this.getNative(size, weight, style)),
            descender: amino.sgtest.getFontDescender(size, this.getNative(size, weight, style))
        };
    }
}

function JSPropAnim(target,name) {
    this._from = null;
    this._to = null;
    this._duration = 1000;
    this._loop = 1;
    this._delay = 0;
    this._autoreverse = 0;
    this._then_fun = null;

    this.from = function(val) {  this._from = val;        return this;  }
    this.to   = function(val) {  this._to = val;          return this;  }
    this.dur  = function(val) {  this._duration = val;    return this;  }
    this.delay= function(val) {  this._delay = val;       return this;  }
    this.loop = function(val) {  this._loop = val;        return this;  }
    this.then = function(fun) {  this._then_fun = fun;    return this;  }
    this.autoreverse = function(val) { this._autoreverse = val?1:0; return this;  }

    this.start = function() {
        console.log("startin anim");
        var self = this;
        setTimeout(function(){
            console.log("after delay. making it.");
            var nat = Core.getCore().getNative();
            self.handle = nat.createAnim(target.handle, name, self._from,self._to,self._duration);
            console.log("handle is",self.handle);
            nat.updateAnimProperty(self.handle, 'count', self._loop);
            nat.updateAnimProperty(self.handle, 'autoreverse', self._autoreverse);
            nat.updateAnimProperty(self.handle, 'lerpprop', 17); //17 is cubic in out
            Core.getCore().anims.push(self);
        },this._delay);
        return this;
    }

    this.finish = function() {
        if(this._then_fun != null) {
            this._then_fun();
        }
    }

}

var PNG_HEADER = new Buffer([ 137, 80, 78, 71, 13, 10, 26, 10 ]); //PNG Header

var gl_native = {
    createNativeFont: function(path) {  return sgtest.createNativeFont(path, __dirname+'/resources/shaders');  },
    registerFont:function(args) { fontmap[args.name] = new JSFont(args); },
    init: function(core) { return sgtest.init(); },
    startEventLoop : function() {
        if (DEBUG) {
            console.log('starting the event loop');
        }

        var self = this;

        function immediateLoop() {
            try {
                self.tick(Core.getCore());
            } catch (ex) {
                //report
                console.log(ex);
                console.log(ex.stack);
                console.log("EXCEPTION. QUITTING!");
                return;
            }
            self.setImmediate(immediateLoop);
        }
        setTimeout(immediateLoop,1);
    },
    createWindow: function(core,w,h) {
        sgtest.createWindow(w* core.DPIScale,h*core.DPIScale);
        Shaders.init(sgtest,OS);
        fontmap['source']  = new JSFont(defaultFonts['source']);
        fontmap['awesome'] = new JSFont(defaultFonts['awesome']);
        core.defaultFont = fontmap['source'];
        this.rootWrapper = this.createGroup();
        this.updateProperty(this.rootWrapper, "scalex", core.DPIScale);
        this.updateProperty(this.rootWrapper, "scaley", core.DPIScale);
        sgtest.setRoot(this.rootWrapper);
    },
    getFont: function(name) { return fontmap[name]; },
    updateProperty: function(handle, name, value) {
        if(handle == undefined) throw new Error("Can't set a property on an undefined handle!!");
        //console.log('setting', handle, name, propsHash[name], value, typeof value);
        sgtest.updateProperty(handle, propsHash[name], value);
    },
    setRoot: function(handle) { return  sgtest.addNodeToGroup(handle,this.rootWrapper);  },
    tick: function() {
        sgtest.tick();
    },
    setImmediate: function(loop) {
        setImmediate(loop);
    },
//    setEventCallback: function(cb) {   return sgtest.setEventCallback(cb);   },
    setEventCallback: function(cb) {   return sgtest.setEventCallback(function(){
        //console.log("got some stuff",arguments);
        cb(arguments[1]);
    });   },
    createRect: function()  {          return sgtest.createRect();           },
    createGroup: function() {          return sgtest.createGroup();          },
    createPoly: function()  {          return sgtest.createPoly();           },
    createText: function() {           return sgtest.createText();           },
    createGLNode: function(cb)  {      return sgtest.createGLNode(cb);       },
    addNodeToGroup: function(h1,h2) {  return sgtest.addNodeToGroup(h1,h2);  },
    removeNodeFromGroup: function(h1, h2) { return sgtest.removeNodeFromGroup(h1, h2);  },
    loadImage: function(src, cb) {
        var buffer;
        var type;

        //check buffer
        if (Buffer.isBuffer(src)) {
            buffer = src;

            //check PNG
            if (buffer.slice(0, 8).equals(PNG_HEADER)) {
                //PNG
                type = 'png';
            } else {
                //JPEG
                type = 'jpg';
            }
        } else if (typeof src === 'string') {
            //load file (blocking)
            var buffer = fs.readFileSync(src);

            if (!buffer) {
                if (DEBUG) {
                    console.log('File not found: ' + src);
                }

                cb();
                return;
            }

            //check file name
            var name = src.toLowerCase();

            if (name.endsWith('.png')) {
                type = 'png';
            } else if (name.endsWith(".jpg")) {
                type = 'jpg';
            } else {
                if (DEBUG) {
                    console.log('Unsupported file format: ' + src);
                }

                cb();
                return;
            }
        } else {
            if (DEBUG) {
                console.log('Invalid src format!');
            }

            cb();
            return;
        }

        //debug
        if (DEBUG) {
            console.log('loadImage() type=' + type + ' length=' + buffer.length);
        }

        //decode
        var nat = Core.getCore().getNative();

        function bufferToTexture(ibuf) {
            //check error
            if (!ibuf) {
                if (DEBUG) {
                    console.log('could not load image: type='  + type);
                }

                cb();
                return;
            }

            //load texture
            nat.loadBufferToTexture(-1, ibuf.w, ibuf.h, ibuf.bpp, ibuf.buffer, function (texture) {
                cb(texture);
            });
        }

        switch (type) {
            case 'png':
                nat.decodePngBuffer(buffer, bufferToTexture);
                break;

            case 'jpg':
                nat.decodeJpegBuffer(buffer, bufferToTexture);
                break;
        }

    },
    decodePngBuffer: function(fbuf, cb) {  return cb(sgtest.decodePngBuffer(fbuf));  },
    decodeJpegBuffer: function(fbuf, cb) { return cb(sgtest.decodeJpegBuffer(fbuf)); },
    loadBufferToTexture: function(texid, w, h, bpp, buf, cb) { return cb(sgtest.loadBufferToTexture(texid, w,h, bpp, buf)); },
    setWindowSize: function(w,h) { sgtest.setWindowSize(w*Core.getCore().DPIScale,h*Core.getCore().DPIScale); },
    getWindowSize: function(w,h) {
        var dpi = Core.getCore().DPIScale;
        var size = sgtest.getWindowSize(w,h);
        return {
            w: size.w/dpi,
            h: size.h/dpi
        };
    },
    createAnim: function(handle,prop,start,end,dur) {
        if(!propsHash[prop]) throw new Error("invalid native property name",prop);
        return sgtest.createAnim(handle,propsHash[prop],start,end,dur);
    },
    createPropAnim: function(obj,name) { return new JSPropAnim(obj,name); },
    updateAnimProperty: function(handle, prop, type) { return  sgtest.updateAnimProperty(handle, propsHash[prop], type); },
    updateWindowProperty:function(stage,prop,value){
        if(!propsHash[prop]) throw new Error("invalid native property name",prop);
        return sgtest.updateWindowProperty(-1,propsHash[prop],value);
    }
}

exports.input = amino_core.input;
exports.start = function(cb) {
    if(!cb) throw new Error("CB parameter missing to start app");
    Core.setCore(new Core());
    var core = Core.getCore();
    core.native = gl_native;
    amino_core.native = gl_native;
    core.init();
    var stage = Core._core.createStage(600,600);
    stage.fill.watch(function(){
        var color = amino_core.ParseRGBString(stage.fill());
        gl_native.updateWindowProperty(stage,'r',color.r);
        gl_native.updateWindowProperty(stage,'g',color.g);
        gl_native.updateWindowProperty(stage,'b',color.b);
    });
    stage.opacity.watch(function() {
        gl_native.updateWindowProperty(stage,'opacity',stage.opacity());
    });
    //mirror fonts to PureImage
    /*
    var source_font = exports.getRegisteredFonts().source;
    var fnt = PImage.registerFont(source_font.filepaths[400],source_font.name);
    fnt.load(function() {
        cb(Core._core,stage);
        Core._core.start();
    });
    */
    cb(core,stage);
    core.start();
};

exports.makeProps = amino_core.makeProps;

exports.Rect      = amino_core.Rect;
exports.Group     = amino_core.Group;
exports.Circle    = amino_core.Circle;
exports.Polygon   = amino_core.Polygon;
exports.Text      = amino_core.Text;
exports.ImageView = amino_core.ImageView;

exports.input.init(OS);

//exports.PureImageView = amino.primitives.PureImageView;
//exports.ConstraintSolver = require('./src/ConstraintSolver');
<commit_msg>added timeFunc() to animations<commit_after>var DEBUG = false;

if (DEBUG) {
    console.log('inside of the aminogfx main.js');
}

var binary = require('node-pre-gyp');
var path = require('path');
var binding_path = binary.find(path.resolve(path.join(__dirname,'./package.json')));
var sgtest = require(binding_path);

//detect platform
var OS = 'KLAATU';

if (process.arch == 'arm') {
    OS = 'RPI';
}
if (process.platform == 'darwin') {
    OS ='MAC';
}

var amino_core = require('aminogfx');
var Core = amino_core.Core;
var Shaders = require('./src/shaders.js');
var fs = require('fs');

//Fonts

var fontmap = {};
var defaultFonts = {
    'source': {
        name: 'source',
        weights: {
            200: {
                normal: 'SourceSansPro-ExtraLight.ttf',
                italic: 'SourceSansPro-ExtraLightItalic.ttf'
            },
            300: {
                normal: 'SourceSansPro-Light.ttf',
                italic: 'SourceSansPro-LightItalic.ttf'
            },
            400: {
                normal: 'SourceSansPro-Regular.ttf',
                italic: 'SourceSansPro-Italic.ttf'
            },

            600: {
                normal: 'SourceSansPro-Semibold.ttf',
                italic: 'SourceSansPro-SemiboldItalic.ttf'
            },
            700: {
                normal: 'SourceSansPro-Bold.ttf',
                italic: 'SourceSansPro-BoldItalic.ttf'
            },
            900: {
                normal: 'SourceSansPro-Black.ttf',
                italic: 'SourceSansPro-BlackItalic.ttf'
            }
        }
    },
    'awesome': {
        name: 'awesome',
        weights: {
            400: {
                normal: 'fontawesome-webfont.ttf'
            }
        }
    }
}

var propsHash = {

    //general
    "visible": 18,
    "opacity": 27,
    "r": 5,
    "g": 6,
    "b": 7,
    "texid": 8,
    "w": 10,
    "h": 11,
    "x": 21,
    "y": 22,

    //transforms  (use x and y for translate in X and Y)
    "sx": 2,
    "sy": 3,
    "rz": 4,
    "rx": 19,
    "ry": 20,

    //text
    "text": 9,
    "fontSize": 12,
    "fontId": 28,

    //animation
    "count": 29,
    "lerplinear": 13,
    "lerpcubicin": 14,
    "lerpcubicout": 15,
    "lerpprop": 16,
    "lerpcubicinout": 17,
    "autoreverse": 35,

    //time function
    'linear':     13,
    'cubicIn':    14,
    'cubicOut':   15,
    'cubicInOut': 17,

    //geometry
    "geometry":  24,
    "filled":    25,
    "closed":    26,
    "dimension": 36,

    //rectangle texture
    "textureLeft":   30,
    "textureRight":  31,
    "textureTop":    32,
    "textureBottom": 33,

    //clipping
    "cliprect": 34
};

/**
 * JSFont constructor.
 */
function JSFont(desc) {
    this.name = desc.name;

    var reg = desc.weights[400];

    this.desc = desc;
    this.weights = {};
    this.filepaths = {};

    var dir = process.cwd();

    process.chdir(__dirname + '/..'); // chdir such that fonts (and internal shaders) may be found

    var aminodir = __dirname + '/resources/';

    if (desc.path) {
        aminodir = desc.path;
    }

    for (var weight in desc.weights) {
        var filepath = aminodir + desc.weights[weight].normal;

        if (!fs.existsSync(filepath)) {
            throw new Error('WARNING. File not found: ' + filepath);
        }

        this.weights[weight] = Core.getCore().getNative().createNativeFont(filepath);
        this.filepaths[weight] = filepath;
    }

    process.chdir(dir);

    this.getNative = function (size, weight, style) {
        if (this.weights[weight] != undefined) {
            return this.weights[weight];
        }

        console.log('ERROR. COULDN\'T find the native for ' + size + ' ' + weight + ' ' + style);

        return this.weights[400];
    }

    /**
     * @func calcStringWidth(string, size)
     *
     * returns the width of the specified string rendered at the specified size
     */
    this.calcStringWidth = function(str, size, weight, style) {
        amino.GETCHARWIDTHCOUNT++;
        return amino.sgtest.getCharWidth(str, size, this.getNative(size, weight, style));
    }

    /**
     * Get font height.
     */
    this.getHeight = function(size, weight, style) {
        amino.GETCHARHEIGHTCOUNT++;

        if (size == undefined) {
            throw new Error("SIZE IS UNDEFINED");
        }

        return amino.sgtest.getFontHeight(size, this.getNative(size, weight, style));
    }

    /**
     * Get font height metrics.
     */
    this.getHeightMetrics = function(size, weight, style) {
        if (size == undefined) {
            throw new Error("SIZE IS UNDEFINED");
        }

        return {
            ascender: amino.sgtest.getFontAscender(size, this.getNative(size, weight, style)),
            descender: amino.sgtest.getFontDescender(size, this.getNative(size, weight, style))
        };
    }
}

/**
 * Animated property.
 */
function JSPropAnim(target, name) {
    this._from = null;
    this._to = null;
    this._duration = 1000;
    this._loop = 1;
    this._delay = 0;
    this._autoreverse = 0;
    this._lerpprop = 17; //cubicInOut
    this._then_fun = null;

    //setters
    this.from  = function(val) {  this._from = val;        return this;  }
    this.to    = function(val) {  this._to = val;          return this;  }
    this.dur   = function(val) {  this._duration = val;    return this;  }
    this.delay = function(val) {  this._delay = val;       return this;  }
    this.loop  = function(val) {  this._loop = val;        return this;  }
    this.then  = function(fun) {  this._then_fun = fun;    return this;  }
    this.autoreverse = function(val) { this._autoreverse = val ? 1:0; return this;  }
    this.timeFunc = function (val) {
        var tf = propsHash[val];

        if (tf) {
            this._lerpprop = tf;
        }

        return this;
    }

    //start the animation
    this.start = function () {
        if (DEBUG) {
            console.log('startin anim');
        }

        var self = this;

        setTimeout(function () {
            if (DEBUG) {
                console.log('after delay. making it.');
            }

            //create native instance
            var core = Core.getCore();
            var nat = core.getNative();

            self.handle = nat.createAnim(target.handle, name, self._from,self._to,self._duration);

            if (DEBUG) {
                console.log('handle is: ', self.handle);
            }

            //set params
            nat.updateAnimProperty(self.handle, 'count', self._loop);
            nat.updateAnimProperty(self.handle, 'autoreverse', self._autoreverse);
            nat.updateAnimProperty(self.handle, 'lerpprop', self._lerpprop);

            //add
            core.anims.push(self);
        }, this._delay);

        return this;
    }

    /**
     * Call finish function.
     */
    this.finish = function () {
        if (this._then_fun) {
            this._then_fun();
        }
    }

}

//native bindings

var PNG_HEADER = new Buffer([ 137, 80, 78, 71, 13, 10, 26, 10 ]); //PNG Header

var gl_native = {
    createNativeFont: function (path) {  return sgtest.createNativeFont(path, __dirname+'/resources/shaders');  },
    registerFont:function (args) { fontmap[args.name] = new JSFont(args); },
    init: function (core) { return sgtest.init(); },
    startEventLoop: function () {
        if (DEBUG) {
            console.log('starting the event loop');
        }

        var self = this;

        function immediateLoop() {
            try {
                self.tick(Core.getCore());
            } catch (ex) {
                //report
                console.log(ex);
                console.log(ex.stack);
                console.log("EXCEPTION. QUITTING!");
                return;
            }

            self.setImmediate(immediateLoop);
        }

        //1 ms interval
        setTimeout(immediateLoop, 1);
    },
    createWindow: function (core, w, h) {
        //create window
        sgtest.createWindow(w * core.DPIScale, h * core.DPIScale);

        //init shaders
        Shaders.init(sgtest, OS);

        //fonts
        fontmap['source']  = new JSFont(defaultFonts['source']);
        fontmap['awesome'] = new JSFont(defaultFonts['awesome']);

        core.defaultFont = fontmap['source'];

        this.rootWrapper = this.createGroup();
        this.updateProperty(this.rootWrapper, 'scalex', core.DPIScale);
        this.updateProperty(this.rootWrapper, 'scaley', core.DPIScale);
        sgtest.setRoot(this.rootWrapper);
    },
    getFont: function(name) { return fontmap[name]; },
    updateProperty: function(handle, name, value) {
        if (handle == undefined) {
            throw new Error('Can\'t set a property on an undefined handle!!');
        }

        //console.log('setting', handle, name, propsHash[name], value, typeof value);

        sgtest.updateProperty(handle, propsHash[name], value);
    },
    setRoot: function (handle) { return  sgtest.addNodeToGroup(handle,this.rootWrapper);  },
    tick: function() {
        sgtest.tick();
    },
    setImmediate: function(loop) {
        setImmediate(loop);
    },
//    setEventCallback: function(cb) {   return sgtest.setEventCallback(cb);   },
    setEventCallback: function (cb) {   return sgtest.setEventCallback(function(){
        //console.log("got some stuff",arguments);
        cb(arguments[1]);
    });   },
    createRect: function()  {          return sgtest.createRect();           },
    createGroup: function() {          return sgtest.createGroup();          },
    createPoly: function()  {          return sgtest.createPoly();           },
    createText: function() {           return sgtest.createText();           },
    createGLNode: function(cb)  {      return sgtest.createGLNode(cb);       },
    addNodeToGroup: function(h1,h2) {  return sgtest.addNodeToGroup(h1,h2);  },
    removeNodeFromGroup: function(h1, h2) { return sgtest.removeNodeFromGroup(h1, h2);  },
    loadImage: function(src, cb) {
        var buffer;
        var type;

        //check buffer
        if (Buffer.isBuffer(src)) {
            buffer = src;

            //check PNG
            if (buffer.slice(0, 8).equals(PNG_HEADER)) {
                //PNG
                type = 'png';
            } else {
                //JPEG
                type = 'jpg';
            }
        } else if (typeof src === 'string') {
            //load file (blocking)
            var buffer = fs.readFileSync(src);

            if (!buffer) {
                if (DEBUG) {
                    console.log('File not found: ' + src);
                }

                cb();
                return;
            }

            //check file name
            var name = src.toLowerCase();

            if (name.endsWith('.png')) {
                type = 'png';
            } else if (name.endsWith(".jpg")) {
                type = 'jpg';
            } else {
                if (DEBUG) {
                    console.log('Unsupported file format: ' + src);
                }

                cb();
                return;
            }
        } else {
            if (DEBUG) {
                console.log('Invalid src format!');
            }

            cb();
            return;
        }

        //debug
        if (DEBUG) {
            console.log('loadImage() type=' + type + ' length=' + buffer.length);
        }

        //decode
        var nat = Core.getCore().getNative();

        function bufferToTexture(ibuf) {
            //check error
            if (!ibuf) {
                if (DEBUG) {
                    console.log('could not load image: type='  + type);
                }

                cb();
                return;
            }

            //load texture
            nat.loadBufferToTexture(-1, ibuf.w, ibuf.h, ibuf.bpp, ibuf.buffer, function (texture) {
                cb(texture);
            });
        }

        switch (type) {
            case 'png':
                nat.decodePngBuffer(buffer, bufferToTexture);
                break;

            case 'jpg':
                nat.decodeJpegBuffer(buffer, bufferToTexture);
                break;
        }

    },
    decodePngBuffer: function (fbuf, cb) {  return cb(sgtest.decodePngBuffer(fbuf));  },
    decodeJpegBuffer: function (fbuf, cb) { return cb(sgtest.decodeJpegBuffer(fbuf)); },
    loadBufferToTexture: function (texid, w, h, bpp, buf, cb) { return cb(sgtest.loadBufferToTexture(texid, w,h, bpp, buf)); },
    setWindowSize: function (w, h) { sgtest.setWindowSize(w * Core.getCore().DPIScale, h * Core.getCore().DPIScale); },
    getWindowSize: function (w, h) {
        var dpi = Core.getCore().DPIScale;
        var size = sgtest.getWindowSize(w, h);

        return {
            w: size.w/dpi,
            h: size.h/dpi
        };
    },
    createAnim: function (handle, prop, start, end, dur) {
        if (!propsHash[prop]) {
            throw new Error('invalid native property name',prop);
        }

        return sgtest.createAnim(handle, propsHash[prop], start, end, dur);
    },
    createPropAnim: function (obj, name) { return new JSPropAnim(obj,name); },
    updateAnimProperty: function (handle, prop, type) { return  sgtest.updateAnimProperty(handle, propsHash[prop], type); },
    updateWindowProperty:function (stage, prop, value){
        if (!propsHash[prop]) {
            throw new Error('invalid native property name', prop);
        }

        return sgtest.updateWindowProperty(-1, propsHash[prop], value);
    }
}

exports.input = amino_core.input;
exports.start = function(cb) {
    if (!cb) {
        throw new Error('CB parameter missing to start app');
    }

    //init core
    Core.setCore(new Core());

    var core = Core.getCore();

    core.native = gl_native;
    amino_core.native = gl_native;
    core.init();

    //create stage
    var stage = Core._core.createStage(600, 600);

    stage.fill.watch(function () {
        var color = amino_core.ParseRGBString(stage.fill());

        gl_native.updateWindowProperty(stage, 'r', color.r);
        gl_native.updateWindowProperty(stage, 'g', color.g);
        gl_native.updateWindowProperty(stage, 'b', color.b);
    });
    stage.opacity.watch(function () {
        gl_native.updateWindowProperty(stage,'opacity',stage.opacity());
    });

    //mirror fonts to PureImage
    /*
    var source_font = exports.getRegisteredFonts().source;
    var fnt = PImage.registerFont(source_font.filepaths[400],source_font.name);
    fnt.load(function() {
        cb(Core._core,stage);
        Core._core.start();
    });
    */
    cb(core,stage);
    core.start();
};

exports.makeProps = amino_core.makeProps;

exports.Rect      = amino_core.Rect;
exports.Group     = amino_core.Group;
exports.Circle    = amino_core.Circle;
exports.Polygon   = amino_core.Polygon;
exports.Text      = amino_core.Text;
exports.ImageView = amino_core.ImageView;

exports.input.init(OS);

//exports.PureImageView = amino.primitives.PureImageView;
//exports.ConstraintSolver = require('./src/ConstraintSolver');
<|endoftext|>