<commit_before>$(document).ready(function() {
    if (window.WebSocket) {
	$("button#refresh-tail").css("display", "none");
	$("button#pause-scroll").click(pauseScroll);
	streamTail();
    } else {
	$("button#pause-scroll").css("display", "none");
	$("button#refresh-tail").click(refreshTail);
	refreshTail();
    }
});

function openWebsocket(path) {
    if (window.location.protocol == "http:") {
	websocket = new WebSocket("ws://"+window.location.host+path);
    } else {
	websocket = new WebSocket("wss://"+window.location.host+path);
    }
    return websocket;
}

var wsTail;
function streamTail() {
    wsTail = openWebsocket("/ajax/tail-log/stream");
    wsTail.onopen = function(){console.log("Tail log open")}
    wsTail.onclose = function(ev){
	console.log("websocket closed with code " + ev.code + ", reopening...");
	streamTail();
    }
    wsTail.onerror = function(ev){
	error("Error streaming tail log. Will re-attempt");
    }
    wsTail.onmessage = function(evt) {
	var data = JSON.parse(evt.data);
	var l = $("#latest tbody");
	l.prepend(tailLogRow(data));
    }
}

function tailLogRow(data) {
    var tr;
    var td;
    var ul;
    tr = document.createElement("tr");

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Time
    tr.appendChild(td);

    var li;
    var button;
    var span;
    td = document.createElement("td");
    td.classList = ["min nostripe"];
    ul = document.createElement("ul");
    ul.classList = ["buttons"];
    type = (data.Method == "CONNECT") ? "https-domain" : "domain";
    ul.appendChild(createButtonLI("Domain", {type: type, value: data.Domain}, data.Domain));
    ul.appendChild(createButtonLI("Host", {type: type, value: data.Host}, data.Host));
    if (data.Method != "CONNECT") {
	ul.appendChild(createButtonLI("Path", {}, data.URL));
    }
    td.appendChild(ul);
    tr.appendChild(td);

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Client
    tr.appendChild(td);

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Method
    tr.appendChild(td);

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Host
    tr.appendChild(td);

    td = document.createElement("td");
    td.innerText = data.Path
    td.classList = ["latest-path max"]
    tr.appendChild(td);

    return tr;
}

function pauseScroll() {
    var btn = $("button#pause-scroll");
    if (btn.data("paused") == true) {
	btn.data("paused", false);
	btn.text("Pause scroll");
	$("#latest tbody").html("");
	streamTail();
    } else {
	btn.data("paused", true);
	btn.text("Unpause scroll");
	wsTail.onclose = function(){}
	wsTail.close();
    }
}

function refreshTail() {
    var l = $("#latest tbody");
    l.html("");
    $.getJSON("/ajax/tail-log", function(data) {
        for (var i = 0; i < data.length; i++) {
	    l.append(tailLogRow(data[i]));
	}
    }).fail(function(o, text, error) {
	error("Error: " + ajaxError(o, text, error));
    });
}

function error(msg) {
    var e = document.createElement("p");
    e.innerText = msg;
    $("#error-messages").append(e);
}

function createButtonLI(name, data, value) {
    button = document.createElement("button");
    button.innerText = name;
    button.squidwarden_data = data;
    button.onclick = buttonClick;
    li = document.createElement("li");
    span = document.createElement("span");
    span.classList = ["tooltip"]
    span.innerText = value;
    li.appendChild(button);
    li.appendChild(span);
    return li;
}

function buttonClick(btn) {
    $("#test").html("Loading...");
    var data = $.extend({}, btn.target.squidwarden_data, {"action": $("#action").val()});
    console.log("Button click ", btn);
    console.log("Button data ",data);
    $.post("/ajax/allow", data)
        .done(function(){
	    $("#test").html("Added");
        })
        .fail(function(o, text, error){
	    $("#test").text("Failed: " + ajaxError(o, text, error));
        });
}
function ajaxError(o, text, error) {
    var msg;
    if (o.readyState == 0) {
	msg = "Network error";
    } else if (o.readyState == 4) {
	msg = text + ", " + error;
    } else {
	msg = "unknown error type for readyState " + o.readyState;
    }
    return msg;
}
<commit_msg>Support adding path rules<commit_after>$(document).ready(function() {
    if (window.WebSocket) {
	$("button#refresh-tail").css("display", "none");
	$("button#pause-scroll").click(pauseScroll);
	streamTail();
    } else {
	$("button#pause-scroll").css("display", "none");
	$("button#refresh-tail").click(refreshTail);
	refreshTail();
    }
});

function openWebsocket(path) {
    if (window.location.protocol == "http:") {
	websocket = new WebSocket("ws://"+window.location.host+path);
    } else {
	websocket = new WebSocket("wss://"+window.location.host+path);
    }
    return websocket;
}

var wsTail;
function streamTail() {
    wsTail = openWebsocket("/ajax/tail-log/stream");
    wsTail.onopen = function(){console.log("Tail log open")}
    wsTail.onclose = function(ev){
	console.log("websocket closed with code " + ev.code + ", reopening...");
	streamTail();
    }
    wsTail.onerror = function(ev){
	error("Error streaming tail log. Will re-attempt");
    }
    wsTail.onmessage = function(evt) {
	var data = JSON.parse(evt.data);
	var l = $("#latest tbody");
	l.prepend(tailLogRow(data));
    }
}

function tailLogRow(data) {
    var tr;
    var td;
    var ul;
    tr = document.createElement("tr");

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Time
    tr.appendChild(td);

    var li;
    var button;
    var span;
    td = document.createElement("td");
    td.classList = ["min nostripe"];
    ul = document.createElement("ul");
    ul.classList = ["buttons"];
    type = (data.Method == "CONNECT") ? "https-domain" : "domain";
    ul.appendChild(createButtonLI("Domain", {type: type, value: data.Domain}, data.Domain));
    ul.appendChild(createButtonLI("Host", {type: type, value: data.Host}, data.Host));
    if (data.Method != "CONNECT") {
	ul.appendChild(createButtonLI("Path", {
	    type: "regex",
	    value: "^" + data.URL.replace(/[.]/g, "[.]") + "$",
	}, data.URL));
    }
    td.appendChild(ul);
    tr.appendChild(td);

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Client
    tr.appendChild(td);

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Method
    tr.appendChild(td);

    td = document.createElement("td");
    td.classList = ["min"];
    td.innerText = data.Host
    tr.appendChild(td);

    td = document.createElement("td");
    td.innerText = data.Path
    td.classList = ["latest-path max"]
    tr.appendChild(td);

    return tr;
}

function pauseScroll() {
    var btn = $("button#pause-scroll");
    if (btn.data("paused") == true) {
	btn.data("paused", false);
	btn.text("Pause scroll");
	$("#latest tbody").html("");
	streamTail();
    } else {
	btn.data("paused", true);
	btn.text("Unpause scroll");
	wsTail.onclose = function(){}
	wsTail.close();
    }
}

function refreshTail() {
    var l = $("#latest tbody");
    l.html("");
    $.getJSON("/ajax/tail-log", function(data) {
        for (var i = 0; i < data.length; i++) {
	    l.append(tailLogRow(data[i]));
	}
    }).fail(function(o, text, error) {
	error("Error: " + ajaxError(o, text, error));
    });
}

function error(msg) {
    var e = document.createElement("p");
    e.innerText = msg;
    $("#error-messages").append(e);
}

function createButtonLI(name, data, tip) {
    button = document.createElement("button");
    button.innerText = name;
    button.squidwarden_data = data;
    button.onclick = buttonClick;
    li = document.createElement("li");
    span = document.createElement("span");
    span.classList = ["tooltip"]
    span.innerText = tip;
    li.appendChild(button);
    li.appendChild(span);
    return li;
}

function buttonClick(btn) {
    $("#test").html("Loading...");
    var data = $.extend({}, btn.target.squidwarden_data, {"action": $("#action").val()});
    console.log("Button click ", btn);
    console.log("Button data ",data);
    $.post("/ajax/allow", data)
        .done(function(){
	    $("#test").html("Added");
        })
        .fail(function(o, text, error){
	    $("#test").text("Failed: " + ajaxError(o, text, error));
        });
}
function ajaxError(o, text, error) {
    var msg;
    if (o.readyState == 0) {
	msg = "Network error";
    } else if (o.readyState == 4) {
	msg = text + ", " + error;
    } else {
	msg = "unknown error type for readyState " + o.readyState;
    }
    return msg;
}
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';

/**
 * Renders simple values (eg. strings, numbers, booleans, etc)
 */

const JSONValueNode = ({
  nodeType,
  styling,
  labelRenderer,
  keyPath,
  valueRenderer,
  value,
  valueGetter
}) => (
  <li
    {...styling('value', nodeType, keyPath)}
  >
    <label {...styling(['label', 'valueLabel'], nodeType, keyPath)}>
      {labelRenderer(...keyPath)}:
    </label>
    <span {...styling('valueText', nodeType, keyPath)}>
      {valueRenderer(valueGetter(value), value)}
    </span>
  </li>
);

JSONValueNode.propTypes = {
  nodeType: PropTypes.string.isRequired,
  styling: PropTypes.func.isRequired,
  labelRenderer: PropTypes.func.isRequired,
  keyPath: PropTypes.arrayOf(
    PropTypes.oneOfType([PropTypes.string, PropTypes.number])
  ).isRequired,
  valueRenderer: PropTypes.func.isRequired,
  value: PropTypes.any,
  valueGetter: PropTypes.func
};

JSONValueNode.defaultProps = {
  valueGetter: value => value
};

