loadErrors: function()

in modules/services/keepRight.js [290:407]


    loadErrors: function(projection) {
        var options = { format: 'geojson' };
        var rules = _krRuleset.join();

        // determine the needed tiles to cover the view
        var tiles = tiler
            .zoomExtent([_krZoom, _krZoom])
            .getTiles(projection);

        // abort inflight requests that are no longer needed
        abortUnwantedRequests(_krCache, tiles);

        // issue new requests..
        tiles.forEach(function(tile) {
            if (_krCache.loadedTile[tile.id] || _krCache.inflightTile[tile.id]) return;

            var rect = tile.extent.rectangle();
            var params = Object.assign({}, options, { left: rect[0], bottom: rect[3], right: rect[2], top: rect[1] });
            var url = _krUrlRoot + 'export.php?' + utilQsString(params) + '&ch=' + rules;

            var controller = new AbortController();
            _krCache.inflightTile[tile.id] = controller;

            d3_json(url, { signal: controller.signal })
                .then(function(data) {
                    delete _krCache.inflightTile[tile.id];
                    _krCache.loadedTile[tile.id] = true;
                    if (!data || !data.features || !data.features.length) {
                        throw new Error('No Data');
                    }

                    data.features.forEach(function(feature) {
                        var loc = feature.geometry.coordinates;
                        var props = feature.properties;

                        // if there is a parent, save its error type e.g.:
                        //  Error 191 = "highway-highway"
                        //  Error 190 = "intersections without junctions"  (parent)
                        var errorType = props.error_type;
                        var errorTemplate = errorTypes[errorType];
                        var parentErrorType = (Math.floor(errorType / 10) * 10).toString();

                        // try to handle error type directly, fallback to parent error type.
                        var whichType = errorTemplate ? errorType : parentErrorType;
                        var whichTemplate = errorTypes[whichType];

                        // Rewrite a few of the errors at this point..
                        // This is done to make them easier to linkify and translate.
                        switch (whichType) {
                            case '170':
                                props.description = 'This feature has a FIXME tag: ' + props.description;
                                break;
                            case '292':
                            case '293':
                                props.description = props.description.replace('A turn-', 'This turn-');
                                break;
                            case '294':
                            case '295':
                            case '296':
                            case '297':
                            case '298':
                                props.description = 'This turn-restriction~' + props.description;
                                break;
                            case '300':
                                props.description = 'This highway is missing a maxspeed tag';
                                break;
                            case '411':
                            case '412':
                            case '413':
                                props.description = 'This feature~' + props.description;
                                break;
                        }

                        // - move markers slightly so it doesn't obscure the geometry,
                        // - then move markers away from other coincident markers
                        var coincident = false;
                        do {
                            // first time, move marker up. after that, move marker right.
                            var delta = coincident ? [0.00001, 0] : [0, 0.00001];
                            loc = geoVecAdd(loc, delta);
                            var bbox = geoExtent(loc).bbox();
                            coincident = _krCache.rtree.search(bbox).length;
                        } while (coincident);

                        var d = new qaError({
                            // Required values
                            loc: loc,
                            service: 'keepRight',
                            error_type: errorType,
                            // Extra values for this service
                            id: props.error_id,
                            comment: props.comment || null,
                            description: props.description || '',
                            error_id: props.error_id,
                            which_type: whichType,
                            parent_error_type: parentErrorType,
                            severity: whichTemplate.severity || 'error',
                            object_id: props.object_id,
                            object_type: props.object_type,
                            schema: props.schema,
                            title: props.title
                        });

                        d.replacements = tokenReplacements(d);

                        _krCache.data[d.id] = d;
                        _krCache.rtree.insert(encodeErrorRtree(d));
                    });

                    dispatch.call('loaded');
                })
                .catch(function() {
                    delete _krCache.inflightTile[tile.id];
                    _krCache.loadedTile[tile.id] = true;
                });

        });
    },