/*
Copyright 2012-2026 VeloViewer. All Rights Reserved
###V69###
*/
var KQOMText = typeof(gender) !== 'undefined' && gender == 'F' ? 'QOM' : 'KOM';
var columns = [
    { id: 0, title: 'Pos', desc: 'Position', lngDesc: 'Your current position on the segment leaderboard.', width: 'auto', class: 'ar', field: 'r', type: 'num', display: 'int', hideZeros: 0, s_s: 1, defOrder: 'asc' },
    { id: 1, title: 'Pos +/-', desc: 'Position change', lngDesc: 'The difference in your position on last changed.', width: 'auto', class: 'ar', field: 'lc', type: 'num', display: 'int', hideZeros: 0, s_s: 1, defOrder: 'asc' },
    { id: 2, title: 'Changed', desc: 'Last changed', lngDesc: 'When your placing changed (when you checked positions).', width: 'auto', class: '', field: 'drc', type: 'date', display: 'date', hideZeros: 0, s_s: 1, defOrder: 'desc' },
    { id: 3, title: 'Pos<br/>Score', desc: 'Position score', lngDesc: 'Your position score is based on your position against the total number of athletes to have completed the segment, close to 100 is good, 0 is bad!', width: 'auto', class: 'ar', field: 's', type: 'num', display: '2dp', hideZeros: 1, s_s: 1, defOrder: 'desc' },
    { id: 4, title: 'Total', desc: 'Total athletes', lngDesc: 'How many athletes have completed the segment.', width: 'auto', class: 'ar', field: 'tac', type: 'num', display: 'int', hideZeros: 0, s_s: (isPRO ? 0 : 1), defOrder: 'desc' },
    { id: 5, title: 'Type', desc: 'Segment type', lngDesc: 'The activity type of the segment.', width: 'auto', class: '', field: 't', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 6, title: 'Name', desc: 'Segment name', lngDesc: 'The segment\'s name.', width: '150px', class: 'clipText', field: 'sn', type: 'text', display: 'text', hideZeros: 0, defOrder: 'asc' },
    { id: 7, title: 'Tries', desc: 'Tries', lngDesc: 'The number of times you\'ve completed the segment.', width: 'auto', class: 'ar', field: 'tr', type: 'num', display: 'int', hideZeros: 0, defOrder: 'desc' },
    { id: 8, title: 'City', desc: 'City', lngDesc: 'The closest city to the segment.', width: 'auto', class: '', field: 'c', type: 'text', display: 'text', maxLen: 15, hideZeros: 0, defOrder: 'asc' },
    { id: 9, title: 'State', desc: 'State', lngDesc: 'The state/county of the segment.', width: 'auto', class: '', field: 'st', type: 'text', display: 'text', maxLen: 15, hideZeros: 0, defOrder: 'asc' },
    { id: 10, title: 'Dist<br/>' + lrgLenUnit, desc: 'Distance ' + lrgLenUnit, lngDesc: 'The length of the segment.', width: 'auto', class: '', field: 'd', type: 'num', display: 'lLen', hideZeros: 0, defOrder: 'desc' },
    { id: 11, title: 'Elapsed<br/>Time', desc: 'Elapsed time', lngDesc: 'The elapsed time (including any stops).', width: 'auto', class: '', field: 'et', type: 'num', display: 'lTime', hideZeros: 0, defOrder: 'asc' },
    { id: 12, title: 'Behind<br/>Leader', desc: 'Time behind leader', lngDesc: 'The amount of time you are behind the leader.', width: 'auto', class: '', field: 'bl', type: 'num', display: 'lTime', hideZeros: 1, defOrder: 'asc' },
    { id: 13, title: 'Behind<br/>Leader %', desc: '% behind leader', lngDesc: 'The percentage of time you are behind the leader.', width: 'auto', class: '', field: 'pbl', type: 'num', display: '1dp', hideZeros: 1, defOrder: 'asc' },
    { id: 14, title: 'Grade<br/>%', desc: 'Grade %', lngDesc: '', width: 'auto', class: '', field: 'gr', type: 'num', display: '2dp', hideZeros: 0, defOrder: 'desc' },
    { id: 15, title: 'Max Grade<br/>%', desc: 'Max Grade %', lngDesc: '', width: 'auto', class: '', field: 'mg', type: 'num', display: '1dp', hideZeros: 0, defOrder: 'desc' },
    { id: 16, title: 'Elv gain<br/>' + smlLenUnit, desc: 'Elevation gain ' + smlLenUnit, lngDesc: '', width: 'auto', class: '', field: 'eg', type: 'num', display: 'sLen', hideZeros: 0, defOrder: 'desc' },
    { id: 17, title: 'Elv change<br/>' + smlLenUnit, desc: 'Elevation change ' + smlLenUnit, lngDesc: '', width: 'auto', class: '', field: 'ed', type: 'num', display: 'sLen', hideZeros: 0, defOrder: 'desc' },
    { id: 18, title: 'Max Elv<br/>' + smlLenUnit, desc: 'Max elevation ' + smlLenUnit, lngDesc: '', width: 'auto', class: '', field: 'eh', type: 'num', display: 'sLen', hideZeros: 0, defOrder: 'desc' },
    { id: 19, title: 'Cat', desc: 'Climb category', lngDesc: '', width: 'auto', class: '', field: 'cc', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 20, title: 'Speed<br/>' + speedUnit, desc: 'Avg speed ' + speedUnit, lngDesc: '', width: 'auto', class: '', field: 'as', type: 'num', display: 'speed', hideZeros: 0, defOrder: 'desc' },
    { id: 21, title: 'Pace<br/>' + lrgPaceUnit, desc: 'Avg pace ' + lrgPaceUnit, lngDesc: '', width: 'auto', class: '', field: 'paLrg', type: 'lrgPace', display: 'sTime', hideZeros: 0, defOrder: 'asc' },
    { id: 22, title: 'Pace<br/>' + smlPaceUnit, desc: 'Avg pace ' + smlPaceUnit, lngDesc: '', width: 'auto', class: '', field: 'paSml', type: 'smlPace', display: 'sTime', hideZeros: 0, defOrder: 'asc' },
    { id: 23, title: 'VAM', desc: 'VAM m/hr', lngDesc: '', width: 'auto', class: 'ar', field: 'v', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 24, title: 'Leader<br/>VAM', lngDesc: ' Leader VAM m/hr', desc: 'Leader VAM', width: 'auto', class: 'ar', field: 'bv', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 25, title: 'RP', desc: 'Relative Power W/kg', lngDesc: '', width: 'auto', class: 'ar', field: 'rp', type: 'num', display: '2dp', hideZeros: 1, defOrder: 'desc' },
    { id: 26, title: 'Leader<br/>RP', desc: 'Leader RP W/kg', lngDesc: '', width: 'auto', class: 'ar', field: 'brp', type: 'num', display: '2dp', hideZeros: 1, defOrder: 'desc' },
    { id: 27, title: 'Activity', desc: 'Activity name', lngDesc: '', width: '150px', class: 'clipText', field: 'an', type: 'text', display: 'text', hideZeros: 0, defOrder: 'asc' },
    { id: 28, title: 'When', desc: 'When', lngDesc: '', width: 'auto', class: '', field: 'sd', type: 'date', display: 'date', hideZeros: 0, defOrder: 'desc' },
    { id: 29, title: 'Dist<br/>away<br/>' + lrgLenUnit, desc: 'Distance away', lngDesc: '', width: 'auto', class: '', field: 'startLngLat', type: 'geo', lat: 'lat', lng: 'lng', display: 'lLen', hideZeros: 1, defOrder: 'asc' },
    { id: 30, title: 'Orig', desc: 'Original position', lngDesc: 'The position of your PR at the time of upload to Strava (only 1-10).', width: 'auto', class: 'ar', field: 'or', type: 'num', display: 'int', hideZeros: 1, s_s: 1, defOrder: 'asc' },
    { id: 31, title: 'pVAM', desc: 'Predicted VAM', lngDesc: '', width: 'auto', class: 'ar', field: 'pv', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 32, title: 'Bearing', desc: 'Bearing', lngDesc: '', width: 'auto', class: 'ar', field: 'b', type: 'num', display: 'arrow', hideZeros: 0, defOrder: 'asc' },
    { id: 33, title: 'Group<br/>Size', desc: 'Group size', lngDesc: 'How many athletes (including you) in the group for the activity', width: 'auto', class: 'ar', field: 'atc', type: 'num', display: 'int', hideZeros: 0, defOrder: 'asc' },
    { id: 34, title: 'Gear', desc: 'Gear', lngDesc: 'Gear (bike or shoes)', width: 'auto', class: 'ar', field: 'gn', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 35, title: 'Heart Rate', desc: 'Heart rate bpm', lngDesc: 'Average heart rate', width: 'auto', class: 'ar', field: 'hr', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 36, title: 'Power W', desc: 'Power W', lngDesc: 'Average power in Watts', width: 'auto', class: 'ar', field: 'p', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 38, title: 'Power<br/>Meter', desc: 'Power meter', lngDesc: 'Has power meter', width: 'auto', class: 'ar', field: 'hp', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 37, title: '★', desc: 'Starred', lngDesc: 'Starred', width: 'auto', class: '', field: 'if', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 39, title: 'Cadence', desc: 'Cadence average rpm', lngDesc: 'Average cadence', width: 'auto', class: 'ar', field: 'ac', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 40, title: 'Max HR', desc: 'Max Heart rate bpm', lngDesc: 'Maximum heart rate', width: 'auto', class: 'ar', field: 'mh', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 41, title: 'FTP<br/>(W)', desc: 'FTP power (W)', lngDesc: 'Functional Threshold Performance using actual power. Only for efforts > 20 minutes. Power meter only.', width: 'auto', class: 'ar', field: 'pftp', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 42, title: 'FTP<br/>bpm', desc: 'FTP heart rate bpm', lngDesc: 'Functional Threshold Performance using heart rate. Only for efforts > 20 minutes.', width: 'auto', class: 'ar', field: 'hrftp', type: 'num', display: 'int', hideZeros: 1, defOrder: 'desc' },
    { id: 44, title: 'Segment Id', desc: 'Segment Id', lngDesc: 'Segment id', width: 'auto', class: 'ar', field: 'si', type: 'num', display: 'text', hideZeros: 0, defOrder: 'asc' },
    { id: 104, title: 'Activity Id', desc: 'Activity Id', lngDesc: 'Activity id', width: 'auto', class: 'ar', field: 'ai', type: 'num', display: 'text', hideZeros: 0, defOrder: 'asc' },
    { id: 45, title: 'Not PR!', desc: 'Not PR!', lngDesc: 'Your PR is not currenlty being used for Strava leaderboard!', width: 'auto', class: 'ar', field: 'notPr', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 46, title: 'Activity<br/>Private', desc: 'Activity private', lngDesc: 'Your PR activity is private.', width: 'auto', class: 'ar', field: 'apri', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 47, title: 'Commute', desc: 'Commute', lngDesc: '', width: 'auto', class: '', field: 'co', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 48, title: 'Trn', desc: 'Trainer', lngDesc: '', width: 'auto', class: '', field: 'trn', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 49, title: KQOMText+'<br/>Time', desc: KQOMText+' time', lngDesc: 'The elapsed time (including any stops) of the '+KQOMText+'.', width: 'auto', class: '', field: 'bet', type: 'num', display: 'lTime', hideZeros: 0, defOrder: 'asc' },
    { id: 51, title: 'Temp<br/>°' + tempUnit, desc: 'Temperature', lngDesc: 'Average temperature for activity', width: 'auto', class: '', field: 'tm', type: 'num', display: 'int', hideZeros: 0, defOrder: 'asc' },
    { id: 52, title: 'Count', desc: 'Count', lngDesc: 'Used in column chart for segment count values', width: 'auto', class: '', field: 'count', type: 'num', display: 'int', hideZeros: 0, defOrder: 'asc' },
    { id: 53, title: 'VVOM', desc: 'VVOM', lngDesc: 'VeloViewer Objective Measure', width: 'auto', class: '', field: 'vo', type: 'num', display: '1dp', hideZeros: 1, defOrder: 'desc' },
    { id: 54, title: 'Dist start<br/>to end ' + lrgLenUnit, desc: 'Distance start to end', lngDesc: 'The distance between the start and end locations', width: 'auto', class: '', field: 'dsf', type: 'num', display: 'lLen', filterActive: 1, hideZeros: 0, defOrder: 'desc' },
    { id: 55, title: 'Device/App', desc: 'Device/App', lngDesc: 'Device/App used to record the data', width: 'auto', class: '', field: 'dv', type: 'list', display: 'list', hideZeros: 0, defOrder: 'asc' },
    { id: 56, title: 'Start latitude', desc: 'Start latitude', lngDesc: '', width: 'auto', class: '', field: 'lat', type: 'num', display: '5dp', hideZeros: 0, defOrder: 'asc' },
    { id: 57, title: 'Start longitude', desc: 'Start longitude', lngDesc: '', width: 'auto', class: '', field: 'lng', type: 'num', display: '5dp', hideZeros: 0, defOrder: 'asc' },
    { id: 58, title: 'End latitude', desc: 'End latitude', lngDesc: '', width: 'auto', class: '', field: 'elat', type: 'num', display: '5dp', hideZeros: 0, defOrder: 'asc' },
    { id: 59, title: 'End longitude', desc: 'End longitude', lngDesc: '', width: 'auto', class: '', field: 'elng', type: 'num', display: '5dp', hideZeros: 0, defOrder: 'asc' }
];
var chartDefX = 3;
var chartDefY = 14;
var chartDefZ = 7;
var chartDefC = 4;

