<commit_before>//= require /bower_components/d3/d3.min.js
//= require /bower_components/dimple/dist/dimple.latest.min.js

"use strict";

var OpenSpeedMonitor = OpenSpeedMonitor || {};
OpenSpeedMonitor.ChartModules = OpenSpeedMonitor.ChartModules || {};

OpenSpeedMonitor.ChartModules.PageAggregation = (function (chartIdentifier) {
    var chart = null,
        width = 600,
        height = 600,
        legendPosition = {x: 200, y: 10, width: 100, height: 100},
        margins = {left: 60, right: 100, top: 110, bottom: 150},
        maxWidthPerBar = 150,
        allMeasurandSeries = {},
        filterRules = {},
        svg = null,
        seriesCount = 0,
        xAxis = null,
        yAxes = {},
        showBarLabels = false,
        showXAxis = true,
        showYAxis = true,
        showGridlines = true;

    var init = function () {
        // add eventHandler
        window.onresize = function () {
            calcChartWidth();
            resize();
        };
    };

    var drawChart = function (barchartData) {
        // Delete old chart in same container
        d3.select("#" + chartIdentifier).selectAll("svg").remove();
        var $adjustBarchartButton = $("#adjust-barchart-modal");
        if ($adjustBarchartButton.hasClass("hidden"))
            $adjustBarchartButton.removeClass("hidden");
        initFilterDropdown(barchartData.filterRules);

        // Reset fields
        allMeasurandSeries = {};
        yAxes = {};
        xAxis = null;
        height = 600;

        // Create SVG
        svg = dimple.newSvg("#" + chartIdentifier, "100%", height);
        chart = new dimple.chart(svg, null);
        chart.setMargins(margins.left, margins.right, margins.top, margins.bottom);
        svg = svg.node();
        seriesCount = Object.keys(barchartData['series']).length;

        // Add x axis
        xAxis = chart.addCategoryAxis("x", "grouping");
        xAxis.title = barchartData['groupingLabel'];
        filterRules = barchartData.filterRules;

        // Add series
        var seriesId = 0;
        for (var currentSeriesId in barchartData.series) {
            var currentSeries = barchartData.series[currentSeriesId];

            // get correct y axis
            var yAxis = yAxes[currentSeries['dimensionalUnit']];
            if (!yAxis) {
                yAxis = chart.addMeasureAxis("y", "indexValue");
                yAxis.title = currentSeries['yAxisLabel'];
                yAxes[currentSeries['dimensionalUnit']] = yAxis;
            }

            allMeasurandSeries[currentSeriesId] = [];
            if (currentSeries.stacked === true) {
                var s = chart.addSeries("index", dimple.plot.bar, [xAxis, yAxis]);
                s.data = currentSeries.data;
                // set originData for filtering
                s.originData = s.data;
                allMeasurandSeries[currentSeriesId].push(seriesId);
                seriesId += 1;
            } else {
                var allMeasurands = removeDuplicatesFromArray(currentSeries.data.map(function (value) {
                    return value.index;
                }));
                allMeasurands.forEach(function (measurand) {
                    var s = chart.addSeries("index", dimple.plot.bar, [xAxis, yAxis]);
                    s.data = currentSeries.data.filter(function (datum) {
                        return datum.index === measurand;
                    });
                    s.originData = s.data;
                    allMeasurandSeries[currentSeriesId].push(seriesId);
                    seriesId += 1;
                })
            }
        }

        // set originSeries for filtering
        chart.originSeries = chart.series;

        chart.addLegend(legendPosition.x, legendPosition.y, legendPosition.width, legendPosition.height, "right");
        draw(false);
        calcChartWidth();
        resize();

        addBarLabels(barchartData);
    };

    var adjustChart = function () {
        // change size
        width = $("#inputChartWidth").val() + "px";
        height = $("#inputChartHeight").val() + "px";

        // change labels
        xAxis.title = $("#x-axis-label").val();
        $("#y-axis-alias-container").children().each(function () {
            yAxes[$(this).find(".unitInput").val()].title = $(this).find(".labelInput").val()
        });

        // assign colors
        var colorAssignments = [];
        $("#assign-color-container").children().each(function () {
            colorAssignments.push({"label": $(this).find("label").html(), "color": $(this).find("input").val()});
        });
        assignColor(colorAssignments);

        // Toggle gridlines
        showGridlines = $("#inputShowGridlines").prop("checked");
        if (showGridlines) {
            d3.select(".dimple-gridline").style("opacity", 1);
        } else {
            d3.select(".dimple-gridline").style("opacity", 0);
        }

        // Toggle yAxis
        showYAxis = $("#inputShowYAxis").prop("checked");
        if (showYAxis) {
            d3.selectAll(".dimple-axis.dimple-axis-y").style("opacity", 1);
        } else {
            d3.selectAll(".dimple-axis.dimple-axis-y").style("opacity", 0);
        }

        // Toggle xAxis
        showXAxis = $("#inputShowXAxis").prop("checked");
        if (showXAxis) {
            d3.select(".domain.dimple-custom-axis-line").style("opacity", 1);
            d3.select(".dimple-axis-x").selectAll("line").style("opacity", 1);
        } else {
            d3.select(".domain.dimple-custom-axis-line").style("opacity", 0);
            d3.select(".dimple-axis-x").selectAll("line").style("opacity", 0);
        }

        // Toggle bar labels
        showBarLabels = $("#inputShowBarLabels").prop("checked");
        if (showYAxis) {
            d3.selectAll(".bar-label").style("opacity", 1);
        } else {
            d3.selectAll(".bar-label").style("opacity", 0);
        }

        resize();
    };

    var assignColor = function (colorAssignments) {
        colorAssignments.forEach(function (assignment) {
            chart.assignColor(assignment.label, assignment.color);
        });

        // reassign data to series so series are redrawn
        chart.series.forEach(function (s) {
            var seriesData = s.data;
            // fake some data change
            s.data = [{"grouping": s.data[0].grouping, "index": "", "indexValue": 0}];
            draw(false);
            s.data = seriesData;
        });

        draw(false);
    };

    /**
     * Redraws the chart.
     * If dataValid = true, then the chart gets drawn without reprocessing data.
     */
    var draw = function (dataValid) {
        chart.draw(0, dataValid);
    };

    var positionBars = function () {
        // Move Bars side to side
        for (var s in allMeasurandSeries) {
            var i = Object.keys(allMeasurandSeries).indexOf(s);
            allMeasurandSeries[s].forEach(function (seriesId) {
                var currentSeriesRects = d3.selectAll(".dimple-series-group-" + seriesId).selectAll("rect");
                if (currentSeriesRects) {
                    var oldWidth = parseInt(currentSeriesRects.attr("width"));
                    var translateX = i * oldWidth / seriesCount;
                    currentSeriesRects.attr("transform", "translate(" + translateX + ", 0)");
                    currentSeriesRects.attr("width", oldWidth / seriesCount);
                }
            })

        }
    };

    var calcChartWidth = function () {
        var maxWidth, containerWidth;

        containerWidth = $("#" + chartIdentifier).width();
        maxWidth = Object.keys(allMeasurandSeries).length * $(".dimple-axis-x .tick").length * maxWidthPerBar;
        width = containerWidth < maxWidth ? "100%" : "" + maxWidth + "px";
    };

    var initFilterDropdown = function (filterRules) {
        var $filterDropdownGroup = $("#filter-dropdown-group");
        var $customerJourneyHeader = $filterDropdownGroup.find("#customer-journey-header");

        if ($filterDropdownGroup.hasClass("hidden"))
            $filterDropdownGroup.removeClass("hidden");

        for (var filterRuleKey in filterRules) {
            if (filterRules.hasOwnProperty(filterRuleKey)) {
                var link = $("
" + filterRuleKey + "
");
                link.click(function (e) {
                    filterCustomerJourney(e.target.innerText);
                });
                link.insertAfter($customerJourneyHeader);
            }
        }

        $filterDropdownGroup.find("#all-bars-desc").click(function (e) {
            filterCustomerJourney(null, true);
        });
        $filterDropdownGroup.find("#all-bars-asc").click(function (e) {
            filterCustomerJourney(null, false);
        })
    };

    var filterCustomerJourney = function (journeyKey, desc) {
        if (journeyKey && filterRules[journeyKey]) {
            // order axis
            xAxis._orderRules = [];
            xAxis.addOrderRule(filterRules[journeyKey]);

            // remove elemts not in customer Journey
            chart.series.forEach(function (currentSeries) {
                currentSeries.data = currentSeries.originData;
                currentSeries.data = currentSeries.originData.filter(function (element) {
                    return filterRules[journeyKey].indexOf(element.grouping) >= 0;
                });
            });
            // remove series containing no data
            chart.series = chart.originSeries.filter(function (s) {
                return s.data.length > 0;
            });

        } else {
            // reset order rules
            desc == desc || false;
            xAxis._orderRules = [];
            xAxis.addOrderRule(function (a, b) {
                var valueA = parseFloat(a.indexValue[0]);
                var valueB = parseFloat(b.indexValue[0]);

                if (valueA < valueB) {
                    return -1;
                } else if (valueA === valueB) {
                    return 0;
                } else {
                    return 1;
                }
            }, desc);

            chart.series = chart.originSeries;
            chart.series.forEach(function (currentSeries) {
                currentSeries.data = currentSeries.originData;
            });
        }

        draw(false);
        resize();
    };

    var resize = function () {
        if (svg) {
            svg.setAttribute("width", width);
            svg.setAttribute("height", height);
            chart.legends[0].x = parseInt(width) - legendPosition.width - margins.right;

            draw(true);
            positionBars();
        }
    };

    var addBarLabels = function (barchartData) {
        // barchartData:
        // stacked: true
        // [[6],[3]]
        // stacked: false
        // [[6],[3]]

        // bar.series:
        // stacked: true
        // [[6],[3]]
        // stacked: false
        // [[3],[3],[3]]

        // allMeasurandSeries:
        // stacked: true
        // [0,1] -> [[0],[0]]
        // stacked: false
        // [0,1] -> [[[0],[1]],[0]]

        for (var barIndex in allMeasurandSeries) {
            allMeasurandSeries[barIndex].forEach( function (seriesIndex) {
                // create labels group container
                var currentSeriesLabelClass = "dimple-series-group-" + seriesIndex.toString() + "-labels";
                chart.svg.append("g").attr("class", currentSeriesLabelClass);

                var currentSeriesRects = d3.selectAll(".dimple-series-group-" + seriesIndex).selectAll("rect");
                currentSeriesRects[0].forEach( function (rectangle, rectangleIndex) {
                    // get the unit
                    // stacked/overlayed bars can only be of the same dimensional unit, therefore accessing the first is sufficient
                    var unit = barchartData.series[barIndex].dimensionalUnit;
                    // get the measurand value and format it
                    var value = barchartData.series[barIndex].data[rectangleIndex].indexValue.toString();
                    value = (unit == "%") ? parseFloat(value).toFixed(1) : Math.round(value);

                    // set the label
                    var label = (unit == "#") ? unit + " " + value : value + " " + unit;

                    // append the label
                    d3.selectAll("." + currentSeriesLabelClass).append("text")
                        .attr("x", rectangle.x.baseVal.value + rectangle.width.baseVal.value / 2)
                        .attr("y", rectangle.y.baseVal.value - 10)
                        .text(label)
                        .style("text-anchor", "middle")
                        .attr("class", "bar-label");
                });
                // move labels if necessary
                var currentSeriesLabels = d3.selectAll(".dimple-series-group-" + seriesIndex + "-labels").selectAll("text");
                var width = parseInt(currentSeriesRects.attr("width"));
                var translateX = barIndex * width;
                currentSeriesLabels.attr("transform", "translate(" + translateX + ", 0)");

                // hide the labels initially
                if (!showBarLabels)
                    currentSeriesLabels.style("opacity", 0);
            });
        }
    };

    var getXLabel = function () {
        return xAxis.title;
    };
    var getYLabels = function () {
        var result = [];
        Object.keys(yAxes).forEach(function (key) {
            result.push({"unit": key, "label": yAxes[key].title})
        });
        return result;
    };
    var getWidth = function () {
        var svgWidth = svg.getAttribute("width");
        if (svgWidth.endsWith("px")) {
            return parseInt(svgWidth);
        } else if (svgWidth.endsWith("%")) {
            return parseInt(svgWidth) * $("#" + chartIdentifier).width() / 100;
        } else {
            return svgWidth;
        }
    };
    var getHeight = function () {
        var svgHeight = svg.getAttribute("height");
        if (svgHeight.endsWith("px")) {
            return parseInt(svgHeight);
        } else if (svgHeight.endsWith("%")) {
            return parseInt(svgHeight) * $("#" + chartIdentifier).height() / 100;
        } else {
            return svgHeight;
        }
    };
    var getColorAssignments = function () {
        var result = [];
        chart.legends[0]._getEntries().forEach(function (legendEntry) {
            result.push({"label": legendEntry.key, "color": legendEntry.fill});
        });
        return result;
    };
    var getShowXAxis = function () {
        return showXAxis;
    };
    var getShowYAxis = function () {
        return showYAxis;
    };
    var getShowGridlines = function () {
        return showGridlines;
    };
    var getShowBarLabels = function () {
        return showBarLabels;
    };

    // returns a new array without removed duplicates
    var removeDuplicatesFromArray = function (array) {
        return array.reduce(function (p, c) {
            if (p.indexOf(c) < 0) p.push(c);
            return p;
        }, []);
    };

    init();
    return {
        adjustChart: adjustChart,
        drawChart: drawChart,
        getColorAssignments: getColorAssignments,
        getHeight: getHeight,
        getWidth: getWidth,
        getXLabel: getXLabel,
        getYLabels: getYLabels,
        getShowXAxis: getShowXAxis,
        getShowYAxis: getShowYAxis,
        getShowGridlines: getShowGridlines,
        getShowBarLabels: getShowBarLabels,
        resize: resize
    };

});
<commit_msg>[IT-1425] WIP, Fixed wrong labeling for the 'in front of each other' mode<commit_after>//= require /bower_components/d3/d3.min.js
//= require /bower_components/dimple/dist/dimple.latest.min.js

"use strict";

var OpenSpeedMonitor = OpenSpeedMonitor || {};
OpenSpeedMonitor.ChartModules = OpenSpeedMonitor.ChartModules || {};

OpenSpeedMonitor.ChartModules.PageAggregation = (function (chartIdentifier) {
    var chart = null,
        width = 600,
        height = 600,
        legendPosition = {x: 200, y: 10, width: 100, height: 100},
        margins = {left: 60, right: 100, top: 110, bottom: 150},
        maxWidthPerBar = 150,
        allMeasurandSeries = {},
        filterRules = {},
        svg = null,
        seriesCount = 0,
        xAxis = null,
        yAxes = {},
        showBarLabels = false,
        showXAxis = true,
        showYAxis = true,
        showGridlines = true;

    var init = function () {
        // add eventHandler
        window.onresize = function () {
            calcChartWidth();
            resize();
        };
    };

    var drawChart = function (barchartData) {
        // Delete old chart in same container
        d3.select("#" + chartIdentifier).selectAll("svg").remove();
        var $adjustBarchartButton = $("#adjust-barchart-modal");
        if ($adjustBarchartButton.hasClass("hidden"))
            $adjustBarchartButton.removeClass("hidden");
        initFilterDropdown(barchartData.filterRules);

        // Reset fields
        allMeasurandSeries = {};
        yAxes = {};
        xAxis = null;
        height = 600;

        // Create SVG
        svg = dimple.newSvg("#" + chartIdentifier, "100%", height);
        chart = new dimple.chart(svg, null);
        chart.setMargins(margins.left, margins.right, margins.top, margins.bottom);
        svg = svg.node();
        seriesCount = Object.keys(barchartData['series']).length;

        // Add x axis
        xAxis = chart.addCategoryAxis("x", "grouping");
        xAxis.title = barchartData['groupingLabel'];
        filterRules = barchartData.filterRules;

        // Add series
        var seriesId = 0;
        for (var currentSeriesId in barchartData.series) {
            var currentSeries = barchartData.series[currentSeriesId];

            // get correct y axis
            var yAxis = yAxes[currentSeries['dimensionalUnit']];
            if (!yAxis) {
                yAxis = chart.addMeasureAxis("y", "indexValue");
                yAxis.title = currentSeries['yAxisLabel'];
                yAxes[currentSeries['dimensionalUnit']] = yAxis;
            }

            allMeasurandSeries[currentSeriesId] = [];
            if (currentSeries.stacked === true) {
                var s = chart.addSeries("index", dimple.plot.bar, [xAxis, yAxis]);
                s.data = currentSeries.data;
                // set originData for filtering
                s.originData = s.data;
                allMeasurandSeries[currentSeriesId].push(seriesId);
                seriesId += 1;
            } else {
                var allMeasurands = removeDuplicatesFromArray(currentSeries.data.map(function (value) {
                    return value.index;
                }));
                allMeasurands.forEach(function (measurand) {
                    var s = chart.addSeries("index", dimple.plot.bar, [xAxis, yAxis]);
                    s.data = currentSeries.data.filter(function (datum) {
                        return datum.index === measurand;
                    });
                    s.originData = s.data;
                    allMeasurandSeries[currentSeriesId].push(seriesId);
                    seriesId += 1;
                })
            }
        }

        // set originSeries for filtering
        chart.originSeries = chart.series;

        chart.addLegend(legendPosition.x, legendPosition.y, legendPosition.width, legendPosition.height, "right");
        draw(false);
        calcChartWidth();
        resize();

        addBarLabels(barchartData);
    };

    var adjustChart = function () {
        // change size
        width = $("#inputChartWidth").val() + "px";
        height = $("#inputChartHeight").val() + "px";

        // change labels
        xAxis.title = $("#x-axis-label").val();
        $("#y-axis-alias-container").children().each(function () {
            yAxes[$(this).find(".unitInput").val()].title = $(this).find(".labelInput").val()
        });

        // assign colors
        var colorAssignments = [];
        $("#assign-color-container").children().each(function () {
            colorAssignments.push({"label": $(this).find("label").html(), "color": $(this).find("input").val()});
        });
        assignColor(colorAssignments);

        // Toggle gridlines
        showGridlines = $("#inputShowGridlines").prop("checked");
        if (showGridlines) {
            d3.select(".dimple-gridline").style("opacity", 1);
        } else {
            d3.select(".dimple-gridline").style("opacity", 0);
        }

        // Toggle yAxis
        showYAxis = $("#inputShowYAxis").prop("checked");
        if (showYAxis) {
            d3.selectAll(".dimple-axis.dimple-axis-y").style("opacity", 1);
        } else {
            d3.selectAll(".dimple-axis.dimple-axis-y").style("opacity", 0);
        }

        // Toggle xAxis
        showXAxis = $("#inputShowXAxis").prop("checked");
        if (showXAxis) {
            d3.select(".domain.dimple-custom-axis-line").style("opacity", 1);
            d3.select(".dimple-axis-x").selectAll("line").style("opacity", 1);
        } else {
            d3.select(".domain.dimple-custom-axis-line").style("opacity", 0);
            d3.select(".dimple-axis-x").selectAll("line").style("opacity", 0);
        }

        // Toggle bar labels
        showBarLabels = $("#inputShowBarLabels").prop("checked");
        if (showYAxis) {
            d3.selectAll(".bar-label").style("opacity", 1);
        } else {
            d3.selectAll(".bar-label").style("opacity", 0);
        }

        resize();
    };

    var assignColor = function (colorAssignments) {
        colorAssignments.forEach(function (assignment) {
            chart.assignColor(assignment.label, assignment.color);
        });

        // reassign data to series so series are redrawn
        chart.series.forEach(function (s) {
            var seriesData = s.data;
            // fake some data change
            s.data = [{"grouping": s.data[0].grouping, "index": "", "indexValue": 0}];
            draw(false);
            s.data = seriesData;
        });

        draw(false);
    };

    /**
     * Redraws the chart.
     * If dataValid = true, then the chart gets drawn without reprocessing data.
     */
    var draw = function (dataValid) {
        chart.draw(0, dataValid);
    };

    var positionBars = function () {
        // Move Bars side to side
        for (var s in allMeasurandSeries) {
            var i = Object.keys(allMeasurandSeries).indexOf(s);
            allMeasurandSeries[s].forEach(function (seriesId) {
                var currentSeriesRects = d3.selectAll(".dimple-series-group-" + seriesId).selectAll("rect");
                if (currentSeriesRects) {
                    var oldWidth = parseInt(currentSeriesRects.attr("width"));
                    var translateX = i * oldWidth / seriesCount;
                    currentSeriesRects.attr("transform", "translate(" + translateX + ", 0)");
                    currentSeriesRects.attr("width", oldWidth / seriesCount);
                }
            })

        }
    };

    var calcChartWidth = function () {
        var maxWidth, containerWidth;

        containerWidth = $("#" + chartIdentifier).width();
        maxWidth = Object.keys(allMeasurandSeries).length * $(".dimple-axis-x .tick").length * maxWidthPerBar;
        width = containerWidth < maxWidth ? "100%" : "" + maxWidth + "px";
    };

    var initFilterDropdown = function (filterRules) {
        var $filterDropdownGroup = $("#filter-dropdown-group");
        var $customerJourneyHeader = $filterDropdownGroup.find("#customer-journey-header");

        if ($filterDropdownGroup.hasClass("hidden"))
            $filterDropdownGroup.removeClass("hidden");

        for (var filterRuleKey in filterRules) {
            if (filterRules.hasOwnProperty(filterRuleKey)) {
                var link = $("
" + filterRuleKey + "
");
                link.click(function (e) {
                    filterCustomerJourney(e.target.innerText);
                });
                link.insertAfter($customerJourneyHeader);
            }
        }

        $filterDropdownGroup.find("#all-bars-desc").click(function (e) {
            filterCustomerJourney(null, true);
        });
        $filterDropdownGroup.find("#all-bars-asc").click(function (e) {
            filterCustomerJourney(null, false);
        })
    };

    var filterCustomerJourney = function (journeyKey, desc) {
        if (journeyKey && filterRules[journeyKey]) {
            // order axis
            xAxis._orderRules = [];
            xAxis.addOrderRule(filterRules[journeyKey]);

            // remove elemts not in customer Journey
            chart.series.forEach(function (currentSeries) {
                currentSeries.data = currentSeries.originData;
                currentSeries.data = currentSeries.originData.filter(function (element) {
                    return filterRules[journeyKey].indexOf(element.grouping) >= 0;
                });
            });
            // remove series containing no data
            chart.series = chart.originSeries.filter(function (s) {
                return s.data.length > 0;
            });

        } else {
            // reset order rules
            desc == desc || false;
            xAxis._orderRules = [];
            xAxis.addOrderRule(function (a, b) {
                var valueA = parseFloat(a.indexValue[0]);
                var valueB = parseFloat(b.indexValue[0]);

                if (valueA < valueB) {
                    return -1;
                } else if (valueA === valueB) {
                    return 0;
                } else {
                    return 1;
                }
            }, desc);

            chart.series = chart.originSeries;
            chart.series.forEach(function (currentSeries) {
                currentSeries.data = currentSeries.originData;
            });
        }

        draw(false);
        resize();
    };

    var resize = function () {
        if (svg) {
            svg.setAttribute("width", width);
            svg.setAttribute("height", height);
            chart.legends[0].x = parseInt(width) - legendPosition.width - margins.right;

            draw(true);
            positionBars();
        }
    };

    var addBarLabels = function (barchartData) {
        for (var barIndex in allMeasurandSeries) {
            allMeasurandSeries[barIndex].forEach( function (seriesID, seriesIndex) {
                // create labels group container
                var currentSeriesLabelClass = "dimple-series-group-" + seriesID.toString() + "-labels";
                chart.svg.append("g").attr("class", currentSeriesLabelClass);

                var currentSeriesRects = d3.selectAll(".dimple-series-group-" + seriesID).selectAll("rect");
                currentSeriesRects[0].forEach( function (rectangle, rectangleIndex) {
                    // get the unit
                    // stacked/overlayed bars can only be of the same dimensional unit, therefore accessing the first is sufficient
                    var unit = barchartData.series[barIndex].dimensionalUnit;
                    // get the measurand value and format it
                    var barchartSeriesDataIndex = seriesIndex * currentSeriesRects[0].length + rectangleIndex;
                    var value = barchartData.series[barIndex].data[barchartSeriesDataIndex].indexValue.toString();
                    value = (unit == "%") ? parseFloat(value).toFixed(1) : Math.round(value);

                    // set the label
                    var label = (unit == "#") ? unit + " " + value : value + " " + unit;

                    // append the label
                    d3.selectAll("." + currentSeriesLabelClass).append("text")
                        .attr("x", rectangle.x.baseVal.value + rectangle.width.baseVal.value / 2)
                        .attr("y", rectangle.y.baseVal.value - 10)
                        .text(label)
                        .style("text-anchor", "middle")
                        .attr("class", "bar-label");
                });
                // move labels if necessary
                var currentSeriesLabels = d3.selectAll(".dimple-series-group-" + seriesID + "-labels").selectAll("text");
                var width = parseInt(currentSeriesRects.attr("width"));
                var translateX = barIndex * width;
                currentSeriesLabels.attr("transform", "translate(" + translateX + ", 0)");

                // hide the labels initially
                if (!showBarLabels)
                    currentSeriesLabels.style("opacity", 0);
            });
        }
    };

    var getXLabel = function () {
        return xAxis.title;
    };
    var getYLabels = function () {
        var result = [];
        Object.keys(yAxes).forEach(function (key) {
            result.push({"unit": key, "label": yAxes[key].title})
        });
        return result;
    };
    var getWidth = function () {
        var svgWidth = svg.getAttribute("width");
        if (svgWidth.endsWith("px")) {
            return parseInt(svgWidth);
        } else if (svgWidth.endsWith("%")) {
            return parseInt(svgWidth) * $("#" + chartIdentifier).width() / 100;
        } else {
            return svgWidth;
        }
    };
    var getHeight = function () {
        var svgHeight = svg.getAttribute("height");
        if (svgHeight.endsWith("px")) {
            return parseInt(svgHeight);
        } else if (svgHeight.endsWith("%")) {
            return parseInt(svgHeight) * $("#" + chartIdentifier).height() / 100;
        } else {
            return svgHeight;
        }
    };
    var getColorAssignments = function () {
        var result = [];
        chart.legends[0]._getEntries().forEach(function (legendEntry) {
            result.push({"label": legendEntry.key, "color": legendEntry.fill});
        });
        return result;
    };
    var getShowXAxis = function () {
        return showXAxis;
    };
    var getShowYAxis = function () {
        return showYAxis;
    };
    var getShowGridlines = function () {
        return showGridlines;
    };
    var getShowBarLabels = function () {
        return showBarLabels;
    };

    // returns a new array without removed duplicates
    var removeDuplicatesFromArray = function (array) {
        return array.reduce(function (p, c) {
            if (p.indexOf(c) < 0) p.push(c);
            return p;
        }, []);
    };

    init();
    return {
        adjustChart: adjustChart,
        drawChart: drawChart,
        getColorAssignments: getColorAssignments,
        getHeight: getHeight,
        getWidth: getWidth,
        getXLabel: getXLabel,
        getYLabels: getYLabels,
        getShowXAxis: getShowXAxis,
        getShowYAxis: getShowYAxis,
        getShowGridlines: getShowGridlines,
        getShowBarLabels: getShowBarLabels,
        resize: resize
    };

});
<|endoftext|>


<commit_before>/**
 * Created by chendanni on 16/7/19.
 */

import mongoose from 'mongoose'
var schema =  mongoose.Schema;

//add schema
var userSchema = schema({
  name: String,
  language:{
    language_id: String,
    level: Number
  },
  application_id: [schema.Types.ObjectId],
  email: String,
  starred: Number,
  fork: Number,
  follower: Number,
  following: Number,
  star_repo_ids: [schema.Types.ObjectId],
  fork_repo_ids: [schema.Types.ObjectId]
});

//add instance methods
userSchema.methods.findSimilarTypes = function(fc) {
  return this.model('users').find({ type: this.type}, fc);
};

//make model and export
var user = mongoose.model('user', tagSchema);
export default user;
<commit_msg>Update userSchema<commit_after>/**
 * Created by chendanni on 16/7/19.
 */

import mongoose from 'mongoose'
var schema =  mongoose.Schema;

//add schema
var userSchema = schema({
  name: String,
  language:{
    language_id: schema.Types.ObjectId,
    level: Number
  },
  application_id: [schema.Types.ObjectId],
  email: String,
  starred: Number,
  fork: Number,
  follower: Number,
  following: Number,
  star_repo_ids: [schema.Types.ObjectId],
  fork_repo_ids: [schema.Types.ObjectId]
});

//add instance methods
userSchema.methods.findSimilarTypes = function(fc) {
  return this.model('users').find({ type: this.type}, fc);
};

//make model and export
var user = mongoose.model('user', tagSchema);
export default user;
<|endoftext|>


<commit_before>'use strict';

const chalk = require('chalk');
const settings = require('./settings');

const TOO_LOW_TO_SELL = 1000;
const TOO_HIGH_TO_BUY = 1100;
const PRICE_IS_SWEET = 1200;

class Formatter {

  constructor() {
    this.timeTillOfflineStatus = 300;
    this.numberOfPriceDecimals = 4;
  }

  tradePair(tradePair) {
    if (tradePair === undefined) {
      return chalk.gray('-');
    }

    return chalk.green.bold(tradePair);
  }

  coins(coins) {
    if (coins === undefined || coins == 0) {
      return chalk.gray('-');
    }

    return this.price(coins);
  }

  currentProfit(numberOfCoins, boughtPrice, lastPriceInBTC) {
    if (numberOfCoins === undefined || boughtPrice === undefined || lastPriceInBTC === undefined) {
      return chalk.gray('-');
    }

    if (parseFloat(lastPriceInBTC) === 0 || parseFloat(boughtPrice) === 0) {
      return chalk.gray('-');
    }

    if (isNaN(parseFloat(lastPriceInBTC)) || isNaN(parseFloat(boughtPrice))) {
      return chalk.gray('-');
    }

    if (parseFloat(numberOfCoins) === 0) {
      return chalk.gray('-');
    }

    let diff = parseFloat(lastPriceInBTC) - parseFloat(boughtPrice);
    let profit = this.price(parseFloat(numberOfCoins) * diff);

    if (diff >= 0) {
      return this.price(profit);
    }

    return this.price(profit);
  }

  currentProfitWithPercent(numberOfCoins, boughtPrice, lastPriceInBTC) {
    let currentProfit = this.currentProfit(numberOfCoins, boughtPrice, lastPriceInBTC);

    if (currentProfit === undefined || currentProfit === chalk.gray('-') || currentProfit === '-') {
      return chalk.gray('-');
    }

    let diff = parseFloat(lastPriceInBTC) - parseFloat(boughtPrice);
    let profitPercent = diff * 100 / parseFloat(boughtPrice);
    let negativePadding = (profitPercent < 0) ? '' : ' '

    return this.profit(currentProfit) + negativePadding + chalk.gray(` ${profitPercent.toFixed(1)}%`);
  }

  totalCurrentProfit(totalBTCValue, totalDiffSinceBuy) {
    if (totalBTCValue === undefined || totalDiffSinceBuy === undefined) {
      return chalk.gray('-');
    }

    if (parseFloat(totalBTCValue) === 0 || parseFloat(totalDiffSinceBuy) === 0) {
      return chalk.gray('-');
    }

    if (isNaN(parseFloat(totalBTCValue)) || isNaN(parseFloat(totalDiffSinceBuy))) {
      return chalk.gray('-');
    }

    let profitPercent = parseFloat(totalDiffSinceBuy) * 100 / parseFloat(totalBTCValue);

    return this.profit(totalDiffSinceBuy) + chalk.gray(` ${profitPercent.toFixed(1)}%`);
  }

  price(price) {
    if (price === '--not set--') {
      return chalk.gray('-');
    }
    if (price === undefined) {
      return chalk.gray('-');
    }

    price = price.toString();

    let posOfDecimalPoint = price.indexOf('.');
    if (posOfDecimalPoint < 1) {
      posOfDecimalPoint = 1;
    }

    let priceOut = parseFloat(price).toFixed(4)
    //return price.slice(0, posOfDecimalPoint + 1 + this.numberOfPriceDecimals);
    return priceOut;
  }

  profit(price) {
    price = this.price(price);
    let priceAsFloat = parseFloat(price);

    if (isNaN(priceAsFloat)) {
      return chalk.white('0');
    }

    if (priceAsFloat < 0) {
      return chalk.red(priceAsFloat);
    }

    if (priceAsFloat > 0) {
      return chalk.green(priceAsFloat);
    }

    return chalk.white(price);
  }

  getLatestBuySellSweetMessage(buyMessageDate, sellMessageDate, sweetMessageDate) {
    if (!(buyMessageDate instanceof Date)) {
      buyMessageDate = new Date(buyMessageDate || 0);
    }

    if (!(sellMessageDate instanceof Date)) {
      sellMessageDate = new Date(sellMessageDate || 0);
    }

    if (!(sweetMessageDate instanceof Date)) {
      sweetMessageDate = new Date(sweetMessageDate || 0);
    }

    if (buyMessageDate > sellMessageDate && buyMessageDate > sweetMessageDate) {
      return TOO_HIGH_TO_BUY;
    }

    if (sellMessageDate > buyMessageDate && sellMessageDate > sweetMessageDate) {
      return TOO_LOW_TO_SELL;
    }

    if (sweetMessageDate > buyMessageDate && sweetMessageDate > sellMessageDate) {
      return PRICE_IS_SWEET;
    }

    return false;
  }

  openOrders(message) {
    if (message === 'Open orders') {
      return chalk.red('yes');
    }

    return chalk.gray('-');
  }

  buySellMessage(buyMessageDate, sellMessageDate, sweetMessageDate) {
    let bss = this.getLatestBuySellSweetMessage(buyMessageDate, sellMessageDate, sweetMessageDate);

    if (bss === TOO_HIGH_TO_BUY) {
      return chalk.blue('too high');
    }

    if (bss === TOO_LOW_TO_SELL) {
      return chalk.magenta('too low');
    }

    if (bss === PRICE_IS_SWEET) {
      return chalk.green('sweet');
    }

    return chalk.gray('-');
  }

  buyPrice(numberOfCoins, boughtPrice, lastPrice) {
    if (
          numberOfCoins === undefined || boughtPrice === undefined || parseFloat(boughtPrice) === 0 ||
          isNaN(parseFloat(boughtPrice)) || parseFloat(numberOfCoins) === 0
    ) {
      return this.price(lastPrice);
    }
    return chalk.yellow(this.price(boughtPrice * 10000));
  }

  priceDiff(buyMessageDate, sellMessageDate, sweetMessageDate, buyPrice, sellPrice, lastPrice) {
    if (isNaN(parseFloat(buyPrice)) || isNaN(parseFloat(sellPrice)) || isNaN(parseFloat(lastPrice))) {
      return chalk.gray('-');
    }

    let bss = this.getLatestBuySellSweetMessage(buyMessageDate, sellMessageDate, sweetMessageDate);
    if (bss === TOO_LOW_TO_SELL) {
      let diff = parseFloat(sellPrice) - parseFloat(lastPrice);
      let percent = (diff / parseFloat(sellPrice) * 100).toFixed(2);
      return `${chalk.magenta(this.price(diff))} ${chalk.gray(`${percent}%`)}`;
    }

    if (bss === TOO_HIGH_TO_BUY) {
      let diff = parseFloat(lastPrice) - parseFloat(buyPrice);
      let percent = (diff / parseFloat(lastPrice) * 100).toFixed(2);
      return `${chalk.blue(this.price(diff))} ${chalk.gray(`${percent}%`)}`;
    }

    return chalk.gray('-');
  }

  btcValue(numberOfCoins, lastPriceInBTC) {
    if (numberOfCoins === undefined || lastPriceInBTC === undefined || numberOfCoins == 0) {
      return chalk.gray('-');
    }

    return this.price(parseFloat(numberOfCoins) * parseFloat(lastPriceInBTC));
  }

  trades(numberOfTrades, lastTradeDate) {
    if (numberOfTrades === undefined || lastTradeDate === undefined) {
      return chalk.gray('-');
    }

    if (numberOfTrades <= 0) {
      return chalk.gray('-');
    }
    return `${chalk.bold(numberOfTrades)} ${this.timeSince(lastTradeDate, 'trades')}`;
  }

  errorCode(errors, lastTimeStamp) {
    if (errors === undefined || errors.length === 0 || lastTimeStamp === undefined) {
      return chalk.gray('-');
    }

    if (!(lastTimeStamp instanceof Date)) {
      lastTimeStamp = new Date(lastTimeStamp);
    }

    let output = [];
    let oldestErrorDate = new Date();

    for (let code of Object.keys(errors)) {
      for (let date of errors[code].dates) {
        if (!(date instanceof Date)) {
          date = new Date(date);
        }
        if (date < oldestErrorDate) {
          oldestErrorDate = date;
        }
      }

      let seconds = Math.floor((lastTimeStamp - oldestErrorDate) / 1000);

      output.push(`${errors[code].counter} x ${chalk.red(code)} in ${this.formatSeconds(seconds, 'errors')}`);
    }

    return output.join('\n');
  }

  lastPrice(lastPrice, tendency) {
    let output = this.price(lastPrice);
    let tendencyOutput = '';

    tendency = parseInt(tendency, 10);

    if (tendency <= -10) {
      tendencyOutput = chalk.red.bold('\u2193\u2193');
    }
    if (tendency > -10 && tendency <= -2) {
      tendencyOutput = chalk.magenta.bold('\u2193');
    }
    if (tendency > -2 && tendency <= 1) {
      tendencyOutput = chalk.yellow.bold('\u2192');
    }
    if (tendency > 1 && tendency <= 9) {
      tendencyOutput = chalk.cyan.bold('\u2191');
    }
    if (tendency > 9) {
      tendencyOutput = chalk.green.bold('\u2191\u2191');
    }
    return `${output} ${tendencyOutput}`;
  }

  tradesInTimeSlots(slots) {
    if (slots === undefined) {
      return chalk.gray('-');
    }

    return `${this.colorizeTradesInTimeSlots(slots['1hr'])} ${this.colorizeTradesInTimeSlots(slots['6hr'])} ${this.colorizeTradesInTimeSlots(slots['12hr'])} ${this.colorizeTradesInTimeSlots(slots['24hr'])} ${this.colorizeTradesInTimeSlots(slots.older)}`;
  }

  colorizeTradesInTimeSlots(number) {
    if (number === undefined || number === 0) {
      return chalk.gray('-');
    }

    return chalk.blue(number);
  }

  pm2Id(pairName, pm2Data) {
    if (pairName === undefined || pm2Data === undefined) {
      return chalk.gray('-');
    }

    if (pm2Data[pairName] === undefined || pm2Data[pairName].id === undefined) {
      return chalk.gray('-');
    }

    return pm2Data[pairName].id;
  }

  /**
   * Converts the given date in a string of status.
   * Like if the date is 300 sec in the past, return "offline".
   * @param pairName
   * @param pm2Data
   * @returns {*}
   */
  pm2Status(pairName, pm2Data) {
    if (pairName === undefined || pm2Data === undefined) {
      return chalk.gray('-');
    }

    if (pm2Data[pairName] === undefined || pm2Data[pairName].status === undefined) {
      return chalk.gray('-');
    }

    return this.colorStatus(pm2Data[pairName].id,pm2Data[pairName].status);
  }

  /**
   * Description
   * @method colorStatus
   * @param {} status
   * @return
   */
  colorStatus(id,status) {
    switch (status) {
      case 'online':
        return chalk.green.bold(id);
      case 'offline':
      case 'stopped':
        return chalk.red.bold(id + ' off');
      case 'launching':
        return chalk.blue.bold(id + ' launching');
      default:
        return chalk.red.bold(id + ' ' + status);
    }
  }

  /**
   * Convert date object to a string containing time since
   *
   * @method timeSince
   * @return String
   * @param date
   * @param timeColorSchemeName
   */
  timeSince(date, timeColorSchemeName = 'll') {
    if (date === undefined) {
      return chalk.gray('');
    }

    if (!(date instanceof Date)) {
      date = new Date(date);
    }

    let seconds = Math.floor((new Date() - date) / 1000);
    return this.formatSeconds(seconds, timeColorSchemeName);
  }

  formatSeconds(seconds, timeColorSchemeName = 'll') {
    if (settings.timeColorScheme[timeColorSchemeName] === undefined) {
      timeColorSchemeName = 'll';
    }

    let interval = Math.floor(seconds / 31536000);

    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].yearsColor](interval + 'Y ');
    }

    interval = Math.floor(seconds / 2592000);
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].monthColor](interval + 'M ');
    }

    interval = Math.floor(seconds / 86400);
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].daysColor](interval + 'D ');
    }

    interval = Math.floor(seconds / 3600);
    if (interval > 1 && interval < 6) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours1pColor](interval + 'h ');
    }
    if (interval > 1 && interval < 24) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours6pColor](interval + 'h ');
    }
    if (interval > 1 && interval < 49) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours24pColor](interval + 'h ');
    }
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours48pColor](interval + 'h ');
    }

    interval = Math.floor(seconds / 60);
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].minutesColor](interval + 'm ');
    }

    return chalk[settings.timeColorScheme[timeColorSchemeName].secondsColor](Math.floor(seconds) + 's ');
  }

}

