<commit_before> WGL.ui.StackedBarChart = function(m, div_id, x_label, filterId, params) {

	var type;
	var div_id;

	var w;
	var h;
	var margin;
	if (typeof(params)=='undefined'){
		w = 500;
		h = 215;
		margin = {
			top : 20,
			right : 20,
			bottom : 65,
			left : 60
			};
	} else {
		w=params.w;
		h=params.h;
		margin=params.margin;
	}

	var dataset;
	var xScale;
	var yScale;
	var colorScale;
	var xAxis;
	var yAxis;
	var bars;
	var svg;
	var chart;
	var active_group = 2;

	var width = w - margin.left - margin.right;
	var height = h - margin.top - margin.bottom;
	var dataset = null;
	var svgbw = "";

	 this.y_label = "detections";

	this.setLinearXScale = function(){
		xScale = new d3.scale.linear();
		xScale = d3.scale.linear().domain([ m.min , m.max ]).range([ 0, width ]);
		var bw = Math.floor(width / dataset.length );
		svgbw= "h"+bw+"V";
		type = 'linear';
		return this;
	}

	this.setOrdinalXScale = function(){
		xScale = d3.scale.ordinal().domain(m.domain).rangeBands([ 0, width ],0.03,0.015);
		var bw =xScale.rangeBand();
		svgbw= "h"+bw+"V";
		type = 'ordinal';
		return this;
	}

	this.xformat = function(d){
			return d;
	};
	var yformat = d3.format(".2n");

	 this.setYFormat = function (fuc) {
		 yformat = fuc;
	 };

/*	this.setTicks = function(n){
		xAxis.ticks(n) ;
	}

	this.setTicksValues = function(v){
		xAxis.ticksValues(v);
	}*/
	this.init = function() {
		// xScale = d3.scale.ordinal().rangeRoundBands([0, width], .1);
		// xScale = d3.scale.ordinal().rangeRoundBands([0, width], .1);

		//this.setLinearXScale();
		if (typeof m.domain == 'undefined'){
			this.setLinearXScale();
		} else {
			this.setOrdinalXScale();
		}

		var cols = [ "#ff8c00", "#7b6888", "#98abc5" ];
		//var cols = [ "#ff8c00", "#3182bd", "#98abc5" ];
		var classes = [ [ "0", "selected", cols[0] ],
				[ "1", "unselected", cols[1] ], [ "2", "out", cols[2] ] ];

		colorScale = d3.scale.ordinal().range(cols);

		yScale = d3.scale.linear().domain([ 0, dataset.max[2] ]).range(
				[ height, 0 ]);

		colorScale.domain([ "selected", "unselected", "out" ]);

		//to update label printing
		//new Date(d*1000).getYear()};

		xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickFormat(this.xformat);

		//yAxis = d3.svg.axis().scale(yScale).orient("left");
		yAxis = d3.svg.axis().scale(yScale).orient("left").tickFormat(yformat); //changes

		// xScale.domain(this.dataset.map(function(d) {
		// return d.max-(d.max-d.min)/2; }));

		svg = d3.select("#" + div_id).append("svg").attr("width",
				width + margin.left + margin.right).attr("height",
				height + margin.top + margin.bottom).append("g").attr(
				"transform",
				"translate(" + margin.left + "," + margin.top + ")");

		chart = svg.select('.chart');
		svg.append("g").attr("class", "x axis").attr("transform",
				"translate(0," + height + ")").call(xAxis).append("text")
			    .attr("y", "3.5em").attr("x",
				width /2 ).style("text-anchor", "end").text(x_label);

		svg.append("g").attr("class", "y axis").call(yAxis).append("text")
				.attr("transform", "rotate(270)").attr("y", "-4.5em").attr("x",
						"-2em").style("text-anchor", "end").text(this.y_label); //changes

		/*
		 * bars = svg.selectAll(".bars").data(dataset).enter()
		 * .append("g").attr("class", "g").attr("transform", function(d) {
		 * return "translate(" + (xScale(d.min)+xScale(d.max))/2 + ",0)"; });
		 */

		/* new bars */
		svg.append("clipPath").attr("id", "clip-" + div_id).append("rect")
				.attr("width", width).attr("height", height);

		bars = svg.selectAll(".bar").data([ "selected", "unselected", "out" ])
				.enter().append("path").attr("class", function(d) {
					return d + " foreground bar ";
				}).datum(dataset);

		//bars.on("click", function(d)
		//		{ d.selected = !d.selected;
		//			console.log(d);
		//		})

		svg.selectAll(".foreground.bar").attr("clip-path",
				"url(#clip-" + div_id + ")");

		// update(dataset);
		// svg.selectAll("selected bar").attr("d", barPathSelected);

		/* data */
		dataset.forEach(function(d) {
			var y0 = 0;
			d.levels = colorScale.domain().map(function(name) {
				return {
					name : name,
					y0 : y0,
					y1 : y0 += +d[name]
				};
			});
			d.total = 0;
		});

		/*
		 * bars.selectAll("path").data(function(m) { return m.levels;
		 * }).enter().append("rect").attr("y", function(d) { return
		 * yScale(d.y1); }).attr("width", bw).attr("height", function(d) {
		 * return yScale(d.y0) - yScale(d.y1); }).attr("fill", function(d) {
		 * return colorScale(d.name); }).attr("class", function(d){return
		 * div_id+d.name});
		 */
		function brushLinear() {
			var f = brush1.extent();
			WGL.filterDim(m.name, filterId, f);
			//console.log(brush1.extent()[0][0]+' '+brush1.extent()[0][1]);
		}

		function brushOrdinal() {
			var f = brush1.extent();
			var of = []
			var l = xScale.domain().length;
			for (var i in f){
				of[i] = [];
				of[i][0] = f[i][0] /width * l;
				of[i][1] = f[i][1] /width * l;
			}
			WGL.filterDim(m.name,filterId, of);
			//console.log(of[0][0]+' '+of[0][1]);

		}
		var brush;
		if (type=='linear') {
			brush = brushLinear;
		}
		else if (type=='ordinal'){
			brush = brushOrdinal;
		}

		var brush1 = d3.svg.multibrush().x(xScale).extentAdaption(resizeExtent)
				.on("brush", brush).on("brushend", function(d) {
					if (brush1.extent().length == 0) {
						brush();
					}

				});
		this.brush = brush1;

		var brushNode = svg.append("g").attr("class", "brush").call(brush1)
				.selectAll("rect").attr("height", height);

		/**
		 * legend and scaling
		 */
		var legendRect = svg.append("g").attr("class", "l").selectAll('rect')
				.data(classes);

		legendRect.enter().append("rect").attr("id", function(d) {
			return div_id+ d[0];
		}).attr("x", w - 150).attr("y", function(d) {
			return (h - 63 + d[0] * 15)
		}).attr("width", 12).attr("height", 12).attr("fill", function(d) {
			return d[2];
		}).on(
				"click",
				function(d) {
					var el = d3.select("#"+div_id + d[0]);
					d3.select(this.parentNode).selectAll("rect").attr("stroke-width", "1").attr("stroke","black");
					el.attr("stroke-width", "3");
					el.attr("stroke", d[2]);

					active_group = d[0];
					for (var i = 0; i < classes.length; i++) {
						calcBar();
					}

				});

		legendRect.enter().append("text").text(function(d) {
			return d[1];
		}).attr("x", w - 130).attr("y", function(d) {
			return (h - 63 + d[0] * 15 + 12)
		}).attr("width", 12).attr("height", 12).attr("stroke", "none");

		var help = d3.select("#"+div_id).append("div").classed('ii',true).append("i").classed('fa', true).classed('fa-info', true);
        var tooltip_content = "
"+
        "
"+
        '
selected
	selected data	'+
        "
"+
        "
"+
        '
unselected
	unselected data in the current map view	'+
        "
"+
        "
"+
        '
out
	data out of the current map view	'+
        "
"+
        "

 When you click on the legend adjust the chart scale";
        $(help).tooltipster({
            content: tooltip_content,
            contentAsHTML: true,
            theme: 'tooltipster-light'

        });

		function resizeExtent(selection) {
			selection.attr("height", height);
		}

		function brushO() {

			var f = brush1.extent();
			var leftEdges = xScale.range();
        	var width = xScale.rangeBand();
        	var l;
        	var r;
        	var left = brush1.extent()[0][0];
        	var right = brush1.extent()[0][1]
        	for(l=0; left > (leftEdges[l] + width); l++) {}
        	for(r=0; right > (leftEdges[r] + width); r++) {}
            //do nothing, just increment j until case fails
        	console.log("Clicked on " + xScale.domain()[l]+ " "+xScale.domain()[r]);

        	var f = [];
        	f[0] = [ xScale.domain()[l],  xScale.domain()[r]];
			WGL.filterDim(id, filterId, f);
			//console.log(xScale.domain()[j]+' '+brush1.extent()[0][1]);

		}
	}

	// Create bars

	this.update = function(data) {
		if (dataset == null) {
			dataset = Array.prototype.slice.call(data);
			dataset.max = data.max;
			this.init();
		}
		dataset = Array.prototype.slice.call(data);

		/*
		 * dataset.forEach(function(d) { var y0 = 0; d.levels =
		 * colorScale.domain().map(function(name) { return { name : name, y0 :
		 * y0, y1 : y0 += +d[name] }; }); d.total = 0; });
		 */

		dataset.max = data.max;

		bars.datum(dataset);

		calcBar();
		// bars.data(dataset).transition().duration(10);
		/*
		 * bars.selectAll("rect").data(function(m) { return m.levels;
		 * }).transition().duration(10).attr("y", function(d) { return
		 * yScale(d.y1); }).attr("height", function(d) { return yScale(d.y0) -
		 * yScale(d.y1); });
		 */

		/*
		 * yAxis = d3.svg.axis().scale(yScale).orient("left");
		 * svg.selectAll('.y.axis').transition().duration(15).call(yAxis);
		 */
	}

	function calcBar(){
		yScale = d3.scale.linear().domain(
				[ 0, dataset.max[active_group] ]).range(
				[ height, 0 ]);
		//console.log(this);
		yAxis = d3.svg.axis().scale(yScale).orient("left").tickFormat(yformat); //changes format
		svg.selectAll('.y.axis').transition().duration(30)
				.call(yAxis);

		svg.selectAll(".selected.bar").attr("d", barPathSelected);
		svg.selectAll(".unselected.bar").attr("d", barPathUnselected);
		svg.selectAll(".out.bar").attr("d", barPathOut);

	}
	function barPathSelected(groups) {
		var path = [], i = -1, n = groups.length, d;
		while (++i < n) {
			var d = groups[i];
			path.push("M", xScale(d.val), ",", height, "V", yScale(d.selected),
					svgbw, height);
		}
		return path.join("");
	}

	function barPathUnselected(groups) {
		var path = [], i = -1, n = groups.length, d;
		while (++i < n) {
			var d = groups[i];
			path.push("M", xScale(d.val), ",", yScale(d.selected), "V",
					yScale(d.selected) + yScale(d.unselected) - height, svgbw,
					yScale(d.selected));
		}
		return path.join("");
	}

	function barPathOut(groups) {
		var path = [], i = -1, n = groups.length, d;
		while (++i < n) {
			var d = groups[i];
			var start = yScale(d.selected) + yScale(d.unselected) - height;
			path.push("M", xScale(d.val), ",", start, "V", start
					+ yScale(d.out) - height, svgbw, start);
		}
		return path.join("");
	}

}<commit_msg>arrow in chart when the data owerflows scale<commit_after> WGL.ui.StackedBarChart = function(m, div_id, x_label, filterId, params) {

	var type;
	var div_id;

	var w;
	var h;
	var margin;
	if (typeof(params)=='undefined'){
		w = 500;
		h = 215;
		margin = {
			top : 20,
			right : 20,
			bottom : 65,
			left : 60
			};
	} else {
		w=params.w;
		h=params.h;
		margin=params.margin;
	}

	var dataset;
	var xScale;
	var yScale;
	var colorScale;
	var xAxis;
	var yAxis;
	var bars;
	var svg;
	var chart;
	var active_group = 2;

	var width = w - margin.left - margin.right;
	var height = h - margin.top - margin.bottom;
	var dataset = null;
	var svgbw = "";
	 var bw = 0.0;

	 this.y_label = "detections";

	this.setLinearXScale = function(){
		xScale = new d3.scale.linear();
		xScale = d3.scale.linear().domain([ m.min , m.max ]).range([ 0, width ]);
		bw = Math.floor(width / dataset.length );
		svgbw= "h"+bw+"V";
		type = 'linear';
		return this;
	}

	this.setOrdinalXScale = function(){
		xScale = d3.scale.ordinal().domain(m.domain).rangeBands([ 0, width ],0.03,0.015);
		bw =xScale.rangeBand();
		svgbw= "h"+bw+"V";
		type = 'ordinal';
		return this;
	}

	this.xformat = function(d){
			return d;
	};
	var yformat = d3.format(".2n");

	 this.setYFormat = function (fuc) {
		 yformat = fuc;
	 };

/*	this.setTicks = function(n){
		xAxis.ticks(n) ;
	}

	this.setTicksValues = function(v){
		xAxis.ticksValues(v);
	}*/
	this.init = function() {
		// xScale = d3.scale.ordinal().rangeRoundBands([0, width], .1);
		// xScale = d3.scale.ordinal().rangeRoundBands([0, width], .1);

		//this.setLinearXScale();
		if (typeof m.domain == 'undefined'){
			this.setLinearXScale();
		} else {
			this.setOrdinalXScale();
		}

		var cols = [ "#ff8c00", "#7b6888", "#98abc5" ];
		//var cols = [ "#ff8c00", "#3182bd", "#98abc5" ];
		var classes = [ [ "0", "selected", cols[0] ],
				[ "1", "unselected", cols[1] ], [ "2", "out", cols[2] ] ];

		colorScale = d3.scale.ordinal().range(cols);

		yScale = d3.scale.linear().domain([ 0, dataset.max[2] ]).range(
				[ height, 0 ]);

		colorScale.domain([ "selected", "unselected", "out" ]);

		//to update label printing
		//new Date(d*1000).getYear()};

		xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickFormat(this.xformat);

		//yAxis = d3.svg.axis().scale(yScale).orient("left");
		yAxis = d3.svg.axis().scale(yScale).orient("left").tickFormat(yformat); //changes

		// xScale.domain(this.dataset.map(function(d) {
		// return d.max-(d.max-d.min)/2; }));

		svg = d3.select("#" + div_id).append("svg").attr("width",
				width + margin.left + margin.right).attr("height",
				height + margin.top + margin.bottom).append("g").attr(
				"transform",
				"translate(" + margin.left + "," + margin.top + ")");

		chart = svg.select('.chart');
		svg.append("g").attr("class", "x axis").attr("transform",
				"translate(0," + height + ")").call(xAxis).append("text")
			    .attr("y", "3.5em").attr("x",
				width /2 ).style("text-anchor", "end").text(x_label);

		svg.append("g").attr("class", "y axis").call(yAxis).append("text")
				.attr("transform", "rotate(270)").attr("y", "-4.5em").attr("x",
						"-2em").style("text-anchor", "end").text(this.y_label); //changes

		/*
		 * bars = svg.selectAll(".bars").data(dataset).enter()
		 * .append("g").attr("class", "g").attr("transform", function(d) {
		 * return "translate(" + (xScale(d.min)+xScale(d.max))/2 + ",0)"; });
		 */

		/* new bars */
		svg.append("clipPath").attr("id", "clip-" + div_id).append("rect")
				.attr("width", width).attr("height", height);

		bars = svg.selectAll(".bar").data([ "selected", "unselected", "out" ])
				.enter().append("path").attr("class", function(d) {
					return d + " foreground bar ";
				}).datum(dataset);

		//bars.on("click", function(d)
		//		{ d.selected = !d.selected;
		//			console.log(d);
		//		})

		svg.selectAll(".foreground.bar").attr("clip-path",
				"url(#clip-" + div_id + ")");

		// update(dataset);
		// svg.selectAll("selected bar").attr("d", barPathSelected);

		/* data */
		dataset.forEach(function(d) {
			var y0 = 0;
			d.levels = colorScale.domain().map(function(name) {
				return {
					name : name,
					y0 : y0,
					y1 : y0 += +d[name]
				};
			});
			d.total = 0;
		});

		/*
		 * bars.selectAll("path").data(function(m) { return m.levels;
		 * }).enter().append("rect").attr("y", function(d) { return
		 * yScale(d.y1); }).attr("width", bw).attr("height", function(d) {
		 * return yScale(d.y0) - yScale(d.y1); }).attr("fill", function(d) {
		 * return colorScale(d.name); }).attr("class", function(d){return
		 * div_id+d.name});
		 */
		function brushLinear() {
			var f = brush1.extent();
			WGL.filterDim(m.name, filterId, f);
			//console.log(brush1.extent()[0][0]+' '+brush1.extent()[0][1]);
		}

		function brushOrdinal() {
			var f = brush1.extent();
			var of = []
			var l = xScale.domain().length;
			for (var i in f){
				of[i] = [];
				of[i][0] = f[i][0] /width * l;
				of[i][1] = f[i][1] /width * l;
			}
			WGL.filterDim(m.name,filterId, of);
			//console.log(of[0][0]+' '+of[0][1]);

		}
		var brush;
		if (type=='linear') {
			brush = brushLinear;
		}
		else if (type=='ordinal'){
			brush = brushOrdinal;
		}

		var brush1 = d3.svg.multibrush().x(xScale).extentAdaption(resizeExtent)
				.on("brush", brush).on("brushend", function(d) {
					if (brush1.extent().length == 0) {
						brush();
					}

				});
		this.brush = brush1;

		var brushNode = svg.append("g").attr("class", "brush").call(brush1)
				.selectAll("rect").attr("height", height);

		/**
		 * legend and scaling
		 */
		var legendRect = svg.append("g").attr("class", "l").selectAll('rect')
				.data(classes);

		legendRect.enter().append("rect").attr("id", function(d) {
			return div_id+ d[0];
		}).attr("x", w - 150).attr("y", function(d) {
			return (h - 63 + d[0] * 15)
		}).attr("width", 12).attr("height", 12).attr("fill", function(d) {
			return d[2];
		}).on(
				"click",
				function(d) {
					var el = d3.select("#"+div_id + d[0]);
					d3.select(this.parentNode).selectAll("rect").attr("stroke-width", "1").attr("stroke","black");
					el.attr("stroke-width", "3");
					el.attr("stroke", d[2]);

					active_group = d[0];
					for (var i = 0; i < classes.length; i++) {
						calcBar();
					}

				});

		legendRect.enter().append("text").text(function(d) {
			return d[1];
		}).attr("x", w - 130).attr("y", function(d) {
			return (h - 63 + d[0] * 15 + 12)
		}).attr("width", 12).attr("height", 12).attr("stroke", "none");

		var help = d3.select("#"+div_id).append("div").classed('ii',true).append("i").classed('fa', true).classed('fa-info', true);
        var tooltip_content = "
"+
        "
"+
        '
selected
	selected data	'+
        "
"+
        "
"+
        '
unselected
	unselected data in the current map view	'+
        "
"+
        "
"+
        '
out
	data out of the current map view	'+
        "
"+
        "

 When you click on the legend adjust the chart scale";
        $(help).tooltipster({
            content: tooltip_content,
            contentAsHTML: true,
            theme: 'tooltipster-light'

        });

		function resizeExtent(selection) {
			selection.attr("height", height);
		}

		function brushO() {

			var f = brush1.extent();
			var leftEdges = xScale.range();
        	var width = xScale.rangeBand();
        	var l;
        	var r;
        	var left = brush1.extent()[0][0];
        	var right = brush1.extent()[0][1]
        	for(l=0; left > (leftEdges[l] + width); l++) {}
        	for(r=0; right > (leftEdges[r] + width); r++) {}
            //do nothing, just increment j until case fails
        	console.log("Clicked on " + xScale.domain()[l]+ " "+xScale.domain()[r]);

        	var f = [];
        	f[0] = [ xScale.domain()[l],  xScale.domain()[r]];
			WGL.filterDim(id, filterId, f);
			//console.log(xScale.domain()[j]+' '+brush1.extent()[0][1]);

		}
	}

	// Create bars

	this.update = function(data) {
		if (dataset == null) {
			dataset = Array.prototype.slice.call(data);
			dataset.max = data.max;
			this.init();
		}
		dataset = Array.prototype.slice.call(data);

		/*
		 * dataset.forEach(function(d) { var y0 = 0; d.levels =
		 * colorScale.domain().map(function(name) { return { name : name, y0 :
		 * y0, y1 : y0 += +d[name] }; }); d.total = 0; });
		 */

		dataset.max = data.max;

		bars.datum(dataset);

		calcBar();
		// bars.data(dataset).transition().duration(10);
		/*
		 * bars.selectAll("rect").data(function(m) { return m.levels;
		 * }).transition().duration(10).attr("y", function(d) { return
		 * yScale(d.y1); }).attr("height", function(d) { return yScale(d.y0) -
		 * yScale(d.y1); });
		 */

		/*
		 * yAxis = d3.svg.axis().scale(yScale).orient("left");
		 * svg.selectAll('.y.axis').transition().duration(15).call(yAxis);
		 */
	}

	function calcBar(){
		yScale = d3.scale.linear().domain(
				[ 0, dataset.max[active_group] ]).range(
				[ height, 0 ]);
		//console.log(this);
		yAxis = d3.svg.axis().scale(yScale).orient("left").tickFormat(yformat); //changes format
		svg.selectAll('.y.axis').transition().duration(30)
				.call(yAxis);

		svg.selectAll(".selected.bar").attr("d", barPathSelected);
		svg.selectAll(".unselected.bar").attr("d", barPathUnselected);
		svg.selectAll(".out.bar").attr("d", barPathOut);

	}
	function barPathSelected(groups) {
		var path = [], i = -1, n = groups.length, d;
		while (++i < n) {
			var d = groups[i];
			path.push("M", xScale(d.val), ",", height, "V", yScale(d.selected),
					svgbw, height);
		}
		return path.join("");
	}

	function barPathUnselected(groups) {
		var path = [], i = -1, n = groups.length, d;
		while (++i < n) {
			var d = groups[i];
			if (yScale(d.selected) + yScale(d.unselected) - height < -0.1 && yScale(d.selected) > 8){
				path.push("M", xScale(d.val), ",", yScale(d.selected),
					"V",8,
					"L",xScale(d.val) + bw/2, ",",0,
					"L",xScale(d.val) + bw,",",8,
					"V",yScale(d.selected)
				);
				//console.log(aa);
			}
			else{
				path.push("M", xScale(d.val), ",", yScale(d.selected), "V",
					yScale(d.selected) + yScale(d.unselected) - height, svgbw,
					yScale(d.selected));
			}
		}
		//console.log(path.join(""));
		return path.join("");
	}

	function barPathOut(groups) {
		var path = [], i = -1, n = groups.length, d;
		while (++i < n) {
			var d = groups[i];
			var start = yScale(d.selected) + yScale(d.unselected) - height;
			if (start + yScale(d.out) - height < -0.1 && start > 8){
				path.push("M", xScale(d.val), ",", start,
					"V",8,
					"L",xScale(d.val) + bw/2, ",",0,
					"L",xScale(d.val) + bw,",",8,
					"V",start
				);
				//console.log(aa);
			}
			else{
				path.push("M", xScale(d.val), ",", start, "V", start
					+ yScale(d.out) - height, svgbw, start);
			}

		}
		return path.join("");
	}

};<|endoftext|>