export default JSONValueNode;
<commit_msg>add the key path as a parameter to the value renderer (#48)<commit_after>import React, { PropTypes } from 'react';

/**
 * Renders simple values (eg. strings, numbers, booleans, etc)
 */

const JSONValueNode = ({
  nodeType,
  styling,
  labelRenderer,
  keyPath,
  valueRenderer,
  value,
  valueGetter
}) => (
  <li
    {...styling('value', nodeType, keyPath)}
  >
    <label {...styling(['label', 'valueLabel'], nodeType, keyPath)}>
      {labelRenderer(...keyPath)}:
    </label>
    <span {...styling('valueText', nodeType, keyPath)}>
      {valueRenderer(valueGetter(value), value, ...keyPath)}
    </span>
  </li>
);

JSONValueNode.propTypes = {
  nodeType: PropTypes.string.isRequired,
  styling: PropTypes.func.isRequired,
  labelRenderer: PropTypes.func.isRequired,
  keyPath: PropTypes.arrayOf(
    PropTypes.oneOfType([PropTypes.string, PropTypes.number])
  ).isRequired,
  valueRenderer: PropTypes.func.isRequired,
  value: PropTypes.any,
  valueGetter: PropTypes.func
};

JSONValueNode.defaultProps = {
  valueGetter: value => value
};

export default JSONValueNode;
<|endoftext|>


<commit_before>/*
 * L.esri.WebMap
 *
 *
 */

L.esri.WebMap = L.Class.extend({
	options: {
		map: {}
	},

	initialize: function(webmapId, options) {
		L.setOptions(this, options);

		this._map = this.options.map;
		this._webmapId = webmapId;
		this._mapOptions = {};
		this._baseMap = {};
		this._operationalLayers = {};
		this._exportOptions = {};
		this._layoutOptions = {};

        this.layers = [];

		this._loadWebMapMetaData(webmapId);
		this._loadWebMap(webmapId);
	},

	_loadWebMapMetaData: function(id) {
        console.log(this);
		var map = this._map;
		var leafletLatlng = this.leafletLatlng;
		var webmapMetaDataRequestUrl = 'https://www.arcgis.com/sharing/rest/content/items/' + id;
		L.esri.request(webmapMetaDataRequestUrl, {}, function(error, response){
		  if(error){
		    console.log(error);
		  } else {
		    console.log(response);
				console.log('extent: ', response.extent);

				map.fitBounds([leafletLatlng(response.extent[0]), leafletLatlng(response.extent[1])]);
		  }
		});
	},

	_loadWebMap: function(id) {
		var map = this._map;
		var generateEsriLayer = this._generateEsriLayer;
		//var basemapKey = this.getBasemapKey;
		var webmapRequestUrl = 'https://www.arcgis.com/sharing/rest/content/items/' + id + '/data?f=json';
		L.esri.request(webmapRequestUrl, {}, function(error, response){
		  if(error){
		    console.log(error);
		  } else {
		    console.log(response);
				console.log('baseMap: ', response.baseMap);
				console.log('operationalLayers: ', response.operationalLayers);

				// Add Basemap
				response.baseMap.baseMapLayers.map(function(baseMapLayer) {
					generateEsriLayer(baseMapLayer).addTo(map);
				});
				/*L.esri.basemapLayer(basemapKey(response.baseMap.title)).addTo(map);
				if(response.baseMap.baseMapLayers.length == 2) {
					L.esri.basemapLayer(basemapKey(response.baseMap.title) + 'Labels').addTo(map);
				}*/

				// Add Operational Layers
				response.operationalLayers.map(function(layer) {
                    var lyr = generateEsriLayer(layer);
                    this.webmap.layers.push(lyr);
                    lyr.addTo(map);
				});
		  }
		});
	},

	leafletLatlng: function(latlng) {
		var changedLatlng = [latlng[1], latlng[0]];
		return changedLatlng;
	},

    _createPopupContent: function(popupInfo, properties) {
        //console.log(popupInfo, properties);
        var content = '
' + popupInfo.title + '
';
        if(popupInfo.fieldInfos.length > 0) {
            popupInfo.fieldInfos.map(function(info) {
                content += info.label + ': ' + properties[info.fieldName] + '
';
            });
        }
        if(popupInfo.mediaInfos.length > 0) {

        }
        return content;
    },

    _pointSymbol: function(symbol) {
        var icon;
        if(symbol.type === 'esriPMS') {
            icon = L.icon({
                iconUrl: symbol.url,
                shadowUrl: '',
                iconSize:     [symbol.height, symbol.width],
                shadowSize:   [0, 0],
                iconAnchor:   [symbol.height-16, symbol.width-1],
                shadowAnchor: [0, 0],
                popupAnchor:  [symbol.width/3, symbol.height*-1]
            });
        }
        if(symbol.type === 'esriSMS') {
            if(symbol.style === 'esriSMSCircle') {
                if(symbol.outline.style === 'esriSLSNull') {
                    icon = L.vectorIcon({
                        //className: 'my-vector-icon',
                        svgHeight: (symbol.size + symbol.outline.width) * 2,
                        svgWidth: (symbol.size + symbol.outline.width) * 2,
                        type: 'circle',
                        shape: {
                            r: symbol.size + '',
                            cx: symbol.size + symbol.outline.width,
                            cy: symbol.size + symbol.outline.width
                        },
                        style: {
                            fill: 'rgba(' + symbol.color[0] + ',' + symbol.color[1] + ',' + symbol.color[2] + ',' + symbol.color[3]/255 + ')',
                            //stroke: '',
                            strokeWidth: 0
                        }
                    });
                }
                else {
                    icon = L.vectorIcon({
                        //className: 'my-vector-icon',
                        svgHeight: (symbol.size + symbol.outline.width) * 2,
                        svgWidth: (symbol.size + symbol.outline.width) * 2,
                        type: 'circle',
                        shape: {
                            r: symbol.size + '',
                            cx: symbol.size + symbol.outline.width,
                            cy: symbol.size + symbol.outline.width
                        },
                        style: {
                            fill: 'rgba(' + symbol.color[0] + ',' + symbol.color[1] + ',' + symbol.color[2] + ',' + symbol.color[3]/255 + ')',
                            stroke: 'rgba(' + symbol.outline.color[0] + ',' + symbol.outline.color[1] + ',' + symbol.outline.color[2] + ',' + symbol.outline.color[3]/255 + ')',
                            strokeWidth: symbol.outline.width
                        }
                    });
                }
            }
            if(symbol.style === '') {

            }
            if(symbol.style === '') {

            }
        }
        return icon;
    },

    _generateIcon: function(renderer, properties) {
        //console.log(renderer);
        var icon;
        if(renderer.type === 'simple') {
            icon = this._pointSymbol(renderer.symbol);
        }
        if(renderer.type === 'uniqueValue') {
            renderer.uniqueValueInfos.map(function(info) {
                if(info.value === properties[renderer.field1]) { // field2, field3は後で考えよう
                    icon = this.webmap._pointSymbol(info.symbol);
                }
            });
        }
        if(renderer.type === 'classBreaks') {
            renderer.classBreakInfos.map(function(info) {
                if(info.classMinValue !== undefined) {
                    if(info.classMinValue <= properties[renderer.field] && info.classMaxValue > properties[renderer.field]) {
                        icon = this.webmap._pointSymbol(info.symbol);
                    }
                }
                else {
                    if(info.classMaxValue > properties[renderer.field]) {
                        icon = this.webmap._pointSymbol(info.symbol);
                    }
                }
            });
        }
        return icon;
    },

    _generateLabel: function(properties, labelingInfo) {
        //console.log('generateLabels: ', properties, labelingInfo);
        var r = /\[([^\]]*)\]/g;
        var labelText = labelingInfo[0].labelExpression;
        labelText = labelText.replace(r, function(s) {
            var m = r.exec(s);
            //console.log(m[1]);
            //console.log(properties[m[1]]);
            return properties[m[1]];
        });
        return labelText;
    },

	_generateEsriLayer: function(layer) {
		console.log('generateEsriLayer: ', layer.title, layer);

		console.log(this.webmap);

		if(layer.featureCollection !== undefined) {
            // Supporting only point geometry
            console.log('create FeatureCollection');
            var renderer = layer.featureCollection.layers[0].layerDefinition.drawingInfo.renderer;
            console.log(renderer);
            var features = [];
            layer.featureCollection.layers[0].featureSet.features.map(function(feature) {

                var popupContent = this.webmap._createPopupContent(layer.featureCollection.layers[0].popupInfo, feature.attributes);
                var icon = this.webmap._generateIcon(renderer, feature.attributes);
                var mercatorToLatlng = L.Projection.SphericalMercator.unproject(L.point(feature.geometry.x, feature.geometry.y));

                var f = L.marker(mercatorToLatlng, { icon: icon, opacity: layer.opacity }).bindPopup(popupContent);

                if(layer.featureCollection.layers[0].layerDefinition.drawingInfo.labelingInfo !== undefined) {
                    var labelingInfo = layer.featureCollection.layers[0].layerDefinition.drawingInfo.labelingInfo;
                    var labelText = this.webmap._generateLabel(feature.attributes, labelingInfo);
                    //f.bindLabel(labelText, { noHide: true }).showLabel();
                }

                features.push(f);
            });

            var lyr = L.featureGroup(features);
            return lyr;
        }
        if(layer.layerType === 'ArcGISFeatureLayer' && layer.layerDefinition !== undefined) {
            if(layer.layerDefinition.drawingInfo.renderer.type === 'heatmap'){
                console.log('create HeatmapLayer');
                var gradient = {};
                layer.layerDefinition.drawingInfo.renderer.colorStops.map(function(stop) {
                    //gradient[stop.ratio] = 'rgba(' + stop.color[0] + ',' + stop.color[1] + ',' + stop.color[2] + ',' + (stop.color[3]/255) + ')';
                    gradient[Math.round(stop.ratio*100)/100] = 'rgb(' + stop.color[0] + ',' + stop.color[1] + ',' + stop.color[2] + ')';
                });
                //console.log(gradient);

                var lyr = L.esri.Heat.heatmapFeatureLayer({ // Esri Leaflet 2.0
                //var lyr = L.esri.heatmapFeatureLayer({ // Esri Leaflet 1.0
                    url: layer.url,
                    //blur: layer.layerDefinition.drawingInfo.renderer.blurRadius,
                    //max: layer.layerDefinition.drawingInfo.renderer.maxPixelIntensity,
                    gradient: gradient
                })
                return lyr;
            }
		}
		if(layer.layerType === 'ArcGISFeatureLayer' && layer.layerDefinition !== undefined) {
            if(layer.layerDefinition.drawingInfo !== undefined){
                console.log('create ArcGISFeatureLayer (with layerDefinition)');
                var renderer = layer.layerDefinition.drawingInfo.renderer;

                var lyr = L.esri.featureLayer({
                    url: layer.url,
                    pointToLayer: function (geojson, latlng) {

                        var popupContent = this.webmap._createPopupContent(layer.popupInfo, geojson.properties);
                        var icon = this.webmap._generateIcon(renderer, geojson.properties);

                        var f = L.marker(latlng, {
                            icon: icon,
                            opacity: layer.opacity
                        }).bindPopup(popupContent);

                        if(layer.layerDefinition.drawingInfo.labelingInfo !== undefined) {
                            var labelingInfo = layer.layerDefinition.drawingInfo.labelingInfo;
                            var labelText = this.webmap._generateLabel(geojson.properties, labelingInfo);
                            //f.bindLabel(labelText, { noHide: true }).showLabel();
                        }

                        return f;
                    }
                });
                return lyr;
            }
		}
		if(layer.layerType === 'ArcGISFeatureLayer') {
			console.log('create ArcGISFeatureLayer');
            var lyr = L.esri.featureLayer({
                url: layer.url,
                pointToLayer: function (geojson, latlng) {

                    var popupContent = this.webmap._createPopupContent(layer.popupInfo, geojson.properties);
                    //var icon = this.webmap._generateIcon(renderer, geojson.properties);

                    var f = L.marker(latlng, {
                        //icon: icon,
                        opacity: layer.opacity
                    }).bindPopup(popupContent);

                    return f;
                }
            });
			return lyr;
		}
		if(layer.layerType === 'ArcGISImageServiceLayer') {
			console.log('create ArcGISImageServiceLayer');
			var lyr = L.esri.imageMapLayer({
				url: layer.url
			});
			return lyr;
		}
		if(layer.layerType === 'ArcGISMapServiceLayer') {
			var lyr = L.esri.dynamicMapLayer({
				url: layer.url
			});
			return lyr;
		}
		if(layer.layerType === 'ArcGISTiledMapServiceLayer') {
			var lyr = L.esri.tiledMapLayer({
				url: layer.url
			});
			return lyr;
		}
		if(layer.layerType === '') {
			return false;
		}
		if(layer.layerType === '') {
			return false;
		}
	}

	/*getBasemapKey: function(title) {
		if(title === '') {
			return 'Streets';
		}
		if(title === 'Topographic') {
			return 'Topographic';
		}
		if(title === '') {
			return 'NationalGeographic';
		}
		if(title === '') {
			return 'Oceans';
		}
		if(title === 'Light Gray Canvas') {
			return 'Gray';
		}
		if(title === '') {
			return 'DarkGray';
		}
		if(title === '') {
			return 'Imagery';
		}
		if(title === '') {
			return 'ShadedRelief';
		}
		if(title === 'Terrain with Labels') {
			return 'Terrain';
		}
		if(title === '') {
			return 'USATopo';
		}
	}*/

});

