@@ -358,6 +358,7 @@ else document.addEventListener('DOMContentLoaded', _bindDelegatedActions);
358358let interval ,
359359 activeReceiver = 0 ,
360360 lastPathFetch = 0 ,
361+ lastFullPathFetch = 0 ,
361362 paths = { } ,
362363 trackCutoff = 0 ,
363364 pathsFrom = - 1 ,
@@ -2633,7 +2634,7 @@ function setTrackHistory(minutes) {
26332634
26342635 // deltas only move forwards, so reaching further back needs a full refetch
26352636 const want = trackWindowStart ( ) ;
2636- const covered = pathsFrom === 0 || ( pathsFrom > 0 && want !== 0 && want >= pathsFrom ) ;
2637+ const covered = pathsFrom === 0 || ( pathsFrom > 0 && want >= pathsFrom ) ;
26372638
26382639 if ( covered ) {
26392640 redrawMap ( ) ;
@@ -3559,7 +3560,7 @@ function loadSettings() {
35593560 settings . android = false ;
35603561}
35613562
3562- function convertStringBooleansToActual ( ) {
3563+ function convertStringSettingsToActual ( ) {
35633564 const booleanSettings = [
35643565 'counter' , 'fading' , 'android' , 'kiosk' , 'welcome' , 'show_range' ,
35653566 'distance_circles' , 'table_shiptype_use_icon' , 'fix_center' ,
@@ -3568,13 +3569,18 @@ function convertStringBooleansToActual() {
35683569 'show_track_on_select' , 'shipcard_max' , 'shipcard_top_left' , 'kiosk_pan_map' , 'show_all_tracks' ,
35693570 'show_signal_graphs' , 'show_ppm_graphs' , 'plot_absolute_time'
35703571 ] ;
3572+ const numericSettings = [
3573+ 'icon_scale' , 'track_weight' , 'track_opacity' , 'track_history' , 'track_trash_threshold' ,
3574+ 'zoom' , 'lat' , 'lon' , 'map_opacity' , 'tooltipLabelFontSize' , 'shipoutline_opacity' ,
3575+ 'circle_scale' , 'center_radius' , 'kiosk_rotation_speed'
3576+ ] ;
35713577
35723578 booleanSettings . forEach ( key => {
3573- if ( Object . hasOwn ( settings , key ) ) {
3574- if ( typeof settings [ key ] === 'string' ) {
3575- settings [ key ] = settings [ key ] === "true" ;
3576- }
3577- }
3579+ if ( typeof settings [ key ] === 'string' ) settings [ key ] = settings [ key ] === "true" ;
3580+ } ) ;
3581+ numericSettings . forEach ( key => {
3582+ if ( typeof settings [ key ] === 'string' && settings [ key ] !== '' && ! isNaN ( settings [ key ] ) )
3583+ settings [ key ] = Number ( settings [ key ] ) ;
35783584 } ) ;
35793585}
35803586
@@ -3590,7 +3596,7 @@ function loadSettingsFromURL() {
35903596 }
35913597 }
35923598
3593- convertStringBooleansToActual ( ) ;
3599+ convertStringSettingsToActual ( ) ;
35943600}
35953601
35963602function mapResetViewZoom ( z , m ) {
@@ -3764,12 +3770,14 @@ async function fetchTracks() {
37643770 let isDelta = false ;
37653771 try {
37663772 if ( settings . show_all_tracks ) {
3767- const windowStart = trackWindowStart ( ) ;
3768- const sinceParam = lastPathFetch > 0
3769- ? "&since=" + lastPathFetch
3770- : ( windowStart ? "&since=" + windowStart : "" ) ;
3771- isDelta = lastPathFetch > 0 ;
3772- if ( ! isDelta ) pathsFrom = windowStart ;
3773+ // deltas accumulate points the server has pruned, so resync with a full fetch every hour
3774+ isDelta = lastPathFetch > 0 && Date . now ( ) - lastFullPathFetch < 3600 * 1000 ;
3775+ let sinceParam = "&since=" + lastPathFetch ;
3776+ if ( ! isDelta ) {
3777+ pathsFrom = trackWindowStart ( ) ;
3778+ sinceParam = pathsFrom ? "&since=" + pathsFrom : "" ;
3779+ lastFullPathFetch = Date . now ( ) ;
3780+ }
37733781 a = await fetch ( "api/allpath.json?receiver=" + activeReceiver + sinceParam ) ;
37743782 } else {
37753783 for ( var mmsi of marker_tracks ) {
@@ -3778,6 +3786,7 @@ async function fetchTracks() {
37783786 }
37793787 }
37803788 const mmsi_str = Array . from ( marker_tracks ) . join ( "," ) ;
3789+ pathsFrom = 0 ;
37813790 a = await fetch ( "api/path.json?" + mmsi_str + "&receiver=" + activeReceiver ) ;
37823791 }
37833792
@@ -4950,6 +4959,7 @@ function redrawMap() {
49504959 }
49514960 }
49524961
4962+ const cutoff = trackWindowStart ( ) ;
49534963 for ( let [ mmsi , entry ] of Object . entries ( paths ) ) {
49544964
49554965 if ( marker_tracks . has ( Number ( mmsi ) ) || settings . show_all_tracks ) {
@@ -4961,7 +4971,6 @@ function redrawMap() {
49614971 if ( path . length > 0 && path [ 0 ] . length >= 4 ) {
49624972 let currentSegment = [ ] ;
49634973 let currentDashed = false ;
4964- const cutoff = trackWindowStart ( ) ;
49654974
49664975 for ( let i = 0 ; i < path . length ; i ++ ) {
49674976 const point = path [ i ] ;
0 commit comments