<commit_before>const path = require('path')
const webpack = require('webpack')

module.exports = {
  devtool: 'source-map',

  entry: [
    './src/index'
  ],

  output: {
    path: path.join(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: '/build/'
  },

  plugins: [
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      minimize: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    })
  ],

  module: {
    loaders: [
      { test: /\.js?$/,
        loader: 'babel',
        exclude: /node_modules/ },
      { test: /\.scss?$/,
        loader: 'style!css!sass',
        include: path.join(__dirname, 'src', 'styles') },
      { test: /\.png$/,
        loader: 'file' },
      { test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        loader: 'file'}
    ]
  }
}
<commit_msg>Fix: remove src and add app to webpack entry<commit_after>const path = require('path')
const webpack = require('webpack')

module.exports = {
  devtool: 'source-map',

  entry: [
    './app/index'
  ],

  output: {
    path: path.join(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: '/build/'
  },

  plugins: [
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      minimize: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    })
  ],

  module: {
    loaders: [
      { test: /\.js?$/,
        loader: 'babel',
        exclude: /node_modules/ },
      { test: /\.scss?$/,
        loader: 'style!css!sass',
        include: path.join(__dirname, 'app', 'styles') },
      { test: /\.png$/,
        loader: 'file' },
      { test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        loader: 'file'}
    ]
  }
}
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  cache: true,
  entry: [
    './client/index.jsx'
  ],
  output: {
    path: path.join(__dirname, './client/dist/'),
    publicPath: './client',
    filename: 'bundle.js'
  },
  externals: {
    Materialize: 'Materialize'
  },
  plugins: [
    new CleanWebpackPlugin(['client/dist']),
    new webpack.EnvironmentPlugin([
      'FIREABSE_DOMAIN',
      'FIREBASE_MESSENGERID',
      'FIREBASE_APIKEY',
      'FIREBASE_URL',
      'FIREBASE_PROJECTID',
      'FIREBASE_STORAGEBUCKET',
      'GOOGLE_ID',
      'FIREBASE_STORAGEBUCKET',
      'secretKey'
    ]),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.LoaderOptionsPlugin({
      debug: false
    }),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
      Hammer: 'hammerjs/hammer'
    }),
    new webpack.optimize.UglifyJsPlugin({
      output: {
        comments: false
      }
    })
  ],
  devServer: {
    contentBase: './client/dist'
  },
  target: 'web',
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /.jsx?$/,
        enforce: 'pre',
        use: [
          {
            loader: 'babel-loader',
            query: {
              cacheDirectory: true,
              presets: ['es2015', 'react']
            }
          }
        ],
        include: path.join(__dirname, './client'),
        exclude: /node_modules/
      },
      {
        test: /(\.s?css)$/,
        loader: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file-loader'
      },
      {
        test: /\.woff2(\?\S*)?$/,
        loader: 'url-loader?limit=100000'
      },
      {
        test: /\.woff(\?\S*)?$/,
        loader: 'url-loader?limit=100000'
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,

        loader: 'url-loader?limit=100000&mimetype=application/octet-stream'
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: [
          'file-loader?name=/assets/img/[name].[ext]',
          {
            loader: 'image-webpack-loader',
            query: {
              mozjpeg: {
                progressive: true
              },
              gifsicle: {
                interlaced: false
              },
              optipng: {
                optimizationLevel: 4
              },
              pngquant: {
                quality: '75-90',
                speed: 3
              }
            }
          }
        ],
        exclude: /node_modules/,
        include: __dirname
      },
      {
        test: /materialize-css\/bin\//,
        loader: 'imports-loader?jQuery=jquery,$=jquery,hammerjs'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,

        loader: 'url-loader?limit=10000&mimetype=image/svg+xml'
      }
    ]
  },
  resolve: { extensions: ['.js', '.jsx', '.css'] },
  node: {
    dns: 'empty',
    net: 'empty',
    fs: 'empty'
  }
};
<commit_msg>bug(fix-webpack-error): Fix error while compiling javascript code<commit_after>const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  cache: true,
  entry: [
    // 'webpack-hot-middleware',
    './client/index.jsx'
  ],
  output: {
    path: path.join(__dirname, './client/dist/'),
    publicPath: './client',
    filename: 'bundle.js'
  },
  externals: {
    Materialize: 'Materialize'
  },
  plugins: [
    new CleanWebpackPlugin(['client/dist']),
    new webpack.EnvironmentPlugin([
      'FIREABSE_DOMAIN',
      'FIREBASE_MESSENGERID',
      'FIREBASE_APIKEY',
      'FIREBASE_URL',
      'FIREBASE_PROJECTID',
      'FIREBASE_STORAGEBUCKET',
      'FIREBASE_STORAGEBUCKET'
    ]),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.LoaderOptionsPlugin({
      debug: false
    }),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
      Hammer: 'hammerjs/hammer'
    }),
    new webpack.optimize.UglifyJsPlugin({
      output: {
        comments: false
      }
    })
  ],
  devServer: {
    contentBase: './client/dist'
  },
  target: 'web',
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /.jsx?$/,
        enforce: 'pre',
        use: [
          {
            loader: 'babel-loader',
            query: {
              cacheDirectory: true,
              presets: ['es2015', 'react']
            }
          }
        ],
        include: path.join(__dirname, './client'),
        exclude: /node_modules/
      },
      {
        test: /(\.s?css)$/,
        loader: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file-loader'
      },
      {
        test: /\.woff2(\?\S*)?$/,
        loader: 'url-loader?limit=100000'
      },
      {
        test: /\.woff(\?\S*)?$/,
        loader: 'url-loader?limit=100000'
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,

        loader: 'url-loader?limit=100000&mimetype=application/octet-stream'
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: [
          'file-loader?name=/assets/img/[name].[ext]',
          {
            loader: 'image-webpack-loader',
            query: {
              mozjpeg: {
                progressive: true
              },
              gifsicle: {
                interlaced: false
              },
              optipng: {
                optimizationLevel: 4
              },
              pngquant: {
                quality: '75-90',
                speed: 3
              }
            }
          }
        ],
        exclude: /node_modules/,
        include: __dirname
      },
      {
        test: /materialize-css\/bin\//,
        loader: 'imports-loader?jQuery=jquery,$=jquery,hammerjs'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,

        loader: 'url-loader?limit=10000&mimetype=image/svg+xml'
      }
    ]
  },
  resolve: { extensions: ['.js', '.jsx', '.css'] },
  node: {
    dns: 'empty',
    net: 'empty',
    fs: 'empty'
  }
};
<|endoftext|>