var chartTypeVal = 0;
// run  : 0,1,2,3,4,5,6,7,8,9,10,11,12,13,21,27,28,29
// ride : 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,23,24,25,26,27,28,29

var segAsyncCount = 0,
    actAsyncCount = 0;

var cpref = 's',
    segmentIdArr, starredSegDets;
var mapsRequired = true;
var segsRequired = false;

var confCookie = 'scnf';
var confType = 1;
var defColOrder = "0," + (s_s ? "1,2,30,3,4," : '') + "5,6,37,7,8,9,10,53,11,49,12,13,14,15,16,17,18,19,20,21,22,23,24,31,25,26,35,40,39,36,38,41,42,27,34,55,28,47,33,51,32,29,54,45,46,44,104,56,57,58,59";

function getConfigs() {
    allCols = defColOrder;
    c = [{
        "id": "1",
        "athleteId": "-1",
        "type": "1",
        "name": "All",
        "colOrder": allCols,
        "dataOrder": "0:0",
        "editable": false,
        "temp": false,
        "filters": (s_s ? "0:-1000000|1000000," : "") + "5:All,10:-1000000|1000000,14:-1000000|1000000,17:-1000000|1000000"
    }, {
        "id": "2",
        "athleteId": "-1",
        "type": "1",
        "name": "Rides",
        "colOrder": "0," + (s_s ? "1,2,30,3,4," : '') + "5,6,37,7,8,9,10,53,11,49,12,13,14,15,16,17,18,19,20,23,24,31,25,26,35,40,36,38,41,42,39,27,34,55,28,47,33,51,29,54",
        "dataOrder": "0:0",
        "editable": false,
        "temp": false,
        "filters": "5:Ride,10:-1000000|1000000,19:All"
    }, {
        "id": "3",
        "athleteId": "-1",
        "type": "1",
        "name": "Runs",
        "colOrder": "0," + (s_s ? "1,2,30,3,4," : '') + "5,6,37,7,8,9,10,53,11,49,12,13,21,35,42,39,27,34,55,28,29,54",
        "dataOrder": "0:0",
        "editable": false,
        "temp": false,
        "filters": "5:Run,10:-1000000|1000000,21:-1000000|1000000"
    }, {
        "id": "4",
        "athleteId": "-1",
        "type": "1",
        "name": "Scoring",
        "colOrder": "0," + (s_s ? "1,2,30,3,4," : '') + "5,6,37,7,8,9,10,53,11,49,12,13,14,15,16,17,18,19,20,21,22,23,24,31,25,26,35,36,38,41,42,27,34,55,28,33,51,32,29,54",
        "dataOrder": "3:1",
        "editable": false,
        "temp": false,
        "filters": "14:-0.25|1000000"
    }, {
        "id": "5",
        "athleteId": "-1",
        "type": "1",
        "name": "Not PR",
        "colOrder": "0," + (s_s ? "1,2,30,3,4," : '') + "5,6,37,7,8,9,10,53,11,49,12,13,14,15,16,17,18,19,20,21,22,23,24,31,25,26,35,40,39,36,38,41,42,27,34,55,28,33,51,32,29,54,45,46,44",
        "dataOrder": "46:1",
        "editable": false,
        "temp": false,
        "filters": "45:1,46:0"
    }];
    curConfig = getCookie(confCookie);
    if (typeof(curConfig) == 'undefined') {
        curConfig = 1;
    }
    var ci = jsonIndexOf(c, 'id', curConfig.toString());

    if (ci == -1) {
        curConfig = 1;
        ci = 0;
    }

    if (window.location.search != '' &&
        ((getParameterByName('f') != '' && c[ci].filters != getParameterByName('f')) ||
            (getParameterByName('o') != '' && c[ci].dataOrder != getParameterByName('o')))) {
        var filters = getParameterByName('f');
        var order = getParameterByName('o');
        customConfig = c.length;
        c.push({
            "id": "6",
            "athleteId": "-1",
            "type": "0",
            "name": "Custom",
            "colOrder": allCols,
            "dataOrder": (order == '' ? "0:0" : order),
            "editable": false,
            "temp": false,
            "filters": filters
        });
        curConfig = 6;
    }

    if (window.location.search != '' && (getParameterByName('c') != '')) {
        var co = getParameterByName('c').split(',').map(function(d) { return +d });
        if (co.length > 2) {
            chartTypeVal = co[0];
            chartDefX = co[1];
            chartDefY = co[2];
            chartDefZ = (co.length > 3 ? co[3] : 0);
            chartDefC = (co.length > 4 ? co[4] : 0);
        }
    }
}
getConfigs();