L.esri.webMap = function (webmapId, options) {
	return new L.esri.WebMap(webmapId, options);
};<commit_msg>minor change: style of a popup content<commit_after>/*
 * L.esri.WebMap
 *
 *
 */

L.esri.WebMap = L.Class.extend({
	options: {
		map: {}
	},

	initialize: function(webmapId, options) {
		L.setOptions(this, options);

		this._map = this.options.map;
		this._webmapId = webmapId;
		this._mapOptions = {};
		this._baseMap = {};
		this._operationalLayers = {};
		this._exportOptions = {};
		this._layoutOptions = {};

        this.layers = [];

		this._loadWebMapMetaData(webmapId);
		this._loadWebMap(webmapId);
	},

	_loadWebMapMetaData: function(id) {
        console.log(this);
		var map = this._map;
		var leafletLatlng = this.leafletLatlng;
		var webmapMetaDataRequestUrl = 'https://www.arcgis.com/sharing/rest/content/items/' + id;
		L.esri.request(webmapMetaDataRequestUrl, {}, function(error, response){
		  if(error){
		    console.log(error);
		  } else {
		    console.log(response);
				console.log('extent: ', response.extent);

				map.fitBounds([leafletLatlng(response.extent[0]), leafletLatlng(response.extent[1])]);
		  }
		});
	},

	_loadWebMap: function(id) {
		var map = this._map;
		var generateEsriLayer = this._generateEsriLayer;
		//var basemapKey = this.getBasemapKey;
		var webmapRequestUrl = 'https://www.arcgis.com/sharing/rest/content/items/' + id + '/data?f=json';
		L.esri.request(webmapRequestUrl, {}, function(error, response){
		  if(error){
		    console.log(error);
		  } else {
		    console.log(response);
				console.log('baseMap: ', response.baseMap);
				console.log('operationalLayers: ', response.operationalLayers);

				// Add Basemap
				response.baseMap.baseMapLayers.map(function(baseMapLayer) {
					generateEsriLayer(baseMapLayer).addTo(map);
				});
				/*L.esri.basemapLayer(basemapKey(response.baseMap.title)).addTo(map);
				if(response.baseMap.baseMapLayers.length == 2) {
					L.esri.basemapLayer(basemapKey(response.baseMap.title) + 'Labels').addTo(map);
				}*/

				// Add Operational Layers
				response.operationalLayers.map(function(layer) {
                    var lyr = generateEsriLayer(layer);
                    this.webmap.layers.push(lyr);
                    lyr.addTo(map);
				});
		  }
		});
	},

	leafletLatlng: function(latlng) {
		var changedLatlng = [latlng[1], latlng[0]];
		return changedLatlng;
	},

    _createPopupContent: function(popupInfo, properties) {
        //console.log(popupInfo, properties);
        var content = '
' + popupInfo.title + '
';
        if(popupInfo.fieldInfos.length > 0) {
            popupInfo.fieldInfos.map(function(info) {
                content += '
' + info.label + '
 ' + properties[info.fieldName] + '
';
            });
        }
        if(popupInfo.mediaInfos.length > 0) {

        }
        return content;
    },

    _pointSymbol: function(symbol) {
        var icon;
        if(symbol.type === 'esriPMS') {
            icon = L.icon({
                iconUrl: symbol.url,
                shadowUrl: '',
                iconSize:     [symbol.height, symbol.width],
                shadowSize:   [0, 0],
                iconAnchor:   [symbol.height-16, symbol.width-1],
                shadowAnchor: [0, 0],
                popupAnchor:  [symbol.width/3, symbol.height*-1]
            });
        }
        if(symbol.type === 'esriSMS') {
            if(symbol.style === 'esriSMSCircle') {
                if(symbol.outline.style === 'esriSLSNull') {
                    icon = L.vectorIcon({
                        //className: 'my-vector-icon',
                        svgHeight: (symbol.size + symbol.outline.width) * 2,
                        svgWidth: (symbol.size + symbol.outline.width) * 2,
                        type: 'circle',
                        shape: {
                            r: symbol.size + '',
                            cx: symbol.size + symbol.outline.width,
                            cy: symbol.size + symbol.outline.width
                        },
                        style: {
                            fill: 'rgba(' + symbol.color[0] + ',' + symbol.color[1] + ',' + symbol.color[2] + ',' + symbol.color[3]/255 + ')',
                            //stroke: '',
                            strokeWidth: 0
                        }
                    });
                }
                else {
                    icon = L.vectorIcon({
                        //className: 'my-vector-icon',
                        svgHeight: (symbol.size + symbol.outline.width) * 2,
                        svgWidth: (symbol.size + symbol.outline.width) * 2,
                        type: 'circle',
                        shape: {
                            r: symbol.size + '',
                            cx: symbol.size + symbol.outline.width,
                            cy: symbol.size + symbol.outline.width
                        },
                        style: {
                            fill: 'rgba(' + symbol.color[0] + ',' + symbol.color[1] + ',' + symbol.color[2] + ',' + symbol.color[3]/255 + ')',
                            stroke: 'rgba(' + symbol.outline.color[0] + ',' + symbol.outline.color[1] + ',' + symbol.outline.color[2] + ',' + symbol.outline.color[3]/255 + ')',
                            strokeWidth: symbol.outline.width
                        }
                    });
                }
            }
            if(symbol.style === '') {

            }
            if(symbol.style === '') {

            }
        }
        return icon;
    },

    _generateIcon: function(renderer, properties) {
        //console.log(renderer);
        var icon;
        if(renderer.type === 'simple') {
            icon = this._pointSymbol(renderer.symbol);
        }
        if(renderer.type === 'uniqueValue') {
            renderer.uniqueValueInfos.map(function(info) {
                if(info.value === properties[renderer.field1]) { // field2, field3は後で考えよう
                    icon = this.webmap._pointSymbol(info.symbol);
                }
            });
        }
        if(renderer.type === 'classBreaks') {
            renderer.classBreakInfos.map(function(info) {
                if(info.classMinValue !== undefined) {
                    if(info.classMinValue <= properties[renderer.field] && info.classMaxValue > properties[renderer.field]) {
                        icon = this.webmap._pointSymbol(info.symbol);
                    }
                }
                else {
                    if(info.classMaxValue > properties[renderer.field]) {
                        icon = this.webmap._pointSymbol(info.symbol);
                    }
                }
            });
        }
        return icon;
    },

    _generateLabel: function(properties, labelingInfo) {
        //console.log('generateLabels: ', properties, labelingInfo);
        var r = /\[([^\]]*)\]/g;
        var labelText = labelingInfo[0].labelExpression;
        labelText = labelText.replace(r, function(s) {
            var m = r.exec(s);
            //console.log(m[1]);
            //console.log(properties[m[1]]);
            return properties[m[1]];
        });
        return labelText;
    },

	_generateEsriLayer: function(layer) {
		console.log('generateEsriLayer: ', layer.title, layer);

		console.log(this.webmap);

		if(layer.featureCollection !== undefined) {
            // Supporting only point geometry
            console.log('create FeatureCollection');
            var renderer = layer.featureCollection.layers[0].layerDefinition.drawingInfo.renderer;
            console.log(renderer);
            var features = [];
            layer.featureCollection.layers[0].featureSet.features.map(function(feature) {

                var popupContent = this.webmap._createPopupContent(layer.featureCollection.layers[0].popupInfo, feature.attributes);
                var icon = this.webmap._generateIcon(renderer, feature.attributes);
                var mercatorToLatlng = L.Projection.SphericalMercator.unproject(L.point(feature.geometry.x, feature.geometry.y));

                var f = L.marker(mercatorToLatlng, { icon: icon, opacity: layer.opacity }).bindPopup(popupContent);

                if(layer.featureCollection.layers[0].layerDefinition.drawingInfo.labelingInfo !== undefined) {
                    var labelingInfo = layer.featureCollection.layers[0].layerDefinition.drawingInfo.labelingInfo;
                    var labelText = this.webmap._generateLabel(feature.attributes, labelingInfo);
                    //f.bindLabel(labelText, { noHide: true }).showLabel();
                }

                features.push(f);
            });

            var lyr = L.featureGroup(features);
            return lyr;
        }
        if(layer.layerType === 'ArcGISFeatureLayer' && layer.layerDefinition !== undefined) {
            if(layer.layerDefinition.drawingInfo.renderer.type === 'heatmap'){
                console.log('create HeatmapLayer');
                var gradient = {};
                layer.layerDefinition.drawingInfo.renderer.colorStops.map(function(stop) {
                    //gradient[stop.ratio] = 'rgba(' + stop.color[0] + ',' + stop.color[1] + ',' + stop.color[2] + ',' + (stop.color[3]/255) + ')';
                    gradient[Math.round(stop.ratio*100)/100] = 'rgb(' + stop.color[0] + ',' + stop.color[1] + ',' + stop.color[2] + ')';
                });
                //console.log(gradient);

                var lyr = L.esri.Heat.heatmapFeatureLayer({ // Esri Leaflet 2.0
                //var lyr = L.esri.heatmapFeatureLayer({ // Esri Leaflet 1.0
                    url: layer.url,
                    //blur: layer.layerDefinition.drawingInfo.renderer.blurRadius,
                    //max: layer.layerDefinition.drawingInfo.renderer.maxPixelIntensity,
                    gradient: gradient
                })
                return lyr;
            }
		}
		if(layer.layerType === 'ArcGISFeatureLayer' && layer.layerDefinition !== undefined) {
            if(layer.layerDefinition.drawingInfo !== undefined){
                console.log('create ArcGISFeatureLayer (with layerDefinition)');
                var renderer = layer.layerDefinition.drawingInfo.renderer;

                var lyr = L.esri.featureLayer({
                    url: layer.url,
                    pointToLayer: function (geojson, latlng) {

                        var popupContent = this.webmap._createPopupContent(layer.popupInfo, geojson.properties);
                        var icon = this.webmap._generateIcon(renderer, geojson.properties);

                        var f = L.marker(latlng, {
                            icon: icon,
                            opacity: layer.opacity
                        }).bindPopup(popupContent);

                        if(layer.layerDefinition.drawingInfo.labelingInfo !== undefined) {
                            var labelingInfo = layer.layerDefinition.drawingInfo.labelingInfo;
                            var labelText = this.webmap._generateLabel(geojson.properties, labelingInfo);
                            //f.bindLabel(labelText, { noHide: true }).showLabel();
                        }

                        return f;
                    }
                });
                return lyr;
            }
		}
		if(layer.layerType === 'ArcGISFeatureLayer') {
			console.log('create ArcGISFeatureLayer');
            var lyr = L.esri.featureLayer({
                url: layer.url,
                pointToLayer: function (geojson, latlng) {

                    var popupContent = this.webmap._createPopupContent(layer.popupInfo, geojson.properties);
                    //var icon = this.webmap._generateIcon(renderer, geojson.properties);

                    var f = L.marker(latlng, {
                        //icon: icon,
                        opacity: layer.opacity
                    }).bindPopup(popupContent);

                    return f;
                }
            });
			return lyr;
		}
		if(layer.layerType === 'ArcGISImageServiceLayer') {
			console.log('create ArcGISImageServiceLayer');
			var lyr = L.esri.imageMapLayer({
				url: layer.url
			});
			return lyr;
		}
		if(layer.layerType === 'ArcGISMapServiceLayer') {
			var lyr = L.esri.dynamicMapLayer({
				url: layer.url
			});
			return lyr;
		}
		if(layer.layerType === 'ArcGISTiledMapServiceLayer') {
			var lyr = L.esri.tiledMapLayer({
				url: layer.url
			});
			return lyr;
		}
		if(layer.layerType === '') {
			return false;
		}
		if(layer.layerType === '') {
			return false;
		}
	}

	/*getBasemapKey: function(title) {
		if(title === '') {
			return 'Streets';
		}
		if(title === 'Topographic') {
			return 'Topographic';
		}
		if(title === '') {
			return 'NationalGeographic';
		}
		if(title === '') {
			return 'Oceans';
		}
		if(title === 'Light Gray Canvas') {
			return 'Gray';
		}
		if(title === '') {
			return 'DarkGray';
		}
		if(title === '') {
			return 'Imagery';
		}
		if(title === '') {
			return 'ShadedRelief';
		}
		if(title === 'Terrain with Labels') {
			return 'Terrain';
		}
		if(title === '') {
			return 'USATopo';
		}
	}*/

});