<commit_before>// @AngularClass

/*
 * Helper: root(), and rootDir() are defined at the bottom
 */
var helpers = require('./helpers');
// Webpack Plugins
var webpack = require('webpack');
var ProvidePlugin = require('webpack/lib/ProvidePlugin');
var DefinePlugin = require('webpack/lib/DefinePlugin');
var OccurenceOrderPlugin = require('webpack/lib/optimize/OccurenceOrderPlugin');
var DedupePlugin = require('webpack/lib/optimize/DedupePlugin');
var UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
var CompressionPlugin = require('compression-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var WebpackMd5Hash    = require('webpack-md5-hash');
var ENV = process.env.NODE_ENV = process.env.ENV = 'production';
var HOST = process.env.HOST || 'localhost';
var PORT = process.env.PORT || 8080;

var metadata = {
  title: 'Angular2 Webpack Starter by @gdi2990 from @AngularClass',
  baseUrl: '/',
  host: HOST,
  port: PORT,
  ENV: ENV
};

/*
 * Config
 */
module.exports = helpers.validate({
  // static data for index.html
  metadata: metadata,

  devtool: 'source-map',
  cache: false,
  debug: false,

  entry: {
    'polyfills':'./src/polyfills.ts',
    'main':'./src/main.ts' // our angular app
  },

  // Config for our build files
  output: {
    path: helpers.root('dist'),
    filename: '[name].[chunkhash].bundle.js',
    sourceMapFilename: '[name].[chunkhash].bundle.map',
    chunkFilename: '[id].[chunkhash].chunk.js'
  },

  resolve: {
    cache: false,
    // ensure loader extensions match
    extensions: ['', '.ts','.js']
  },

  module: {
    preLoaders: [
      {
        test: /\.ts$/,
        loader: 'tslint-loader',
        exclude: [
          helpers.root('node_modules')
        ]
      },
      {
        test: /\.js$/,
        loader: 'source-map-loader',
        exclude: [
          helpers.root('node_modules/rxjs')
        ]
      }
    ],
    loaders: [
      // Support Angular 2 async routes via .async.ts
      // Support for .ts files.
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        query: {
          // remove TypeScript helpers to be injected below by DefinePlugin
          'compilerOptions': {
            'removeComments': true,
            'noEmitHelpers': true,
          }
        },
        exclude: [
          /\.(spec|e2e)\.ts$/
        ]
      },

      // Support for *.json files.
      {
        test: /\.json$/,
        loader: 'json-loader'
      },

      // Support for CSS as raw text
      {
        test: /\.css$/,
        loader: 'raw-loader'
      },

      // support for .html as raw text
      {
        test: /\.html$/,
        loader: 'raw-loader',
        exclude: [
          helpers.root('src/index.html')
        ]
      }

    ]
  },

  plugins: [
    new WebpackMd5Hash(),
    new DedupePlugin(),
    new OccurenceOrderPlugin(true),
    new CommonsChunkPlugin({
      name: 'polyfills',
      filename: 'polyfills.[chunkhash].bundle.js',
      chunks: Infinity
    }),
    // static assets
    new CopyWebpackPlugin([
      {
        from: 'src/assets',
        to: 'assets'
      }
    ]),
    // generating html
    new HtmlWebpackPlugin({ template: 'src/index.html' }),
    new DefinePlugin({
      // Environment helpers
      'process.env': {
        'ENV': JSON.stringify(metadata.ENV),
        'NODE_ENV': JSON.stringify(metadata.ENV)
      }
    }),
    new ProvidePlugin({
      // TypeScript helpers
      '__metadata': 'ts-helper/metadata',
      '__decorate': 'ts-helper/decorate',
      '__awaiter': 'ts-helper/awaiter',
      '__extends': 'ts-helper/extends',
      '__param': 'ts-helper/param'
    }),
    new UglifyJsPlugin({
      // to debug prod builds uncomment //debug lines and comment //prod lines

      // beautify: true,//debug
      // mangle: false,//debug
      // dead_code: false,//debug
      // unused: false,//debug
      // deadCode: false,//debug
      // compress : { screw_ie8 : true, keep_fnames: true, drop_debugger: false, dead_code: false, unused: false, }, // debug
      // comments: true,//debug

      beautify: false,//prod
      // disable mangling because of a bug in angular2 beta.1, beta.2 and beta.3
      // TODO(mastertinner): enable mangling as soon as angular2 beta.4 is out
      // mangle: { screw_ie8 : true },//prod
      mangle: false,
      compress : { screw_ie8 : true },//prod
      comments: false//prod

    }),
   // include uglify in production
    new CompressionPlugin({
      algorithm: helpers.gzipMaxLevel,
      regExp: /\.css$|\.html$|\.js$|\.map$/,
      threshold: 2 * 1024
    })
  ],
  // Other module loader config
  tslint: {
    emitErrors: true,
    failOnHint: true
  },
  // don't use devServer for production

  // we need this due to problems with es6-shim
  node: {
    global: 'window',
    progress: false,
    crypto: 'empty',
    module: false,
    clearImmediate: false,
    setImmediate: false
  }
});
<commit_msg>feat(webpack.prod): minimize html<commit_after>// @AngularClass