function localInit() {
    if (segCacheReady && actCacheReady && segAsyncCount + actAsyncCount == 0) {
        if (typeof(cacheSeg) !== 'undefined' && typeof(cacheAct) !== 'undefined') {
            if ( /*cacheSeg.length > 0 &&*/ cacheAct.length > 0) {
                delete cacheAct;
                a = cacheSeg;
                delete cacheSeg;

                /*a.sort(function(a,b){return a.r - b.r});
                var maxRank = d3.quantile(a.map(function(d) { return d.r }), 0.25); //Math.ceil(d3.median(a, function(d) { return d.r }));
                var minRank = d3.min(a, function(d) { return d.r });
                if (maxRank == minRank) {
                    var colour_scale = function(a) {return '#1a9641'};
                } else {
                    var domain = d3.merge([d3.range(minRank, maxRank + 1, (maxRank - minRank) / 4), [10000000]]);
                    var colour_range = ['#1a9641','#9dd35d', '#e0e096','#ea9746','#d7191c','#d7191c'];
                    var colour_scale = d3.scale.log().domain(domain).range(colour_range);
                }

                var lineOpacity = typeof(getCookie(cpref + 'o')) === 'undefined' ? 0.5 : +getCookie(cpref + 'o')*/

                segmentIdArr = a.map(function(d) {
                    /*d.mapLineStyle = {
                        color: colour_scale(d.r),
                        opacity: lineOpacity,
                        weight: 3,
                        smoothFactor: 1
                    };
                    d.mapLineHighlightStyle = {
                        color: colour_scale(d.r),
                        opacity: 1,
                        weight: 5,
                        smoothFactor: 1
                    };
                    d.count = 1;*/
                    d.ll1 = decompressN(d.map, 5, 2);
                    d.ll1 = d.ll1.slice(0, d.ll1.length / 2).map(function(e, i) {
                        return [d.ll1[i * 2], d.ll1[i * 2 + 1]]
                    });
                    d.elat = 0;
                    d.elng = 0;
                    if (d.ll1.length > 0) {
                        var ll = d.ll1.last();
                        d.elat = ll[0];
                        d.elng = ll[1];
                    }

                    d.dsf = d.ll1.length == 0 ? 0 : distLatLon(d.ll1[0][0], d.ll1[0][1], d.ll1.last()[0], d.ll1.last()[1]);
                    return d.si
                }).sort();

                setConfig();
                init();
                setStarredData();
            } else {
                if (hasLocalStorage) {
                    localStorage.clear();
                }
                alert('Your data doesn\'t appear to be complete! Make sure you\'ve completed at least one, full sync on the update page. If you think all your data is already synced then try refreshing the page. Also make sure that your activities in Strava contain at least one segment.');
            }
        } else {
            if (hasLocalStorage) {
                localStorage.clear();
            }
            alert('Oh dear, something\'s not gone right. Try refreshing the page (Ctrl+F5 to clear your cache might help) and see if it helps. If you keep seeing this message then let me know.');
        }
    }
}