module.exports = new Formatter();

<commit_msg>Fix right align for double symbols<commit_after>'use strict';

const chalk = require('chalk');
const settings = require('./settings');

const TOO_LOW_TO_SELL = 1000;
const TOO_HIGH_TO_BUY = 1100;
const PRICE_IS_SWEET = 1200;

class Formatter {

  constructor() {
    this.timeTillOfflineStatus = 300;
    this.numberOfPriceDecimals = 4;
  }

  tradePair(tradePair) {
    if (tradePair === undefined) {
      return chalk.gray('-');
    }

    return chalk.green.bold(tradePair);
  }

  coins(coins) {
    if (coins === undefined || coins == 0) {
      return chalk.gray('-');
    }

    return this.price(coins);
  }

  currentProfit(numberOfCoins, boughtPrice, lastPriceInBTC) {
    if (numberOfCoins === undefined || boughtPrice === undefined || lastPriceInBTC === undefined) {
      return chalk.gray('-');
    }

    if (parseFloat(lastPriceInBTC) === 0 || parseFloat(boughtPrice) === 0) {
      return chalk.gray('-');
    }

    if (isNaN(parseFloat(lastPriceInBTC)) || isNaN(parseFloat(boughtPrice))) {
      return chalk.gray('-');
    }

    if (parseFloat(numberOfCoins) === 0) {
      return chalk.gray('-');
    }

    let diff = parseFloat(lastPriceInBTC) - parseFloat(boughtPrice);
    let profit = this.price(parseFloat(numberOfCoins) * diff);

    if (diff >= 0) {
      return this.price(profit);
    }

    return this.price(profit);
  }