/*
 * Helper: root(), and rootDir() are defined at the bottom
 */
var helpers = require('./helpers');
// Webpack Plugins
var webpack = require('webpack');
var ProvidePlugin = require('webpack/lib/ProvidePlugin');
var DefinePlugin = require('webpack/lib/DefinePlugin');
var OccurenceOrderPlugin = require('webpack/lib/optimize/OccurenceOrderPlugin');
var DedupePlugin = require('webpack/lib/optimize/DedupePlugin');
var UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
var CompressionPlugin = require('compression-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var WebpackMd5Hash    = require('webpack-md5-hash');
var ENV = process.env.NODE_ENV = process.env.ENV = 'production';
var HOST = process.env.HOST || 'localhost';
var PORT = process.env.PORT || 8080;

var metadata = {
  title: 'Angular2 Webpack Starter by @gdi2990 from @AngularClass',
  baseUrl: '/',
  host: HOST,
  port: PORT,
  ENV: ENV
};

/*
 * Config
 */
module.exports = helpers.validate({
  // static data for index.html
  metadata: metadata,

  devtool: 'source-map',
  cache: false,
  debug: false,

  entry: {
    'polyfills':'./src/polyfills.ts',
    'main':'./src/main.ts' // our angular app
  },

  // Config for our build files
  output: {
    path: helpers.root('dist'),
    filename: '[name].[chunkhash].bundle.js',
    sourceMapFilename: '[name].[chunkhash].bundle.map',
    chunkFilename: '[id].[chunkhash].chunk.js'
  },

  resolve: {
    cache: false,
    // ensure loader extensions match
    extensions: ['', '.ts','.js']
  },

  module: {
    preLoaders: [
      {
        test: /\.ts$/,
        loader: 'tslint-loader',
        exclude: [
          helpers.root('node_modules')
        ]
      },
      {
        test: /\.js$/,
        loader: 'source-map-loader',
        exclude: [
          helpers.root('node_modules/rxjs')
        ]
      }
    ],
    loaders: [
      // Support Angular 2 async routes via .async.ts
      // Support for .ts files.
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        query: {
          // remove TypeScript helpers to be injected below by DefinePlugin
          'compilerOptions': {
            'removeComments': true,
            'noEmitHelpers': true,
          }
        },
        exclude: [
          /\.(spec|e2e)\.ts$/
        ]
      },

      // Support for *.json files.
      {
        test: /\.json$/,
        loader: 'json-loader'
      },

      // Support for CSS as raw text
      {
        test: /\.css$/,
        loader: 'raw-loader'
      },

      // support for .html as raw text
      {
        test: /\.html$/,
        loader: 'raw-loader',
        exclude: [
          helpers.root('src/index.html')
        ]
      }

    ]
  },

  plugins: [
    new WebpackMd5Hash(),
    new DedupePlugin(),
    new OccurenceOrderPlugin(true),
    new CommonsChunkPlugin({
      name: 'polyfills',
      filename: 'polyfills.[chunkhash].bundle.js',
      chunks: Infinity
    }),
    // static assets
    new CopyWebpackPlugin([
      {
        from: 'src/assets',
        to: 'assets'
      }
    ]),
    // generating html
    new HtmlWebpackPlugin({ template: 'src/index.html' }),
    new DefinePlugin({
      // Environment helpers
      'process.env': {
        'ENV': JSON.stringify(metadata.ENV),
        'NODE_ENV': JSON.stringify(metadata.ENV)
      }
    }),
    new ProvidePlugin({
      // TypeScript helpers
      '__metadata': 'ts-helper/metadata',
      '__decorate': 'ts-helper/decorate',
      '__awaiter': 'ts-helper/awaiter',
      '__extends': 'ts-helper/extends',
      '__param': 'ts-helper/param'
    }),
    new UglifyJsPlugin({
      // to debug prod builds uncomment //debug lines and comment //prod lines

      // beautify: true,//debug
      // mangle: false,//debug
      // dead_code: false,//debug
      // unused: false,//debug
      // deadCode: false,//debug
      // compress : { screw_ie8 : true, keep_fnames: true, drop_debugger: false, dead_code: false, unused: false, }, // debug
      // comments: true,//debug

      beautify: false,//prod
      // disable mangling because of a bug in angular2 beta.1, beta.2 and beta.3
      // TODO(mastertinner): enable mangling as soon as angular2 beta.4 is out
      // mangle: { screw_ie8 : true },//prod
      mangle: false,
      compress : { screw_ie8 : true },//prod
      comments: false//prod

    }),
   // include uglify in production
    new CompressionPlugin({
      algorithm: helpers.gzipMaxLevel,
      regExp: /\.css$|\.html$|\.js$|\.map$/,
      threshold: 2 * 1024
    })
  ],
  // Other module loader config
  tslint: {
    emitErrors: true,
    failOnHint: true,
    resourcePath: 'src',
  },

  htmlLoader: {
    minimize: true,
    removeAttributeQuotes: false,
    caseSensitive: true,
    customAttrSurround: [ [/#/, /(?:)/], [/\*/, /(?:)/], [/\[?\(?/, /(?:)/] ],
    customAttrAssign: [ /\)?\]?=/ ]
  },
  // don't use devServer for production

  // we need this due to problems with es6-shim
  node: {
    global: 'window',
    progress: false,
    crypto: 'empty',
    module: false,
    clearImmediate: false,
    setImmediate: false
  }
});
<|endoftext|>


<commit_before>import Image from '../image';
import validateChannel from '../misc/validateChannel';

export default function setChannel(channel, image) {

    this.checkProcessable('setChannel', {
        bitDepth: [8, 16]
    });

    image.checkProcessable('setChannel (image parameter check)', {
        bitDepth: [this.bitDepth],
        alpha: [0],
        components: [1]
    });

    channel = validateChannel(this,channel);

    let ptr=channel;
    for (let i=0; i<image.data.length; i++) {
        this.data[ptr]=image.data[i];
        ptr+=this.channels;
    }
}
<commit_msg>Check the size in setChannel<commit_after>import Image from '../image';
import validateChannel from '../misc/validateChannel';

export default function setChannel(channel, image) {

    this.checkProcessable('setChannel', {
        bitDepth: [8, 16]
    });

    image.checkProcessable('setChannel (image parameter check)', {
        bitDepth: [this.bitDepth],
        alpha: [0],
        components: [1]
    });

    if (image.width!==this.width || image.height!==this.height) {
        throw new Error('Images must have exactly the same width and height');
    }

    channel = validateChannel(this,channel);

    let ptr=channel;
    for (let i=0; i<image.data.length; i++) {
        this.data[ptr]=image.data[i];
        ptr+=this.channels;
    }
}
<|endoftext|>


<commit_before>import Rx from 'rx'
const merge = Rx.Observable.merge
const of = Rx.Observable.of
const scase = Rx.Observable.case

import {exists,getExtension,getNameAndExtension,isValidFile} from './utils'

import postProcessMesh from './meshUtils'
import helpers         from 'glView-helpers'
const centerMesh         = helpers.mesthTools.centerMesh

import {equals, cond, T, always} from 'ramda'
import {combineLatestObj} from './obsUtils'
import {mergeData} from './modelUtils'
import StlParser    from 'usco-stl-parser'

import assign from 'fast.js/object/assign'//faster object.assign

function dataSource(data){
  if(isValidFile(data)){
    return {
      src:'desktop'
      ,uri: data.name
    }
  }
  else{
    return {
      src:'http'
      ,uri:data
    }
  }
}