L.esri.webMap = function (webmapId, options) {
	return new L.esri.WebMap(webmapId, options);
};<|endoftext|>


<commit_before>var LGraphObject = require('./LGraphObject');
var Integer = require('./Integer');
var LayoutConstants = require('./LayoutConstants');
var LGraphManager = require('./LGraphManager');
var LNode = require('./LNode');
var LEdge = require('./LEdge');
var HashSet = require('./HashSet');
var RectangleD = require('./RectangleD');
var Point = require('./Point');

function LGraph(parent, obj2, vGraph) {
  LGraphObject.call(this, vGraph);
  this.estimatedSize = Integer.MIN_VALUE;
  this.margin = LayoutConstants.DEFAULT_GRAPH_MARGIN;
  this.edges = [];
  this.nodes = [];
  this.isConnected = false;
  this.parent = parent;

  if (obj2 != null && obj2 instanceof LGraphManager) {
    this.graphManager = obj2;
  }
  else if (obj2 != null && obj2 instanceof Layout) {
    this.graphManager = obj2.graphManager;
  }
}

LGraph.prototype = Object.create(LGraphObject.prototype);
for (var prop in LGraphObject) {
  LGraph[prop] = LGraphObject[prop];
}

LGraph.prototype.getNodes = function () {
  return this.nodes;
};

LGraph.prototype.getEdges = function () {
  return this.edges;
};

LGraph.prototype.getGraphManager = function ()
{
  return this.graphManager;
};

LGraph.prototype.getParent = function ()
{
  return this.parent;
};

LGraph.prototype.getLeft = function ()
{
  return this.left;
};

LGraph.prototype.getRight = function ()
{
  return this.right;
};

LGraph.prototype.getTop = function ()
{
  return this.top;
};

LGraph.prototype.getBottom = function ()
{
  return this.bottom;
};

LGraph.prototype.isConnected = function ()
{
  return this.isConnected;
};

LGraph.prototype.add = function (obj1, sourceNode, targetNode) {
  if (sourceNode == null && targetNode == null) {
    var newNode = obj1;
    if (this.graphManager == null) {
      throw "Graph has no graph mgr!";
    }
    if (this.getNodes().indexOf(newNode) > -1) {
      throw "Node already in graph!";
    }
    newNode.owner = this;
    this.getNodes().push(newNode);

    return newNode;
  }
  else {
    var newEdge = obj1;
    if (!(this.getNodes().indexOf(sourceNode) > -1 && (this.getNodes().indexOf(targetNode)) > -1)) {
      throw "Source or target not in graph!";
    }

    if (!(sourceNode.owner == targetNode.owner && sourceNode.owner == this)) {
      throw "Both owners must be this graph!";
    }

    if (sourceNode.owner != targetNode.owner)
    {
      return null;
    }

    // set source and target
    newEdge.source = sourceNode;
    newEdge.target = targetNode;

    // set as intra-graph edge
    newEdge.isInterGraph = false;

    // add to graph edge list
    this.getEdges().push(newEdge);

    // add to incidency lists
    sourceNode.edges.push(newEdge);

    if (targetNode != sourceNode)
    {
      targetNode.edges.push(newEdge);
    }

    return newEdge;
  }
};

LGraph.prototype.remove = function (obj) {
  var node = obj;
  if (obj instanceof LNode) {
    if (node == null) {
      throw "Node is null!";
    }
    if (!(node.owner != null && node.owner == this)) {
      throw "Owner graph is invalid!";
    }
    if (this.graphManager == null) {
      throw "Owner graph manager is invalid!";
    }
    // remove incident edges first (make a copy to do it safely)
    var edgesToBeRemoved = node.edges.slice();
    var edge;
    var s = edgesToBeRemoved.length;
    for (var i = 0; i < s; i++)
    {
      edge = edgesToBeRemoved[i];

      if (edge.isInterGraph)
      {
        this.graphManager.remove(edge);
      }
      else
      {
        edge.source.owner.remove(edge);
      }
    }

    // now the node itself
    var index = this.nodes.indexOf(node);
    if (index == -1) {
      throw "Node not in owner node list!";
    }

    this.nodes.splice(index, 1);
  }
  else if (obj instanceof LEdge) {
    var edge = obj;
    if (edge == null) {
      throw "Edge is null!";
    }
    if (!(edge.source != null && edge.target != null)) {
      throw "Source and/or target is null!";
    }
    if (!(edge.source.owner != null && edge.target.owner != null &&
            edge.source.owner == this && edge.target.owner == this)) {
      throw "Source and/or target owner is invalid!";
    }

    var sourceIndex = edge.source.edges.indexOf(edge);
    var targetIndex = edge.target.edges.indexOf(edge);
    if (!(sourceIndex > -1 && targetIndex > -1)) {
      throw "Source and/or target doesn't know this edge!";
    }

    edge.source.edges.splice(sourceIndex, 1);

    if (edge.target != edge.source)
    {
      edge.target.edges.splice(targetIndex, 1);
    }

    var index = edge.source.owner.getEdges().indexOf(edge);
    if (index == -1) {
      throw "Not in owner's edge list!";
    }

    edge.source.owner.getEdges().splice(index, 1);
  }
};

LGraph.prototype.updateLeftTop = function ()
{
  var top = Integer.MAX_VALUE;
  var left = Integer.MAX_VALUE;
  var nodeTop;
  var nodeLeft;
  var margin;

  var nodes = this.getNodes();
  var s = nodes.length;

  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];
    nodeTop = lNode.getTop();
    nodeLeft = lNode.getLeft();

    if (top > nodeTop)
    {
      top = nodeTop;
    }

    if (left > nodeLeft)
    {
      left = nodeLeft;
    }
  }

  // Do we have any nodes in this graph?
  if (top == Integer.MAX_VALUE)
  {
    return null;
  }

  if(nodes[0].getParent().paddingLeft != undefined){
    margin = nodes[0].getParent().paddingLeft;
  }
  else{
    margin = this.margin;
  }

  this.left = left - margin;
  this.top = top - margin;

  // Apply the margins and return the result
  return new Point(this.left, this.top);
};