  currentProfitWithPercent(numberOfCoins, boughtPrice, lastPriceInBTC) {
    let currentProfit = this.currentProfit(numberOfCoins, boughtPrice, lastPriceInBTC);

    if (currentProfit === undefined || currentProfit === chalk.gray('-') || currentProfit === '-') {
      return chalk.gray('-');
    }

    let diff = parseFloat(lastPriceInBTC) - parseFloat(boughtPrice);
    let profitPercent = diff * 100 / parseFloat(boughtPrice);
    let negativePadding = (profitPercent < 0) ? '' : ' '

    return this.profit(currentProfit) + negativePadding + chalk.gray(` ${profitPercent.toFixed(1)}%`);
  }

  totalCurrentProfit(totalBTCValue, totalDiffSinceBuy) {
    if (totalBTCValue === undefined || totalDiffSinceBuy === undefined) {
      return chalk.gray('-');
    }

    if (parseFloat(totalBTCValue) === 0 || parseFloat(totalDiffSinceBuy) === 0) {
      return chalk.gray('-');
    }

    if (isNaN(parseFloat(totalBTCValue)) || isNaN(parseFloat(totalDiffSinceBuy))) {
      return chalk.gray('-');
    }

    let profitPercent = parseFloat(totalDiffSinceBuy) * 100 / parseFloat(totalBTCValue);

    return this.profit(totalDiffSinceBuy) + chalk.gray(` ${profitPercent.toFixed(1)}%`);
  }