export function requests(inputs, drivers){
  const {meshSources$,srcSources$} = inputs

  //FIXME: caching should be done at a higher level , to prevent useless requests
  const resourceCache$ = undefined
  const cache = {}
  function getCached({meshSources$,srcSources$}){
    //this one needs to be store independant too
  }

  const baseRequest$ = merge(
      meshSources$
      ,srcSources$
    )
    .flatMap(Rx.Observable.fromArray)
    .map(function(data){
      const source     = dataSource(data)
      const uri        = source.uri
      const {name,ext} = getNameAndExtension(uri)
      return {src:source.src, uri, data, ext, name}
    })
    .filter(function(req){
      const cached = cache[req.uri]
      return cached ===undefined
    })

  baseRequest$
    .forEach(e=>console.log("sort of requests",e))

  /*const results$ = merge(
      fetch(drivers)
      //TODO: merge with cached results
    )*/

  //

  /*const request  = of( e.request )
      const response = e.pluck("response")
      const progress = e.pluck("progress")
      return combineLatestObj({response,request,progress})*/

  /*var sources = {
    'desktop': of("desktop"),
    'http': of("bar")
  }
  var source = Rx.Observable.case(
    function(){
      return 'http'
    }
    ,sources)
    .forEach(e=>console.log("testing",e))*/

  // request from http driver
  const httpRequests$ = baseRequest$
    .filter(r=>r.src==="http")
    .map(function(req){
      return assign({
        url:req.uri
        ,method:'get'
        ,responseType:'json'
        ,type:'resource'},req)
    })

  //request from desktop store (source only)
  const desktopRequests$ = baseRequest$
    .filter(r=>r.src==="desktop")
    .map(function(req){
      return assign({
        url:req.uri
        ,method:'get'
        ,responseType:'json'
        ,type:'resource'},req)
    })

  const requests = {
    http$:httpRequests$
    ,desktop$:desktopRequests$
  }

  return {
    requests
  }
}

function makeParsers(){
  //other
  let parsers = {}
  parsers["stl"] = new StlParser()
  return parsers
}
const parsers = makeParsers()

function postProcessParsedData(data){
  let mesh = data
  mesh = postProcessMesh(mesh)
  mesh = centerMesh(mesh)
  return mesh
}

function fetch(drivers, sourceNames=["http","desktop"]){
  const chosenDrivers = sourceNames
    .map(function(name){
      return drivers[name]
    })

  const fetched$ = merge(...chosenDrivers)
    .filter(res$ => res$.request.type === 'resource')
    .retry(3)
    .catch(function(e){
      console.log("ouch , problem fetching data ",e)
      return Rx.Observable.empty()
    })
    .flatMap(function(e){
      const request  = of( e.request )
      const response = e.pluck("response")
      const progress = e.pluck("progress")
      return combineLatestObj({response,request,progress})
    })
    .share()

  return fetched$
}

function parse(fetched$){
  const parseBase$ = fetched$
    .filter(data=>(data.response !== undefined && data.progress === undefined))
    .distinctUntilChanged(d=>d.request.uri,equals)
    //.debounce(10)
    .shareReplay(1)

  const parsed$ = parseBase$
    //.do(e=>console.log("parsedA",e))
    .map(function(data){
      const uri = data.request.uri
      const {name,ext} = getNameAndExtension(uri)
      return {uri, data:data.response, ext, name}
    })
    //actual parsing part
    .filter(data=>parsers[data.ext]!==undefined)//does parser exist?
    .flatMap(function({uri, data, ext, name}){
      const parseOptions={useWorker:true,useBuffers:true}

      const deferred = parsers[ext].parse(data, parseOptions)

      const data$  = Rx.Observable.fromPromise(deferred.promise)
        .map(postProcessParsedData)
      const meta$    = of({uri, ext, name})

      console.log("basics ready")
      return combineLatestObj({meta$,data$})
    })
    .do(e=>console.log("parsed data ready",e))

  return parsed$
}

function computeCombinedFetchProgress(resources$){
  const combinedProgress$ = resources$.scan(function(combined,entry){
    const uri = entry.request.uri
    if(entry.progress || entry.response){
      combined.entries[uri]  = entry.progress || 1

      let totalProgress = Object.keys(combined.entries)
        .reduce(function(acc,cur){
          return acc + combined.entries[cur]
        },0)

      totalProgress /= Object.keys(combined.entries).length
      combined.totalProgress = totalProgress
    }

    return combined
  },{entries:{}})
  .pluck("totalProgress")
  .distinctUntilChanged(null, equals)
  .debounce(10)

  return combinedProgress$
}

/*
       => p =>
  =====       ======>
       => p =>
*/

export function resources(drivers){

  const fetched$ = fetch(drivers)
  const parsed$  = parse(fetched$)
  const combinedProgress$ = computeCombinedFetchProgress(fetched$)

  parsed$
    .forEach(e=>console.log("parsed",e))

  return {
    combinedProgress$
    , parsed$
  }
}

  /*const fn = cond([
    [equals(0),   always('water freezes at 0°C')],
    [equals(100), always('water boils at 100°C')],
    [T,           temp => 'nothing special happens at ' + temp + '°C']
  ])

  console.log( fn(0) ) //=> 'water freezes at 0°C'
  console.log( fn(50) ) //=> 'nothing special happens at 50°C'
  console.log( fn(100) ) //=> 'water boils at 100°C'*/

/*
function makeAssetManager(drivers){

}

function load(fileUri, options){
  const defaults = {
    parentUri   :undefined
    ,transient  :false
    ,keepRawData:false
    ,parse      :true

    ,fetchOptions:{}
    ,parseOptions:{}
  }
  options = mergeData(options,defaults)

  input
    .filter(exists)

  if (fileUri == null) {
    error = "Invalid file name : " + fileUri
  }

  input
    .filter(isValidFile)
    .map(function(){
      //we have been given a file , or file like structure, default store to desktop ?
      [storeName,filename] = ["desktop", fileUri.name]
      file = fileUri
      _file = fileUri
      fileUri = fileUri.name
    })

  input
    .filter(!isValidFile)
    .map(function(){
      fileUri = pathUtils.toAbsoluteUri(fileUri, parentUri)
      [storeName,filename] = pathUtils.parseFileUri(fileUri, parentUri)
    })

  log.info("Attempting to load :", filename, "from store:", storeName)

  let resource = {
    ext:"foo"
    ,file:_file//FIXME a bit of a hack: for future uploads we keep the original file?
  }

  //the resource was already loaded, return it
  if (filename in this.assetCache){
    log.info("resource already in cache, returning cached version")
    resource = this.assetCache[filename]
    return resource
  }

  //not cached
  store = this.stores[storeName]
  if (!store) {
    error = new Error("No store named " + storeName)
    error.name = "storeNotFoundError"
  }

  //get parser instance , if it exists
  parser = this.parsers[extension]
  if (!parser) {
    error = new Error("No parser found for '" + extension + "' file format")
    error.name = "parserNotFoundError"
  }

  //if extension not in @codeExtensions
  //get prefered input data type for parser/extension
  //FIXME: do this more elegantly

  fileOrFileName = storeName === "desktop" ? file : filename//if desktop, then file, else fileName

  function getRawData(){
    //get raw data (not parsed)
    //returns observable
    return store.read(fileOrFileName, {
      dataType: parser.inputDataType
    })
  }

  function parseRawData(rawData){
    //returns observable
    return parser.parse(rawData, parseOptions)
  }

  function onSuccess(loadedResource)
    resource.fetched = true

    obs.onNext({
      parsing:0
    })

    resource.rawData = keepRawData ? loadedResource : null
    resource.data = loadedResource
    resource.loaded = true
    if (!transient) {
      assetCache[fileUri] = resource
    }
  }

  function onProgress = function(progress) {
    log.debug("got some progress", JSON.stringify(progress))
    if ("fetching" in progress) {
      resource.fetchProgress = progress.fetching
    }
    if ("parsing" in progress) {
      resource.parseProgress = progress.parsing
    }
    deferred.notify(progress)
    resource.size = progress.total
  }

  function onError( error ){
    log.error("failure in data reading step", error)
    error = new Error(error.message)
    fetchError.name = "fetchError"
  }

  //load raw data from uri/file, get an observable
  rawDataDeferred.promise.then( onSuccess, onError, onProgress)

  return obs

}
*/

<commit_msg>feature(assetManager): - added handling of parsers with updated api (they return observables instead of promises etc) - added progress tracking for parsing , now combined with fetching, for better progress handling - tweaks related to the items above<commit_after>import Rx from 'rx'
const merge = Rx.Observable.merge
const of = Rx.Observable.of
const scase = Rx.Observable.case

import {exists,getExtension,getNameAndExtension,isValidFile} from './utils'

import {postProcessMesh,geometryFromBuffers} from './meshUtils'
import helpers         from 'glView-helpers'
const centerMesh         = helpers.mesthTools.centerMesh

import {equals, cond, T, always} from 'ramda'
import {combineLatestObj} from './obsUtils'
import {mergeData} from './modelUtils'
import StlParser    from 'usco-stl-parser'

import assign from 'fast.js/object/assign'//faster object.assign

function dataSource(data){
  if(isValidFile(data)){
    return {
      src:'desktop'
      ,uri: data.name
    }
  }
  else{
    return {
      src:'http'
      ,uri:data
    }
  }
}

export function requests(inputs, drivers){
  const {meshSources$,srcSources$} = inputs

  //FIXME: caching should be done at a higher level , to prevent useless requests
  const resourceCache$ = undefined
  const cache = {}
  function getCached({meshSources$,srcSources$}){
    //this one needs to be store independant too
  }

  const baseRequest$ = merge(
      meshSources$
      ,srcSources$
    )
    .flatMap(Rx.Observable.fromArray)
    .map(function(data){
      const source     = dataSource(data)
      const uri        = source.uri
      const {name,ext} = getNameAndExtension(uri)
      return {src:source.src, uri, data, ext, name}
    })

  //baseRequest$
  //  .forEach(e=>console.log("sort of requests",e))

  const requests$ = baseRequest$
    .filter(function(req){
      const cached = cache[req.uri]
      return cached ===undefined
    })

  /*const results$ = merge(
      fetch(drivers)
      //TODO: merge with cached results
    )*/

  //

  /*const request  = of( e.request )
      const response = e.pluck("response")
      const progress = e.pluck("progress")
      return combineLatestObj({response,request,progress})*/

  /*var sources = {
    'desktop': of("desktop"),
    'http': of("bar")
  }
  var source = Rx.Observable.case(
    function(){
      return 'http'
    }
    ,sources)
    .forEach(e=>console.log("testing",e))*/

  // request from http driver
  const httpRequests$ = requests$
    .filter(r=>r.src==="http")
    .map(function(req){
      return assign({
        url:req.uri
        ,method:'get'
        ,type:'resource'},req)
    })

  //request from desktop store (source only)
  const desktopRequests$ = requests$
    .filter(r=>r.src==="desktop")
    .map(function(req){
      return assign({
        url:req.uri
        ,method:'get'
        ,type:'resource'},req)
    })

  const requests = {
    http$:httpRequests$
    ,desktop$:desktopRequests$
  }

  return {
    requests
  }
}

//import parse as stlParser,  {outputs} from 'stlParser'
import * as stlParser from 'stlParser'
console.log("stlParser",stlParser)

function makeParsers(){
  //other
  let parsers = {}
  parsers["stl"] = stlParser.default//new StlParser()
  console.log(".inputDataType",parsers["stl"].inputDataType)
  return parsers
}
const parsers = makeParsers()