function setStarredData() {
    if (contextAthleteId == athleteId && starred.length > 0 && typeof(segmentIdArr) !== 'undefined') {
        let otherStarred = starred.filter(function(d) {
            return segmentIdArr.indexOf(d.toString()) == -1
        }).length;
        if (otherStarred > 0) {
            d3.select('#viewOtherStarredBtn').remove();
            d3.select('#tableContainer .pager')
                .append('button')
                .attr({
                    'id': 'viewOtherStarredBtn',
                    'type': 'button',
                    'class': 'btn btn-primary btn-mini',
                    'data-toggle': 'modal',
                    'data-target': '#starredSegmentsModal'
                })
                .text('View ' + otherStarred + ' other starred segments');
            addModalPopup('starredSegments', 'Other Starred Segments', undefined, 0);

            $('#starredSegmentsModal').on('show', function() {
                if (typeof(starredSegDets) === 'undefined') {
                    var s = starred.filter(function(d) {
                        return segmentIdArr.indexOf(d.toString()) == -1
                    }).join();
                    $.ajax({
                        url: '/api/getStarredSegDetails.php?',
                        type: "POST",
                        data: {
                        i: s
                        },
                        async: true,
                        success: function(result) {
                            if (typeof(result.error) === 'undefined') {
                                var starredSegDetsIds = [];
                                starredSegDets = result;
                                starredSegDets.forEach(function(d) {
                                    d.d = +d.d;
                                    d.g = +d.g;
                                    starredSegDetsIds.push(d.i);
                                });
                                starred.filter(function(d) {
                                    return segmentIdArr.indexOf(d.toString()) == -1 && starredSegDetsIds.indexOf(d.toString()) == -1
                                }).forEach(function(d) {
                                    starredSegDets.push({ i: d, n: 'Not available, click to populate (' + d + ')' });
                                })
                                drawStarredSegs();
                            }
                        }
                    });
                }
            });
        }
    }
}