  price(price) {
    if (price === '--not set--') {
      return chalk.gray('-');
    }
    if (price === undefined) {
      return chalk.gray('-');
    }

    price = price.toString();

    let posOfDecimalPoint = price.indexOf('.');
    if (posOfDecimalPoint < 1) {
      posOfDecimalPoint = 1;
    }

    let priceOut = parseFloat(price).toFixed(4)
    //return price.slice(0, posOfDecimalPoint + 1 + this.numberOfPriceDecimals);
    return priceOut;
  }

  profit(price) {
    price = this.price(price);
    let priceAsFloat = parseFloat(price);

    if (isNaN(priceAsFloat)) {
      return chalk.white('0');
    }

    if (priceAsFloat < 0) {
      return chalk.red(priceAsFloat);
    }

    if (priceAsFloat > 0) {
      return chalk.green(priceAsFloat);
    }

    return chalk.white(price);
  }

  getLatestBuySellSweetMessage(buyMessageDate, sellMessageDate, sweetMessageDate) {
    if (!(buyMessageDate instanceof Date)) {
      buyMessageDate = new Date(buyMessageDate || 0);
    }

    if (!(sellMessageDate instanceof Date)) {
      sellMessageDate = new Date(sellMessageDate || 0);
    }

    if (!(sweetMessageDate instanceof Date)) {
      sweetMessageDate = new Date(sweetMessageDate || 0);
    }

    if (buyMessageDate > sellMessageDate && buyMessageDate > sweetMessageDate) {
      return TOO_HIGH_TO_BUY;
    }

    if (sellMessageDate > buyMessageDate && sellMessageDate > sweetMessageDate) {
      return TOO_LOW_TO_SELL;
    }

    if (sweetMessageDate > buyMessageDate && sweetMessageDate > sellMessageDate) {
      return PRICE_IS_SWEET;
    }

    return false;
  }