function postProcessParsedData(data){
  let mesh = data
  mesh = geometryFromBuffers(mesh)
  mesh = postProcessMesh(mesh)
  mesh = centerMesh(mesh)
  return mesh
}

function fetch(drivers, sourceNames=["http","desktop"]){
  const chosenDrivers = sourceNames
    .map(function(name){
      return drivers[name]
    })

  const fetched$ = merge(...chosenDrivers)
    .filter(res$ => res$.request.type === 'resource')
    .do(e=>console.log("progress",e))
    .retry(3)
    .catch(function(e){
      console.log("ouch , problem fetching data ",e)
      return Rx.Observable.empty()
    })
    .flatMap(function(e){
      const request  = of( e.request )
      const response = e.pluck("response")
      const progress = e.pluck("progress")
      return combineLatestObj({response,request,progress})
    })
    .share()

  return fetched$
}

function parse(fetched$){
  const parseBase$ = fetched$
    .filter(data=>(data.response !== undefined && data.progress === undefined))
    .distinctUntilChanged(d=>d.request.uri,equals)
    //.debounce(10)
    .shareReplay(1)

  const parsed$ = parseBase$
    //.do(e=>console.log("parsedA",e))
    .map(function(data){
      const uri = data.request.uri
      const {name,ext} = getNameAndExtension(uri)
      return {uri, data:data.response, ext, name}
    })
    //actual parsing part
    .filter(data=>parsers[data.ext]!==undefined)//does parser exist?
    .flatMap(function({uri, data, ext, name}){
      const parseOptions={useWorker:true}

      const parsedObs$ = parsers[ext](data, parseOptions)
        //.do(e=>console.log("parsing data",e))
        .doOnError(e=>console.log("error in parse",e))

      const data$  = parsedObs$
        .filter(e=>e.progress === undefined)//seperate out progress data
        .map(postProcessParsedData)

      const progress$ = parsedObs$
        .filter(e=>e.progress !== undefined)//keep ONLY progress data
        .pluck("progress")
        .distinctUntilChanged()
        .startWith(0)

      progress$
        .forEach(e=>console.log("parse progress",e))

      const meta$    = of({uri, ext, name})

      return combineLatestObj({meta$, data$, progress$})
    })
    .shareReplay(1)
    //.do(e=>console.log("parsed data ready",e))

  return parsed$
}

function computeCombinedProgress(fetched$, parsed$){
  const fetchToParseRatio = 0.95

  function preProcess(selector,data$){
    return data$
      .map(selector)
      .distinctUntilChanged()
      .filter(d=>exists(d.progress))
  }

  //we merge fetch information with parse information
  const progress$ = merge(
    preProcess(f=>({id:f.request.uri,progress:f.progress}), fetched$)
      .map(e=>({id:e.id, fetched:e.progress*fetchToParseRatio}))

    ,preProcess(f=>({id:f.meta.uri,progress:f.progress}), parsed$)
      .map(e=>({id:e.id, parsed:e.progress*(1-fetchToParseRatio)}))
  )

  const combinedProgress$ = progress$.scan(function(combined,entry){
    const fetched  = entry.fetched || fetchToParseRatio
    const parsed   = entry.parsed || 0
    const progress = fetched + parsed

    combined.entries[entry.id]  = progress

    let totalProgress = Object.keys(combined.entries)
      .reduce(function(acc,cur){
        return acc + combined.entries[cur]
      },0)

    totalProgress /= Object.keys(combined.entries).length
    combined.totalProgress = totalProgress

    return combined
  },{entries:{},totalProgress:0})
  .pluck("totalProgress")
  .distinctUntilChanged(null, equals)
  .debounce(10)

  return combinedProgress$
}

export function resources(drivers){
  const fetched$ = fetch(drivers)
  const parsed$  = parse(fetched$)
  const combinedProgress$ = computeCombinedProgress( fetched$, parsed$ )

  parsed$
    .forEach(e=>console.log("parsed",e))

  return {
    combinedProgress$
    , parsed$
  }
}

  /*const fn = cond([
    [equals(0),   always('water freezes at 0°C')],
    [equals(100), always('water boils at 100°C')],
    [T,           temp => 'nothing special happens at ' + temp + '°C']
  ])

  console.log( fn(0) ) //=> 'water freezes at 0°C'
  console.log( fn(50) ) //=> 'nothing special happens at 50°C'
  console.log( fn(100) ) //=> 'water boils at 100°C'*/

/*
function makeAssetManager(drivers){

}

function load(fileUri, options){
  const defaults = {
    parentUri   :undefined
    ,transient  :false
    ,keepRawData:false
    ,parse      :true

    ,fetchOptions:{}
    ,parseOptions:{}
  }
  options = mergeData(options,defaults)

  input
    .filter(exists)

  if (fileUri == null) {
    error = "Invalid file name : " + fileUri
  }

  input
    .filter(isValidFile)
    .map(function(){
      //we have been given a file , or file like structure, default store to desktop ?
      [storeName,filename] = ["desktop", fileUri.name]
      file = fileUri
      _file = fileUri
      fileUri = fileUri.name
    })

  input
    .filter(!isValidFile)
    .map(function(){
      fileUri = pathUtils.toAbsoluteUri(fileUri, parentUri)
      [storeName,filename] = pathUtils.parseFileUri(fileUri, parentUri)
    })

  log.info("Attempting to load :", filename, "from store:", storeName)

  let resource = {
    ext:"foo"
    ,file:_file//FIXME a bit of a hack: for future uploads we keep the original file?
  }

  //the resource was already loaded, return it
  if (filename in this.assetCache){
    log.info("resource already in cache, returning cached version")
    resource = this.assetCache[filename]
    return resource
  }

  //not cached
  store = this.stores[storeName]
  if (!store) {
    error = new Error("No store named " + storeName)
    error.name = "storeNotFoundError"
  }

  //get parser instance , if it exists
  parser = this.parsers[extension]
  if (!parser) {
    error = new Error("No parser found for '" + extension + "' file format")
    error.name = "parserNotFoundError"
  }

  //if extension not in @codeExtensions
  //get prefered input data type for parser/extension
  //FIXME: do this more elegantly

  fileOrFileName = storeName === "desktop" ? file : filename//if desktop, then file, else fileName

  function getRawData(){
    //get raw data (not parsed)
    //returns observable
    return store.read(fileOrFileName, {
      dataType: parser.inputDataType
    })
  }

  function parseRawData(rawData){
    //returns observable
    return parser.parse(rawData, parseOptions)
  }

  function onSuccess(loadedResource)
    resource.fetched = true

    obs.onNext({
      parsing:0
    })

    resource.rawData = keepRawData ? loadedResource : null
    resource.data = loadedResource
    resource.loaded = true
    if (!transient) {
      assetCache[fileUri] = resource
    }
  }

  function onProgress = function(progress) {
    log.debug("got some progress", JSON.stringify(progress))
    if ("fetching" in progress) {
      resource.fetchProgress = progress.fetching
    }
    if ("parsing" in progress) {
      resource.parseProgress = progress.parsing
    }
    deferred.notify(progress)
    resource.size = progress.total
  }

  function onError( error ){
    log.error("failure in data reading step", error)
    error = new Error(error.message)
    fetchError.name = "fetchError"
  }

  //load raw data from uri/file, get an observable
  rawDataDeferred.promise.then( onSuccess, onError, onProgress)

  return obs

}
*/

<|endoftext|>


<commit_before>import Rx from 'rx'
const merge = Rx.Observable.merge
const of = Rx.Observable.of
const scase = Rx.Observable.case

import {exists,getExtension,getNameAndExtension,isValidFile, isEmpty} from './utils'

import {equals, cond, T, always} from 'ramda'
import {combineLatestObj} from './obsUtils'
import {mergeData} from './modelUtils'
import assign from 'fast.js/object/assign'//faster object.assign

import {postProcessParsedData} from './parseUtils'

function getParser(extension){
  return lazyLoad(extension)
}

function lazyLoad(moduleNamePath){

  let obs = new Rx.ReplaySubject(1)
  //let waitForChunk = require('dynamic?' + moduleNamePath)

    //require("bundle?lazy!usco-ctm-parser")(function(module) {
    //const requireStr = `bundle?lazy!./node_modules/${moduleNamePath}`
    //const requireStr = `bundle?lazy!./`
    //let req = require.context("./node-modules", true, /^\.\/.*\.jade$/)
    //const requireStr = `bundle?lazy!./node_modules/${moduleNamePath}/lib/ctm-parser.js`

    //var req = require.context('../../node_modules', true, /^\.\/.*\.js$/)

    /*require.ensure(['usco-ctm-parser'], function(require) {
      //require('usco-ctm-parser')
      let module = require(moduleNamePath)
      console.log("dynamic load of module",module)
      //obs.onNext(module)
    })*/
    /*require(requireStr)(function(module) {
      // now you can use the b-module
      console.log("dynamic load of module",module)
      obs.onNext(module)
    })*/
    //System.import('usco-ctm-parser').then(module=>console.log("module",module))

    //FIXME: awfull, horrible horrrible horrible
    //NOTE : chunk names can be specified like this : &name=stl-parser
    switch(moduleNamePath){
      case 'stl':
        require("bundle?lazy!usco-stl-parser")(module => obs.onNext(module))
      break
      case 'ctm':
        require("bundle?lazy!usco-ctm-parser")(module => obs.onNext(module))
      break
      case 'obj':
        require("bundle?lazy!usco-obj-parser")(module => obs.onNext(module))
      break
      case '3mf':
        require("bundle?lazy!usco-3mf-parser")(module => obs.onNext(module))
      break
    }
  return obs
}

//this functions extracts data recieved from sources, adds error handling etc
function fetch(sources, sourceNames=["http","desktop"]){
  const chosenSources = sourceNames
    .map(function(name){
      return sources[name]
    })

  const fetched$ = merge(...chosenSources)
    .filter(res$ => res$.request.type === 'resource')//only responses we deal with are resources
    .flatMap(data => {
      const responseWrapper$ = data.catch(e=>{
        console.log("caught error in fetching data",e)
        return Rx.Observable.empty()
      })
      const request$  = of(data.request)
      const response$ = responseWrapper$.pluck("response")
      const progress$ = responseWrapper$.pluck("progress")

      return combineLatestObj({response$, request$, progress$})
    })
    .share()
  return fetched$
}