LGraph.prototype.updateBounds = function (recursive)
{
  // calculate bounds
  var left = Integer.MAX_VALUE;
  var right = -Integer.MAX_VALUE;
  var top = Integer.MAX_VALUE;
  var bottom = -Integer.MAX_VALUE;
  var nodeLeft;
  var nodeRight;
  var nodeTop;
  var nodeBottom;
  var margin;

  var nodes = this.nodes;
  var s = nodes.length;
  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];

    if (recursive && lNode.child != null)
    {
      lNode.updateBounds();
    }
    nodeLeft = lNode.getLeft();
    nodeRight = lNode.getRight();
    nodeTop = lNode.getTop();
    nodeBottom = lNode.getBottom();

    if (left > nodeLeft)
    {
      left = nodeLeft;
    }

    if (right < nodeRight)
    {
      right = nodeRight;
    }

    if (top > nodeTop)
    {
      top = nodeTop;
    }

    if (bottom < nodeBottom)
    {
      bottom = nodeBottom;
    }
  }

  var boundingRect = new RectangleD(left, top, right - left, bottom - top);
  if (left == Integer.MAX_VALUE)
  {
    this.left = this.parent.getLeft();
    this.right = this.parent.getRight();
    this.top = this.parent.getTop();
    this.bottom = this.parent.getBottom();
  }

  if(nodes[0].getParent().paddingLeft != undefined){
    margin = nodes[0].getParent().paddingLeft;
  }
  else{
    margin = this.margin;
  }

  this.left = boundingRect.x - margin;
  this.right = boundingRect.x + boundingRect.width + margin;
  this.top = boundingRect.y - margin;
  this.bottom = boundingRect.y + boundingRect.height + margin;
};

LGraph.calculateBounds = function (nodes)
{
  var left = Integer.MAX_VALUE;
  var right = -Integer.MAX_VALUE;
  var top = Integer.MAX_VALUE;
  var bottom = -Integer.MAX_VALUE;
  var nodeLeft;
  var nodeRight;
  var nodeTop;
  var nodeBottom;

  var s = nodes.length;

  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];
    nodeLeft = lNode.getLeft();
    nodeRight = lNode.getRight();
    nodeTop = lNode.getTop();
    nodeBottom = lNode.getBottom();

    if (left > nodeLeft)
    {
      left = nodeLeft;
    }

    if (right < nodeRight)
    {
      right = nodeRight;
    }

    if (top > nodeTop)
    {
      top = nodeTop;
    }

    if (bottom < nodeBottom)
    {
      bottom = nodeBottom;
    }
  }

  var boundingRect = new RectangleD(left, top, right - left, bottom - top);

  return boundingRect;
};

LGraph.prototype.getInclusionTreeDepth = function ()
{
  if (this == this.graphManager.getRoot())
  {
    return 1;
  }
  else
  {
    return this.parent.getInclusionTreeDepth();
  }
};

LGraph.prototype.getEstimatedSize = function ()
{
  if (this.estimatedSize == Integer.MIN_VALUE) {
    throw "assert failed";
  }
  return this.estimatedSize;
};

LGraph.prototype.calcEstimatedSize = function ()
{
  var size = 0;
  var nodes = this.nodes;
  var s = nodes.length;

  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];
    size += lNode.calcEstimatedSize();
  }

  if (size == 0)
  {
    this.estimatedSize = LayoutConstants.EMPTY_COMPOUND_NODE_SIZE;
  }
  else
  {
    this.estimatedSize = size / Math.sqrt(this.nodes.length);
  }

  return this.estimatedSize;
};

LGraph.prototype.updateConnected = function ()
{
  var self = this;
  if (this.nodes.length == 0)
  {
    this.isConnected = true;
    return;
  }

  var toBeVisited = [];
  var visited = new HashSet();
  var currentNode = this.nodes[0];
  var neighborEdges;
  var currentNeighbor;
  var childrenOfNode = currentNode.withChildren();
  childrenOfNode.forEach(function(node) {
    toBeVisited.push(node);
  });

  while (toBeVisited.length !== 0)
  {
    currentNode = toBeVisited.shift();
    visited.add(currentNode);

    // Traverse all neighbors of this node
    neighborEdges = currentNode.getEdges();
    var s = neighborEdges.length;
    for (var i = 0; i < s; i++)
    {
      var neighborEdge = neighborEdges[i];
      currentNeighbor =
              neighborEdge.getOtherEndInGraph(currentNode, this);

      // Add unvisited neighbors to the list to visit
      if (currentNeighbor != null &&
              !visited.contains(currentNeighbor))
      {
        var childrenOfNeighbor = currentNeighbor.withChildren();

        childrenOfNeighbor.forEach(function(node) {
          toBeVisited.push(node);
        });
      }
    }
  }

  this.isConnected = false;

  if (visited.size() >= this.nodes.length)
  {
    var noOfVisitedInThisGraph = 0;

    var s = visited.size();
     Object.keys(visited.set).forEach(function(visitedId) {
      var visitedNode = visited.set[visitedId];
      if (visitedNode.owner == self)
      {
        noOfVisitedInThisGraph++;
      }
    });

    if (noOfVisitedInThisGraph == this.nodes.length)
    {
      this.isConnected = true;
    }
  }
};

module.exports = LGraph;
<commit_msg>Swap toBeVisited impl w/ a LinkedList, with same Array/queue interface<commit_after>var LGraphObject = require('./LGraphObject');
var Integer = require('./Integer');
var LayoutConstants = require('./LayoutConstants');
var LGraphManager = require('./LGraphManager');
var LNode = require('./LNode');
var LEdge = require('./LEdge');
var HashSet = require('./HashSet');
var RectangleD = require('./RectangleD');
var Point = require('./Point');
var LinkedList = require('./LinkedList');

function LGraph(parent, obj2, vGraph) {
  LGraphObject.call(this, vGraph);
  this.estimatedSize = Integer.MIN_VALUE;
  this.margin = LayoutConstants.DEFAULT_GRAPH_MARGIN;
  this.edges = [];
  this.nodes = [];
  this.isConnected = false;
  this.parent = parent;

  if (obj2 != null && obj2 instanceof LGraphManager) {
    this.graphManager = obj2;
  }
  else if (obj2 != null && obj2 instanceof Layout) {
    this.graphManager = obj2.graphManager;
  }
}

LGraph.prototype = Object.create(LGraphObject.prototype);
for (var prop in LGraphObject) {
  LGraph[prop] = LGraphObject[prop];
}

LGraph.prototype.getNodes = function () {
  return this.nodes;
};

LGraph.prototype.getEdges = function () {
  return this.edges;
};

LGraph.prototype.getGraphManager = function ()
{
  return this.graphManager;
};

LGraph.prototype.getParent = function ()
{
  return this.parent;
};

LGraph.prototype.getLeft = function ()
{
  return this.left;
};

LGraph.prototype.getRight = function ()
{
  return this.right;
};

LGraph.prototype.getTop = function ()
{
  return this.top;
};

LGraph.prototype.getBottom = function ()
{
  return this.bottom;
};

LGraph.prototype.isConnected = function ()
{
  return this.isConnected;
};

LGraph.prototype.add = function (obj1, sourceNode, targetNode) {
  if (sourceNode == null && targetNode == null) {
    var newNode = obj1;
    if (this.graphManager == null) {
      throw "Graph has no graph mgr!";
    }
    if (this.getNodes().indexOf(newNode) > -1) {
      throw "Node already in graph!";
    }
    newNode.owner = this;
    this.getNodes().push(newNode);

    return newNode;
  }
  else {
    var newEdge = obj1;
    if (!(this.getNodes().indexOf(sourceNode) > -1 && (this.getNodes().indexOf(targetNode)) > -1)) {
      throw "Source or target not in graph!";
    }

    if (!(sourceNode.owner == targetNode.owner && sourceNode.owner == this)) {
      throw "Both owners must be this graph!";
    }

    if (sourceNode.owner != targetNode.owner)
    {
      return null;
    }

    // set source and target
    newEdge.source = sourceNode;
    newEdge.target = targetNode;

    // set as intra-graph edge
    newEdge.isInterGraph = false;

    // add to graph edge list
    this.getEdges().push(newEdge);

    // add to incidency lists
    sourceNode.edges.push(newEdge);

    if (targetNode != sourceNode)
    {
      targetNode.edges.push(newEdge);
    }

    return newEdge;
  }
};

LGraph.prototype.remove = function (obj) {
  var node = obj;
  if (obj instanceof LNode) {
    if (node == null) {
      throw "Node is null!";
    }
    if (!(node.owner != null && node.owner == this)) {
      throw "Owner graph is invalid!";
    }
    if (this.graphManager == null) {
      throw "Owner graph manager is invalid!";
    }
    // remove incident edges first (make a copy to do it safely)
    var edgesToBeRemoved = node.edges.slice();
    var edge;
    var s = edgesToBeRemoved.length;
    for (var i = 0; i < s; i++)
    {
      edge = edgesToBeRemoved[i];

      if (edge.isInterGraph)
      {
        this.graphManager.remove(edge);
      }
      else
      {
        edge.source.owner.remove(edge);
      }
    }

    // now the node itself
    var index = this.nodes.indexOf(node);
    if (index == -1) {
      throw "Node not in owner node list!";
    }

    this.nodes.splice(index, 1);
  }
  else if (obj instanceof LEdge) {
    var edge = obj;
    if (edge == null) {
      throw "Edge is null!";
    }
    if (!(edge.source != null && edge.target != null)) {
      throw "Source and/or target is null!";
    }
    if (!(edge.source.owner != null && edge.target.owner != null &&
            edge.source.owner == this && edge.target.owner == this)) {
      throw "Source and/or target owner is invalid!";
    }

    var sourceIndex = edge.source.edges.indexOf(edge);
    var targetIndex = edge.target.edges.indexOf(edge);
    if (!(sourceIndex > -1 && targetIndex > -1)) {
      throw "Source and/or target doesn't know this edge!";
    }

    edge.source.edges.splice(sourceIndex, 1);

    if (edge.target != edge.source)
    {
      edge.target.edges.splice(targetIndex, 1);
    }

    var index = edge.source.owner.getEdges().indexOf(edge);
    if (index == -1) {
      throw "Not in owner's edge list!";
    }

    edge.source.owner.getEdges().splice(index, 1);
  }
};

LGraph.prototype.updateLeftTop = function ()
{
  var top = Integer.MAX_VALUE;
  var left = Integer.MAX_VALUE;
  var nodeTop;
  var nodeLeft;
  var margin;

  var nodes = this.getNodes();
  var s = nodes.length;

  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];
    nodeTop = lNode.getTop();
    nodeLeft = lNode.getLeft();

    if (top > nodeTop)
    {
      top = nodeTop;
    }

    if (left > nodeLeft)
    {
      left = nodeLeft;
    }
  }

  // Do we have any nodes in this graph?
  if (top == Integer.MAX_VALUE)
  {
    return null;
  }

  if(nodes[0].getParent().paddingLeft != undefined){
    margin = nodes[0].getParent().paddingLeft;
  }
  else{
    margin = this.margin;
  }

  this.left = left - margin;
  this.top = top - margin;

  // Apply the margins and return the result
  return new Point(this.left, this.top);
};