  openOrders(message) {
    if (message === 'Open orders') {
      return chalk.red('yes');
    }

    return chalk.gray('-');
  }

  buySellMessage(buyMessageDate, sellMessageDate, sweetMessageDate) {
    let bss = this.getLatestBuySellSweetMessage(buyMessageDate, sellMessageDate, sweetMessageDate);

    if (bss === TOO_HIGH_TO_BUY) {
      return chalk.blue('too high');
    }

    if (bss === TOO_LOW_TO_SELL) {
      return chalk.magenta('too low');
    }

    if (bss === PRICE_IS_SWEET) {
      return chalk.green('sweet');
    }

    return chalk.gray('-');
  }

  buyPrice(numberOfCoins, boughtPrice, lastPrice) {
    if (
          numberOfCoins === undefined || boughtPrice === undefined || parseFloat(boughtPrice) === 0 ||
          isNaN(parseFloat(boughtPrice)) || parseFloat(numberOfCoins) === 0
    ) {
      return this.price(lastPrice);
    }
    return chalk.yellow(this.price(boughtPrice * 10000));
  }

  priceDiff(buyMessageDate, sellMessageDate, sweetMessageDate, buyPrice, sellPrice, lastPrice) {
    if (isNaN(parseFloat(buyPrice)) || isNaN(parseFloat(sellPrice)) || isNaN(parseFloat(lastPrice))) {
      return chalk.gray('-');
    }

    let bss = this.getLatestBuySellSweetMessage(buyMessageDate, sellMessageDate, sweetMessageDate);
    if (bss === TOO_LOW_TO_SELL) {
      let diff = parseFloat(sellPrice) - parseFloat(lastPrice);
      let percent = (diff / parseFloat(sellPrice) * 100).toFixed(2);
      return `${chalk.magenta(this.price(diff))} ${chalk.gray(`${percent}%`)}`;
    }

    if (bss === TOO_HIGH_TO_BUY) {
      let diff = parseFloat(lastPrice) - parseFloat(buyPrice);
      let percent = (diff / parseFloat(lastPrice) * 100).toFixed(2);
      return `${chalk.blue(this.price(diff))} ${chalk.gray(`${percent}%`)}`;
    }

    return chalk.gray('-');
  }

  btcValue(numberOfCoins, lastPriceInBTC) {
    if (numberOfCoins === undefined || lastPriceInBTC === undefined || numberOfCoins == 0) {
      return chalk.gray('-');
    }

    return this.price(parseFloat(numberOfCoins) * parseFloat(lastPriceInBTC));
  }

  trades(numberOfTrades, lastTradeDate) {
    if (numberOfTrades === undefined || lastTradeDate === undefined) {
      return chalk.gray('-');
    }

    if (numberOfTrades <= 0) {
      return chalk.gray('-');
    }
    return `${chalk.bold(numberOfTrades)} ${this.timeSince(lastTradeDate, 'trades')}`;
  }

  errorCode(errors, lastTimeStamp) {
    if (errors === undefined || errors.length === 0 || lastTimeStamp === undefined) {
      return chalk.gray('-');
    }

    if (!(lastTimeStamp instanceof Date)) {
      lastTimeStamp = new Date(lastTimeStamp);
    }

    let output = [];
    let oldestErrorDate = new Date();

    for (let code of Object.keys(errors)) {
      for (let date of errors[code].dates) {
        if (!(date instanceof Date)) {
          date = new Date(date);
        }
        if (date < oldestErrorDate) {
          oldestErrorDate = date;
        }
      }

      let seconds = Math.floor((lastTimeStamp - oldestErrorDate) / 1000);

      output.push(`${errors[code].counter} x ${chalk.red(code)} in ${this.formatSeconds(seconds, 'errors')}`);
    }

    return output.join('\n');
  }

  lastPrice(lastPrice, tendency) {
    let output = this.price(lastPrice);
    let tendencyOutput = '';

    tendency = parseInt(tendency, 10);

    if (tendency <= -10) {
      tendencyOutput = chalk.red.bold('\u2193\u2193');
    }
    if (tendency > -10 && tendency <= -2) {
      tendencyOutput = chalk.magenta.bold(' \u2193');
    }
    if (tendency > -2 && tendency <= 1) {
      tendencyOutput = chalk.yellow.bold(' \u2192');
    }
    if (tendency > 1 && tendency <= 9) {
      tendencyOutput = chalk.cyan.bold(' \u2191');
    }
    if (tendency > 9) {
      tendencyOutput = chalk.green.bold('\u2191\u2191');
    }
    return `${output} ${tendencyOutput}`;
  }

  tradesInTimeSlots(slots) {
    if (slots === undefined) {
      return chalk.gray('-');
    }

    return `${this.colorizeTradesInTimeSlots(slots['1hr'])} ${this.colorizeTradesInTimeSlots(slots['6hr'])} ${this.colorizeTradesInTimeSlots(slots['12hr'])} ${this.colorizeTradesInTimeSlots(slots['24hr'])} ${this.colorizeTradesInTimeSlots(slots.older)}`;
  }

  colorizeTradesInTimeSlots(number) {
    if (number === undefined || number === 0) {
      return chalk.gray('-');
    }

    return chalk.blue(number);
  }

  pm2Id(pairName, pm2Data) {
    if (pairName === undefined || pm2Data === undefined) {
      return chalk.gray('-');
    }

    if (pm2Data[pairName] === undefined || pm2Data[pairName].id === undefined) {
      return chalk.gray('-');
    }

    return pm2Data[pairName].id;
  }

  /**
   * Converts the given date in a string of status.
   * Like if the date is 300 sec in the past, return "offline".
   * @param pairName
   * @param pm2Data
   * @returns {*}
   */
  pm2Status(pairName, pm2Data) {
    if (pairName === undefined || pm2Data === undefined) {
      return chalk.gray('-');
    }

    if (pm2Data[pairName] === undefined || pm2Data[pairName].status === undefined) {
      return chalk.gray('-');
    }

    return this.colorStatus(pm2Data[pairName].id,pm2Data[pairName].status);
  }

  /**
   * Description
   * @method colorStatus
   * @param {} status
   * @return
   */
  colorStatus(id,status) {
    switch (status) {
      case 'online':
        return chalk.green.bold(id);
      case 'offline':
      case 'stopped':
        return chalk.red.bold(id + ' off');
      case 'launching':
        return chalk.blue.bold(id + ' launching');
      default:
        return chalk.red.bold(id + ' ' + status);
    }
  }

  /**
   * Convert date object to a string containing time since
   *
   * @method timeSince
   * @return String
   * @param date
   * @param timeColorSchemeName
   */
  timeSince(date, timeColorSchemeName = 'll') {
    if (date === undefined) {
      return chalk.gray('');
    }

    if (!(date instanceof Date)) {
      date = new Date(date);
    }

    let seconds = Math.floor((new Date() - date) / 1000);
    return this.formatSeconds(seconds, timeColorSchemeName);
  }

  formatSeconds(seconds, timeColorSchemeName = 'll') {
    if (settings.timeColorScheme[timeColorSchemeName] === undefined) {
      timeColorSchemeName = 'll';
    }

    let interval = Math.floor(seconds / 31536000);

    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].yearsColor](interval + 'Y ');
    }

    interval = Math.floor(seconds / 2592000);
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].monthColor](interval + 'M ');
    }

    interval = Math.floor(seconds / 86400);
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].daysColor](interval + 'D ');
    }

    interval = Math.floor(seconds / 3600);
    if (interval > 1 && interval < 6) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours1pColor](interval + 'h ');
    }
    if (interval > 1 && interval < 24) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours6pColor](interval + 'h ');
    }
    if (interval > 1 && interval < 49) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours24pColor](interval + 'h ');
    }
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].hours48pColor](interval + 'h ');
    }

    interval = Math.floor(seconds / 60);
    if (interval > 1) {
      return chalk[settings.timeColorScheme[timeColorSchemeName].minutesColor](interval + 'm ');
    }

    return chalk[settings.timeColorScheme[timeColorSchemeName].secondsColor](Math.floor(seconds) + 's ');
  }

}

module.exports = new Formatter();

<|endoftext|>


<commit_before>/**
 * Created by thram on 20/07/15.
 *
 * Templates Module
 *
 * Render templates with embebed js
 *
 * Dependencies:
 *
 * thram
 * thram.exceptions
 * thram.toolbox
 * thram.dom
 * * thram.ajax
 * (Optional) thram.storage // The module + the cacheEnable flag enables Caching the templates for faster rendering
 *
 */