//parse the data extracted from a fetched data observable
function parse(fetched$){
  const parseBase$ = fetched$
    .filter(data=>(data.response !== undefined && data.progress === undefined))
    .distinctUntilChanged(d=>d.request.uri,equals)
    //.debounce(10)
    .shareReplay(1)

  const parsed$ = parseBase$
    .flatMap(function(data){
      const {uri,id} = data.request//extract uri & id if any
      const {name, ext} = getNameAndExtension(uri)

      //pack up the data, the parser etc nicely
      const data$   = of({uri, id, rawData:data.response, ext, name})
      const parser$ = getParser(ext).pluck('default')// FIXME: for now workaround for es6 modules & babel
      return combineLatestObj({data$, parser$})
    })
    //actual parsing part
    .flatMap(function( {data,parser} ){
      const {rawData, uri, ext, name, id} = data
      const parseOptions = {useWorker:true}

      const parsedObs$ = parser(rawData, parseOptions)
        .doOnError(e=>console.log("error in parse",e))

      const parsedData$  = parsedObs$
        .filter(e=> e.progress === undefined)//seperate out progress data
        .map(postProcessParsedData)

      const progress$ = parsedObs$
        .filter(e=> e.progress !== undefined)//keep ONLY progress data
        .pluck("progress")
        .distinctUntilChanged()
        .startWith(0)

      const meta$ = of({uri, ext, name, id})

      return combineLatestObj({meta$, data:parsedData$, progress$})
    })
    .shareReplay(1)

  return parsed$
}

//helper function to output combine fetch & parse data
function computeCombinedProgress(fetched$, parsed$){
  const fetchToParseRatio = 0.95

  function preProcess(selector,data$){
    return data$
      .map(selector)
      .distinctUntilChanged()
      .filter(d=>exists(d.progress))
  }

  //we merge fetch information with parse information
  const progress$ = merge(
    preProcess(f=>({id:f.request.uri,progress:f.progress}), fetched$)
      .map(e=>({id:e.id, fetched:e.progress*fetchToParseRatio}))

    ,preProcess(f=>({id:f.meta.uri,progress:f.progress}), parsed$)
      .map(e=>({id:e.id, parsed:e.progress*(1-fetchToParseRatio)}))
  )

  const combinedProgress$ = progress$.scan(function(combined,entry){
    const fetched  = entry.fetched || fetchToParseRatio
    const parsed   = entry.parsed || 0
    const progress = fetched + parsed

    combined.entries[entry.id]  = progress

    let totalProgress = Object.keys(combined.entries)
      .reduce(function(acc,cur){
        return acc + combined.entries[cur]
      },0)

    totalProgress /= Object.keys(combined.entries).length
    combined.totalProgress = totalProgress

    return combined
  },{entries:{},totalProgress:0})
  .pluck("totalProgress")
  .distinctUntilChanged(null, equals)
  .debounce(10)

  return combinedProgress$
}

export function resources(sources){
  const fetched$ = fetch(sources)
  const parsed$  = parse(fetched$)
  const combinedProgress$ = computeCombinedProgress( fetched$, parsed$ )

  return {
    combinedProgress$
    , parsed$
  }
}

  /*const fn = cond([
    [equals(0),   always('water freezes at 0°C')],
    [equals(100), always('water boils at 100°C')],
    [T,           temp => 'nothing special happens at ' + temp + '°C']
  ])

  console.log( fn(0) ) //=> 'water freezes at 0°C'
  console.log( fn(50) ) //=> 'nothing special happens at 50°C'
  console.log( fn(100) ) //=> 'water boils at 100°C'*/
<commit_msg>fix(assetManager): fixed excessive filtering of consecutive requests in assetManager<commit_after>import Rx from 'rx'
const merge = Rx.Observable.merge
const of = Rx.Observable.of
const scase = Rx.Observable.case

import {exists,getExtension,getNameAndExtension,isValidFile, isEmpty} from './utils'

import {equals, cond, T, always} from 'ramda'
import {combineLatestObj} from './obsUtils'
import {mergeData} from './modelUtils'
import assign from 'fast.js/object/assign'//faster object.assign

import {postProcessParsedData} from './parseUtils'

function getParser(extension){
  return lazyLoad(extension)
}

function lazyLoad(moduleNamePath){

  let obs = new Rx.ReplaySubject(1)
  //let waitForChunk = require('dynamic?' + moduleNamePath)

    //require("bundle?lazy!usco-ctm-parser")(function(module) {
    //const requireStr = `bundle?lazy!./node_modules/${moduleNamePath}`
    //const requireStr = `bundle?lazy!./`
    //let req = require.context("./node-modules", true, /^\.\/.*\.jade$/)
    //const requireStr = `bundle?lazy!./node_modules/${moduleNamePath}/lib/ctm-parser.js`

    //var req = require.context('../../node_modules', true, /^\.\/.*\.js$/)

    /*require.ensure(['usco-ctm-parser'], function(require) {
      //require('usco-ctm-parser')
      let module = require(moduleNamePath)
      console.log("dynamic load of module",module)
      //obs.onNext(module)
    })*/
    /*require(requireStr)(function(module) {
      // now you can use the b-module
      console.log("dynamic load of module",module)
      obs.onNext(module)
    })*/
    //System.import('usco-ctm-parser').then(module=>console.log("module",module))

    //FIXME: awfull, horrible horrrible horrible
    //NOTE : chunk names can be specified like this : &name=stl-parser
    switch(moduleNamePath){
      case 'stl':
        require("bundle?lazy!usco-stl-parser")(module => obs.onNext(module))
      break
      case 'ctm':
        require("bundle?lazy!usco-ctm-parser")(module => obs.onNext(module))
      break
      case 'obj':
        require("bundle?lazy!usco-obj-parser")(module => obs.onNext(module))
      break
      case '3mf':
        require("bundle?lazy!usco-3mf-parser")(module => obs.onNext(module))
      break
    }
  return obs
}

//this functions extracts data recieved from sources, adds error handling etc
function fetch(sources, sourceNames=["http","desktop"]){
  const chosenSources = sourceNames
    .map(function(name){
      return sources[name]
    })

  const fetched$ = merge(...chosenSources)
    .filter(res$ => res$.request.type === 'resource')//only responses we deal with are resources
    .flatMap(data => {
      const responseWrapper$ = data.catch(e=>{
        console.log("caught error in fetching data",e)
        return Rx.Observable.empty()
      })
      const request$  = of(data.request)
      const response$ = responseWrapper$.pluck("response")
      const progress$ = responseWrapper$.pluck("progress")

      return combineLatestObj({response$, request$, progress$})
    })
    .share()
  return fetched$
}

//parse the data extracted from a fetched data observable
function parse(fetched$){
  const parseBase$ = fetched$
    .filter(data=>(data.response !== undefined && data.progress === undefined))
    //.distinctUntilChanged(d=>d.request.uri,equals)
    .shareReplay(1)

  const parsed$ = parseBase$
    .flatMap(function(data){
      const {uri,id} = data.request//extract uri & id if any
      const {name, ext} = getNameAndExtension(uri)

      //pack up the data, the parser etc nicely
      const data$   = of({uri, id, rawData:data.response, ext, name})
      const parser$ = getParser(ext).pluck('default')// FIXME: for now workaround for es6 modules & babel
      return combineLatestObj({data$, parser$})
    })
    //actual parsing part
    .flatMap(function( {data,parser} ){
      const {rawData, uri, ext, name, id} = data
      const parseOptions = {useWorker:true}

      const parsedObs$ = parser(rawData, parseOptions)
        .doOnError(e=>console.log("error in parse",e))

      const parsedData$  = parsedObs$
        .filter(e=> e.progress === undefined)//seperate out progress data
        .map(postProcessParsedData)
        //.tap(e=>console.log("parsedData",e))

      const progress$ = parsedObs$
        .filter(e=> e.progress !== undefined)//keep ONLY progress data
        .pluck("progress")
        .distinctUntilChanged()
        .startWith(0)

      const meta$ = of({uri, ext, name, id})

      return combineLatestObj({meta$, data:parsedData$, progress$})
    })
    .shareReplay(1)

  return parsed$
}

//helper function to output combine fetch & parse data
function computeCombinedProgress(fetched$, parsed$){
  const fetchToParseRatio = 0.95

  function preProcess(selector,data$){
    return data$
      .map(selector)
      //.distinctUntilChanged()
      .filter(d=>exists(d.progress))
  }

  //we merge fetch information with parse information
  const progress$ = merge(
    preProcess(f=>({id:f.request.uri,progress:f.progress}), fetched$)
      .map(e=>({id:e.id, fetched:e.progress*fetchToParseRatio}))

    ,preProcess(f=>({id:f.meta.uri,progress:f.progress}), parsed$)
      .map(e=>({id:e.id, parsed:e.progress*(1-fetchToParseRatio)}))
  )

  const combinedProgress$ = progress$.scan(function(combined,entry){
    const fetched  = entry.fetched || fetchToParseRatio
    const parsed   = entry.parsed || 0
    const progress = fetched + parsed

    combined.entries[entry.id]  = progress

    let totalProgress = Object.keys(combined.entries)
      .reduce(function(acc,cur){
        return acc + combined.entries[cur]
      },0)

    totalProgress /= Object.keys(combined.entries).length
    combined.totalProgress = totalProgress

    return combined
  },{entries:{},totalProgress:0})
  .pluck("totalProgress")
  .distinctUntilChanged(null, equals)
  .debounce(10)

  return combinedProgress$
}

export function resources(sources){
  const fetched$ = fetch(sources)
  const parsed$  = parse(fetched$)
  const combinedProgress$ = computeCombinedProgress( fetched$, parsed$ )

  return {
    combinedProgress$
    , parsed$
  }
}

  /*const fn = cond([
    [equals(0),   always('water freezes at 0°C')],
    [equals(100), always('water boils at 100°C')],
    [T,           temp => 'nothing special happens at ' + temp + '°C']
  ])

  console.log( fn(0) ) //=> 'water freezes at 0°C'
  console.log( fn(50) ) //=> 'nothing special happens at 50°C'
  console.log( fn(100) ) //=> 'water boils at 100°C'*/
<|endoftext|>


<commit_before>/**************************************************
 *  Copyright (c) 2014 AnsibleWorks, Inc.
 */
  /**
 *  @ngdoc function
 *  @name lib.ansible.function:Socket
 *  @description
 *  Socket.js
 *
 *  Wrapper for lib/socket.io-client/dist/socket.io.js.
 */

/* global io */

'use strict';
/**
 * @ngdoc method
 * @name lib.ansible.function:Socket#SocketIO
 * @methodOf lib.ansible.function:Socket
 * @description
 */