LGraph.prototype.updateBounds = function (recursive)
{
  // calculate bounds
  var left = Integer.MAX_VALUE;
  var right = -Integer.MAX_VALUE;
  var top = Integer.MAX_VALUE;
  var bottom = -Integer.MAX_VALUE;
  var nodeLeft;
  var nodeRight;
  var nodeTop;
  var nodeBottom;
  var margin;

  var nodes = this.nodes;
  var s = nodes.length;
  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];

    if (recursive && lNode.child != null)
    {
      lNode.updateBounds();
    }
    nodeLeft = lNode.getLeft();
    nodeRight = lNode.getRight();
    nodeTop = lNode.getTop();
    nodeBottom = lNode.getBottom();

    if (left > nodeLeft)
    {
      left = nodeLeft;
    }

    if (right < nodeRight)
    {
      right = nodeRight;
    }

    if (top > nodeTop)
    {
      top = nodeTop;
    }

    if (bottom < nodeBottom)
    {
      bottom = nodeBottom;
    }
  }

  var boundingRect = new RectangleD(left, top, right - left, bottom - top);
  if (left == Integer.MAX_VALUE)
  {
    this.left = this.parent.getLeft();
    this.right = this.parent.getRight();
    this.top = this.parent.getTop();
    this.bottom = this.parent.getBottom();
  }

  if(nodes[0].getParent().paddingLeft != undefined){
    margin = nodes[0].getParent().paddingLeft;
  }
  else{
    margin = this.margin;
  }

  this.left = boundingRect.x - margin;
  this.right = boundingRect.x + boundingRect.width + margin;
  this.top = boundingRect.y - margin;
  this.bottom = boundingRect.y + boundingRect.height + margin;
};

LGraph.calculateBounds = function (nodes)
{
  var left = Integer.MAX_VALUE;
  var right = -Integer.MAX_VALUE;
  var top = Integer.MAX_VALUE;
  var bottom = -Integer.MAX_VALUE;
  var nodeLeft;
  var nodeRight;
  var nodeTop;
  var nodeBottom;

  var s = nodes.length;

  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];
    nodeLeft = lNode.getLeft();
    nodeRight = lNode.getRight();
    nodeTop = lNode.getTop();
    nodeBottom = lNode.getBottom();

    if (left > nodeLeft)
    {
      left = nodeLeft;
    }

    if (right < nodeRight)
    {
      right = nodeRight;
    }

    if (top > nodeTop)
    {
      top = nodeTop;
    }

    if (bottom < nodeBottom)
    {
      bottom = nodeBottom;
    }
  }

  var boundingRect = new RectangleD(left, top, right - left, bottom - top);

  return boundingRect;
};

LGraph.prototype.getInclusionTreeDepth = function ()
{
  if (this == this.graphManager.getRoot())
  {
    return 1;
  }
  else
  {
    return this.parent.getInclusionTreeDepth();
  }
};

LGraph.prototype.getEstimatedSize = function ()
{
  if (this.estimatedSize == Integer.MIN_VALUE) {
    throw "assert failed";
  }
  return this.estimatedSize;
};

LGraph.prototype.calcEstimatedSize = function ()
{
  var size = 0;
  var nodes = this.nodes;
  var s = nodes.length;

  for (var i = 0; i < s; i++)
  {
    var lNode = nodes[i];
    size += lNode.calcEstimatedSize();
  }

  if (size == 0)
  {
    this.estimatedSize = LayoutConstants.EMPTY_COMPOUND_NODE_SIZE;
  }
  else
  {
    this.estimatedSize = size / Math.sqrt(this.nodes.length);
  }

  return this.estimatedSize;
};

LGraph.prototype.updateConnected = function ()
{
  var self = this;
  if (this.nodes.length == 0)
  {
    this.isConnected = true;
    return;
  }

  var toBeVisited = new LinkedList();
  var visited = new HashSet();
  var currentNode = this.nodes[0];
  var neighborEdges;
  var currentNeighbor;
  var childrenOfNode = currentNode.withChildren();
  childrenOfNode.forEach(function(node) {
    toBeVisited.push(node);
  });

  while (toBeVisited.length !== 0)
  {
    currentNode = toBeVisited.shift();
    visited.add(currentNode);

    // Traverse all neighbors of this node
    neighborEdges = currentNode.getEdges();
    var s = neighborEdges.length;
    for (var i = 0; i < s; i++)
    {
      var neighborEdge = neighborEdges[i];
      currentNeighbor =
              neighborEdge.getOtherEndInGraph(currentNode, this);

      // Add unvisited neighbors to the list to visit
      if (currentNeighbor != null &&
              !visited.contains(currentNeighbor))
      {
        var childrenOfNeighbor = currentNeighbor.withChildren();

        childrenOfNeighbor.forEach(function(node) {
          toBeVisited.push(node);
        });
      }
    }
  }

  this.isConnected = false;

  if (visited.size() >= this.nodes.length)
  {
    var noOfVisitedInThisGraph = 0;

    var s = visited.size();
     Object.keys(visited.set).forEach(function(visitedId) {
      var visitedNode = visited.set[visitedId];
      if (visitedNode.owner == self)
      {
        noOfVisitedInThisGraph++;
      }
    });

    if (noOfVisitedInThisGraph == this.nodes.length)
    {
      this.isConnected = true;
    }
  }
};

module.exports = LGraph;
<|endoftext|>


<commit_before>import { Vertex } from './Geometry';
import Victor from 'victor';

// Determines which of 8 neighbor areas the point is in:
//   https://stackoverflow.com/questions/3746274/line-intersection-with-aabb-rectangle
//
//           |          |
//   0b1001  |  0b0001  |  0b0101
//           |          |
// ------------------------------ y_max
//           |          |
//   0b1000  |  0b0000  |  0b0100
//           |          |
// ------------------------------ y_min
//           |          |
//   0b1010  |  0b0010  |  0b0110
//           |          |
//         x_min      x_max
//
function pointLocation(point, size_x, size_y) {
  var location = 0b0;
  if (point.x < -size_x) {
    location += 0b1000;
  } else if (point.x > size_x) {
    location += 0b0100;
  }

  if (point.y < -size_y) {
    location += 0b0001;
  } else if (point.y > size_y) {
    location += 0b0010;
  }

  return location;
}

// Determine intersection with one of the sides
function intersection(line_start, line_end, side_start, side_end) {

  var line = line_end.clone().subtract(line_start);
  var side = side_end.clone().subtract(side_start);
  var lineCrossSidePerp = line.x * side.y - line.y * side.x;

  // if line Cross side === 0, it means the lines are parallel so have infinite intersection points
  if (lineCrossSidePerp === 0) {
    return null;
  }

  var diff = side_start.clone().subtract(line_start);
  var t = (diff.x * side.y - diff.y * side.x) / lineCrossSidePerp;
  if (t < 0 || t >= 1) {
    return null;
  }

  var u = (diff.x * line.y - diff.y * line.x) / lineCrossSidePerp;
  if (u < 0 || u >= 1) {
    return null;
  }

  var intersection = line_start.clone().add(line.clone().multiply(Victor(t, t)));
  return intersection;
}

function clipLine(line_start, line_end, size_x, size_y) {

  var quadrant_start = pointLocation(line_start, size_x, size_y);
  var quadrant_end = pointLocation(line_end, size_x, size_y);

  if (quadrant_start === 0b0000 && quadrant_end === 0b0000) {
    // The line is inside the boundaries
    return [line_start, line_end];
  }

  if (quadrant_start === quadrant_end) {
    // We are in the same box, and we are out of bounds.
    console.log('stay')
    return [nearestVertex(line_start, size_x, size_y), nearestVertex(line_end, size_x, size_y)];
  }

  if (quadrant_start & quadrant_end) {
    console.log('one side')
    // These points are all on one side of the box.
    return [nearestVertex(line_start, size_x, size_y), nearestVertex(line_end, size_x, size_y)];
  }

  if (quadrant_start === 0b000) {
    console.log('leaving')
    // We are exiting the box.
    var line = [line_start];
    line.push(boundPoint(line_start, line_end, size_x, size_y));
    line.push(nearestVertex(line_end, size_x, size_y));
    return line;
  }

  if (quadrant_end === 0b000) {
    console.log('returning')
    // We are re-entering the box.
    return [boundPoint(line_end, line_start, size_x, size_y), line_end];
  }

  // We have reached a terrible place, where both points are oob, but it might intersect with the
  // work area.
  const sides = [
    // left
    [Victor(-size_x, -size_y), Victor(-size_x, size_y)],
    // right
    [Victor(size_x, -size_y), Victor(size_x, size_y)],
    // bottom
    [Victor(-size_x, -size_y), Victor(size_x, -size_y)],
    // top
    [Victor(-size_x, size_y), Victor(size_x, size_y)],
  ]

  var intersections = []
  for (var s=0; s<sides.length; s++) {
    var int_point = intersection(Victor.fromObject(line_start),
                                 Victor.fromObject(line_end),
                                 sides[s][0],
                                 sides[s][1]);
    if (int_point) {
      intersections.push(Vertex(int_point.x, int_point.y));
    }
  }

  if (intersections.length !== 0) {
    if (intersections.length !== 2) {
      // We should never get here
      console.log(intersections);
      throw Error("Software Geometry Error");
    }
    console.log('through');

    // Determine if they are in the right order.
    if (Victor.fromObject(intersections[0]).subtract(Victor.fromObject(line_start)).lengthSq() >
        Victor.fromObject(intersections[1]).subtract(Victor.fromObject(line_start)).lengthSq()) {
      var temp = intersections[0];
      intersections[0] = intersections[1];
      intersections[1] = temp;
      console.log("swapped");
    }
    return intersections;
  }

  // We might need to insert some corner points...
  console.log('give up');
  var midpoint = Victor.fromObject(line_start).add(Victor.fromObject(line_end)).multiply(Victor(0.5, 0.5));
  // recurse, and find smaller segments until we don't end up in this place again.
  return [...clipLine(line_start, midpoint, size_x, size_y),
          ...clipLine(midpoint,   line_end, size_x, size_y)];
}