(function () {
    window.thram           = window.thram || {};
    window.thram.templates = (function () {
        var _TemplatesApi = {},
            _pool         = {},
            _toolbox      = thram.toolbox,
            _storage      = thram.storage,
            _render       = thram.render,
            _exceptions   = thram.exceptions;

        function _getData(element) {
            var thramData = element.data('thram-data');
            return _toolbox.isString(thramData) ? eval("(" + thramData + ")") : thramData;
        }

        //function process(id, data) {
        //  var html = document.querySelector('script#' + id + '[type=template]').innerHTML;
        function _loader(templateUrl, container, success, error) {
            _pool[templateUrl] = _pool[templateUrl] || {status: 'pending', queue: []};
            var html           = _TemplatesApi.cacheEnabled && _storage ? _storage.get('template:' + templateUrl) : undefined;
            if (html)   _pool[templateUrl].status = 'loaded';
            switch (_pool[templateUrl].status) {
                case 'pending':
                    _pool[templateUrl].status = 'loading';
                    return $t.ajax({
                        type   : 'html',
                        url    : templateUrl,
                        success: function (res) {
                            _pool[templateUrl].status = 'loaded';
                            _TemplatesApi.cacheEnabled && _storage && _storage.set('template:' + templateUrl, res);
                            var done                  = 0;
                            _pool[templateUrl].queue.forEach(function (template) {
                                template.success && template.success(res, template.container);
                                done++;
                                if (done === _pool[templateUrl].queue.length) {
                                    _pool[templateUrl].queue = [];
                                }
                            });

                            return success && success(res, container);
                        },
                        error  : error
                    });
                case 'loading':
                    _pool[templateUrl].queue.push({success: success, error: error, container: container});
                    break;
                case 'loaded':
                    return success && success(html, container);
            }

        }

        function _processMarkup(template, data) {
            // Based on the article by Krasimir: http://krasimirtsonev.com/blog/article/Javascript-template-engine-in-just-20-line;
            if (template) {
                data       = data || {};
                var re     = /\{\{(.+?)}}/g,
                    reExp  = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g,
                    code   = 'with(obj) { var r=[];\n',
                    cursor = 0,
                    result, match;
                var add    = function (line, js) {
                    js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
                        (code += line !== '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
                    return add;
                };
                while (match = re.exec(template)) {
                    add(template.slice(cursor, match.index))(match[1], true);
                    cursor = match.index + match[0].length;
                }
                add(template.substr(cursor, template.length - cursor));
                code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, '');
                try {
                    result = new Function('obj', code).apply(data, [data]);
                }
                catch (err) {
                    console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n");
                }
                return result;
            } else {
                throw _exceptions.no_template;
            }

        }

        _TemplatesApi.process = function (template, options) {
            try {

                function _processComponents($el, tmpl, data) {
                    var html       = _processMarkup(tmpl, data);
                    $el.remove('data', 'thram-data');
                    $el.html(html);
                    var components = $el.find('[data-thram-component]');
                    if (components) {
                        components.each(function (component) {
                            _render.component({container: component, data: _getData(component)});
                        });
                    }
                    options.success && options.success($el, tmpl);
                }

                var container = options.container || $t('[data-thram-view]');
                if (options.async) {
                    container.data('thram-data', JSON.stringify(options.data || _getData(container)));
                    _loader(template, container, function (res, $el) {
                        _processComponents($el, res, _getData($el));
                    });
                } else {
                    _processComponents(container, template, options.data);
                }
            } catch (e) {
                e.template = template;
                console.error(e);
                options.error && options.error(e);
            }

        };

        _TemplatesApi.cacheEnabled = false;

        return _TemplatesApi;
    })();

})();<commit_msg>- Fix problems creating multiple elements from a template<commit_after>/**
 * Created by thram on 20/07/15.
 *
 * Templates Module
 *
 * Render templates with embebed js
 *
 * Dependencies:
 *
 * thram
 * thram.exceptions
 * thram.toolbox
 * thram.dom
 * * thram.ajax
 * (Optional) thram.storage // The module + the cacheEnable flag enables Caching the templates for faster rendering
 *
 */
(function () {
    window.thram           = window.thram || {};
    window.thram.templates = (function () {
        var _TemplatesApi = {},
            _pool         = {},
            _ajax         = thram.ajax,
            _toolbox      = thram.toolbox,
            _storage      = thram.storage,
            _render       = thram.render,
            _exceptions   = thram.exceptions;

        function _getData(element) {
            var thramData = element.data('thram-data');
            return _toolbox.isString(thramData) ? eval("(" + thramData + ")") : thramData;
        }

        //function process(id, data) {
        //  var html = document.querySelector('script#' + id + '[type=template]').innerHTML;
        function _loader(templateUrl, container, success, error) {
            _pool[templateUrl] = _pool[templateUrl] || {status: 'pending', queue: []};
            var html           = _TemplatesApi.cacheEnabled && _storage ? _storage.get('template:' + templateUrl) : undefined;
            if (html)   _pool[templateUrl].status = 'loaded';
            switch (_pool[templateUrl].status) {
                case 'pending':
                    _pool[templateUrl].status = 'loading';
                    return _ajax.get({
                        type   : 'html',
                        url    : templateUrl,
                        success: function (res) {
                            _pool[templateUrl].status = 'loaded';
                            _TemplatesApi.cacheEnabled && _storage && _storage.set('template:' + templateUrl, res);
                            var done                  = 0;
                            _pool[templateUrl].queue.forEach(function (template) {
                                template.success && template.success(res, template.container);
                                done++;
                                if (done === _pool[templateUrl].queue.length) {
                                    _pool[templateUrl].queue = [];
                                }
                            });

                            return success && success(res, container);
                        },
                        error  : error
                    });
                case 'loading':
                    _pool[templateUrl].queue.push({success: success, error: error, container: container});
                    break;
                case 'loaded':
                    return success && success(html, container);
            }

        }

        function _processMarkup(template, data) {
            // Based on the article by Krasimir: http://krasimirtsonev.com/blog/article/Javascript-template-engine-in-just-20-line;
            if (template) {
                data       = data || {};
                var re     = /\{\{(.+?)}}/g,
                    reExp  = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g,
                    code   = 'with(obj) { var r=[];\n',
                    cursor = 0,
                    result, match;
                var add    = function (line, js) {
                    js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
                        (code += line !== '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
                    return add;
                };
                while (match = re.exec(template)) {
                    add(template.slice(cursor, match.index))(match[1], true);
                    cursor = match.index + match[0].length;
                }
                add(template.substr(cursor, template.length - cursor));
                code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, '');
                try {
                    result = new Function('obj', code).apply(data, [data]);
                }
                catch (err) {
                    console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n");
                }
                return result;
            } else {
                throw _exceptions.no_template;
            }

        }

        _TemplatesApi.process = function (template, options) {
            try {

                function _processComponents($el, tmpl, data) {
                    var html       = _processMarkup(tmpl, data);
                    $el.remove('data', 'thram-data');
                    $el.html(html);
                    var components = $el.find('[data-thram-component]');
                    if (components) {
                        components.each(function (component) {
                            _render.component({container: component, data: _getData(component)});
                        });
                    }
                    options.success && options.success($el, tmpl);
                }

                var container = options.container || $t('[data-thram-view]');
                if (options.async) {
                    container.data('thram-data', JSON.stringify(options.data || _getData(container)));
                    _loader(template, container, function (res, $el) {
                        _processComponents($el, res, _getData($el));
                    });
                } else {
                    _processComponents(container, template, options.data);
                }
            } catch (e) {
                e.template = template;
                console.error(e);
                options.error && options.error(e);
            }

        };

        _TemplatesApi.cacheEnabled = false;

        return _TemplatesApi;
    })();

})();<|endoftext|>


<commit_before>/*
** Module: aireas2json
**
**
**
**
*/

// **********************************************************************************

var fs 		= require('fs'),
	path = require("path");
var pg = require('pg');

var aireasFolder, aireasUrl, aireasFileName, aireasLocalPathRoot, fileFolder,
	tmpFolder, tmpFolderName, localPath, fileFolderName, resultsFolder, resultsFolderName;
var dataRecords;

// **********************************************************************************