angular.module('SocketIO', ['AuthService', 'Utilities'])

    .factory('Socket', ['$rootScope', '$location', '$log', 'Authorization', 'Store', function ($rootScope, $location, $log, Authorization, Store) {
        return function(params) {
            var scope = params.scope,
                host = $location.host(),
                endpoint = params.endpoint,
                protocol = $location.protocol(),
                config, socketPort,
                // handshakeData,
                url;

            // Since some pages are opened in a new tab, we might get here before AnsibleConfig is available.
            // In that case, load from local storage.
            if ($AnsibleConfig) {
                socketPort = $AnsibleConfig.websocket_port;
            }
            else {
                $log.debug('getting web socket port from local storage');
                config = Store('AnsibleConfig');
                socketPort = config.websocket_port;
            }
            url = protocol + '://' + host + ':' + socketPort + '/socket.io/' + endpoint;
            $log.debug('opening socket connection to: ' + url);

            function getSocketTip(status) {
                var result = '';
                switch(status) {
                    case 'error':
                        result = "Live events: error connecting to the Tower server. Click for troubleshooting help.";
                        break;
                    case 'connecting':
                        result = "Live events: attempting to connect to the Tower server. Click for troubleshooting help.";
                        break;
                    case "ok":
                        result = "Live events: connected. Pages containing job status information will automatically update in real-time.";
                }
                return result;
            }

            return {
                scope: scope,
                url:  url,
                socket: null,

                init: function() {
                    var self = this,
                        token = Authorization.getToken();
                    if (!$rootScope.sessionTimer || ($rootScope.sessionTimer && !$rootScope.sessionTimer.isExpired())) {
                        // We have a valid session token, so attempt socket connection
                        $log.debug('Socket connecting to: ' + url);
                        self.scope.socket_url = url;
                        // handshakeData = {
                        //    headers:  {
                        //         'Authorization': 'Token ' + token,
                        //         'X-Auth-Token': 'Token ' + token
                        //     }
                        //  }

                        self.socket = io.connect(url, {
                            headers:
                            {
                                'Authorization': 'Token ' + token,
                                'X-Auth-Token': 'Token ' + token
                            },
                            'connect timeout': 3000,
                            'try multiple transports': false,
                            'max reconneciton attemps': 3,
                            'reconnection limit': 3000,
                            'force new connection': true,
                        });

                        self.socket.on('connection', function() {
                            $log.debug('Socket connecting...');
                            self.scope.$apply(function () {
                                self.scope.socketStatus = 'connecting';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('connect', function() {
                            $log.debug('Socket connection established');
                            self.scope.$apply(function () {
                                self.scope.socketStatus = 'ok';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('connect_failed', function(reason) {
                            var r = reason || 'connection refused by host';
                            $log.error('Socket connection failed: ' + r);
                            self.scope.$apply(function () {
                                self.scope.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });

                        });
                        self.socket.on('diconnect', function() {
                            $log.debug('Socket disconnected');
                            self.scope.$apply(function() {
                                self.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('error', function(reason) {
                            var r = reason || 'connection refused by host';
                            $log.debug('Socket error: ' + r);
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('reconnecting', function() {
                            $log.debug('Socket attempting reconnect...');
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'connecting';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('reconnect', function() {
                            $log.debug('Socket reconnected');
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'ok';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('reconnect_failed', function(reason) {
                            $log.error('Socket reconnect failed: ' + reason);
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                    }
                    else {
                        // encountered expired token, redirect to login page
                        $rootScope.sessionTimer.expireSession();
                        $location.url('/login');
                    }
                },
                checkStatus: function() {
                    // Check connection status
                    var self = this;
                    if (self.socket.socket.connected) {
                        self.scope.socketStatus = 'ok';
                    }
                    else if (self.socket.socket.connecting || self.socket.socket.reconnecting) {
                        self.scope.socketStatus = 'connecting';
                    }
                    else {
                        self.scope.socketStatus = 'error';
                    }
                    self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                    return self.scope.socketStatus;
                },
                on: function (eventName, callback) {
                    var self = this;
                    self.socket.on(eventName, function () {
                        var args = arguments;
                        self.scope.$apply(function () {
                            callback.apply(self.socket, args);
                        });
                    });
                },
                emit: function (eventName, data, callback) {
                    var self = this;
                    self.socket.emit(eventName, data, function () {
                        var args = arguments;
                        self.scope.$apply(function () {
                            if (callback) {
                                callback.apply(self.socket, args);
                            }
                        });
                    });
                },
                getUrl: function() {
                    return url;
                }
            };
        };
    }]);
<commit_msg>Socket again<commit_after>/**************************************************
 *  Copyright (c) 2014 AnsibleWorks, Inc.
 */
  /**
 *  @ngdoc function
 *  @name lib.ansible.function:Socket
 *  @description
 *  Socket.js
 *
 *  Wrapper for lib/socket.io-client/dist/socket.io.js.
 */

/* global io */

'use strict';
/**
 * @ngdoc method
 * @name lib.ansible.function:Socket#SocketIO
 * @methodOf lib.ansible.function:Socket
 * @description
 */
angular.module('SocketIO', ['AuthService', 'Utilities'])

    .factory('Socket', ['$rootScope', '$location', '$log', 'Authorization', 'Store', function ($rootScope, $location, $log, Authorization, Store) {
        return function(params) {
            var scope = params.scope,
                host = $location.host(),
                endpoint = params.endpoint,
                protocol = $location.protocol(),
                config, socketPort,
                // handshakeData,
                url;

            // Since some pages are opened in a new tab, we might get here before AnsibleConfig is available.
            // In that case, load from local storage.
            if ($AnsibleConfig) {
                socketPort = $AnsibleConfig.websocket_port;
            }
            else {
                $log.debug('getting web socket port from local storage');
                config = Store('AnsibleConfig');
                socketPort = config.websocket_port;
            }
            url = protocol + '://' + host + ':' + socketPort + '/socket.io/' + endpoint;
            $log.debug('opening socket connection to: ' + url);

            function getSocketTip(status) {
                var result = '';
                switch(status) {
                    case 'error':
                        result = "Live events: error connecting to the Tower server. Click for troubleshooting help.";
                        break;
                    case 'connecting':
                        result = "Live events: attempting to connect to the Tower server. Click for troubleshooting help.";
                        break;
                    case "ok":
                        result = "Live events: connected. Pages containing job status information will automatically update in real-time.";
                }
                return result;
            }

            return {
                scope: scope,
                url:  url,
                socket: null,

                init: function() {
                    var self = this,
                        token = Authorization.getToken();
                    if (!$rootScope.sessionTimer || ($rootScope.sessionTimer && !$rootScope.sessionTimer.isExpired())) {
                        // We have a valid session token, so attempt socket connection
                        $log.debug('Socket connecting to: ' + url);
                        self.scope.socket_url = url;
                        // handshakeData = {
                        //    headers:  {
                        //         'Authorization': 'Token ' + token,
                        //         'X-Auth-Token': 'Token ' + token
                        //     }
                        //  }

                        self.socket = io.connect(url, {
                            headers:
                            {
                                'Authorization': 'Token ' + token,
                                'X-Auth-Token': 'Token ' + token
                            },
                            'connect timeout': 3000,
                            'try multiple transports': false,
                            'max reconneciton attemps': 3,
                            'reconnection limit': 3000,
                            'force new connection': true,
                        });

                        self.socket.on('connection', function() {
                            $log.debug('Socket connecting...');
                            self.scope.$apply(function () {
                                self.scope.socketStatus = 'connecting';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('connect', function() {
                            $log.debug('Socket connection established');
                            self.scope.$apply(function () {
                                self.scope.socketStatus = 'ok';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('connect_failed', function(reason) {
                            var r = reason || 'connection refused by host';
                            $log.error('Socket connection failed: ' + r);
                            self.scope.$apply(function () {
                                self.scope.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });

                        });
                        self.socket.on('diconnect', function() {
                            $log.debug('Socket disconnected');
                            self.scope.$apply(function() {
                                self.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('error', function(reason) {
                            var r = reason || 'connection refused by host';
                            $log.debug('Socket error: ' + r);
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('reconnecting', function() {
                            $log.debug('Socket attempting reconnect...');
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'connecting';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('reconnect', function() {
                            $log.debug('Socket reconnected');
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'ok';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                        self.socket.on('reconnect_failed', function(reason) {
                            $log.error('Socket reconnect failed: ' + reason);
                            self.scope.$apply(function() {
                                self.scope.socketStatus = 'error';
                                self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                            });
                        });
                    }
                    else {
                        // encountered expired token, redirect to login page
                        $rootScope.sessionTimer.expireSession();
                        $location.url('/login');
                    }
                },
                checkStatus: function() {
                    // Check connection status
                    var self = this;
                    if (self.socket.socket.connected) {
                        self.scope.socketStatus = 'ok';
                    }
                    else if (self.socket.socket.connecting || self.socket.socket.reconnecting) {
                        self.scope.socketStatus = 'connecting';
                    }
                    else {
                        self.scope.socketStatus = 'error';
                    }
                    self.scope.socketTip = getSocketTip(self.scope.socketStatus);
                    return self.scope.socketStatus;
                },
                on: function (eventName, callback) {
                    var self = this;
                    self.socket.on(eventName, function () {
                        var args = arguments;
                        self.scope.$apply(function () {
                            callback.apply(self.socket, args);
                        });
                    });
                },
                emit: function (eventName, data, callback) {
                    var self = this;
                    self.socket.emit(eventName, data, function () {
                        var args = arguments;
                        self.scope.$apply(function () {
                            if (callback) {
                                callback.apply(self.socket, args);
                            }
                        });
                    });
                },
                getUrl: function() {
                    return url;
                }
            };
        };
    }]);
<|endoftext|>


<commit_before>export default function decorators() {
  console.group('ES-next: Stage-2: decorators');
  {
    console.log(`
      class Hoge {
        @decorator()
        method() {
          console.log('Hoge.prototype.method()');
        }
      }

      function decorator() {
        return (target, key, descriptor) => {
          console.log('decorator(): target =>', target);
          console.log('decorator(): key =>', key);
          console.log('decorator(): descriptor =>', descriptor);
        };
      }
    `);

    class Hoge {
      @decorator()
      method() {
        console.log('Hoge.prototype.method()');
      }
    }

    function decorator() {
      return (target, key, descriptor) => {
        console.log('decorator(): target =>', target);
        console.log('decorator(): key =>', key);
        console.log('decorator(): descriptor =>', descriptor);
      };
    }

    const hoge = new Hoge();
    hoge.method();
  }
  console.groupEnd();
}
<commit_msg>babel_es2015: add a code of decorators<commit_after>export default function decorators() {
  console.group('ES-next: Stage-2: decorators');
  {
    console.log(`
      class Hoge {
        @decorator
        instance = 1;

        @decorator
        method() {
          console.log('Hoge.prototype.method()');
        }
      }

      function decorator(...args) {
        console.log('decorator()', ...args);
        return (target, key, descriptor) => {
          console.log('decorator(): target =>', target);
          console.log('decorator(): key =>', key);
          console.log('decorator(): descriptor =>', descriptor);
        };
      }
    `);

    class Hoge {
      @decorator
      instance = 1;

      @decorator
      method() {
        console.log('Hoge.prototype.method()');
      }
    }

    function decorator(...args) {
      console.log('decorator()', ...args);
      return (target, key, descriptor) => {
        console.log('decorator(): target =>', target);
        console.log('decorator(): key =>', key);
        console.log('decorator(): descriptor =>', descriptor);
      };
    }

    const hoge = new Hoge();
    hoge.method();
    hoge.instance;
  }
  console.groupEnd();
}
<|endoftext|>