// Finds the nearest vertex that is in the bounds.
function nearestVertex(vertex, size_x, size_y) {
  return Vertex(Math.min(size_x, Math.max(-size_x, vertex.x)),
                Math.min(size_y, Math.max(-size_y, vertex.y)));
}

// Determines of a point is in bounds or out.
function outOfBounds(vertex, size_x, size_y) {
  return (vertex.x < -size_x || vertex.x > size_x ||
          vertex.y < -size_y || vertex.y > size_y);
}

// Find the point on the line defined by these two vertices that is exactly within the limits.
function boundPoint(good, bad, size_x, size_y) {
  var dx = good.x - bad.x;
  var dy = good.y - bad.y;

  if (outOfBounds(good)) {
    console.log('===================');
    console.log(good);
    console.log(bad);
  }
  var fixed = Vertex(bad.x, bad.y);
  var distance = 0;
  if (bad.x < -size_x || bad.x > size_x) {
    if (bad.x < -size_x) {
      // we are leaving the left
      fixed.x = -size_x;
    } else {
      // we are leaving the right
      fixed.x = size_x;
    }
    distance = (fixed.x - good.x) / dx;
    fixed.y = good.y + distance * dy;
    // We fixed x, but y might have the same problem, so we'll rerun this, with different points.
    return boundPoint(good, fixed, size_x, size_y);
  }
  if (bad.y < -size_y || bad.y > size_y) {
    if (bad.y < -size_y) {
      // we are leaving the bottom
      fixed.y = -size_y;
    } else {
      // we are leaving the top
      fixed.y = size_y;
    }
    distance = (fixed.y - good.y) / dy;
    fixed.x = good.x + distance * dx;
  }
  return fixed;
}

function enforceLimits(vertices, size_x, size_y) {
  var cleanVertices = []
  var previous = null;
  console.log('=============');
  for (var next=0; next<vertices.length; next++) {
    var vertex = vertices[next];
    if (previous) {
      var line = clipLine(previous, vertex, size_x, size_y);
      for (var pt=0; pt<line.length; pt++) {
        if (line[pt] !== previous) {
          cleanVertices.push(line[pt]);
        }
      }
    } else {
      cleanVertices.push(nearestVertex(vertex, size_x, size_y));
    }
    previous = vertex;
  }

  // // Just for sanity, and cases that I haven't thought of, clean this list again.
  // var cleanerVertices = []
  // for (var i=0; i<cleanVertices.length; i++) {
  //   cleanerVertices.push(nearestVertex(cleanVertices[i], size_x, size_y));
  // }

  return cleanVertices;
}

export default enforceLimits
<commit_msg>Cleanup, and comments.<commit_after>import { Vertex } from './Geometry';
import Victor from 'victor';

// Determines which of 8 neighbor areas the point is in:
//   https://stackoverflow.com/questions/3746274/line-intersection-with-aabb-rectangle
//
//           |          |
//   0b1001  |  0b0001  |  0b0101
//           |          |
// ------------------------------ y_max
//           |          |
//   0b1000  |  0b0000  |  0b0100
//           |          |
// ------------------------------ y_min
//           |          |
//   0b1010  |  0b0010  |  0b0110
//           |          |
//         x_min      x_max
//
function pointLocation(point, size_x, size_y) {
  var location = 0b0;
  if (point.x < -size_x) {
    location += 0b1000;
  } else if (point.x > size_x) {
    location += 0b0100;
  }

  if (point.y < -size_y) {
    location += 0b0001;
  } else if (point.y > size_y) {
    location += 0b0010;
  }

  return location;
}

// Determine intersection with one of the sides
function intersection(line_start, line_end, side_start, side_end) {

  var line = line_end.clone().subtract(line_start);
  var side = side_end.clone().subtract(side_start);
  var lineCrossSidePerp = line.x * side.y - line.y * side.x;

  // if line Cross side === 0, it means the lines are parallel so have infinite intersection points
  if (lineCrossSidePerp === 0) {
    return null;
  }

  var diff = side_start.clone().subtract(line_start);
  var t = (diff.x * side.y - diff.y * side.x) / lineCrossSidePerp;
  if (t < 0 || t >= 1) {
    return null;
  }

  var u = (diff.x * line.y - diff.y * line.x) / lineCrossSidePerp;
  if (u < 0 || u >= 1) {
    return null;
  }

  var intersection = line_start.clone().add(line.clone().multiply(Victor(t, t)));
  return intersection;
}

// This method is the guts of logic for this limits enforcer. It will take a single line (defined by
// start and end) and if the line goes out of bounds, returns the vertices around the outside edge
// to follow around without messing up the shape of the vertices.
//
function clipLine(line_start, line_end, size_x, size_y) {

  var quadrant_start = pointLocation(line_start, size_x, size_y);
  var quadrant_end = pointLocation(line_end, size_x, size_y);

  if (quadrant_start === 0b0000 && quadrant_end === 0b0000) {
    // The line is inside the boundaries
    return [line_start, line_end];
  }

  if (quadrant_start === quadrant_end) {
    // We are in the same box, and we are out of bounds.
    return [nearestVertex(line_start, size_x, size_y), nearestVertex(line_end, size_x, size_y)];
  }

  if (quadrant_start & quadrant_end) {
    // These points are all on one side of the box.
    return [nearestVertex(line_start, size_x, size_y), nearestVertex(line_end, size_x, size_y)];
  }

  if (quadrant_start === 0b000) {
    // We are exiting the box. Return the start, the intersection with the boundary, and the closest
    // boundary point to the exited point.
    var line = [line_start];
    line.push(boundPoint(line_start, line_end, size_x, size_y));
    line.push(nearestVertex(line_end, size_x, size_y));
    return line;
  }

  if (quadrant_end === 0b000) {
    // We are re-entering the box.
    return [boundPoint(line_end, line_start, size_x, size_y), line_end];
  }

  // We have reached a terrible place, where both points are oob, but it might intersect with the
  // work area.

  // First, define the boundaries as lines.
  const sides = [
    // left
    [Victor(-size_x, -size_y), Victor(-size_x, size_y)],
    // right
    [Victor(size_x, -size_y), Victor(size_x, size_y)],
    // bottom
    [Victor(-size_x, -size_y), Victor(size_x, -size_y)],
    // top
    [Victor(-size_x, size_y), Victor(size_x, size_y)],
  ]

  // Count up the number of boundary lines intersect with our line segment.
  var intersections = []
  for (var s=0; s<sides.length; s++) {
    var int_point = intersection(Victor.fromObject(line_start),
                                 Victor.fromObject(line_end),
                                 sides[s][0],
                                 sides[s][1]);
    if (int_point) {
      intersections.push(Vertex(int_point.x, int_point.y));
    }
  }

  if (intersections.length !== 0) {
    if (intersections.length !== 2) {
      // We should never get here. How would we have something other than 2 or 0 intersections with
      // a box?
      console.log(intersections);
      throw Error("Software Geometry Error");
    }

    // The intersections are tested in some normal order, but the line could be going through them
    // in any direction. This check will flip the intersections if they are reversed somehow.
    if (Victor.fromObject(intersections[0]).subtract(Victor.fromObject(line_start)).lengthSq() >
        Victor.fromObject(intersections[1]).subtract(Victor.fromObject(line_start)).lengthSq()) {
      var temp = intersections[0];
      intersections[0] = intersections[1];
      intersections[1] = temp;
    }
    return intersections;
  }

  // Damn. We got here because we have a start and end that are failing different boundary checks,
  // and the line segment doesn't intersect the box. We have to crawl around the outside of the
  // box until we reach the other point.
  //
  // Here, I'm going to split this line into two parts, and send each half line segment back
  // through the clipLine algorithm. Eventually, that should result in only one of the other cases.
  var midpoint = Victor.fromObject(line_start).add(Victor.fromObject(line_end)).multiply(Victor(0.5, 0.5));
  // recurse, and find smaller segments until we don't end up in this place again.
  return [...clipLine(line_start, midpoint, size_x, size_y),
          ...clipLine(midpoint,   line_end, size_x, size_y)];
}

// Finds the nearest vertex that is in the bounds. This will change the shape. i.e. this doesn't
// care about the line segment, only about the point.
function nearestVertex(vertex, size_x, size_y) {
  return Vertex(Math.min(size_x, Math.max(-size_x, vertex.x)),
                Math.min(size_y, Math.max(-size_y, vertex.y)));
}

// Intersect the line with the boundary, and return the point exactly on the boundary.
// This will keep the shape. i.e. It will follow the line segment, and return the point on that line
// segment.
function boundPoint(good, bad, size_x, size_y) {
  var dx = good.x - bad.x;
  var dy = good.y - bad.y;

  var fixed = Vertex(bad.x, bad.y);
  var distance = 0;
  if (bad.x < -size_x || bad.x > size_x) {
    if (bad.x < -size_x) {
      // we are leaving the left
      fixed.x = -size_x;
    } else {
      // we are leaving the right
      fixed.x = size_x;
    }
    distance = (fixed.x - good.x) / dx;
    fixed.y = good.y + distance * dy;
    // We fixed x, but y might have the same problem, so we'll rerun this, with different points.
    return boundPoint(good, fixed, size_x, size_y);
  }
  if (bad.y < -size_y || bad.y > size_y) {
    if (bad.y < -size_y) {
      // we are leaving the bottom
      fixed.y = -size_y;
    } else {
      // we are leaving the top
      fixed.y = size_y;
    }
    distance = (fixed.y - good.y) / dy;
    fixed.x = good.x + distance * dx;
  }
  return fixed;
}

// Manipulates the points to make them all in bounds, while doing the least amount of damage to the
// desired shape.
function enforceLimits(vertices, size_x, size_y) {
  var cleanVertices = []
  var previous = null;

  for (var next=0; next<vertices.length; next++) {
    var vertex = vertices[next];
    if (previous) {
      var line = clipLine(previous, vertex, size_x, size_y);
      for (var pt=0; pt<line.length; pt++) {
        if (line[pt] !== previous) {
          cleanVertices.push(line[pt]);
        }
      }
    } else {
      cleanVertices.push(nearestVertex(vertex, size_x, size_y));
    }
    previous = vertex;
  }

  // // Just for sanity, and cases that I haven't thought of, clean this list again.
  var cleanerVertices = []
  for (var i=0; i<cleanVertices.length; i++) {
    cleanerVertices.push(nearestVertex(cleanVertices[i], size_x, size_y));
  }

  return cleanerVertices;
}

export default enforceLimits
<|endoftext|>


<commit_before>var constructor = Meteor.Collection;
var Document = {};