module.exports = {

	init: function (options) {

		sqlConnString = options.configParameter.databaseType + '://' +
			options.configParameter.databaseAccount + ':' +
			options.configParameter.databasePassword + '@' +
			options.configParameter.databaseServer + '/' +
			options.systemCode + '_' + options.configParameter.databaseName;

		aireasLocalPathRoot = options.systemFolderParent+'/aireas/';
		fileFolderName 		= 'aireas-hist';
		tmpFolderName 		= 'tmp';
		resultsFolderName 	= 'results';

		//aireasFileName 		= 'aireas.txt';
		aireasFileNameOutput= 'aireas.json';

		aireasFolder 		= aireasLocalPathRoot 	+ fileFolderName 	+ "/";
		tmpFolder 			= aireasFolder 			+ tmpFolderName 	+ "/";
		resultsFolder 		= aireasFolder 			+ resultsFolderName + "/";

		// create subfolders
		try {fs.mkdirSync(resultsFolder );} catch (e) {};//console.log('ERROR: no tmp folder found, batch run aborted.'); return } ;

		var executeFile = this.executeFile;

		fs.readdir(tmpFolder, function (err, files) {
    		if (err) {
        		throw err;
    		}

    		files.map(function (file) {
        		return path.join(tmpFolder, file);
    		}).filter(function (file) {
        		return fs.statSync(file).isFile();
    		}).forEach(function (file) {
        		console.log("%s (%s)", file, path.extname(file));
				executeFile(file, path.extname(file))
    		});
		});

	}, // end of init

	executeFile: function(file, extention) {

		var convertGPS2LatLng = function(gpsValue){
			var degrees = Math.floor(gpsValue /100);
			var minutes = gpsValue - (degrees*100);
			var result  = degrees + (minutes /60);
			return result;
		};

		var	createExportFile = function () {

		var outputArray;
		var outputRecord;
		var inputRecord;
		var filePath;
		var outputFileJson;

/*
		var currDate = new Date();
		var year = (currDate.getYear()+1900);

		var month = (currDate.getMonth()+1);
		var monthStr = "";
		if (month<10) {
			monthStr = "0" + month;
		} else {
			monthStr = "" + month;
		}

		var day = currDate.getDate();
		var dayStr = "";
		if (day<10) {
			dayStr = "0" + day;
		} else {
			dayStr = "" + day;
		}

		var hour = currDate.getHours();
		var hourStr = "";
		if (hour<10) {
			hourStr = "0" + hour;
		} else {
			hourStr = "" + hour;
		}

		var minute = currDate.getMinutes();
		var minuteStr = "";
		if (minute<10) {
			minuteStr = "0" + minute;
		} else {
			minuteStr = "" + minute;
		}
*/

//		filePath = resultsFolder + year + "/" + monthStr + "/" + dayStr + "/" + hourStr + "/" + minuteStr;
		filePath = resultsFolder;

//		try {fs.mkdirSync(resultsFolder + year + "/" );} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/");} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/" + dayStr + "/" );} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/" + dayStr + "/"  + hourStr + "/");} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/" + dayStr + "/" + hourStr + "/" + minuteStr);} catch (e) {} ;

		console.log("- creating: " , aireasFileNameOutput);
		outputFileJson = JSON.stringify(dataRecords);
//		this.writeFile (filePath, aireasFileNameOutput, outputFileJson );
		//writeFile (filePath, aireasFileNameOutput, outputFileJson );
		createSqlAireas(dataRecords);

	}

//	convertGPS2LatLng: function(gpsValue){
//		var degrees = Math.floor(gpsValue /100);
//		var minutes = gpsValue - (degrees*100);
//		var result  = degrees + (minutes /60);
//		return result;
//	},

		var writeFile = function(path, fileName, content ) {
			var _path = path;
			try {
				fs.mkdirSync(_path);
			} catch (e) {} ;
			fs.writeFileSync(_path + "/" + fileName, content);
		};

		var createSqlAireas = function(inputFileJson , outputFilePath) {

		var i;

// 		var inputFile = JSON.parse(inputFileJson);
 		var inputFile = inputFileJson;
		var outputFile = "";

	        var executeSql = function  (query, callback) {
        	        console.log('sql start: ');
                	var client = new pg.Client(sqlConnString);
                	client.connect(function(err) {
                        	if(err) {
                                	return console.error('could not connect to postgres', err);
                        	}
                        	client.query(query, function(err, result) {
                                	if(err) {
                                	return console.error('error running query', err);
                        	}
                        	console.log('sql result: ' + result);
                        	client.end();
                        	});
                	});
        	};

		var sqlCallBack = function (err, result) {
			if (err) {
				console.log('ERROR:','sql error:', err, result);
			} else {
				//console.log('Query','sql result:', result);
			}
		};

  //      	var writeFile = function(fileContent, filepath ) {
   //             	var _path = filepath;
   //             	fs.writeFileSync(_path, fileContent);
   //     	};

		for (i=0;i<inputFile.length;i++) {

			var inputRecord = inputFile[i];
			var outputRecord = "";

			//var _measureDate		 			= inputRecord.measureDate==""?"null":"'"+inputRecord.measureDate + "', ";

			outputRecord = "\nINSERT INTO aireas ( airbox, retrieveddatechar, measuredatechar, retrieveddate, measuredate, " +
				" gpslat, gpslng, lat, lng, pm1, pm25, pm10, ufp, ozon, hum, celc, no2, " +
				" gpslatfloat, gpslngfloat, pm1float, pm25float, pm10float, ufpfloat, ozonfloat, humfloat, celcfloat, no2float, " +
				" geom28992, geom ) VALUES (\n" +
					"'" + 	inputRecord.airbox 			+ "', " +
					"'" + 	inputRecord.retrievedDate 	+ "', " +
					"'" + 	inputRecord.measureDate 	+ "', " +
					"'" +	inputRecord.retrievedDate 	+ "', " + 	// timestamp with time zone,
					"'" + 	inputRecord.measureDate		+ "', \n" +	// timestamp with time zone,
					"'" + 	inputRecord.gpsLat 			+ "', " +
					"'" + 	inputRecord.gpsLng 			+ "', " +
							inputRecord.lat 			+ ", "  +
							inputRecord.lng 			+ ", "  +
					"'" + 	inputRecord.PM1 			+ "', " +
					"'" + 	inputRecord.PM25 			+ "', " +
					"'" +	inputRecord.PM10 			+ "', " +
					"'" + 	inputRecord.UFP 			+ "', " +
					"'" + 	inputRecord.OZON 			+ "', " +
					"'" + 	inputRecord.HUM 			+ "', " +
					"'" + 	inputRecord.CELC 			+ "', " +
					"'" + 	inputRecord.NO2 			+ "', \n" +
							inputRecord.gpsLatFloat 	+ ", "  +
							inputRecord.gpsLngFloat 	+ ", "  +
							inputRecord.PM1Float 		+ ", "  +
							inputRecord.PM25Float 		+ ", "  +
							inputRecord.PM10Float 		+ ", "  +
							inputRecord.UFPFloat 		+ ", "  +
							inputRecord.OZONFloat 		+ ", "  +
							inputRecord.HUMFloat 		+ ", "  +
							inputRecord.CELCFloat 		+ ", "  +
							inputRecord.NO2Float 		+ ", "  +
							" ST_Transform(ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326), 28992 ), " +
							" ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326) ); ";

			outputFile=outputFile.concat(outputRecord);
		}
	console.log('Write: ' + outputFilePath);
		//writeFile(outputFile, outputFilePath);
		executeSql(outputFile, sqlCallBack);
		outputFile = null;  // clear memory

	};

//		localPath 		= tmpFolder + aireasFileName;
		var localPath 		= file;
    	console.log("Local AiREAS data: " + localPath );

    	var _datFile	= fs.readFileSync(localPath);

		var i, j, _dataRecord, _waardeDataRecord, inpRecordArray,
			inpRecordPM1, inpRecordPM25, inpRecordPM10,
			inpRecordUFP, inpRecordOZON, inpRecordHUM, inpRecordCELC;

//		var inRecord1 = "" + _datFile.toString();
//		var inRecord2 = inRecord1.replace(/\'/g,'"');
//		var inRecord = JSON.parse(inRecord2);

		var records1 = ""+_datFile;
		var records2 = records1.split('\n');

		console.log('Aantal records:' + records2.length)

//		{"airbox": "39_cal", "retrievedDate": "2015-07-06T18:57:06.596Z", "content":

		var firstRecParts = records2[0].split(',');
		var firstRecJson = firstRecParts[0] + ', '+ firstRecParts[1] + '} ';
		console.log(firstRecJson);
		var firstRec = JSON.parse(firstRecJson);
		console.log('Verwerk airbox %s van retrievedate %s', firstRec.airbox, firstRec.retrievedDate );

//		console.log(inRecord);
//		console.log(inRecord.airboxes);
//		console.log(inRecord.airboxes[0]);

//		tmpArray = inRecord.content.airboxes;
		tmpArray = records2;

/*
		var tmp0 = _datFile.toString();
		var dateRetrievedLength = tmp0.indexOf(' ');
		var dateRetrieved = tmp0.substring(0, dateRetrievedLength);
		var dateRetrievedDate = Date.parse(dateRetrieved);
		console.log('x'+dateRetrieved+'x');
		var tmp1 = tmp0.substr(dateRetrievedLength+1);
		//var tmp2 = tmp1.replace(/<p>/g,'');
		//var tmp3 = tmp2.replace(/<\/p>/g,'');
		//var tmpArray = tmp3.split(')');
		var tmp2 = tmp1.replace(/\[/,'');
		var tmpArray = tmp3.split('],');
*/

		dataRecords	= [];

		// Let op skip first and last record(s) for now!
		console.log('Aantal records: ' + tmpArray.length);

		for ( i=1; i<tmpArray.length-2;i++) {
			if (i>tmpArray.length - 5) {
				console.log(' %n %s ', i, _waardeDataRecord[9] );
			}
//			inpRecordArray 		= tmpArray[i].split(':(');
//			inpRecordArray 		= tmpArray[i].split('[');
			//inpRecordArray 		= tmpArray[i];
			inpRecordArray 		= tmpArray[i].split(',');

//			console.log(inpRecordArray);

			_dataRecord			= {};
//			_dataRecord.airBox	= inpRecordArray[0];
			_dataRecord.airBox	= firstRec.airbox;

//			inpMetingenArray 	= inpRecordArray[1].split(',');
			_waardeDataRecord	= inpRecordArray;

//			_waardeDataRecord 	= [];
//			for(j=0;j<inpMetingenArray.length;j++) {
//				_waardeDataRecord[j] = inpRecordArray[j];// parseFloat(inpMetingenArray[j]);
//			}

			//_dataRecord.airbox 	= _waardeDataRecord[0];

//			console.log(_dataRecord.airbox);

			_dataRecord.retrievedDate 	= firstRec.retrievedDate;
			_dataRecord.measureDate 	= _waardeDataRecord[9];
			_dataRecord.gpsLat 	= _waardeDataRecord[0];
			_dataRecord.gpsLng 	= _waardeDataRecord[1];
			_dataRecord.lat 	= convertGPS2LatLng(_waardeDataRecord[0]);
			_dataRecord.lng 	= convertGPS2LatLng(_waardeDataRecord[1]);
			_dataRecord.PM1 	= _waardeDataRecord[5];
			_dataRecord.PM25 	= _waardeDataRecord[6];
			_dataRecord.PM10 	= _waardeDataRecord[4];
			_dataRecord.UFP 	= _waardeDataRecord[2];
			_dataRecord.OZON 	= _waardeDataRecord[3];
			_dataRecord.HUM 	= _waardeDataRecord[7];
			_dataRecord.CELC 	= _waardeDataRecord[8];
			_dataRecord.NO2 	= 0; //_waardeDataRecord[9];

			_dataRecord.gpsLatFloat = parseFloat(_waardeDataRecord[0]);
			_dataRecord.gpsLngFloat	= parseFloat(_waardeDataRecord[1]);
			_dataRecord.PM1Float 	= parseFloat(_waardeDataRecord[5]);
			_dataRecord.PM25Float 	= parseFloat(_waardeDataRecord[6]);
			_dataRecord.PM10Float 	= parseFloat(_waardeDataRecord[4]);
			_dataRecord.UFPFloat 	= parseFloat(_waardeDataRecord[2]);
			if (_dataRecord.UFPFloat > 0) _dataRecord.UFPFloat = Math.round(_dataRecord.UFPFloat / 1000); // in units of 1000
			_dataRecord.OZONFloat 	= parseFloat(_waardeDataRecord[3]);
			_dataRecord.HUMFloat 	= parseFloat(_waardeDataRecord[7]);
			_dataRecord.CELCFloat 	= parseFloat(_waardeDataRecord[8]);
			_dataRecord.NO2Float 	= 0; //parseFloat(_waardeDataRecord[9]);

			dataRecords.push(_dataRecord);

		}

		createExportFile();

	},

} // end of module.exports
<commit_msg>aireas-hist-json<commit_after>/*
** Module: aireas2json
**
**
**
**
*/

// **********************************************************************************

var fs 		= require('fs'),
	path = require("path");
var pg = require('pg');

var aireasFolder, aireasUrl, aireasFileName, aireasLocalPathRoot, fileFolder,
	tmpFolder, tmpFolderName, localPath, fileFolderName, resultsFolder, resultsFolderName;
var dataRecords;

// **********************************************************************************

