<commit_before>var inside = require('point-in-polygon');
var URI = require('uri-js');

module.exports = {

    isPosition: function ( x ) {
        // Validate a GeoJSON Position.
        return (
            Array.isArray(x) &&
            x.length > 1 &&
            x.every(
                function ( element ) {
                    return (typeof element === 'number');
                }
            )
        );
    },

    isPointCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON Point.
        return GeoJSON.isPosition(x);
    },

    isMultiPointCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON MultiPoint.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isPosition)
        );
    },

    isLineStringCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON LineString.
        return (
            Array.isArray(x) &&
            x.length > 1 &&
            GeoJSON.isMultiPointCoordinates(x)
        );
    },

    isLinearRingCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON LinearRing.
        return (
            Array.isArray(x) &&
            x.length > 3 &&
            GeoJSON.isLineStringCoordinates(x) &&
            GeoJSON.equalPositions(x[0],x[x.length-1])
        );
    },

    isMultiLineStringCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON MultiLineString.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isLineStringCoordinates)
        );
    },

    isPolygonCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON Polygon.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isLinearRingCoordinates) &&
            x.every(
                function ( LinearRingCoordinates , i , PolygonCoordinates ) {
                    if (i == 0) return true;
                    else return GeoJSON.containedPolygon(
                        LinearRingCoordinates,
                        PolygonCoordinates[0]
                    );
                }
            )
        );
    },

    isMultiPolygonCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON MultiPolygon.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isPolygonCoordinates)
        );
    },

    validCRS: function ( x ) {
        // Validate the CRS property of a GeoJSON object.
        return (
            x != null &&
            (
                typeof x.crs === 'undefined' ||
                x.crs === null ||
                GeoJSON.isCRS(x.crs)
            )
        )
    },

    validBbox: function ( x ) {
        // Validate the bbox property of a GeoJSON object.
        return (
            x != null &&
            (
                typeof x.bbox === 'undefined' ||
                (
                    Array.isArray(x.bbox) &&
                    x.bbox.length%2 === 0 &&
                    true  // TODO Validate the bbox.
                )
            )
        );
    },

    isLink: function ( x ) {
        // Validate a GeoJSON Link.
        return (
            x != null &&
            x.properties != null &&
            typeof x.properties.href === 'string' &&
            URI.parse(x.properties.href).errors.length < 1 &&
            (
                typeof x.properties.type === 'undefined' ||
                (
                    typeof x.properties.type === 'string' &&
                    x.properties.type.length > 0
                )
            )
        );
    },

    isCRS: function ( x ) {
        // Validate a GeoJSON Coordinate Reference System.
        return (
            x != null &&
            (
                (
                    x.type === 'name' &&
                    x.properties != null &&
                    typeof x.properties.name === 'string' &&
                    x.properties.name.length > 0
                ) ||
                (
                    x.type === 'link' &&
                    GeoJSON.isLink(x.properties)
                )
            )
        );
    },

    isPoint: function ( x ) {
        // Validate a GeoJSON Point.
        return (
            x != null &&
            x.type === 'Point' &&
            GeoJSON.isPointCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isMultiPoint: function ( x ) {
        // Validate a GeoJSON MultiPoint.
        return (
            x != null &&
            x.type === 'MultiPoint' &&
            GeoJSON.isMultiPointCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isLineString: function ( x ) {
        // Validate a GeoJSON LineString.
        return (
            x != null &&
            x.type === 'LineString' &&
            GeoJSON.isLineStringCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isMultiLineString: function ( x ) {
        // Validate a GeoJSON MultiLineString.
        return (
            x != null &&
            x.type === 'MultiLineString' &&
            GeoJSON.isMultiLineStringCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isPolygon: function ( x ) {
        // Validate a GeoJSON Polygon.
        return (
            x != null &&
            x.type === 'Polygon' &&
            GeoJSON.isPolygonCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isMultiPolygon: function ( x ) {
        // Validate a GeoJSON MultiPolygon.
        return (
            x != null &&
            x.type === 'MultiPolygon' &&
            GeoJSON.isMultiPolygonCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isGeometryCollection: function ( x ) {
        // Validate a GeoJSON GeometryCollection.
        return (
            x != null &&
            x.type === 'GeometryCollection' &&
            Array.isArray(x.geometries) &&
            x.geometries.every(GeoJSON.isGeometry) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isFeature: function ( x ) {
        // Validate a GeoJSON Feature.
        return (
            x != null &&
            x.type === 'Feature' &&
            typeof x.properties === 'object' &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x) &&
            (
                x.geometry === null ||
                GeoJSON.isGeometry(x.geometry)
            )
        );
    },

    isFeatureCollection: function ( x ) {
        // Validate a GeoJSON FeatureCollection.
        return (
            x != null &&
            x.type === 'FeatureCollection' &&
            Array.isArray(x.features) &&
            x.features.every(GeoJSON.isFeature) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isGeometry: function ( x ) {
        // Validate a GeoJSON Geometry.
        return (
            GeoJSON.isPoint(x) ||
            GeoJSON.isMultiPoint(x) ||
            GeoJSON.isLineString(x) ||
            GeoJSON.isMultiLineString(x) ||
            GeoJSON.isPolygon(x) ||
            GeoJSON.isMultiPolygon(x) ||
            GeoJSON.isGeometryCollection(x)
        );
    },

    isGeoJSON: function ( x ) {
        // Validate a GeoJSON object.
        return (
            GeoJSON.isGeometry(x) ||
            GeoJSON.isFeature(x)  ||
            GeoJSON.isFeatureCollection(x)
        );
    },

///////////////////////////////////////////////////////////////////////////// 80

    equalPositions: function ( a , b ) {
        // Compare two GeoJSON Positions for equality.
        return (
            GeoJSON.isPosition(a) && GeoJSON.isPosition(b) &&
            a.length == b.length &&
            a.every(
                function ( element , index ) {
                    return (a[index] == b[index]);
                }
            )
        );
    },

    containedPolygon: function ( inner , outer ) {
        // Determine whether one GeoJSON LinearRing contains another.
        return inner.every(
            function ( Position ) {
                return inside(Position,outer);
            }
        );
    },

    Point: function ( latitude , longitude , altitude ) {
        // Create a valid GeoJSON Point geometry.
        var Point = null;
        if (typeof longitude === 'number' && typeof latitude === 'number') {
            Point = {
                type: 'Point',
                coordinates: [longitude,latitude]
            };
            if (typeof altitude === 'number') Point.coordinates.push(altitude);
        }
        return Point;
    },

    Feature: function ( Geometry , properties ) {
        // Create a valid GeoJSON Feature.
        var Feature = {
            type: 'Feature',
            geometry: null,
            properties: (typeof properties === 'object') ? properties : {}
        };
        if (GeoJSON.isGeometry(Geometry)) Feature.geometry = Geometry;
        return Feature;
    },

    FeatureCollection: function ( Features ) {
        // Create a valid GeoJSON FeatureCollection.
        var FeatureCollection = {
            type: 'FeatureCollection',
            features: []
        };
        if (GeoJSON.isFeature(Features)) {
            FeatureCollection.features.push(Features);
        }
        else if (Array.isArray(Features)) Features.forEach(
            function ( Feature ) {
                if (GeoJSON.isFeature(Feature)) {
                    FeatureCollection.features.push(Feature);
                }
            }
        );
        return FeatureCollection;
    },

    GeometryCollection: function ( Geometries ) {
        // Create a valid GeoJSON GeometryCollection.
        var GeometryCollection = {
            type: 'GeometryCollection',
            geometries: []
        };
        if (GeoJSON.isGeometry(Geometries)) {
            GeometryCollection.geometries.push(Geometries);
        }
        else if (Array.isArray(Geometries)) Geometries.forEach(
            function ( Geometry ) {
                if (GeoJSON.isGeometry(Geometry)) {
                    GeometryCollection.geometries.push(Geometry);
                }
            }
        );
        return GeometryCollection;
    },

    positionsOf: function ( geojson ) {
        // Find all the Positions in a valid GeoJSON object.
        var positions = [];
        var extractLineStringPositions = function ( LineStringCoordinates ) {
            LineStringCoordinates.forEach(
                function ( Position ) {
                    positions.push(Position);
                }
            );
        };
        var extractPolygonPositions = function ( PolygonCoordinates ) {
            PolygonCoordinates.forEach(extractLineStringPositions);
        };
        switch (geojson.type) {
            case 'Point':
                positions.push(geojson.coordinates);
                break;
            case 'MultiPoint':
            case 'LineString':
                extractLineStringPositions(geojson.coordinates);
                break;
            case 'MultiLineString':
            case 'Polygon':
                extractPolygonPositions(geojson.coordinates);
                break;
            case 'MultiPolygon':
                geojson.coordinates.forEach(extractPolygonPositions);
                break;
            case 'GeometryCollection':
                extractLineStringPositions(
                    GeoJSON.positionsOf(geojson.geometries)
                );
                break;
            case 'Feature':
                extractLineStringPositions(
                    GeoJSON.positionsOf(geojson.geometry)
                );
                break;
            case 'FeatureCollection':
                geojson.features.forEach(
                    function ( Feature ) {
                        extractLineStringPositions(
                            GeoJSON.positionsOf(Feature.geometry)
                        );
                    }
                );
                break;
        }
        return positions;
    },

    featuresOf: function ( geojson ) {
        // Find all Features in a valid GeoJSON object.
        var features = [];
        switch (geojson.type) {
            case 'Feature':
                features.push(geojson);
                break;
            case 'FeatureCollection':
                geojson.features.forEach(
                    function ( Feature ) {
                        GeoJSON.featuresOf(Feature).forEach(
                            function ( Feature ) {
                                features.push(Feature);
                            }
                        );
                    }
                );
                break;
        }
        return features;
    },

    geometriesOf: function ( geojson ) {
        // Find all Geometries in a valid GeoJSON object.
        var geometries = [];
        var extractFeatureGeometries = function ( Feature ) {
            GeoJSON.geometriesOf(Feature.geometry).forEach(
                function ( Geometry ) {
                    geometries.push(Geometry);
                }
            );
        };
        switch (geojson.type) {
            case 'Point':
            case 'MultiPoint':
            case 'LineString':
            case 'MultiLineString':
            case 'Polygon':
            case 'MultiPolygon':
                geometries.push(geojson);
                break;
            case 'GeometryCollection':
                geojson.geometries.forEach(
                    function ( Geometry ) {
                        GeoJSON.geometriesOf(Geometry).forEach(
                            function ( Geometry ) {
                                geometries.push(Geometry);
                            }
                        );
                    }
                );
                break;
            case 'Feature':
                extractFeatureGeometries(geojson);
                break;
            case 'FeatureCollection':
                geojson.features.forEach(extractFeatureGeometries);
                break;
        }
        return geometries;
    }

};
<commit_msg>Fixes references to GeoJSON<commit_after>var inside = require('point-in-polygon');
var URI = require('uri-js');

var GeoJSON = module.exports = {

    isPosition: function ( x ) {
        // Validate a GeoJSON Position.
        return (
            Array.isArray(x) &&
            x.length > 1 &&
            x.every(
                function ( element ) {
                    return (typeof element === 'number');
                }
            )
        );
    },

    isPointCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON Point.
        return GeoJSON.isPosition(x);
    },

    isMultiPointCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON MultiPoint.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isPosition)
        );
    },

    isLineStringCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON LineString.
        return (
            Array.isArray(x) &&
            x.length > 1 &&
            GeoJSON.isMultiPointCoordinates(x)
        );
    },

    isLinearRingCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON LinearRing.
        return (
            Array.isArray(x) &&
            x.length > 3 &&
            GeoJSON.isLineStringCoordinates(x) &&
            GeoJSON.equalPositions(x[0],x[x.length-1])
        );
    },

    isMultiLineStringCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON MultiLineString.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isLineStringCoordinates)
        );
    },

    isPolygonCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON Polygon.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isLinearRingCoordinates) &&
            x.every(
                function ( LinearRingCoordinates , i , PolygonCoordinates ) {
                    if (i == 0) return true;
                    else return GeoJSON.containedPolygon(
                        LinearRingCoordinates,
                        PolygonCoordinates[0]
                    );
                }
            )
        );
    },

    isMultiPolygonCoordinates: function ( x ) {
        // Validate the coordinates of a GeoJSON MultiPolygon.
        return (
            Array.isArray(x) &&
            x.every(GeoJSON.isPolygonCoordinates)
        );
    },

    validCRS: function ( x ) {
        // Validate the CRS property of a GeoJSON object.
        return (
            x != null &&
            (
                typeof x.crs === 'undefined' ||
                x.crs === null ||
                GeoJSON.isCRS(x.crs)
            )
        )
    },

    validBbox: function ( x ) {
        // Validate the bbox property of a GeoJSON object.
        return (
            x != null &&
            (
                typeof x.bbox === 'undefined' ||
                (
                    Array.isArray(x.bbox) &&
                    x.bbox.length%2 === 0 &&
                    true  // TODO Validate the bbox.
                )
            )
        );
    },

    isLink: function ( x ) {
        // Validate a GeoJSON Link.
        return (
            x != null &&
            x.properties != null &&
            typeof x.properties.href === 'string' &&
            URI.parse(x.properties.href).errors.length < 1 &&
            (
                typeof x.properties.type === 'undefined' ||
                (
                    typeof x.properties.type === 'string' &&
                    x.properties.type.length > 0
                )
            )
        );
    },

    isCRS: function ( x ) {
        // Validate a GeoJSON Coordinate Reference System.
        return (
            x != null &&
            (
                (
                    x.type === 'name' &&
                    x.properties != null &&
                    typeof x.properties.name === 'string' &&
                    x.properties.name.length > 0
                ) ||
                (
                    x.type === 'link' &&
                    GeoJSON.isLink(x.properties)
                )
            )
        );
    },

    isPoint: function ( x ) {
        // Validate a GeoJSON Point.
        return (
            x != null &&
            x.type === 'Point' &&
            GeoJSON.isPointCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isMultiPoint: function ( x ) {
        // Validate a GeoJSON MultiPoint.
        return (
            x != null &&
            x.type === 'MultiPoint' &&
            GeoJSON.isMultiPointCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isLineString: function ( x ) {
        // Validate a GeoJSON LineString.
        return (
            x != null &&
            x.type === 'LineString' &&
            GeoJSON.isLineStringCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isMultiLineString: function ( x ) {
        // Validate a GeoJSON MultiLineString.
        return (
            x != null &&
            x.type === 'MultiLineString' &&
            GeoJSON.isMultiLineStringCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isPolygon: function ( x ) {
        // Validate a GeoJSON Polygon.
        return (
            x != null &&
            x.type === 'Polygon' &&
            GeoJSON.isPolygonCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isMultiPolygon: function ( x ) {
        // Validate a GeoJSON MultiPolygon.
        return (
            x != null &&
            x.type === 'MultiPolygon' &&
            GeoJSON.isMultiPolygonCoordinates(x.coordinates) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isGeometryCollection: function ( x ) {
        // Validate a GeoJSON GeometryCollection.
        return (
            x != null &&
            x.type === 'GeometryCollection' &&
            Array.isArray(x.geometries) &&
            x.geometries.every(GeoJSON.isGeometry) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isFeature: function ( x ) {
        // Validate a GeoJSON Feature.
        return (
            x != null &&
            x.type === 'Feature' &&
            typeof x.properties === 'object' &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x) &&
            (
                x.geometry === null ||
                GeoJSON.isGeometry(x.geometry)
            )
        );
    },

    isFeatureCollection: function ( x ) {
        // Validate a GeoJSON FeatureCollection.
        return (
            x != null &&
            x.type === 'FeatureCollection' &&
            Array.isArray(x.features) &&
            x.features.every(GeoJSON.isFeature) &&
            GeoJSON.validCRS(x) &&
            GeoJSON.validBbox(x)
        );
    },

    isGeometry: function ( x ) {
        // Validate a GeoJSON Geometry.
        return (
            GeoJSON.isPoint(x) ||
            GeoJSON.isMultiPoint(x) ||
            GeoJSON.isLineString(x) ||
            GeoJSON.isMultiLineString(x) ||
            GeoJSON.isPolygon(x) ||
            GeoJSON.isMultiPolygon(x) ||
            GeoJSON.isGeometryCollection(x)
        );
    },

    isGeoJSON: function ( x ) {
        // Validate a GeoJSON object.
        return (
            GeoJSON.isGeometry(x) ||
            GeoJSON.isFeature(x)  ||
            GeoJSON.isFeatureCollection(x)
        );
    },

///////////////////////////////////////////////////////////////////////////// 80

    equalPositions: function ( a , b ) {
        // Compare two GeoJSON Positions for equality.
        return (
            GeoJSON.isPosition(a) && GeoJSON.isPosition(b) &&
            a.length == b.length &&
            a.every(
                function ( element , index ) {
                    return (a[index] == b[index]);
                }
            )
        );
    },

    containedPolygon: function ( inner , outer ) {
        // Determine whether one GeoJSON LinearRing contains another.
        return inner.every(
            function ( Position ) {
                return inside(Position,outer);
            }
        );
    },

    Point: function ( latitude , longitude , altitude ) {
        // Create a valid GeoJSON Point geometry.
        var Point = null;
        if (typeof longitude === 'number' && typeof latitude === 'number') {
            Point = {
                type: 'Point',
                coordinates: [longitude,latitude]
            };
            if (typeof altitude === 'number') Point.coordinates.push(altitude);
        }
        return Point;
    },

    Feature: function ( Geometry , properties ) {
        // Create a valid GeoJSON Feature.
        var Feature = {
            type: 'Feature',
            geometry: null,
            properties: (typeof properties === 'object') ? properties : {}
        };
        if (GeoJSON.isGeometry(Geometry)) Feature.geometry = Geometry;
        return Feature;
    },

    FeatureCollection: function ( Features ) {
        // Create a valid GeoJSON FeatureCollection.
        var FeatureCollection = {
            type: 'FeatureCollection',
            features: []
        };
        if (GeoJSON.isFeature(Features)) {
            FeatureCollection.features.push(Features);
        }
        else if (Array.isArray(Features)) Features.forEach(
            function ( Feature ) {
                if (GeoJSON.isFeature(Feature)) {
                    FeatureCollection.features.push(Feature);
                }
            }
        );
        return FeatureCollection;
    },

    GeometryCollection: function ( Geometries ) {
        // Create a valid GeoJSON GeometryCollection.
        var GeometryCollection = {
            type: 'GeometryCollection',
            geometries: []
        };
        if (GeoJSON.isGeometry(Geometries)) {
            GeometryCollection.geometries.push(Geometries);
        }
        else if (Array.isArray(Geometries)) Geometries.forEach(
            function ( Geometry ) {
                if (GeoJSON.isGeometry(Geometry)) {
                    GeometryCollection.geometries.push(Geometry);
                }
            }
        );
        return GeometryCollection;
    },

    positionsOf: function ( geojson ) {
        // Find all the Positions in a valid GeoJSON object.
        var positions = [];
        var extractLineStringPositions = function ( LineStringCoordinates ) {
            LineStringCoordinates.forEach(
                function ( Position ) {
                    positions.push(Position);
                }
            );
        };
        var extractPolygonPositions = function ( PolygonCoordinates ) {
            PolygonCoordinates.forEach(extractLineStringPositions);
        };
        switch (geojson.type) {
            case 'Point':
                positions.push(geojson.coordinates);
                break;
            case 'MultiPoint':
            case 'LineString':
                extractLineStringPositions(geojson.coordinates);
                break;
            case 'MultiLineString':
            case 'Polygon':
                extractPolygonPositions(geojson.coordinates);
                break;
            case 'MultiPolygon':
                geojson.coordinates.forEach(extractPolygonPositions);
                break;
            case 'GeometryCollection':
                extractLineStringPositions(
                    GeoJSON.positionsOf(geojson.geometries)
                );
                break;
            case 'Feature':
                extractLineStringPositions(
                    GeoJSON.positionsOf(geojson.geometry)
                );
                break;
            case 'FeatureCollection':
                geojson.features.forEach(
                    function ( Feature ) {
                        extractLineStringPositions(
                            GeoJSON.positionsOf(Feature.geometry)
                        );
                    }
                );
                break;
        }
        return positions;
    },

    featuresOf: function ( geojson ) {
        // Find all Features in a valid GeoJSON object.
        var features = [];
        switch (geojson.type) {
            case 'Feature':
                features.push(geojson);
                break;
            case 'FeatureCollection':
                geojson.features.forEach(
                    function ( Feature ) {
                        GeoJSON.featuresOf(Feature).forEach(
                            function ( Feature ) {
                                features.push(Feature);
                            }
                        );
                    }
                );
                break;
        }
        return features;
    },

    geometriesOf: function ( geojson ) {
        // Find all Geometries in a valid GeoJSON object.
        var geometries = [];
        var extractFeatureGeometries = function ( Feature ) {
            GeoJSON.geometriesOf(Feature.geometry).forEach(
                function ( Geometry ) {
                    geometries.push(Geometry);
                }
            );
        };
        switch (geojson.type) {
            case 'Point':
            case 'MultiPoint':
            case 'LineString':
            case 'MultiLineString':
            case 'Polygon':
            case 'MultiPolygon':
                geometries.push(geojson);
                break;
            case 'GeometryCollection':
                geojson.geometries.forEach(
                    function ( Geometry ) {
                        GeoJSON.geometriesOf(Geometry).forEach(
                            function ( Geometry ) {
                                geometries.push(Geometry);
                            }
                        );
                    }
                );
                break;
            case 'Feature':
                extractFeatureGeometries(geojson);
                break;
            case 'FeatureCollection':
                geojson.features.forEach(extractFeatureGeometries);
                break;
        }
        return geometries;
    }

};
<|endoftext|>


<commit_before>/*globals FMT_WRAPPER*/
(function() {
    "use strict";
    var vp;
    var swf_url;

    onReady(() => {
        // onInit does not works on channel/user page videos
        changePlayer();
        window.addEventListener("spfrequest", function() {
            if (vp)
                vp.stop();
        });
        window.addEventListener("spfdone", function() {
            changePlayer();
        });
    });

    function changePlayer() {
        getConfig()
            .then(getVideoInfo)
            .then((conf) => {
                try {
                    if (vp)
                        vp.end();
                    var player_container = getPlayerContainer(conf);
                    if (!player_container)
                        return;
                    vp = new VP(player_container);
                    vp.srcs(conf.fmts, FMT_WRAPPER, (fmt) => fmt.url);
                    vp.containerProps({
                        className: conf.className || ""
                    });
                    vp.props({
                        id: "video_player",
                        className: conf.className || "",
                        autoplay: autoPlay(!conf.isEmbed),
                        preload: preLoad(),
                        controls: true,
                        poster: conf.poster || "",
                        volume: OPTIONS.volume / 100
                    });
                    vp.style({
                        position: "relative"
                    });
                    vp.tracksList((conf.tracks || []).map(i => i.lc), (lang, resolve, reject) => {
                        var o = conf.tracks.find((i) => i.lc === lang);
                        if (o === undefined)
                            return reject();
                        addWebVTT(lang, o.u, resolve, reject);
                    });
                    vp.setup();
                    if (conf.isWatch)
                        playNextOnFinish();
                } catch (e) {
                    logify("EXCEPTION: unexpected error on changePlayer",
                        e.lineNumber, e.columnNumber, e.message, e.stack);
                }
            })
            .catch((rej) => {
                if (rej === undefined)
                    return;
                switch (rej.error) {
                    case "VIDEO_URL_UNACCESSIBLE":
                        if (rej.data.reason)
                            errorMessage("Failed to load video url with the following error message: " +
                                rej.data.reason, rej.conf);
                        break;
                    case "NO_SUPPORTED_VIDEO_FOUND":
                        errorMessage("Failed to find any playable video url." +
                            (rej.unsig ? " All urls are not signed" : ""), rej.conf);
                        break;
                    default:
                        logify("EXCEPTION: unexpected error on changePlayer", rej);
                        break;
                }
            });
    }

    function errorMessage(msg, conf) {
        var error_container;
        if (vp)
            vp.end();
        if (conf)
            error_container = getPlayerContainer(conf);
        if (!error_container)
            error_container = document.getElementById("player-unavailable") || document.getElementById("player");
        if (!error_container)
            return;
        vp = new VP(error_container);
        vp.srcs(conf.fmts, FMT_WRAPPER);
        if (conf && conf.isWatch)
            vp.containerProps({
                className: " player-height player-width"
            });
        if (conf && conf.isChannel)
            vp.containerProps({
                className: " c4-player-container"
            }); //" html5-main-video";
        if (conf && conf.isEmbed) {
            vp.containerProps({
                className: " full-frame"
            });
        }
        vp.containerStyle({
            background: "linear-gradient(to bottom, #383838 0px, #131313 100%) repeat scroll 0% 0% #262626"
        });
        vp.error(msg);
    }

    function getPlayerContainer(conf) {
        if (conf.isWatch)
            return document.getElementById("player-mole-container");
        if (conf.isEmbed)
            return document.body;
        if (conf.isChannel)
            return document.getElementsByClassName("c4-player-container")[0];
    }

    function getConfig() {
        return new Promise((resolve, reject) => {
            var conf = {};
            conf.isEmbed = location.href.search("youtube.com/embed/") > -1;
            conf.isWatch = location.href.search("youtube.com/watch?") > -1;
            conf.isChannel = location.href.search("youtube.com/channel/") > -1 || location.href.search("youtube.com/user/") > -1;
            if (!conf.isEmbed && !conf.isWatch && !conf.isChannel)
                reject();
            if (conf.isEmbed) {
                conf.id = location.pathname.match(/^\/embed\/([^?#/]*)/)[1];
                conf.className = "full-frame";
            } else if (conf.isChannel) {
                var upsell = document.getElementById("upsell-video");
                if (!upsell)
                    reject();
                conf.id = upsell.dataset["videoId"];
                conf.className = "c4-player-container"; //+ " html5-main-video"
            } else {
                conf.id = location.search.slice(1).match(/v=([^/?#]*)/)[1];
                conf.className = "player-width player-height";
            }
            if (!conf.id)
                reject({
                    error: "PLAYER_ID_NOT_FOUND",
                    conf: conf
                });
            else
                resolve(conf);
        });
    }

    function getVideoInfo(conf) {
        return new Promise((resolve, reject) => {
            var INFO_URL = "https://www.youtube.com/get_video_info?html5=1&hl=en_US&el=detailpage&video_id=";
            if (unsafeWindow.ytplayer && unsafeWindow.ytplayer.config) {
                conf.info = unsafeWindow.ytplayer.config.args.url_encoded_fmt_stream_map;
                if (unsafeWindow.ytplayer.config.args.caption_tracks)
                    conf.tracks = parse(unsafeWindow.ytplayer.config.args.caption_tracks, true);
                conf.poster = unsafeWindow.ytplayer.config.iurlhq;
                swf_url = unsafeWindow.ytplayer.config.url;
                resolve(conf);
            } else {
                asyncGet(INFO_URL + conf.id, {}, "text/plain").then((data) => {
                    if (data.endsWith("="))
                        try {
                            data = atob(data);
                        } catch (_) {}
                    data = parse(data);
                    if (data.status === "fail") {
                        return reject({
                            error: "VIDEO_URL_UNACCESSIBLE",
                            data: data,
                            conf: conf
                        });
                    }
                    // get the poster url
                    if (data.iurlhq)
                        conf.poster = data.iurlhq;
                    // extract avalable formats to fmts object
                    conf.info = data.url_encoded_fmt_stream_map;
                    if (data.caption_tracks)
                        conf.tracks = parse(data.caption_tracks, true);
                    resolve(conf);
                });
            }
        }).then((conf) => {
            var player = createNode("video");
            var unsignedVideos = false;
            conf.fmts = {};
            parse(conf.info, true)
                .filter(it5 => {
                    if (player.canPlayType(it5.type) !== "probably")
                        return false;
                    if (it5.url.search("signature=") === -1) {
                        unsignedVideos = true;
                        if (!OPTIONS.genYTSign)
                            return false;
                    }
                    return true;
                })
                .forEach(fmt => {
                    conf.fmts[fmt.itag] = fmt;
                });
            if (unsignedVideos && OPTIONS.genYTSign) {
                return fixSignature(conf);
            } else {
                return Promise.resolve(conf);
            }
        });
    }

    function fixSignature(conf) {
        return new Promise((resolve, reject) => {
            self.port.emit("fix_signature", {
                fmts: conf.fmts,
                swf_url: swf_url
            });
            self.port.on("fixed_signature", (fmts) => {
                conf.fmts = fmts;
                logify("fixed Signature");
                resolve(conf);
            });
        });
    }

    function playNextOnFinish() {
        //Credits to @durazell github.com/lejenome/youtube-html5-player/issues/9
        if (document.getElementsByClassName("playlist-header").length > 0) {
            vp.on("ended", function(e) {
                if (this.currentTime !== this.duration || OPTIONS.autoNext === false)
                    return;
                var cur = 0,
                    len = 0;
                var current, playlist;
                if ((current = document.getElementsByClassName("currently-playing")).length > 0) {
                    cur = parseInt(current[0].dataset["index"]) + 1;
                } else if ((current = document.getElementById("playlist-current-index"))) {
                    cur = parseInt(current.textContent);
                }
                if ((playlist = document.getElementsByClassName("playlist-videos-list")).length > 0) {
                    len = playlist[0].childElementCount;
                } else if ((playlist = document.getElementById("playlist-length"))) {
                    len = parseInt(playlist.textContent);
                }

                if (isNaN(cur) === true || isNaN(len) === true) {
                    logify("Cannot find location in playlist, autoplay failed");
                    return;
                }

                if (cur < len) {
                    window.location.href = document.getElementsByClassName("yt-uix-scroller-scroll-unit")[cur].getElementsByTagName("a")[0].href;
                }
            });
        }
    }

    function parse(data, splitComma) {
        if (splitComma) {
            return data.split(",").map(i => parse(i));
        } else {
            var res = {};
            var nv;
            data.split("&").forEach((p) => {
                try {
                    nv = p.split("=").map(function(v) {
                        return decodeURIComponent(v.replace(/\+/g, " "));
                    });
                    if (!(nv[0] in res)) res[nv[0]] = nv[1];
                } catch (e) {}
            });
            return res;
        }
    }

    function addWebVTT(lang, url, resolve, reject) {
        asyncGet(url).then((data) => {
            var webvtt = "WEBVTT\n\n";
            var XMLParser = new DOMParser();
            var xml = XMLParser.parseFromString(data, "text/xml");
            if (xml.documentElement.nodeName !== "transcript")
                reject();
            var els = xml.documentElement.childNodes;
            for (var i = 0; i < els.length; i++) {
                var start = els[i].attributes.getNamedItem("start");
                var dur = els[i].attributes.getNamedItem("dur");
                if (start === null || dur === null)
                    continue;
                start = parseFloat(start.value);
                dur = parseFloat(dur.value);
                var s = start % 60;
                var m = (start - s) / 60;
                var tl1 = "" + (m < 10 ? "0" : "") + m + ":" +
                    (s < 10 ? "0" : "") + s.toFixed(3);
                s = (start + dur) % 60;
                m = (start + dur - s) / 60;
                var tl2 = "" + (m < 10 ? "0" : "") + m + ":" +
                    (s < 10 ? "0" : "") + s.toFixed(3);

                webvtt += (i + 1) + "\n" + tl1 + " --> " + tl2 + "\n" + els[i].textContent + "\n\n";
            }
            resolve("data:text/vtt;base64," + btoa(webvtt.replace("'", "'", "g")));
        });
    }
}());<commit_msg>fix typo error to pickup poster image on youtube<commit_after>/*globals FMT_WRAPPER*/
(function() {
    "use strict";
    var vp;
    var swf_url;

    onReady(() => {
        // onInit does not works on channel/user page videos
        changePlayer();
        window.addEventListener("spfrequest", function() {
            if (vp)
                vp.stop();
        });
        window.addEventListener("spfdone", function() {
            changePlayer();
        });
    });

    function changePlayer() {
        getConfig()
            .then(getVideoInfo)
            .then((conf) => {
                try {
                    if (vp)
                        vp.end();
                    var player_container = getPlayerContainer(conf);
                    if (!player_container)
                        return;
                    vp = new VP(player_container);
                    vp.srcs(conf.fmts, FMT_WRAPPER, (fmt) => fmt.url);
                    vp.containerProps({
                        className: conf.className || ""
                    });
                    vp.props({
                        id: "video_player",
                        className: conf.className || "",
                        autoplay: autoPlay(!conf.isEmbed),
                        preload: preLoad(),
                        controls: true,
                        poster: conf.poster || "",
                        volume: OPTIONS.volume / 100
                    });
                    vp.style({
                        position: "relative"
                    });
                    vp.tracksList((conf.tracks || []).map(i => i.lc), (lang, resolve, reject) => {
                        var o = conf.tracks.find((i) => i.lc === lang);
                        if (o === undefined)
                            return reject();
                        addWebVTT(lang, o.u, resolve, reject);
                    });
                    vp.setup();
                    if (conf.isWatch)
                        playNextOnFinish();
                } catch (e) {
                    logify("EXCEPTION: unexpected error on changePlayer",
                        e.lineNumber, e.columnNumber, e.message, e.stack);
                }
            })
            .catch((rej) => {
                if (rej === undefined)
                    return;
                switch (rej.error) {
                    case "VIDEO_URL_UNACCESSIBLE":
                        if (rej.data.reason)
                            errorMessage("Failed to load video url with the following error message: " +
                                rej.data.reason, rej.conf);
                        break;
                    case "NO_SUPPORTED_VIDEO_FOUND":
                        errorMessage("Failed to find any playable video url." +
                            (rej.unsig ? " All urls are not signed" : ""), rej.conf);
                        break;
                    default:
                        logify("EXCEPTION: unexpected error on changePlayer", rej);
                        break;
                }
            });
    }

    function errorMessage(msg, conf) {
        var error_container;
        if (vp)
            vp.end();
        if (conf)
            error_container = getPlayerContainer(conf);
        if (!error_container)
            error_container = document.getElementById("player-unavailable") || document.getElementById("player");
        if (!error_container)
            return;
        vp = new VP(error_container);
        vp.srcs(conf.fmts, FMT_WRAPPER);
        if (conf && conf.isWatch)
            vp.containerProps({
                className: " player-height player-width"
            });
        if (conf && conf.isChannel)
            vp.containerProps({
                className: " c4-player-container"
            }); //" html5-main-video";
        if (conf && conf.isEmbed) {
            vp.containerProps({
                className: " full-frame"
            });
        }
        vp.containerStyle({
            background: "linear-gradient(to bottom, #383838 0px, #131313 100%) repeat scroll 0% 0% #262626"
        });
        vp.error(msg);
    }

    function getPlayerContainer(conf) {
        if (conf.isWatch)
            return document.getElementById("player-mole-container");
        if (conf.isEmbed)
            return document.body;
        if (conf.isChannel)
            return document.getElementsByClassName("c4-player-container")[0];
    }

    function getConfig() {
        return new Promise((resolve, reject) => {
            var conf = {};
            conf.isEmbed = location.href.search("youtube.com/embed/") > -1;
            conf.isWatch = location.href.search("youtube.com/watch?") > -1;
            conf.isChannel = location.href.search("youtube.com/channel/") > -1 || location.href.search("youtube.com/user/") > -1;
            if (!conf.isEmbed && !conf.isWatch && !conf.isChannel)
                reject();
            if (conf.isEmbed) {
                conf.id = location.pathname.match(/^\/embed\/([^?#/]*)/)[1];
                conf.className = "full-frame";
            } else if (conf.isChannel) {
                var upsell = document.getElementById("upsell-video");
                if (!upsell)
                    reject();
                conf.id = upsell.dataset["videoId"];
                conf.className = "c4-player-container"; //+ " html5-main-video"
            } else {
                conf.id = location.search.slice(1).match(/v=([^/?#]*)/)[1];
                conf.className = "player-width player-height";
            }
            if (!conf.id)
                reject({
                    error: "PLAYER_ID_NOT_FOUND",
                    conf: conf
                });
            else
                resolve(conf);
        });
    }

    function getVideoInfo(conf) {
        return new Promise((resolve, reject) => {
            var INFO_URL = "https://www.youtube.com/get_video_info?html5=1&hl=en_US&el=detailpage&video_id=";
            if (unsafeWindow.ytplayer && unsafeWindow.ytplayer.config) {
                conf.info = unsafeWindow.ytplayer.config.args.url_encoded_fmt_stream_map;
                conf.poster = unsafeWindow.ytplayer.config.args.iurlhq;
                if (unsafeWindow.ytplayer.config.args.caption_tracks)
                    conf.tracks = parse(unsafeWindow.ytplayer.config.args.caption_tracks, true);
                swf_url = unsafeWindow.ytplayer.config.url;
                resolve(conf);
            } else {
                asyncGet(INFO_URL + conf.id, {}, "text/plain").then((data) => {
                    if (data.endsWith("="))
                        try {
                            data = atob(data);
                        } catch (_) {}
                    data = parse(data);
                    if (data.status === "fail") {
                        return reject({
                            error: "VIDEO_URL_UNACCESSIBLE",
                            data: data,
                            conf: conf
                        });
                    }
                    // get the poster url
                    if (data.iurlhq)
                        conf.poster = data.iurlhq;
                    // extract avalable formats to fmts object
                    conf.info = data.url_encoded_fmt_stream_map;
                    if (data.caption_tracks)
                        conf.tracks = parse(data.caption_tracks, true);
                    resolve(conf);
                });
            }
        }).then((conf) => {
            var player = createNode("video");
            var unsignedVideos = false;
            conf.fmts = {};
            parse(conf.info, true)
                .filter(it5 => {
                    if (player.canPlayType(it5.type) !== "probably")
                        return false;
                    if (it5.url.search("signature=") === -1) {
                        unsignedVideos = true;
                        if (!OPTIONS.genYTSign)
                            return false;
                    }
                    return true;
                })
                .forEach(fmt => {
                    conf.fmts[fmt.itag] = fmt;
                });
            if (unsignedVideos && OPTIONS.genYTSign) {
                return fixSignature(conf);
            } else {
                return Promise.resolve(conf);
            }
        });
    }

    function fixSignature(conf) {
        return new Promise((resolve, reject) => {
            self.port.emit("fix_signature", {
                fmts: conf.fmts,
                swf_url: swf_url
            });
            self.port.on("fixed_signature", (fmts) => {
                conf.fmts = fmts;
                logify("fixed Signature");
                resolve(conf);
            });
        });
    }

    function playNextOnFinish() {
        //Credits to @durazell github.com/lejenome/youtube-html5-player/issues/9
        if (document.getElementsByClassName("playlist-header").length > 0) {
            vp.on("ended", function(e) {
                if (this.currentTime !== this.duration || OPTIONS.autoNext === false)
                    return;
                var cur = 0,
                    len = 0;
                var current, playlist;
                if ((current = document.getElementsByClassName("currently-playing")).length > 0) {
                    cur = parseInt(current[0].dataset["index"]) + 1;
                } else if ((current = document.getElementById("playlist-current-index"))) {
                    cur = parseInt(current.textContent);
                }
                if ((playlist = document.getElementsByClassName("playlist-videos-list")).length > 0) {
                    len = playlist[0].childElementCount;
                } else if ((playlist = document.getElementById("playlist-length"))) {
                    len = parseInt(playlist.textContent);
                }

                if (isNaN(cur) === true || isNaN(len) === true) {
                    logify("Cannot find location in playlist, autoplay failed");
                    return;
                }

                if (cur < len) {
                    window.location.href = document.getElementsByClassName("yt-uix-scroller-scroll-unit")[cur].getElementsByTagName("a")[0].href;
                }
            });
        }
    }

    function parse(data, splitComma) {
        if (splitComma) {
            return data.split(",").map(i => parse(i));
        } else {
            var res = {};
            var nv;
            data.split("&").forEach((p) => {
                try {
                    nv = p.split("=").map(function(v) {
                        return decodeURIComponent(v.replace(/\+/g, " "));
                    });
                    if (!(nv[0] in res)) res[nv[0]] = nv[1];
                } catch (e) {}
            });
            return res;
        }
    }

    function addWebVTT(lang, url, resolve, reject) {
        asyncGet(url).then((data) => {
            var webvtt = "WEBVTT\n\n";
            var XMLParser = new DOMParser();
            var xml = XMLParser.parseFromString(data, "text/xml");
            if (xml.documentElement.nodeName !== "transcript")
                reject();
            var els = xml.documentElement.childNodes;
            for (var i = 0; i < els.length; i++) {
                var start = els[i].attributes.getNamedItem("start");
                var dur = els[i].attributes.getNamedItem("dur");
                if (start === null || dur === null)
                    continue;
                start = parseFloat(start.value);
                dur = parseFloat(dur.value);
                var s = start % 60;
                var m = (start - s) / 60;
                var tl1 = "" + (m < 10 ? "0" : "") + m + ":" +
                    (s < 10 ? "0" : "") + s.toFixed(3);
                s = (start + dur) % 60;
                m = (start + dur - s) / 60;
                var tl2 = "" + (m < 10 ? "0" : "") + m + ":" +
                    (s < 10 ? "0" : "") + s.toFixed(3);

                webvtt += (i + 1) + "\n" + tl1 + " --> " + tl2 + "\n" + els[i].textContent + "\n\n";
            }
            resolve("data:text/vtt;base64," + btoa(webvtt.replace("'", "'", "g")));
        });
    }
}());<|endoftext|>


<commit_before>var mongodb = require('mongodb'),
	dbServer = new mongodb.Server('localhost', 27017, {auto_reconnect:true}),
	db = new mongodb.Db('mydb', dbServer, {w:1});

/* INSERT 5 DOCUMENTS
// open database connection
db.open( function(err, conn){
	// select and or add a collection to the db
	db.collection('myNewCollection', function(err, collection){
		// cache a count variable
		var count = 0;
		// insert numbers into the collection
		for(var i=0; i<5; i++) {
			collection.insert({
				num: i
			}, function(err, result) {
			  // log the result
			  console.log(result);
			  // increment the count value
			  count++;
			  // if the count is high enough, close the connection
			  if (count > 4) {
				  db.close();
			  }
			});
		}
	});
});
*/

/* FIND ALL DOCUMENTS
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// select all the documents in the collection
		collection.find().toArray(function(err, result) {
			// log the data
			console.log(result);
			// close the connection
			db.close();
		});
	});
});
*/

/* FIND ALL DOCUMENT WITH num = 2
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// select all the documents where num is 2 in the collection
		collection.find({num: 2}).toArray(function(err, result) {
			// log the data
			console.log(result);
			// close the connection
			db.close();
		});
	});
});
*/

/* FIND ALL DOCUMENT WITH num greater than 1 but less than 4, limit to 10 results, sort in descending order
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// select all the documents where num is greater than 1 but less than 4 in the collection, limit to 10 results, sort in descending order
		collection.find({num: {$gt: 1, $lt: 4}}, {limit: 10}, {sort: [['num', 'desc']]}).toArray(function(err, result) {
			// log the data
			console.log(result);
			// close the connection
			db.close();
		});
	});
});
*/

/* UPDATING AN ENTIRE ENTRY
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// update one of the documents
		collection.update({num: 2}, {num: 10}, {safe: true}, function(err) {
			if(err) {
				console.log(err);
			}
			else {
				console.log('Successfully updated');
			}
			db.close();
		});
	});
});
*/

/* UPSERTING AN ENTIRE ENTRY
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// upsert one of the documents
		collection.update({num: 8}, {num: 7}, {safe: true, upsert: true}, function(err) {
			if(err) {
				console.log(err);
			}
			else {
				console.log('Successfully upserted');
			}
			db.close();
		});
	});
});
*/

/* UPDATING AN PARTICULAR FIELD OF AN ENTRY */
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// update one of the documents
		collection.update({num: 3}, {$set: {desc: 'favourite number'}}, {safe: true}, function(err) {
			if(err) {
				console.log(err);
			}
			else {
				console.log('Successfully updated');
			}
			db.close();
		});
	});
});

<commit_msg>Modified<commit_after>var mongodb = require('mongodb'),
	dbServer = new mongodb.Server('localhost', 27017, {auto_reconnect:true}),
	db = new mongodb.Db('mydb', dbServer, {w:1});

/* INSERT 5 DOCUMENTS
// open database connection
db.open( function(err, conn){
	// select and or add a collection to the db
	db.collection('myNewCollection', function(err, collection){
		// cache a count variable
		var count = 0;
		// insert numbers into the collection
		for(var i=0; i<5; i++) {
			collection.insert({
				num: i
			}, function(err, result) {
			  // log the result
			  console.log(result);
			  // increment the count value
			  count++;
			  // if the count is high enough, close the connection
			  if (count > 4) {
				  db.close();
			  }
			});
		}
	});
});
*/

/* FIND ALL DOCUMENTS
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// select all the documents in the collection
		collection.find().toArray(function(err, result) {
			// log the data
			console.log(result);
			// close the connection
			db.close();
		});
	});
});
*/

/* FIND ALL DOCUMENT WITH num = 2
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// select all the documents where num is 2 in the collection
		collection.find({num: 2}).toArray(function(err, result) {
			// log the data
			console.log(result);
			// close the connection
			db.close();
		});
	});
});
*/

/* FIND ALL DOCUMENT WITH num greater than 1 but less than 4, limit to 10 results, sort in descending order
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// select all the documents where num is greater than 1 but less than 4 in the collection, limit to 10 results, sort in descending order
		collection.find({num: {$gt: 1, $lt: 4}}, {limit: 10}, {sort: [['num', 'desc']]}).toArray(function(err, result) {
			// log the data
			console.log(result);
			// close the connection
			db.close();
		});
	});
});
*/

/* UPDATING AN ENTIRE ENTRY
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// update one of the documents
		collection.update({num: 2}, {num: 10}, {safe: true}, function(err) {
			if(err) {
				console.log(err);
			}
			else {
				console.log('Successfully updated');
			}
			db.close();
		});
	});
});
*/

/* UPSERTING AN ENTIRE ENTRY
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// upsert one of the documents
		collection.update({num: 8}, {num: 7}, {safe: true, upsert: true}, function(err) {
			if(err) {
				console.log(err);
			}
			else {
				console.log('Successfully upserted');
			}
			db.close();
		});
	});
});
*/

/* UPDATING AN PARTICULAR FIELD OF AN ENTRY
// open database connection
db.open(function(err, conn){
	// select the collection
	db.collection('myNewCollection', function(err, collection) {
		// update one of the documents
		collection.update({num: 3}, {$set: {desc: 'favourite number'}}, {safe: true}, function(err) {
			if (err) {
				console.log(err);
			}
			else {
				console.log('Successfully updated');
			}
			db.close();
		});
	});
});
*/

/* UPDATING AN PARTICULAR FIELD OF AN ENTRY */
// open database connection
db.open(function(err, conn){
	// select the collection
    db.collection('myNewCollection', function(err, collection) {
	    // find and modify
	    // NOTE: findAndModify returns the document as it stood BEFORE the modification!!
	    collection.findAndModify({num: 4}, [['_id', 'asc']], {num: 25}, {safe: true}, function(err, result) {
		   if (err) {
			   console.log(err);
		   }
		   // log the affected document
		   else {
			   console.log(result);
		   }
		   db.close({});
	    });
    });
});

<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { Router } from 'meteor/iron:router';
import { Bert } from 'meteor/themeteorchef:bert';
import 'meteor/sacha:spin';

import { MangasData } from '../../../api/mangasData/schema.js';

import './editManga.jade';

Template.editManga.onCreated(function() {
	this.autorun(() => {
		this.subscribe('oneMangasData', Router.current().params._id);
	});
});

Template.editManga.helpers({
	mangaData() {
		return MangasData.findOne({ _id: Router.current().params._id });
	},
	mangaTomes() {
		return this.tomes.sort((a, b) => {
			if (a.number < b.number) {
				return -1
			} else if (a.number > b.number) {
				return 1
			} else if (a.number === b.number) {
				return 0;
			}
		});
	}
});

Template.editManga.events({
	'click #mangaTitlesSave': function(event) {
		event.preventDefault();
		const data = {
			mangaId: this._id,
			fr: $('#namesFr').val(),
			en: $('#namesEn').val(),
			jp: $('#namesJp').val()
		};
		if (data.fr || data.en || data.jp) {
			Meteor.call('updateMangaNames', data, (error, result) => {
				if (error) {
					return Bert.alert(error.message, 'danger', 'growl-top-right');
				}
			});
		}
	},
	'click #mangaAuthorsSave': function(event) {
		event.preventDefault();
	},
	'click #mangaCoverSave': function(event) {
		event.preventDefault();
	},
	'click #mangaGenreSave': function(event) {
		event.preventDefault();
	},
	'click .tomeSave': function(event) {
		event.preventDefault();
	},
	'click #addATome': function(event) {
		event.preventDefault();
		const data = {
			mangaId: Router.current().params._id,
			number: this.tomes.length
		};
		console.log(data);
		Meteor.call('addATomeInAManga', data, (error, result) => {
			if (error) {
				return Bert.alert(error.message, 'danger', 'growl-top-right');
			}
		});
	}
});
<commit_msg>Fix eslint error<commit_after>import { Template } from 'meteor/templating';
import { Router } from 'meteor/iron:router';
import { Bert } from 'meteor/themeteorchef:bert';
import 'meteor/sacha:spin';

import { MangasData } from '../../../api/mangasData/schema.js';

import './editManga.jade';

Template.editManga.onCreated(function() {
	this.autorun(() => {
		this.subscribe('oneMangasData', Router.current().params._id);
	});
});

Template.editManga.helpers({
	mangaData() {
		return MangasData.findOne({ _id: Router.current().params._id });
	},
	mangaTomes() {
		return this.tomes.sort((a, b) => {
			if (a.number < b.number) {
				return -1;
			} else if (a.number > b.number) {
				return 1;
			} else if (a.number === b.number) {
				return 0;
			}
		});
	}
});

Template.editManga.events({
	'click #mangaTitlesSave': function(event) {
		event.preventDefault();
		const data = {
			mangaId: this._id,
			fr: $('#namesFr').val(),
			en: $('#namesEn').val(),
			jp: $('#namesJp').val()
		};
		if (data.fr || data.en || data.jp) {
			Meteor.call('updateMangaNames', data, (error, result) => {
				if (error) {
					return Bert.alert(error.message, 'danger', 'growl-top-right');
				}
			});
		}
	},
	'click #mangaAuthorsSave': function(event) {
		event.preventDefault();
	},
	'click #mangaCoverSave': function(event) {
		event.preventDefault();
	},
	'click #mangaGenreSave': function(event) {
		event.preventDefault();
	},
	'click .tomeSave': function(event) {
		event.preventDefault();
	},
	'click #addATome': function(event) {
		event.preventDefault();
		const data = {
			mangaId: Router.current().params._id,
			number: this.tomes.length
		};
		//console.log(data);
		Meteor.call('addATomeInAManga', data, (error, result) => {
			if (error) {
				return Bert.alert(error.message, 'danger', 'growl-top-right');
			}
		});
	}
});
<|endoftext|>


<commit_before>let sql = require('./postgressql');
let usercontrol = require('./usercontrol');

function question_retrive(type) {
	let rows;
    let command = '';
    let result = [];

    command += 'SELECT * FROM ' + type + '_question where question_ver = (select MAX(question_ver) from ' + type + '_question)';
    rows = sql.excute(command);

    if(rows.length == 0) {
        return ['Data empty'];
    }
    result.push(rows[0].question_ver);
    for(let i=0;i<rows.length;i++) {
        result.push(rows[i].description);
    }

    return result;
}

function account_name_collect(type) {
    let rows;
    let command = '';
    let result = [];
    let condition_sqlstring;

    if(type === 'all') { // non-admin
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.leader;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.leader_admin;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.normal;
    }
    else if(type === 'normal') {
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.normal;
    }
    else if(type === 'leader') {
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.leader;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.leader_admin;
    }
    else if(type === 'admin') {
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.admin;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.leader_admin;
    }

    command += 'SELECT name FROM account ' + condition_sqlstring + ' ORDER BY name ASC';
    rows = sql.excute(command);

    for(let i=0;i<rows.length;i++) {
        result.push(rows[i].name);
    }
    return result;
}

function account_retrive() {
    return sql.excute('SELECT * FROM account ORDER BY name ASC');
}

function account_lookup(username) {
    let rows;
    let command = '';
    let result;

    command += 'SELECT * FROM account where name=\'' + username + '\'';
    rows = sql.excute(command);

    if(rows.length == 0) {
        result = null;
    }
    else {
        result = rows[0];
    }

    return result;
}

function account_create(data) {
    let command = 'INSERT INTO account (name, password, employeeno, arrivedate, email, \"group\") VALUES ';
    command += '(' +
               '\'' + data.name +'\', ' +
               '\'' + data.password +'\', ' +
               '\'' + data.employee_no +'\', ' +
               '\'' + data.arrivedate +'\', ' +
               '\'' + data.email +'\', ' +
               Number(data.group) +
               ')';

    sql.excute(command);

    return true; // should do error handling
}

function account_modify(data) {
    let command = 'UPDATE account SET ';
    command += 'name = \'' + data.name + '\', ' +
               'password = \'' + data.password + '\', ' +
               'employeeno = \'' + data.employee_no + '\', ' +
               'arrivedate = \'' + data.arrivedate + '\', ' +
               'email = \'' + data.email + '\', ' +
               '\"group\" = \'' + data.group + '\' ';
    command += 'WHERE name = \'' + data.oldname + '\'';

    sql.excute(command);

    return true; // should do error handling
}

function account_delete(data) {
    let command = 'DELETE FROM account where name = \'' + data.name + '\'';

    sql.excute(command);

    return true; // should do error handling
}

function grade_give(req, type) {
    let q_list = question_retrive(type);
    let command = '';
    let value_sqlstring = '';

    if(req.body.account === req.body.provider) {
        return false; // here should throw something to let caller know what happens
    }

    let locate_sqlstring = 'WHERE ' +
                            'candidate = \'' + req.body.account + '\' and ' +
                            'provider = \'' + req.body.provider + '\' and ' +
                            'year = ' + req.body.year + ' and ' +
                            'quarter = ' + req.body.quarter;
    let rows = sql.excute('SELECT FROM ' + type + '_grade ' + locate_sqlstring);

    if(rows.length != 0) {
        let grade_update_sqlstring = '';

        for(let i=1;i<q_list.length;i++) {
            grade_update_sqlstring += 'grade' + i + '=' + req.body['grade'+i];
            if(i < (q_list.length-1)) {
                grade_update_sqlstring += ', ';
            }
        }

        command += 'UPDATE ' + type + '_grade SET ' +
                   'question_ver=' + req.body.question_ver + ', ' +
                   'apply_time=\'now()\', ' +
                   grade_update_sqlstring + ' ' +
                   locate_sqlstring;
    }
    else {
        let grade_column_sqlstring = '';
        let grade_value_sqlstring = '';

        for(let i=1;i<q_list.length;i++) {
            grade_column_sqlstring += ', grade' + i;
            grade_value_sqlstring += ', ' + req.body['grade'+i];
        }

        value_sqlstring += '('  +
                            '\'' + req.body.account      + '\', ' +
                                   req.body.question_ver + ', ' +
                            '\'now()\', ' +
                            '\'' + req.body.provider     + '\',' +
                            req.body.year + ', ' +
                            req.body.quarter +
                            grade_value_sqlstring +
                            ')';

        command += 'INSERT INTO ' + type + '_grade ' +
                   '(candidate, question_ver, apply_time, provider, year, quarter' +
                   grade_column_sqlstring + ') ' +
                   'VALUES ' + value_sqlstring;
    }
    sql.excute(command);

    return true; // should do error handling
}

function giving_comment(req) {
    let command = '';
    let value_sqlstring = '';

    if( (req.body.good.length == 0) && (req.body.improve.length == 0) ) {
        return true;
    }

    if(req.body.account === req.body.provider) {
        return false; // here should throw something to let caller know what happens
    }

    let locate_sqlstring = 'WHERE ' +
                            'candidate = \'' + req.body.account + '\' and ' +
                            'provider = \'' + req.body.provider + '\' and ' +
                            'year = ' + req.body.year + ' and ' +
                            'quarter = ' + req.body.quarter;
    let rows = sql.excute('SELECT FROM comment ' + locate_sqlstring);

    if(rows.length != 0) {
        command += 'UPDATE comment SET ' +
                   'good_thing=\'' + req.body.good + '\', ' +
                   'to_improve=\'' + req.body.improve + '\', ' +
                   'apply_time=\'now()\' ' +
                   locate_sqlstring;
    }
    else {
        value_sqlstring += '('  +
                           '\'' + req.body.account  + '\', ' +
                           '\'now()\', ' +
                           '\'' + req.body.provider + '\', ' +
                           '\'' + req.body.good + '\', ' +
                           '\'' + req.body.improve + '\', ' +
                           req.body.year + ', ' +
                           req.body.quarter +
                           ')';

        command += 'INSERT INTO comment ' +
                   '(candidate, apply_time, provider, good_thing, to_improve, year, quarter) ' +
                   'VALUES ' + value_sqlstring;
    }
    sql.excute(command);

    return true; // should do error handling
}

function rawdata_list(type) {
    let rows;
    let command = '';
    let q_list = question_retrive(type);
    let select_sqlstring = 'SELECT candidate';

    for(let i=1;i<q_list.length;i++) {
        select_sqlstring += ', sum(grade' + i + ') AS G' + i;
    }

    command += select_sqlstring + ' FROM ' + type + '_grade GROUP BY candidate ORDER BY candidate ASC';
    rows = sql.excute(command);

    return rows;
}

function comment_retrive(account, year, quarter) {
    let rows;
    let command = '';
    let select_sqlstring = 'SELECT ';
    let condition_sqlstring = 'WHERE ';

    select_sqlstring += 'good_thing AS C1, ';
    select_sqlstring += 'to_improve AS C2';

    condition_sqlstring += 'candidate = \'' + account + '\'';
    condition_sqlstring += ' AND year = ' + year;
    condition_sqlstring += ' AND quarter = ' + quarter;

    command += select_sqlstring + ' FROM comment ' + condition_sqlstring;
    rows = sql.excute(command);

    return rows;
}

// should be replaced by some exist API or collected in a utility js.
function percentage(fractions, numerator) {
    return fractions / numerator * 100;
}

function upward_calculate(who, year, quarter) {
    let account;
    let candidate_name;
    let question_list = question_retrive('upward');
    let question_count = question_list.length - 1;
    let grade_cmd_string = {'favor':'>0', 'unfavor':'<0', 'neural':'=0'};

    if(who == 'all') {
        account = account_name_collect('leader');
        account_iteration = account.length;
    }
    else {
        account_iteration = 1;
    }

    for(let i=0;i<account_iteration;i++) {

        if(who == 'all') {
            candidate_name = account[i];
        }
        else {
            candidate_name = who;
        }

        for(let j=1;j<=question_count;j++) {
            let favor_total, neural_total, unfavor_total;
            let favor_percent, neural_percent, unfavor_percent;
            let total=0;
            let command='';
            let rows;

            command = 'SELECT count(grade' + j + ') FROM upward_grade';
            command += ' WHERE candidate=\'' + candidate_name + '\'';
            command += ' AND year = ' + year;
            command += ' AND quarter = ' + quarter;
            command += ' AND grade' + j;

            rows = sql.excute(command + grade_cmd_string.favor);
            favor_total = Number(rows[0].count);

            rows = sql.excute(command + grade_cmd_string.neural);
            neural_total = Number(rows[0].count);

            rows = sql.excute(command + grade_cmd_string.unfavor);
            unfavor_total = Number(rows[0].count);

            total = favor_total + neural_total + unfavor_total;

            if(total == 0) {
                continue;
            }

            favor_percent = Math.round(percentage(favor_total, total));
            unfavor_percent = Math.round(percentage(unfavor_total, total));
            neural_percent = 100 - favor_percent - unfavor_percent;

            rows = sql.excute('SELECT * FROM upward_result WHERE candidate=\'' +
                              candidate_name + '\' AND year=' + year + ' AND quarter=' +
                              quarter + ' AND grade_num='+ j + ' AND question_ver=' + question_list[0]);

            if(rows.length == 0) {
                command = 'INSERT INTO upward_result ' +
                          '(candidate, year, quarter, total, favorable, neutral, unfavorable, question_ver, grade_num) ';
                command += 'VALUES (' +
                           '\'' + candidate_name + '\', ' +
                           year + ', ' +
                           quarter + ', ' +
                           total + ', ' +
                           favor_percent + ', ' +
                           neural_percent + ', ' +
                           unfavor_percent + ', ' +
                           question_list[0] + ', ' +
                           j +
                           ')';
            }
            else {
                command = 'UPDATE upward_result SET ';
                command += 'total=' + total +
                           ', favorable=' + favor_percent +
                           ', unfavorable=' + unfavor_percent +
                           ', neutral=' + neural_percent;
                command += ' WHERE candidate=\'' + candidate_name + '\'' +
                           ' and year=' + year +
                           ' and quarter=' + quarter +
                           ' and question_ver=' + question_list[0] +
                           ' and grade_num=' + j;
            }

            sql.excute(command);
        }
    }

    return true; // should do error handling
}

function upward_view(who, year, quarter) {
    let account;
    let candidate_name;
    let question_list = question_retrive('upward');
    let question_count = question_list.length - 1;
    let result=[];

    if(who == 'all') {
        account = account_name_collect('leader');
        account_iteration = account.length;
    }
    else {
        account_iteration = 1;
    }

    for(let i=0;i<account_iteration;i++) {
        let command='';
        let rows;

        if(who == 'all') {
            candidate_name = account[i];
        }
        else {
            candidate_name = who;
        }

        command = 'SELECT * FROM upward_result';
        command += ' WHERE candidate=\'' + candidate_name + '\'';
        command += ' AND year = ' + year;
        command += ' AND quarter = ' + quarter;
        command += ' ORDER BY grade_num';

        rows = sql.excute(command);
        if( rows.length != 0 ) {
            // console.log(rows[0]);
            result = result.concat(rows);
        }
    }

    // console.log(result.length);

    return result;
}

exports.question_retrive = question_retrive;
exports.account_retrive = account_retrive;
exports.account_name_collect = account_name_collect;
exports.account_lookup = account_lookup;
exports.account_create = account_create;
exports.account_modify = account_modify;
exports.account_delete = account_delete;

exports.grade_give = grade_give;
exports.rawdata_list = rawdata_list;

exports.giving_comment = giving_comment;
exports.comment_retrive = comment_retrive;

exports.upward_calculate = upward_calculate;
exports.upward_view = upward_view;<commit_msg>Add a function to retrieve MAX question version<commit_after>let sql = require('./postgressql');
let usercontrol = require('./usercontrol');

function question_retrive(type) {
	let rows;
    let command = '';
    let result = [];
    let max_question_ver = question_max_version_retrive(type);

    command += 'SELECT * FROM ' + type + '_question WHERE question_ver = ' + max_question_ver;
    rows = sql.excute(command);

    if(rows.length == 0) {
        return ['Data empty'];
    }
    result.push(rows[0].question_ver);
    for(let i=0;i<rows.length;i++) {
        result.push(rows[i].description);
    }

    return result;
}

function question_max_version_retrive(type) {
    let rows;
    let command = '';

    command += 'SELECT MAX(question_ver) FROM ' + type + '_question';
    rows = sql.excute(command);

    return rows[0].max;
}

function account_name_collect(type) {
    let rows;
    let command = '';
    let result = [];
    let condition_sqlstring;

    if(type === 'all') { // non-admin
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.leader;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.leader_admin;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.normal;
    }
    else if(type === 'normal') {
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.normal;
    }
    else if(type === 'leader') {
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.leader;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.leader_admin;
    }
    else if(type === 'admin') {
        condition_sqlstring = 'WHERE "group" = ' + usercontrol.privelidge.admin;
        condition_sqlstring += ' OR "group" = ' + usercontrol.privelidge.leader_admin;
    }

    command += 'SELECT name FROM account ' + condition_sqlstring + ' ORDER BY name ASC';
    rows = sql.excute(command);

    for(let i=0;i<rows.length;i++) {
        result.push(rows[i].name);
    }
    return result;
}

function account_retrive() {
    return sql.excute('SELECT * FROM account ORDER BY name ASC');
}

function account_lookup(username) {
    let rows;
    let command = '';
    let result;

    command += 'SELECT * FROM account where name=\'' + username + '\'';
    rows = sql.excute(command);

    if(rows.length == 0) {
        result = null;
    }
    else {
        result = rows[0];
    }

    return result;
}

function account_create(data) {
    let command = 'INSERT INTO account (name, password, employeeno, arrivedate, email, \"group\") VALUES ';
    command += '(' +
               '\'' + data.name +'\', ' +
               '\'' + data.password +'\', ' +
               '\'' + data.employee_no +'\', ' +
               '\'' + data.arrivedate +'\', ' +
               '\'' + data.email +'\', ' +
               Number(data.group) +
               ')';

    sql.excute(command);

    return true; // should do error handling
}

function account_modify(data) {
    let command = 'UPDATE account SET ';
    command += 'name = \'' + data.name + '\', ' +
               'password = \'' + data.password + '\', ' +
               'employeeno = \'' + data.employee_no + '\', ' +
               'arrivedate = \'' + data.arrivedate + '\', ' +
               'email = \'' + data.email + '\', ' +
               '\"group\" = \'' + data.group + '\' ';
    command += 'WHERE name = \'' + data.oldname + '\'';

    sql.excute(command);

    return true; // should do error handling
}

function account_delete(data) {
    let command = 'DELETE FROM account where name = \'' + data.name + '\'';

    sql.excute(command);

    return true; // should do error handling
}

function grade_give(req, type) {
    let q_list = question_retrive(type);
    let command = '';
    let value_sqlstring = '';

    if(req.body.account === req.body.provider) {
        return false; // here should throw something to let caller know what happens
    }

    let locate_sqlstring = 'WHERE ' +
                            'candidate = \'' + req.body.account + '\' and ' +
                            'provider = \'' + req.body.provider + '\' and ' +
                            'year = ' + req.body.year + ' and ' +
                            'quarter = ' + req.body.quarter;
    let rows = sql.excute('SELECT FROM ' + type + '_grade ' + locate_sqlstring);

    if(rows.length != 0) {
        let grade_update_sqlstring = '';

        for(let i=1;i<q_list.length;i++) {
            grade_update_sqlstring += 'grade' + i + '=' + req.body['grade'+i];
            if(i < (q_list.length-1)) {
                grade_update_sqlstring += ', ';
            }
        }

        command += 'UPDATE ' + type + '_grade SET ' +
                   'question_ver=' + req.body.question_ver + ', ' +
                   'apply_time=\'now()\', ' +
                   grade_update_sqlstring + ' ' +
                   locate_sqlstring;
    }
    else {
        let grade_column_sqlstring = '';
        let grade_value_sqlstring = '';

        for(let i=1;i<q_list.length;i++) {
            grade_column_sqlstring += ', grade' + i;
            grade_value_sqlstring += ', ' + req.body['grade'+i];
        }

        value_sqlstring += '('  +
                            '\'' + req.body.account      + '\', ' +
                                   req.body.question_ver + ', ' +
                            '\'now()\', ' +
                            '\'' + req.body.provider     + '\',' +
                            req.body.year + ', ' +
                            req.body.quarter +
                            grade_value_sqlstring +
                            ')';

        command += 'INSERT INTO ' + type + '_grade ' +
                   '(candidate, question_ver, apply_time, provider, year, quarter' +
                   grade_column_sqlstring + ') ' +
                   'VALUES ' + value_sqlstring;
    }
    sql.excute(command);

    return true; // should do error handling
}

function giving_comment(req) {
    let command = '';
    let value_sqlstring = '';

    if( (req.body.good.length == 0) && (req.body.improve.length == 0) ) {
        return true;
    }

    if(req.body.account === req.body.provider) {
        return false; // here should throw something to let caller know what happens
    }

    let locate_sqlstring = 'WHERE ' +
                            'candidate = \'' + req.body.account + '\' and ' +
                            'provider = \'' + req.body.provider + '\' and ' +
                            'year = ' + req.body.year + ' and ' +
                            'quarter = ' + req.body.quarter;
    let rows = sql.excute('SELECT FROM comment ' + locate_sqlstring);

    if(rows.length != 0) {
        command += 'UPDATE comment SET ' +
                   'good_thing=\'' + req.body.good + '\', ' +
                   'to_improve=\'' + req.body.improve + '\', ' +
                   'apply_time=\'now()\' ' +
                   locate_sqlstring;
    }
    else {
        value_sqlstring += '('  +
                           '\'' + req.body.account  + '\', ' +
                           '\'now()\', ' +
                           '\'' + req.body.provider + '\', ' +
                           '\'' + req.body.good + '\', ' +
                           '\'' + req.body.improve + '\', ' +
                           req.body.year + ', ' +
                           req.body.quarter +
                           ')';

        command += 'INSERT INTO comment ' +
                   '(candidate, apply_time, provider, good_thing, to_improve, year, quarter) ' +
                   'VALUES ' + value_sqlstring;
    }
    sql.excute(command);

    return true; // should do error handling
}

function rawdata_list(type) {
    let rows;
    let command = '';
    let q_list = question_retrive(type);
    let select_sqlstring = 'SELECT candidate';

    for(let i=1;i<q_list.length;i++) {
        select_sqlstring += ', sum(grade' + i + ') AS G' + i;
    }

    command += select_sqlstring + ' FROM ' + type + '_grade GROUP BY candidate ORDER BY candidate ASC';
    rows = sql.excute(command);

    return rows;
}

function comment_retrive(account, year, quarter) {
    let rows;
    let command = '';
    let select_sqlstring = 'SELECT ';
    let condition_sqlstring = 'WHERE ';

    select_sqlstring += 'good_thing AS C1, ';
    select_sqlstring += 'to_improve AS C2';

    condition_sqlstring += 'candidate = \'' + account + '\'';
    condition_sqlstring += ' AND year = ' + year;
    condition_sqlstring += ' AND quarter = ' + quarter;

    command += select_sqlstring + ' FROM comment ' + condition_sqlstring;
    rows = sql.excute(command);

    return rows;
}

// should be replaced by some exist API or collected in a utility js.
function percentage(fractions, numerator) {
    return fractions / numerator * 100;
}

function upward_calculate(who, year, quarter) {
    let account;
    let candidate_name;
    let question_list = question_retrive('upward');
    let question_count = question_list.length - 1;
    let grade_cmd_string = {'favor':'>0', 'unfavor':'<0', 'neural':'=0'};

    if(who == 'all') {
        account = account_name_collect('leader');
        account_iteration = account.length;
    }
    else {
        account_iteration = 1;
    }

    for(let i=0;i<account_iteration;i++) {

        if(who == 'all') {
            candidate_name = account[i];
        }
        else {
            candidate_name = who;
        }

        for(let j=1;j<=question_count;j++) {
            let favor_total, neural_total, unfavor_total;
            let favor_percent, neural_percent, unfavor_percent;
            let total=0;
            let command='';
            let rows;

            command = 'SELECT count(grade' + j + ') FROM upward_grade';
            command += ' WHERE candidate=\'' + candidate_name + '\'';
            command += ' AND year = ' + year;
            command += ' AND quarter = ' + quarter;
            command += ' AND grade' + j;

            rows = sql.excute(command + grade_cmd_string.favor);
            favor_total = Number(rows[0].count);

            rows = sql.excute(command + grade_cmd_string.neural);
            neural_total = Number(rows[0].count);

            rows = sql.excute(command + grade_cmd_string.unfavor);
            unfavor_total = Number(rows[0].count);

            total = favor_total + neural_total + unfavor_total;

            if(total == 0) {
                continue;
            }

            favor_percent = Math.round(percentage(favor_total, total));
            unfavor_percent = Math.round(percentage(unfavor_total, total));
            neural_percent = 100 - favor_percent - unfavor_percent;

            rows = sql.excute('SELECT * FROM upward_result WHERE candidate=\'' +
                              candidate_name + '\' AND year=' + year + ' AND quarter=' +
                              quarter + ' AND grade_num='+ j + ' AND question_ver=' + question_list[0]);

            if(rows.length == 0) {
                command = 'INSERT INTO upward_result ' +
                          '(candidate, year, quarter, total, favorable, neutral, unfavorable, question_ver, grade_num) ';
                command += 'VALUES (' +
                           '\'' + candidate_name + '\', ' +
                           year + ', ' +
                           quarter + ', ' +
                           total + ', ' +
                           favor_percent + ', ' +
                           neural_percent + ', ' +
                           unfavor_percent + ', ' +
                           question_list[0] + ', ' +
                           j +
                           ')';
            }
            else {
                command = 'UPDATE upward_result SET ';
                command += 'total=' + total +
                           ', favorable=' + favor_percent +
                           ', unfavorable=' + unfavor_percent +
                           ', neutral=' + neural_percent;
                command += ' WHERE candidate=\'' + candidate_name + '\'' +
                           ' and year=' + year +
                           ' and quarter=' + quarter +
                           ' and question_ver=' + question_list[0] +
                           ' and grade_num=' + j;
            }

            sql.excute(command);
        }
    }

    return true; // should do error handling
}

function upward_view(who, year, quarter) {
    let account;
    let candidate_name;
    let question_list = question_retrive('upward');
    let question_count = question_list.length - 1;
    let result=[];

    if(who == 'all') {
        account = account_name_collect('leader');
        account_iteration = account.length;
    }
    else {
        account_iteration = 1;
    }

    for(let i=0;i<account_iteration;i++) {
        let command='';
        let rows;

        if(who == 'all') {
            candidate_name = account[i];
        }
        else {
            candidate_name = who;
        }

        command = 'SELECT * FROM upward_result';
        command += ' WHERE candidate=\'' + candidate_name + '\'';
        command += ' AND year = ' + year;
        command += ' AND quarter = ' + quarter;
        command += ' ORDER BY grade_num';

        rows = sql.excute(command);
        if( rows.length != 0 ) {
            // console.log(rows[0]);
            result = result.concat(rows);
        }
    }

    // console.log(result.length);

    return result;
}

exports.question_retrive = question_retrive;
exports.question_max_version_retrive = question_max_version_retrive;

exports.account_retrive = account_retrive;
exports.account_name_collect = account_name_collect;
exports.account_lookup = account_lookup;
exports.account_create = account_create;
exports.account_modify = account_modify;
exports.account_delete = account_delete;

exports.grade_give = grade_give;
exports.rawdata_list = rawdata_list;

exports.giving_comment = giving_comment;
exports.comment_retrive = comment_retrive;

exports.upward_calculate = upward_calculate;
exports.upward_view = upward_view;<|endoftext|>