function drawStarredSegs() {
    if (d3.select('#starredSegmentsModal ul').node() == null) {
        if (starredSegDets.length == 0) {
            d3.select('#starredSegmentsModal .modal-body').append('p').text('You have completed all of your starred segments. Use the filters above the main list to view just those which are starred.');
        } else {
            d3.select('#starredSegmentsModal .modal-body').append('p').text('This is a list of the segments you have starred that you have not yet completed:');
            d3.select('#starredSegmentsModal .modal-body').append('ul');
        }
    }
    var ul = d3.select('#starredSegmentsModal ul')
        .selectAll('li')
        .data(starredSegDets, function(d) { return d.i });

    ul.exit().remove();

    ul.enter()
        .append('li')
        .each(function(d) {
            var item = d3.select(this);
            item.append('button')
                .attr({
                    'type': 'button',
                    'class': 'btn btn-primary btn-mini'
                })
                .text('Unstar')
                .on('click', function(d) {
                    $.ajax({
                        url: '/api/setSegmentStarred.php?i=' + d.i + '&v=0',
                        id: d.i,
                        async: true,
                        success: function(result) {
                            if (typeof(result.success) !== 'undefined' && result.success) {
                                var i = starred.indexOf(this.id);
                                if (i > -1) {
                                    starred.splice(i, 1);
                                }
                                var i = starredSegDets.map(function(d) { return d.i }).indexOf(this.id);
                                if (i > -1) {
                                    starredSegDets.splice(i, 1);
                                }
                                drawStarredSegs();
                                if (starredSegDets.length > 0) {
                                    d3.select('#viewOtherStarredBtn').text('View ' + starredSegDets.length + ' other starred segments');
                                } else {
                                    d3.select('#viewOtherStarredBtn').style('display', 'none');
                                }
                            } else {
                                alert('Failed to unstar segment :-(');
                            }
                        }
                    });
                });
            item.append('a').attr('target', '_blank').attr('href', 'https://www.strava.com/segments/' + d.i).style('margin-left', '10px').append('img').attr('src', 'https://cf.veloviewer.com/img/strava_icon.svg').style("height", "16px");
            item.append('a').attr('target', '_blank').attr('href', '/segments/' + d.i).style('margin-left', '10px').text(function(d) {
                return d.n + (d.d ? ' ' + fDist(d.d) + ' ' + f2dp(d.g) + '%' : '')
            });
        });
}