module.exports = {

	init: function (options) {

		sqlConnString = options.configParameter.databaseType + '://' +
			options.configParameter.databaseAccount + ':' +
			options.configParameter.databasePassword + '@' +
			options.configParameter.databaseServer + '/' +
			options.systemCode + '_' + options.configParameter.databaseName;

		aireasLocalPathRoot = options.systemFolderParent+'/aireas/';
		fileFolderName 		= 'aireas-hist';
		tmpFolderName 		= 'tmp';
		resultsFolderName 	= 'results';

		//aireasFileName 		= 'aireas.txt';
		aireasFileNameOutput= 'aireas.json';

		aireasFolder 		= aireasLocalPathRoot 	+ fileFolderName 	+ "/";
		tmpFolder 			= aireasFolder 			+ tmpFolderName 	+ "/";
		resultsFolder 		= aireasFolder 			+ resultsFolderName + "/";

		// create subfolders
		try {fs.mkdirSync(resultsFolder );} catch (e) {};//console.log('ERROR: no tmp folder found, batch run aborted.'); return } ;

		var executeFile = this.executeFile;

		fs.readdir(tmpFolder, function (err, files) {
    		if (err) {
        		throw err;
    		}

    		files.map(function (file) {
        		return path.join(tmpFolder, file);
    		}).filter(function (file) {
        		return fs.statSync(file).isFile();
    		}).forEach(function (file) {
        		console.log("%s (%s)", file, path.extname(file));
				executeFile(file, path.extname(file))
    		});
		});

	}, // end of init

	executeFile: function(file, extention) {

		var convertGPS2LatLng = function(gpsValue){
			var degrees = Math.floor(gpsValue /100);
			var minutes = gpsValue - (degrees*100);
			var result  = degrees + (minutes /60);
			return result;
		};

		var	createExportFile = function () {

		var outputArray;
		var outputRecord;
		var inputRecord;
		var filePath;
		var outputFileJson;

/*
		var currDate = new Date();
		var year = (currDate.getYear()+1900);

		var month = (currDate.getMonth()+1);
		var monthStr = "";
		if (month<10) {
			monthStr = "0" + month;
		} else {
			monthStr = "" + month;
		}

		var day = currDate.getDate();
		var dayStr = "";
		if (day<10) {
			dayStr = "0" + day;
		} else {
			dayStr = "" + day;
		}

		var hour = currDate.getHours();
		var hourStr = "";
		if (hour<10) {
			hourStr = "0" + hour;
		} else {
			hourStr = "" + hour;
		}

		var minute = currDate.getMinutes();
		var minuteStr = "";
		if (minute<10) {
			minuteStr = "0" + minute;
		} else {
			minuteStr = "" + minute;
		}
*/

//		filePath = resultsFolder + year + "/" + monthStr + "/" + dayStr + "/" + hourStr + "/" + minuteStr;
		filePath = resultsFolder;

//		try {fs.mkdirSync(resultsFolder + year + "/" );} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/");} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/" + dayStr + "/" );} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/" + dayStr + "/"  + hourStr + "/");} catch (e) {} ;
//		try {fs.mkdirSync(resultsFolder + year + "/" + monthStr + "/" + dayStr + "/" + hourStr + "/" + minuteStr);} catch (e) {} ;

		console.log("- creating: " , aireasFileNameOutput);
		outputFileJson = JSON.stringify(dataRecords);
//		this.writeFile (filePath, aireasFileNameOutput, outputFileJson );
		//writeFile (filePath, aireasFileNameOutput, outputFileJson );
		createSqlAireas(dataRecords);

	}

//	convertGPS2LatLng: function(gpsValue){
//		var degrees = Math.floor(gpsValue /100);
//		var minutes = gpsValue - (degrees*100);
//		var result  = degrees + (minutes /60);
//		return result;
//	},

		var writeFile = function(path, fileName, content ) {
			var _path = path;
			try {
				fs.mkdirSync(_path);
			} catch (e) {} ;
			fs.writeFileSync(_path + "/" + fileName, content);
		};

		var createSqlAireas = function(inputFileJson , outputFilePath) {

		var i;

// 		var inputFile = JSON.parse(inputFileJson);
 		var inputFile = inputFileJson;
		var outputFile = "";

	        var executeSql = function  (query, callback) {
        	        console.log('sql start: ');
                	var client = new pg.Client(sqlConnString);
                	client.connect(function(err) {
                        	if(err) {
                                	return console.error('could not connect to postgres', err);
                        	}
                        	client.query(query, function(err, result) {
                                	if(err) {
                                	return console.error('error running query', err);
                        	}
                        	console.log('sql result: ' + result);
                        	client.end();
                        	});
                	});
        	};

		var sqlCallBack = function (err, result) {
			if (err) {
				console.log('ERROR:','sql error:', err, result);
			} else {
				//console.log('Query','sql result:', result);
			}
		};

  //      	var writeFile = function(fileContent, filepath ) {
   //             	var _path = filepath;
   //             	fs.writeFileSync(_path, fileContent);
   //     	};

		for (i=0;i<inputFile.length;i++) {

			var inputRecord = inputFile[i];
			var outputRecord = "";

			//var _measureDate		 			= inputRecord.measureDate==""?"null":"'"+inputRecord.measureDate + "', ";

			outputRecord = "\nINSERT INTO aireas_hist ( airbox, retrieveddatechar, measuredatechar, retrieveddate, measuredate, " +
				" gpslat, gpslng, lat, lng, pm1, pm25, pm10, ufp, ozon, hum, celc, no2, " +
				" gpslatfloat, gpslngfloat, pm1float, pm25float, pm10float, ufpfloat, ozonfloat, humfloat, celcfloat, no2float, " +
				" geom28992, geom ) VALUES (\n" +
					"'" + 	inputRecord.airbox 			+ "', " +
					"'" + 	inputRecord.retrievedDate 	+ "', " +
					"'" + 	inputRecord.measureDate 	+ "', " +
					"'" +	inputRecord.retrievedDate 	+ "', " + 	// timestamp with time zone,
					"'" + 	inputRecord.measureDate		+ "', \n" +	// timestamp with time zone,
					"'" + 	inputRecord.gpsLat 			+ "', " +
					"'" + 	inputRecord.gpsLng 			+ "', " +
							inputRecord.lat 			+ ", "  +
							inputRecord.lng 			+ ", "  +
					"'" + 	inputRecord.PM1 			+ "', " +
					"'" + 	inputRecord.PM25 			+ "', " +
					"'" +	inputRecord.PM10 			+ "', " +
					"'" + 	inputRecord.UFP 			+ "', " +
					"'" + 	inputRecord.OZON 			+ "', " +
					"'" + 	inputRecord.HUM 			+ "', " +
					"'" + 	inputRecord.CELC 			+ "', " +
					"'" + 	inputRecord.NO2 			+ "', \n" +
							inputRecord.gpsLatFloat 	+ ", "  +
							inputRecord.gpsLngFloat 	+ ", "  +
							inputRecord.PM1Float 		+ ", "  +
							inputRecord.PM25Float 		+ ", "  +
							inputRecord.PM10Float 		+ ", "  +
							inputRecord.UFPFloat 		+ ", "  +
							inputRecord.OZONFloat 		+ ", "  +
							inputRecord.HUMFloat 		+ ", "  +
							inputRecord.CELCFloat 		+ ", "  +
							inputRecord.NO2Float 		+ ", "  +
							" ST_Transform(ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326), 28992 ), " +
							" ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326) ); ";

			outputFile=outputFile.concat(outputRecord);
		}
	console.log('Write: ' + outputFilePath);
		//writeFile(outputFile, outputFilePath);
		executeSql(outputFile, sqlCallBack);
		outputFile = null;  // clear memory

	};

//		localPath 		= tmpFolder + aireasFileName;
		var localPath 		= file;
    	console.log("Local AiREAS data: " + localPath );

    	var _datFile	= fs.readFileSync(localPath);

		var i, j, _dataRecord, _waardeDataRecord, inpRecordArray,
			inpRecordPM1, inpRecordPM25, inpRecordPM10,
			inpRecordUFP, inpRecordOZON, inpRecordHUM, inpRecordCELC;

//		var inRecord1 = "" + _datFile.toString();
//		var inRecord2 = inRecord1.replace(/\'/g,'"');
//		var inRecord = JSON.parse(inRecord2);

		var records1 = ""+_datFile;
		var records2 = records1.split('\n');

		console.log('Aantal records:' + records2.length)

//		{"airbox": "39_cal", "retrievedDate": "2015-07-06T18:57:06.596Z", "content":

		var firstRecParts = records2[0].split(',');
		var firstRecJson = firstRecParts[0] + ', '+ firstRecParts[1] + '} ';
		console.log(firstRecJson);
		var firstRec = JSON.parse(firstRecJson);
		console.log('Verwerk airbox %s van retrievedate %s', firstRec.airbox, firstRec.retrievedDate );

//		console.log(inRecord);
//		console.log(inRecord.airboxes);
//		console.log(inRecord.airboxes[0]);

//		tmpArray = inRecord.content.airboxes;
		tmpArray = records2;

/*
		var tmp0 = _datFile.toString();
		var dateRetrievedLength = tmp0.indexOf(' ');
		var dateRetrieved = tmp0.substring(0, dateRetrievedLength);
		var dateRetrievedDate = Date.parse(dateRetrieved);
		console.log('x'+dateRetrieved+'x');
		var tmp1 = tmp0.substr(dateRetrievedLength+1);
		//var tmp2 = tmp1.replace(/<p>/g,'');
		//var tmp3 = tmp2.replace(/<\/p>/g,'');
		//var tmpArray = tmp3.split(')');
		var tmp2 = tmp1.replace(/\[/,'');
		var tmpArray = tmp3.split('],');
*/

		dataRecords	= [];

		// Let op skip first and last record(s) for now!
		console.log('Aantal records: ' + tmpArray.length);

		for ( i=1; i<tmpArray.length-2;i++) {
			if (i>tmpArray.length - 5) {
				console.log(' %n %s ', i, _waardeDataRecord[9] );
			}
//			inpRecordArray 		= tmpArray[i].split(':(');
//			inpRecordArray 		= tmpArray[i].split('[');
			//inpRecordArray 		= tmpArray[i];
			inpRecordArray 		= tmpArray[i].split(',');

//			console.log(inpRecordArray);

			_dataRecord			= {};
//			_dataRecord.airBox	= inpRecordArray[0];
			_dataRecord.airBox	= firstRec.airbox;

//			inpMetingenArray 	= inpRecordArray[1].split(',');
			_waardeDataRecord	= inpRecordArray;

//			_waardeDataRecord 	= [];
//			for(j=0;j<inpMetingenArray.length;j++) {
//				_waardeDataRecord[j] = inpRecordArray[j];// parseFloat(inpMetingenArray[j]);
//			}

			//_dataRecord.airbox 	= _waardeDataRecord[0];

//			console.log(_dataRecord.airbox);

			_dataRecord.retrievedDate 	= firstRec.retrievedDate;
			_dataRecord.measureDate 	= _waardeDataRecord[9];
			_dataRecord.gpsLat 	= _waardeDataRecord[0];
			_dataRecord.gpsLng 	= _waardeDataRecord[1];
			_dataRecord.lat 	= convertGPS2LatLng(_waardeDataRecord[0]);
			_dataRecord.lng 	= convertGPS2LatLng(_waardeDataRecord[1]);
			_dataRecord.PM1 	= _waardeDataRecord[5];
			_dataRecord.PM25 	= _waardeDataRecord[6];
			_dataRecord.PM10 	= _waardeDataRecord[4];
			_dataRecord.UFP 	= _waardeDataRecord[2];
			_dataRecord.OZON 	= _waardeDataRecord[3];
			_dataRecord.HUM 	= _waardeDataRecord[7];
			_dataRecord.CELC 	= _waardeDataRecord[8];
			_dataRecord.NO2 	= 0; //_waardeDataRecord[9];

			_dataRecord.gpsLatFloat = parseFloat(_waardeDataRecord[0]);
			_dataRecord.gpsLngFloat	= parseFloat(_waardeDataRecord[1]);
			_dataRecord.PM1Float 	= parseFloat(_waardeDataRecord[5]);
			_dataRecord.PM25Float 	= parseFloat(_waardeDataRecord[6]);
			_dataRecord.PM10Float 	= parseFloat(_waardeDataRecord[4]);
			_dataRecord.UFPFloat 	= parseFloat(_waardeDataRecord[2]);
			if (_dataRecord.UFPFloat > 0) _dataRecord.UFPFloat = Math.round(_dataRecord.UFPFloat / 1000); // in units of 1000
			_dataRecord.OZONFloat 	= parseFloat(_waardeDataRecord[3]);
			_dataRecord.HUMFloat 	= parseFloat(_waardeDataRecord[7]);
			_dataRecord.CELCFloat 	= parseFloat(_waardeDataRecord[8]);
			_dataRecord.NO2Float 	= 0; //parseFloat(_waardeDataRecord[9]);

			dataRecords.push(_dataRecord);

		}

		createExportFile();

	},

} // end of module.exports
<|endoftext|>