Meteor.Collection = function(name, options) {
  if (typeof options === 'undefined')
    options = {};

  Document[name] = function(doc) { return _.extend(this, doc); };
  options.transform = function(doc) { return new Document[name](doc); };

  return constructor.call(this, name, options);
};

Meteor.Collection.prototype = Object.create(constructor.prototype);
Meteor.Collection.prototype.helpers = function(helpers) {
  var self = this;
  _.each(helpers, function(helper, key) {
    Document[self._name].prototype[key] = helper;
  });
};

for (var func in constructor) {
  if (constructor.hasOwnProperty(func)) {
    Meteor.Collection[func] = constructor[func];
  }
}

if (typeof Meteor.users !== 'undefined') {
  var User = function(doc) { return _.extend(this, doc); };
  Meteor.users._transform = function(doc) { return new User(doc); };
  Meteor.users.helpers = function(helpers) {
    _.each(helpers, function(helper, key) {
      User.prototype[key] = helper;
    });
  };
}<commit_msg>big refactor<commit_after>var Document = {};

Meteor.Collection.prototype.helpers = function(helpers) {
  var self = this;
  if (! Document[self._name]) Document[self._name] = function(doc) { return _.extend(this, doc); };
  _.each(helpers, function(helper, key) {
    Document[self._name].prototype[key] = helper;
  });
  if (! this._transform)
    this._transform = function(doc) { return new Document[self._name](doc); };
};
<|endoftext|>


<commit_before>// ======== DB-Model: ========
// "_id" -> ID
// "title" -> string
// "description" -> string
// "mentors" -> [userIDs]   optional
// "startdate" -> ISODate
// "hosts" -> [userIDs]     optional
// "location" -> ...............
// "createdby" -> userId
// "time_created" -> timestamp
// "time_lastedit" -> timestamp
// "course_id" -> ID_course          (maybe list in Future)
// ===========================

Events = new Meteor.Collection("Events");

Events.allow({
	update: function (userId, doc, fieldNames, modifier) {
		return userId && true;	// allow only if UserId is present
	},
	insert: function (userId, doc) {
		return userId && true;	// allow only if UserId is present
	},
	remove: function (userId, doc) {
		return userId && true;	// allow only if UserId is present
	}
});
<commit_msg>Update events.js<commit_after>// ======== DB-Model: ========
// "_id" -> ID
// "title" -> string
// "description" -> string
// "mentors" -> [userIDs]   optional
// "startdate" -> ISODate
// "host" -> [userIDs]     optional
// "location" -> ...............
// "createdby" -> userId
// "time_created" -> timestamp
// "time_lastedit" -> timestamp
// "course_id" -> ID_course          (maybe list in Future)
// ===========================

Events = new Meteor.Collection("Events");

Events.allow({
	update: function (userId, doc, fieldNames, modifier) {
		return userId && true;	// allow only if UserId is present
	},
	insert: function (userId, doc) {
		return userId && true;	// allow only if UserId is present
	},
	remove: function (userId, doc) {
		return userId && true;	// allow only if UserId is present
	}
});
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');

const getFileList = (dirName) => {
  const fileList = fs.readdirSync(dirName);
  return fileList || [];
};

const loadHelpText = (filename) => {
  const content = fs.readFileSync(filename);
  return content || '';
};

// basic help commands
const simpleResponses = {};

module.exports = {
  usage: 'help <topic> - displays known resources about <topic>',

  run: (bot, message, cmdArgs) => {
    if (cmdArgs) {
      const response = simpleResponses[cmdArgs.toLowerCase()];
      bot.client.reply(message, response ||
        "I don't know anything about that. If you have a suggestion, let us know!");
    } else {
      bot.client.reply(message,
        "Awesome is my name, don't wear it out! Please give a me topic for more info.");
    }
  },

  init: () => {
    console.log('Loading help topics');
    getFileList(path.join(__dirname, 'topics')).forEach(fn => {
      simpleResponses[path.basename(fn, '.txt')] = loadHelpText(path.join(__dirname, 'topics', fn));
    });
  },
};

<commit_msg>if no topic is given, lists known topics<commit_after>const fs = require('fs');
const path = require('path');

const getFileList = (dirName) => {
  const fileList = fs.readdirSync(dirName);
  return fileList || [];
};

const loadHelpText = (filename) => {
  const content = fs.readFileSync(filename);
  return content || '';
};

// basic help commands
const knownTopics = {};

module.exports = {
  usage: [
    'help <topic> - displays known resources about <topic>',
    'help - list known topics',
  ],

  run: (bot, message, cmdArgs) => {
    if (cmdArgs) {
      const response = knownTopics[cmdArgs.toLowerCase()];
      bot.client.reply(message, response ||
        'I don\'t know anything about that. If you have a suggestion, let us know!');
    } else {
      let r = 'Awesome is my name, don\'t wear it out! Please give a me topic for more info.';
      r += '\n\nTopics I know something about:';
      r += '\n```';
      Object.keys(knownTopics).forEach(t => {
        r += `\n  - ${t}`;
      });
      r += '\n```';
      bot.client.reply(message, r);
    }
  },

  init: () => {
    console.log('Loading help topics...');
    getFileList(path.join(__dirname, 'topics')).forEach(fn => {
      knownTopics[path.basename(fn, '.txt')] = loadHelpText(path.join(__dirname, 'topics', fn));
    });
  },
};

<|endoftext|>


<commit_before>'use strict';

const request = require('request');
const auth = require('../../auth');

module.exports.getLink = function(link, query) {
    if(!query) return Promise.resolve(link);

      request({
          uri: 'https://www.googleapis.com/youtube/v3/search',
          qs: {
            q: link,
            part: 'snippet',
            key: auth.yt_key,
            maxResults: '1',
            type: 'video'
          },
          json: true
      },
      (err, response, body) => {
        if(err) {
          console.log(`Error geting YT song: ${err.stack}`);
          throw new Error(`Error getting YT song`);
        }

        if(response.statusCode !== 200 || !body) {
          console.log(`Didn\t receive a 200 from youtube song query, or there was no body`);
          throw new Error(`Error getting YT song`);
        }

        return Promise.resolve(body.items[0].id.videoId);
      });
    }
}

module.exports.getSource = function(song) {
    try {
        if(song.test(/s\w*c|y\w*t/)) {
            if(song.test(/s\w*c/)) return 'sc';
            if(song.test(/y\w*t/)) return 'yt';
        }
        else {
            if(song.test(/http/)) return;
            return 'query';
        }
    } catch(err) {
        console.log(`Error with regex in getSongSource function: ${err}`);
        return;
    }
}

module.exports.strToMs = function(time) {
    let num = 0;
    try {
        num = time.match(/(\d+ ?[mhs])/gi);
    } catch(err) {
        console.log(`Error with regex in strToMs function: ${err}`);
        return;
    }

    if(!num || num.length < 1 || num.length > 3) return;
    num = num.splice(0, 3);

    let hours = 0,
        minutes = 0,
        seconds = 0;

    for(let i of num) {
        if(~i.indexOf('h'))
            hours = i.match(/\d+/);
        if(~i.indexOf('m'))
            minutes = i.match(/\d+/);
        if(~i.indexOf('s'))
            seconds = i.match(/\d+/);
    }

    let retStr = '';
    if(hours)
        retStr += `${parseInt(hours)} hour(s) `;
    if(minutes)
        retStr += `${parseInt(minutes)} minute(s) `;
    if(seconds)
        retStr += `${parseInt(seconds)} second(s) `;

    let indexLstMatch = time.lastIndexOf(num[num.length - 1]) + num[num.length - 1].length - 1;
    let lstSpcAftMtch = time.indexOf(' ', indexLstMatch);   //these variable names tho

    return {
        ms: (parseInt(hours) * 3600000) + (parseInt(minutes) * 60000) + (parseInt(seconds) * 1000),
        str: retStr,
        content: time.substring(lstSpcAftMtch)
    }
}
<commit_msg>fixed small error with brackets<commit_after>'use strict';

const request = require('request');
const auth = require('../../auth');

module.exports.getLink = function(link, query) {
    if(!query) return Promise.resolve(link);

    request({
        uri: 'https://www.googleapis.com/youtube/v3/search',
        qs: {
            q: link,
            part: 'snippet',
            key: auth.yt_key,
            maxResults: '1',
            type: 'video'
        },
        json: true
    },
    (err, response, body) => {
        if(err) {
            console.log(`Error geting YT song: ${err.stack}`);
            throw new Error(`Error getting YT song`);
        }

        if(response.statusCode !== 200 || !body) {
            console.log(`Didn\t receive a 200 from youtube song query, or there was no body`);
            throw new Error(`Error getting YT song`);
        }

        return Promise.resolve(body.items[0].id.videoId);
    });
}

module.exports.getSource = function(song) {
    try {
        if(song.test(/s\w*c|y\w*t/)) {
            if(song.test(/s\w*c/)) return 'sc';
            if(song.test(/y\w*t/)) return 'yt';
        }
        else {
            if(song.test(/http/)) return;
            return 'query';
        }
    } catch(err) {
        console.log(`Error with regex in getSongSource function: ${err}`);
        return;
    }
}

module.exports.strToMs = function(time) {
    let num = 0;
    try {
        num = time.match(/(\d+ ?[mhs])/gi);
    } catch(err) {
        console.log(`Error with regex in strToMs function: ${err}`);
        return;
    }

    if(!num || num.length < 1 || num.length > 3) return;
    num = num.splice(0, 3);

    let hours = 0,
    minutes = 0,
    seconds = 0;

    for(let i of num) {
        if(~i.indexOf('h'))
        hours = i.match(/\d+/);
        if(~i.indexOf('m'))
        minutes = i.match(/\d+/);
        if(~i.indexOf('s'))
        seconds = i.match(/\d+/);
    }

    let retStr = '';
    if(hours)
    retStr += `${parseInt(hours)} hour(s) `;
    if(minutes)
    retStr += `${parseInt(minutes)} minute(s) `;
    if(seconds)
    retStr += `${parseInt(seconds)} second(s) `;

    let indexLstMatch = time.lastIndexOf(num[num.length - 1]) + num[num.length - 1].length - 1;
    let lstSpcAftMtch = time.indexOf(' ', indexLstMatch);   //these variable names tho

    return {
        ms: (parseInt(hours) * 3600000) + (parseInt(minutes) * 60000) + (parseInt(seconds) * 1000),
        str: retStr,
        content: time.substring(lstSpcAftMtch)
    }
}
<|endoftext|>