var s_sNotice = (!s_s ? '<p style="' + (isFree ? 'margin-top:8px;' : '') + '"><b>Important note:</b> Segment placings are <a href="' + s_sBlogLink + '" target="_blank">only available to Strava Subscribers</a>. VeloViewer users can get a <a href="https://promo.strava.com/veloviewer/" target="_blank">60 day free Strava Premium trial here</a>.</p>' : '');
if (isFree) {
    d3.select('#tourInfo')
        .style('display', null)
        .classed('alert alert-info', true)
        .html('<h4>VeloViewer Tour Notes</h4>' + s_sNotice + '<p style="' + (s_s ? 'margin-top:8px;' : '') + 'font-weight:bold">Restricted to 250 segments for free users. <a href="/update">Upgrade to PRO</a> to see your entire Strava history of segments.</p><p>This is where VeloViewer all began! I wanted to see a list of all of my segments with up-to-date placings, so I built one! The page is bascially the same as the activity list so read the Tour Notes on that page about the filters, maps and charts. You\'ll need to go back to your <b>Update</b> page to update your placings from time to time and remember to also check for new segments as there may well be a newly created segment that you are '+KQOMText+' of that you never knew about!</p><p><b>Go to your Update page at any time to <a href="/update">Upgrade to PRO</a> to view your entire Strava history and segments in VeloViewer (and to hide these notes).</b></p>');
} else {
    if (!s_s) {
        d3.select('#tourInfo')
            .style('display', null)
            .classed('alert alert-info', true)
            .html(s_sNotice);
        d3.select('#tourInfo p').style('margin-bottom', '0px');
    }
}
