2022-10-13 17:43:56 +00:00
{ //run in own scope for fast switch
2022-09-21 19:33:14 +00:00
const STORAGE = require ( "Storage" ) ;
2022-11-01 23:31:06 +00:00
const BAT _FULL = require ( "Storage" ) . readJSON ( "setting.json" ) . batFullVoltage || 0.3144 ;
2022-10-13 17:43:56 +00:00
let init = function ( ) {
global . screen = 1 ;
global . drawTimeout = undefined ;
global . lastDrawnScreen = 0 ;
global . firstDraw = true ;
global . slices = [ ] ;
global . maxScreens = 1 ;
global . scheduleDraw = false ;
2022-09-21 19:33:14 +00:00
Bangle . loadWidgets ( ) ;
2022-10-21 15:04:53 +00:00
WIDGETS . gpstrek . start ( false ) ;
2023-05-16 17:48:30 +00:00
if ( ! WIDGETS . gpstrek . getState ( ) . numberOfSlices ) WIDGETS . gpstrek . getState ( ) . numberOfSlices = 2 ;
2022-10-13 17:43:56 +00:00
} ;
let cleanup = function ( ) {
if ( global . drawTimeout ) clearTimeout ( global . drawTimeout ) ;
delete global . screen ;
delete global . drawTimeout ;
delete global . lastDrawnScreen ;
delete global . firstDraw ;
delete global . slices ;
delete global . maxScreens ;
} ;
2022-09-21 19:33:14 +00:00
2023-05-17 20:56:06 +00:00
let rotate = function ( point , rotation , center ) {
return {
x : ( ( point . x - center . x ) * Math . cos ( rotation ) - ( point . y - center . y ) * Math . sin ( rotation ) ) + center . x ,
y : ( ( point . y - center . y ) * Math . cos ( rotation ) + ( point . x - center . x ) * Math . sin ( rotation ) ) + center . y
} ;
} ;
2022-10-13 17:43:56 +00:00
init ( ) ;
scheduleDraw = true ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let parseNumber = function ( toParse ) {
2022-09-21 19:33:14 +00:00
if ( toParse . includes ( "." ) ) return parseFloat ( toParse ) ;
return parseFloat ( "" + toParse + ".0" ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let parseWaypoint = function ( filename , offset , result ) {
2022-09-21 19:33:14 +00:00
result . lat = parseNumber ( STORAGE . read ( filename , offset , 11 ) ) ;
result . lon = parseNumber ( STORAGE . read ( filename , offset += 11 , 12 ) ) ;
return offset + 12 ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let parseWaypointWithElevation = function ( filename , offset , result ) {
2022-09-21 19:33:14 +00:00
offset = parseWaypoint ( filename , offset , result ) ;
result . alt = parseNumber ( STORAGE . read ( filename , offset , 6 ) ) ;
return offset + 6 ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let parseWaypointWithName = function ( filename , offset , result ) {
2022-09-21 19:33:14 +00:00
offset = parseWaypoint ( filename , offset , result ) ;
return parseName ( filename , offset , result ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let parseName = function ( filename , offset , result ) {
2022-09-21 19:33:14 +00:00
let nameLength = STORAGE . read ( filename , offset , 2 ) - 0 ;
result . name = STORAGE . read ( filename , offset += 2 , nameLength ) ;
return offset + nameLength ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let parseWaypointWithElevationAndName = function ( filename , offset , result ) {
2022-09-21 19:33:14 +00:00
offset = parseWaypointWithElevation ( filename , offset , result ) ;
return parseName ( filename , offset , result ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2023-05-18 18:20:55 +00:00
let cache = { } ;
let cacheInsertion = [ ] ;
2022-10-13 17:43:56 +00:00
let getEntry = function ( filename , offset , result ) {
2023-05-18 18:20:55 +00:00
if ( cache . filename != filename ) cache = { } ;
if ( filename && cache [ offset ] ) {
Object . assign ( result , cache [ offset ] ) ;
result . access = Date . now ( ) ;
return offset + cache [ offset ] . fileLength ;
}
2022-09-21 19:33:14 +00:00
result . fileOffset = offset ;
let type = STORAGE . read ( filename , offset ++ , 1 ) ;
if ( type == "" ) return - 1 ;
switch ( type ) {
case "A" :
offset = parseWaypoint ( filename , offset , result ) ;
break ;
case "B" :
offset = parseWaypointWithName ( filename , offset , result ) ;
break ;
case "C" :
offset = parseWaypointWithElevation ( filename , offset , result ) ;
break ;
case "D" :
offset = parseWaypointWithElevationAndName ( filename , offset , result ) ;
break ;
default :
print ( "Unknown entry type" , type ) ;
return - 1 ;
}
offset ++ ;
result . fileLength = offset - result . fileOffset ;
2023-05-18 18:20:55 +00:00
cache [ result . fileOffset ] = result ;
cacheInsertion . push ( result . fileOffset ) ;
if ( process . memory ( false ) . free < 1000 ) {
if ( cacheInsertion . length > 0 ) cache [ cacheInsertion . shift ( ) ] = undefined ;
}
cache . filename = filename ;
2022-09-21 19:33:14 +00:00
return offset ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
const labels = [ "N" , "NE" , "E" , "SE" , "S" , "SW" , "W" , "NW" ] ;
const loc = require ( "locale" ) ;
2022-10-13 17:43:56 +00:00
let matchFontSize = function ( graphics , text , height , width ) {
2022-09-21 19:33:14 +00:00
graphics . setFontVector ( height ) ;
let metrics ;
let size = 1 ;
while ( graphics . stringMetrics ( text ) . width > 0.90 * width ) {
size -= 0.05 ;
graphics . setFont ( "Vector" , Math . floor ( height * size ) ) ;
}
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2023-05-16 16:15:52 +00:00
let getDoubleLineSlice = function ( title1 , title2 , provider1 , provider2 ) {
2022-11-02 17:02:47 +00:00
let lastValue1 = 0 ;
let lastValue2 = 0 ;
2022-09-21 19:33:14 +00:00
return {
refresh : function ( ) {
2022-11-02 17:02:47 +00:00
let bigChange1 = ( Math . abs ( lastValue1 - provider1 ( ) ) > 1 ) ;
let bigChange2 = ( Math . abs ( lastValue2 - provider2 ( ) ) > 1 ) ;
2023-05-16 16:15:52 +00:00
return ( bigChange1 || bigChange2 ) ;
2022-09-21 19:33:14 +00:00
} ,
draw : function ( graphics , x , y , height , width ) {
lastDrawn = Date . now ( ) ;
if ( typeof title1 == "function" ) title1 = title1 ( ) ;
if ( typeof title2 == "function" ) title2 = title2 ( ) ;
graphics . clearRect ( x , y , x + width , y + height ) ;
2022-11-02 17:02:47 +00:00
lastValue1 = provider1 ( ) ;
matchFontSize ( graphics , title1 + lastValue1 , Math . floor ( height * 0.5 ) , width ) ;
2022-09-21 19:33:14 +00:00
graphics . setFontAlign ( - 1 , - 1 ) ;
graphics . drawString ( title1 , x + 2 , y ) ;
graphics . setFontAlign ( 1 , - 1 ) ;
2022-11-02 17:02:47 +00:00
graphics . drawString ( lastValue1 , x + width , y ) ;
2022-09-21 19:33:14 +00:00
2022-11-02 17:02:47 +00:00
lastValue2 = provider2 ( ) ;
matchFontSize ( graphics , title2 + lastValue2 , Math . floor ( height * 0.5 ) , width ) ;
2022-09-21 19:33:14 +00:00
graphics . setFontAlign ( - 1 , - 1 ) ;
graphics . drawString ( title2 , x + 2 , y + ( height * 0.5 ) ) ;
graphics . setFontAlign ( 1 , - 1 ) ;
2022-11-02 17:02:47 +00:00
graphics . drawString ( lastValue2 , x + width , y + ( height * 0.5 ) ) ;
2022-09-21 19:33:14 +00:00
}
} ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2023-05-16 17:48:30 +00:00
const arrow = Graphics . createImage ( `
2023-05-17 21:47:57 +00:00
X
2023-05-16 17:48:30 +00:00
XXX
XXXXX
XXX XXX
XXX XXX
XXX XXX
` );
const cross = Graphics . createImage ( `
XX XX
XX XX
XX XX
XX XX
XXX
XX XX
XX XX
XX XX
XX XX
` );
const point = Graphics . createImage ( `
2023-05-17 20:56:06 +00:00
XXX
XXXXXXX
XXX XXX
XX XX
XX XX
XXX XXX
XXXXXXX
XXX
2023-05-16 17:48:30 +00:00
` );
2023-05-16 16:15:52 +00:00
let getMapSlice = function ( ) {
2023-05-14 13:37:54 +00:00
return {
2023-05-18 18:20:55 +00:00
draw : function ( graphics , x , y , height , width ) {
2023-05-14 13:37:54 +00:00
graphics . clearRect ( x , y , x + width , y + height ) ;
graphics . setClipRect ( x , y , x + width , y + height ) ;
let course = WIDGETS . gpstrek . getState ( ) . currentPos . course ;
2023-05-18 21:36:43 +00:00
if ( isNaN ( course ) ) course = getAveragedCompass ( ) ; ;
if ( isNaN ( course ) ) course = 0 ;
2023-05-14 14:43:42 +00:00
2023-05-14 13:37:54 +00:00
let route = WIDGETS . gpstrek . getState ( ) . route ;
2023-05-18 18:20:55 +00:00
if ( ! route ) return ;
2023-05-14 13:37:54 +00:00
let startingPoint = Bangle . project ( route . currentWaypoint ) ;
2023-05-16 17:48:30 +00:00
let current = Bangle . project ( WIDGETS . gpstrek . getState ( ) . currentPos ) ;
2023-05-17 21:47:57 +00:00
let compassHeight = height * 0.4 ;
if ( compassHeight > g . getHeight ( ) * 0.1 ) compassHeight = g . getHeight ( ) * 0.1 ;
let mapCenterX = x + ( width - 10 ) / 2 + compassHeight + 5 ;
2023-05-18 18:20:55 +00:00
let mapRot = require ( "graphics_utils" ) . degreesToRadians ( 180 - course ) ;
let mapTrans = {
scale : 0.05 ,
rotate : mapRot ,
x : mapCenterX ,
y : y + height * 0.7
} ;
2023-05-14 14:43:42 +00:00
2023-05-16 17:48:30 +00:00
let drawPath = function ( iter , reverse ) {
let i = 0 ;
2023-05-18 18:20:55 +00:00
let time = Date . now ( ) ;
let poly ;
let breakLoop = false ;
2023-05-18 20:10:14 +00:00
graphics . setFont6x15 ( ) ;
2023-05-16 17:48:30 +00:00
do {
2023-05-18 18:20:55 +00:00
poly = [ ] ;
2023-05-18 20:10:14 +00:00
let named = [ ] ;
2023-05-18 18:20:55 +00:00
for ( let j = 0 ; j < 10 ; j ++ ) {
i = i + ( reverse ? - 1 : 1 ) ;
let p = iter ( route , route . index + i ) ;
if ( ! p || ! p . lat ) {
breakLoop = true ;
break ;
}
let toDraw = Bangle . project ( p ) ;
2023-05-18 20:10:14 +00:00
if ( p . name ) named . push ( { i : poly . length , n : p . name } ) ;
2023-05-18 18:20:55 +00:00
poly . push ( startingPoint . x - toDraw . x ) ;
poly . push ( ( startingPoint . y - toDraw . y ) * - 1 ) ;
2023-05-16 17:48:30 +00:00
}
2023-05-18 18:20:55 +00:00
poly = graphics . transformVertices ( poly , mapTrans ) ;
graphics . drawPoly ( poly , false ) ;
2023-05-18 20:10:14 +00:00
for ( let c of named ) {
graphics . drawImage ( cross , poly [ c . i ] - 5 , poly [ c . i + 1 ] - 4.5 ) ;
graphics . drawString ( c . n , poly [ c . i ] + 10 , poly [ c . i + 1 ] ) ;
}
i -= 1 ;
2023-05-18 18:20:55 +00:00
if ( i > 50 || breakLoop ) break ;
} while ( poly [ poly . length - 2 ] > x
&& poly [ poly . length - 2 ] < x + width
&& poly [ poly . length - 1 ] > y
&& poly [ poly . length - 1 ] < y + height ) ;
2023-05-16 17:48:30 +00:00
} ;
2023-05-18 18:20:55 +00:00
2023-05-16 17:48:30 +00:00
drawPath ( getNext , false ) ;
drawPath ( getPrev , true ) ;
2023-05-17 20:56:06 +00:00
graphics . setColor ( graphics . theme . fg ) ;
2023-05-19 07:54:24 +00:00
const errorMarkerSize = 3 ;
2023-05-17 20:56:06 +00:00
if ( WIDGETS . gpstrek . getState ( ) . currentPos . lat ) {
current . x = startingPoint . x - current . x ;
current . y = ( startingPoint . y - current . y ) * - 1 ;
current . x *= 0.05 ;
current . y *= 0.05 ;
2023-05-17 21:47:57 +00:00
current . x += mapCenterX ;
2023-05-17 20:56:06 +00:00
current . y += y + height * 0.7 ;
2023-05-19 07:54:24 +00:00
if ( current . x < x ) { current . x = x + errorMarkerSize + 5 ; graphics . setColor ( 1 , 0 , 0 ) . fillRect ( x , y , x + errorMarkerSize , y + height ) ; }
if ( current . x > x + width ) { current . x = x + width - errorMarkerSize - 5 ; graphics . setColor ( 1 , 0 , 0 ) . fillRect ( x + width - errorMarkerSize , y , x + width , y + height ) ; }
if ( current . y < y ) { current . y = y + errorMarkerSize + 5 ; graphics . setColor ( 1 , 0 , 0 ) . fillRect ( x , y , x + width , y + errorMarkerSize ) ; }
if ( current . y > y + height ) { current . y = y + height - errorMarkerSize - 5 ; graphics . setColor ( 1 , 0 , 0 ) . fillRect ( x , y + height - errorMarkerSize , x + width , y + height ) ; }
2023-05-17 20:56:06 +00:00
2023-05-19 07:54:24 +00:00
graphics . drawImage ( arrow , current . x - 5 , current . y - 2 ) ;
2023-05-17 20:56:06 +00:00
} else {
2023-05-17 21:47:57 +00:00
graphics . drawImage ( point , mapCenterX - 5 , y + height * 0.7 - 4 ) ;
2023-05-17 20:56:06 +00:00
}
2023-05-17 21:47:57 +00:00
let compass = [ 0 , 0 , 0 , compassHeight , 0 , - compassHeight , compassHeight , 0 , - compassHeight , 0 ] ;
2023-05-19 07:54:24 +00:00
let compassCenterX = x + errorMarkerSize + 5 + compassHeight ;
let compassCenterY = y + errorMarkerSize + 5 + compassHeight + 3 ;
2023-05-17 20:56:06 +00:00
compass = graphics . transformVertices ( compass , {
2023-05-17 21:47:57 +00:00
rotate : require ( "graphics_utils" ) . degreesToRadians ( 180 - course ) ,
2023-05-19 07:54:24 +00:00
x : compassCenterX ,
y : compassCenterY
2023-05-17 20:56:06 +00:00
} ) ;
graphics . setFontAlign ( 0 , 0 ) ;
2023-05-17 21:47:57 +00:00
graphics . setColor ( graphics . theme . bg ) ;
2023-05-19 07:54:24 +00:00
graphics . fillCircle ( compassCenterX , compassCenterY , compassHeight + 5 ) ;
2023-05-17 21:47:57 +00:00
graphics . setColor ( graphics . theme . fg ) ;
2023-05-19 07:54:24 +00:00
graphics . drawCircle ( compassCenterX , compassCenterY , compassHeight ) ;
2023-05-17 20:56:06 +00:00
graphics . drawString ( "N" , compass [ 2 ] , compass [ 3 ] , true ) ;
graphics . drawString ( "S" , compass [ 4 ] , compass [ 5 ] , true ) ;
graphics . drawString ( "W" , compass [ 6 ] , compass [ 7 ] , true ) ;
2023-05-17 21:47:57 +00:00
graphics . drawString ( "E" , compass [ 8 ] , compass [ 9 ] , true ) ;
2023-05-14 13:37:54 +00:00
}
} ;
} ;
2022-10-13 17:43:56 +00:00
let getTargetSlice = function ( targetDataSource ) {
2022-09-21 19:33:14 +00:00
let nameIndex = 0 ;
return {
draw : function ( graphics , x , y , height , width ) {
graphics . clearRect ( x , y , x + width , y + height ) ;
if ( targetDataSource . icon ) {
graphics . drawImage ( targetDataSource . icon , x , y + ( height - 16 ) / 2 ) ;
x += 16 ;
width -= 16 ;
}
2023-05-12 08:19:23 +00:00
let start = targetDataSource . getStart ( ) ;
let target = targetDataSource . getTarget ( ) ;
2022-09-21 19:33:14 +00:00
2023-05-12 08:19:23 +00:00
if ( ! target || ! start ) return ;
let dist = distance ( start , target ) ;
2022-09-21 19:33:14 +00:00
if ( isNaN ( dist ) ) dist = Infinity ;
2023-05-12 08:19:23 +00:00
let bearingString = bearing ( start , target ) + "°" ;
if ( target . name ) {
2022-09-21 19:33:14 +00:00
graphics . setFont ( "Vector" , Math . floor ( height * 0.5 ) ) ;
2023-05-12 08:19:23 +00:00
let scrolledName = ( target . name || "" ) . substring ( nameIndex ) ;
2022-09-21 19:33:14 +00:00
if ( graphics . stringMetrics ( scrolledName ) . width > width ) {
nameIndex ++ ;
} else {
nameIndex = 0 ;
}
graphics . drawString ( scrolledName , x + 2 , y ) ;
let distanceString = loc . distance ( dist , 2 ) ;
matchFontSize ( graphics , distanceString + bearingString , height * 0.5 , width ) ;
graphics . drawString ( bearingString , x + 2 , y + ( height * 0.5 ) ) ;
graphics . setFontAlign ( 1 , - 1 ) ;
graphics . drawString ( distanceString , x + width , y + ( height * 0.5 ) ) ;
} else {
graphics . setFont ( "Vector" , Math . floor ( height * 1 ) ) ;
2023-05-12 08:19:23 +00:00
let bearingString = bearing ( start , target ) + "°" ;
2022-09-21 19:33:14 +00:00
let formattedDist = loc . distance ( dist , 2 ) ;
let distNum = ( formattedDist . match ( /[0-9\.]+/ ) || [ Infinity ] ) [ 0 ] ;
let size = 0.8 ;
let distNumMetrics ;
while ( graphics . stringMetrics ( bearingString ) . width + ( distNumMetrics = graphics . stringMetrics ( distNum ) ) . width > 0.90 * width ) {
size -= 0.05 ;
graphics . setFont ( "Vector" , Math . floor ( height * size ) ) ;
}
graphics . drawString ( bearingString , x + 2 , y + ( height - distNumMetrics . height ) / 2 ) ;
graphics . setFontAlign ( 1 , - 1 ) ;
graphics . drawString ( distNum , x + width , y + ( height - distNumMetrics . height ) / 2 ) ;
graphics . setFont ( "Vector" , Math . floor ( height * 0.25 ) ) ;
graphics . setFontAlign ( - 1 , 1 ) ;
if ( targetDataSource . getProgress ) {
graphics . drawString ( targetDataSource . getProgress ( ) , x + 2 , y + height ) ;
}
graphics . setFontAlign ( 1 , 1 ) ;
if ( ! isNaN ( distNum ) && distNum != Infinity )
graphics . drawString ( formattedDist . match ( /[a-zA-Z]+/ ) , x + width , y + height ) ;
}
}
} ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let drawCompass = function ( graphics , x , y , height , width , increment , start ) {
2022-09-21 19:33:14 +00:00
graphics . setFont12x20 ( ) ;
graphics . setFontAlign ( 0 , - 1 ) ;
graphics . setColor ( graphics . theme . fg ) ;
let frag = 0 - start % 15 ;
if ( frag > 0 ) frag = 0 ;
let xpos = 0 + frag * increment ;
for ( let i = start ; i <= 720 ; i += 15 ) {
2022-10-21 15:04:53 +00:00
var res = i + frag ;
2022-09-21 19:33:14 +00:00
if ( res % 90 == 0 ) {
graphics . drawString ( labels [ Math . floor ( res / 45 ) % 8 ] , xpos , y + 2 ) ;
2023-05-18 19:40:20 +00:00
graphics . fillRect ( xpos - 2 , Math . floor ( y + height * 0.8 ) , xpos + 2 , Math . floor ( y + height ) ) ;
2022-09-21 19:33:14 +00:00
} else if ( res % 45 == 0 ) {
graphics . drawString ( labels [ Math . floor ( res / 45 ) % 8 ] , xpos , y + 2 ) ;
2023-05-18 19:40:20 +00:00
graphics . fillRect ( xpos - 2 , Math . floor ( y + height * 0.7 ) , xpos + 2 , Math . floor ( y + height ) ) ;
2022-09-21 19:33:14 +00:00
} else if ( res % 15 == 0 ) {
graphics . fillRect ( xpos , Math . floor ( y + height * 0.9 ) , xpos + 1 , Math . floor ( y + height ) ) ;
}
xpos += increment * 15 ;
if ( xpos > width + 20 ) break ;
}
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2023-05-18 14:50:45 +00:00
let getCompassSlice = function ( ) {
let compassDataSource = {
getCourseType : function ( ) {
return ( WIDGETS . gpstrek . getState ( ) . currentPos && WIDGETS . gpstrek . getState ( ) . currentPos . course ) ? "GPS" : "MAG" ;
} ,
getCourse : function ( ) {
if ( compassDataSource . getCourseType ( ) == "GPS" ) return WIDGETS . gpstrek . getState ( ) . currentPos . course ;
return getAveragedCompass ( ) ;
} ,
getPoints : function ( ) {
let points = [ ] ;
let s = WIDGETS . gpstrek . getState ( ) ;
if ( s . currentPos && s . currentPos . lon && s . route ) {
points . push ( { bearing : bearing ( s . currentPos , getLast ( s . route ) ) , icon : finishIcon } ) ;
}
if ( s . currentPos && s . currentPos . lon && s . waypoint ) {
points . push ( { bearing : bearing ( s . currentPos , s . waypoint ) , icon : finishIcon } ) ;
}
if ( s . currentPos && s . currentPos . lon && s . route && s . route . currentWaypoint ) {
points . push ( { bearing : bearing ( s . currentPos , s . route . currentWaypoint ) , color : "#0f0" } ) ;
}
return points ;
} ,
getMarkers : function ( ) {
return [ { xpos : 0.5 , width : 10 , height : 10 , linecolor : g . theme . fg , fillcolor : "#f00" } ] ;
}
} ;
2022-11-02 17:02:47 +00:00
let lastDrawnValue = 0 ;
2022-09-21 19:33:14 +00:00
const buffers = 4 ;
let buf = [ ] ;
return {
2022-11-02 17:02:47 +00:00
refresh : function ( ) {
2023-05-16 16:15:52 +00:00
return ( Math . abs ( lastDrawnValue - compassDataSource . getCourse ( ) ) > 2 ) ;
2022-11-02 17:02:47 +00:00
} ,
2022-09-21 19:33:14 +00:00
draw : function ( graphics , x , y , height , width ) {
const max = 180 ;
const increment = width / max ;
graphics . clearRect ( x , y , x + width , y + height ) ;
2022-11-02 17:02:47 +00:00
lastDrawnValue = compassDataSource . getCourse ( ) ;
var start = lastDrawnValue - 90 ;
if ( isNaN ( lastDrawnValue ) ) start = - 90 ;
2022-09-21 19:33:14 +00:00
if ( start < 0 ) start += 360 ;
start = start % 360 ;
2022-10-13 17:43:56 +00:00
if ( WIDGETS . gpstrek . getState ( ) . acc && compassDataSource . getCourseType ( ) == "MAG" ) {
2022-09-21 19:33:14 +00:00
drawCompass ( graphics , 0 , y + width * 0.05 , height - width * 0.05 , width , increment , start ) ;
} else {
drawCompass ( graphics , 0 , y , height , width , increment , start ) ;
}
if ( compassDataSource . getPoints ) {
2022-12-04 20:13:10 +00:00
let points = compassDataSource . getPoints ( ) ; //storing this in a variable works around a minifier bug causing a problem in the next line: for(let a of a.getPoints())
for ( let p of points ) {
2022-11-05 20:45:51 +00:00
g . reset ( ) ;
2022-11-02 17:02:47 +00:00
var bpos = p . bearing - lastDrawnValue ;
2022-09-21 19:33:14 +00:00
if ( bpos > 180 ) bpos -= 360 ;
if ( bpos < - 180 ) bpos += 360 ;
bpos += 120 ;
let min = 0 ;
let max = 180 ;
if ( bpos <= min ) {
bpos = Math . floor ( width * 0.05 ) ;
} else if ( bpos >= max ) {
bpos = Math . ceil ( width * 0.95 ) ;
} else {
bpos = Math . round ( bpos * increment ) ;
}
2022-11-03 20:24:51 +00:00
if ( p . color ) {
graphics . setColor ( p . color ) ;
}
if ( p . icon ) {
graphics . drawImage ( p . icon , bpos , y + height - 12 , { rotate : 0 , scale : 2 } ) ;
} else {
graphics . fillCircle ( bpos , y + height - 12 , Math . floor ( width * 0.03 ) ) ;
}
2022-09-21 19:33:14 +00:00
}
}
if ( compassDataSource . getMarkers ) {
2022-12-04 20:13:10 +00:00
let markers = compassDataSource . getMarkers ( ) ; //storing this in a variable works around a minifier bug causing a problem in the next line: for(let a of a.getMarkers())
for ( let m of markers ) {
2022-11-05 20:45:51 +00:00
g . reset ( ) ;
2022-09-21 19:33:14 +00:00
g . setColor ( m . fillcolor ) ;
let mpos = m . xpos * width ;
if ( m . xpos < 0.05 ) mpos = Math . floor ( width * 0.05 ) ;
if ( m . xpos > 0.95 ) mpos = Math . ceil ( width * 0.95 ) ;
g . fillPoly ( triangle ( mpos , y + height - m . height , m . height , m . width ) ) ;
g . setColor ( m . linecolor ) ;
g . drawPoly ( triangle ( mpos , y + height - m . height , m . height , m . width ) , true ) ;
}
}
graphics . setColor ( g . theme . fg ) ;
graphics . fillRect ( x , y , Math . floor ( width * 0.05 ) , y + height ) ;
graphics . fillRect ( Math . ceil ( width * 0.95 ) , y , width , y + height ) ;
2022-10-13 17:43:56 +00:00
if ( WIDGETS . gpstrek . getState ( ) . acc && compassDataSource . getCourseType ( ) == "MAG" ) {
let xh = E . clip ( width * 0.5 - height / 2 + ( ( ( WIDGETS . gpstrek . getState ( ) . acc . x + 1 ) / 2 ) * height ) , width * 0.5 - height / 2 , width * 0.5 + height / 2 ) ;
let yh = E . clip ( y + ( ( ( WIDGETS . gpstrek . getState ( ) . acc . y + 1 ) / 2 ) * height ) , y , y + height ) ;
2022-09-21 19:33:14 +00:00
graphics . fillRect ( width * 0.5 - height / 2 , y , width * 0.5 + height / 2 , y + Math . floor ( width * 0.05 ) ) ;
graphics . setColor ( g . theme . bg ) ;
graphics . drawLine ( width * 0.5 - 5 , y , width * 0.5 - 5 , y + Math . floor ( width * 0.05 ) ) ;
graphics . drawLine ( width * 0.5 + 5 , y , width * 0.5 + 5 , y + Math . floor ( width * 0.05 ) ) ;
graphics . fillRect ( xh - 1 , y , xh + 1 , y + Math . floor ( width * 0.05 ) ) ;
let left = Math . floor ( width * 0.05 ) ;
let right = Math . ceil ( width * 0.95 ) ;
graphics . drawLine ( 0 , y + height / 2 - 5 , left , y + height / 2 - 5 ) ;
graphics . drawLine ( right , y + height / 2 - 5 , x + width , y + height / 2 - 5 ) ;
graphics . drawLine ( 0 , y + height / 2 + 5 , left , y + height / 2 + 5 ) ;
graphics . drawLine ( right , y + height / 2 + 5 , x + width , y + height / 2 + 5 ) ;
graphics . fillRect ( 0 , yh - 1 , left , yh + 1 ) ;
graphics . fillRect ( right , yh - 1 , x + width , yh + 1 ) ;
}
graphics . setColor ( g . theme . fg ) ;
graphics . drawRect ( Math . floor ( width * 0.05 ) , y , Math . ceil ( width * 0.95 ) , y + height ) ;
}
} ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let radians = function ( a ) {
2022-09-21 19:33:14 +00:00
return a * Math . PI / 180 ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let degrees = function ( a ) {
let d = a * 180 / Math . PI ;
2022-09-21 19:33:14 +00:00
return ( d + 360 ) % 360 ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let bearing = function ( a , b ) {
2022-09-21 19:33:14 +00:00
if ( ! a || ! b || ! a . lon || ! a . lat || ! b . lon || ! b . lat ) return Infinity ;
2022-10-13 17:43:56 +00:00
let delta = radians ( b . lon - a . lon ) ;
let alat = radians ( a . lat ) ;
let blat = radians ( b . lat ) ;
let y = Math . sin ( delta ) * Math . cos ( blat ) ;
let x = Math . cos ( alat ) * Math . sin ( blat ) -
2022-09-21 19:33:14 +00:00
Math . sin ( alat ) * Math . cos ( blat ) * Math . cos ( delta ) ;
return Math . round ( degrees ( Math . atan2 ( y , x ) ) ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let distance = function ( a , b ) {
2022-09-21 19:33:14 +00:00
if ( ! a || ! b || ! a . lon || ! a . lat || ! b . lon || ! b . lat ) return Infinity ;
2022-10-13 17:43:56 +00:00
let x = radians ( a . lon - b . lon ) * Math . cos ( radians ( ( a . lat + b . lat ) / 2 ) ) ;
let y = radians ( b . lat - a . lat ) ;
2022-09-21 19:33:14 +00:00
return Math . round ( Math . sqrt ( x * x + y * y ) * 6371000 ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-11-01 23:09:34 +00:00
let getAveragedCompass = function ( ) {
return Math . round ( WIDGETS . gpstrek . getState ( ) . avgComp ) ;
} ;
2022-10-13 17:43:56 +00:00
let triangle = function ( x , y , width , height ) {
2022-09-21 19:33:14 +00:00
return [
Math . round ( x ) , Math . round ( y ) ,
Math . round ( x + width * 0.5 ) , Math . round ( y + height ) ,
Math . round ( x - width * 0.5 ) , Math . round ( y + height )
] ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let onSwipe = function ( dir ) {
2022-10-19 19:04:46 +00:00
if ( dir < 0 ) {
nextScreen ( ) ;
} else if ( dir > 0 ) {
switchMenu ( ) ;
} else {
nextScreen ( ) ;
}
2022-10-13 17:43:56 +00:00
} ;
2022-10-19 19:04:46 +00:00
2022-10-13 17:43:56 +00:00
let setButtons = function ( ) {
2022-10-19 19:04:46 +00:00
let options = {
mode : "custom" ,
2022-10-21 15:04:53 +00:00
swipe : onSwipe ,
btn : nextScreen ,
touch : nextScreen
2022-10-19 19:04:46 +00:00
} ;
Bangle . setUI ( options ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let getApproxFileSize = function ( name ) {
2022-09-21 19:33:14 +00:00
let currentStart = STORAGE . getStats ( ) . totalBytes ;
let currentSize = 0 ;
for ( let i = currentStart ; i > 500 ; i /= 2 ) {
let currentDiff = i ;
//print("Searching", currentDiff);
while ( STORAGE . read ( name , currentSize + currentDiff , 1 ) == "" ) {
//print("Loop", currentDiff);
currentDiff = Math . ceil ( currentDiff / 2 ) ;
}
i = currentDiff * 2 ;
currentSize += currentDiff ;
}
return currentSize ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let parseRouteData = function ( filename , progressMonitor ) {
2022-09-21 19:33:14 +00:00
let routeInfo = { } ;
routeInfo . filename = filename ;
routeInfo . refs = [ ] ;
let c = { } ;
let scanOffset = 0 ;
routeInfo . length = 0 ;
routeInfo . count = 0 ;
routeInfo . mirror = false ;
let lastSeenWaypoint ;
let lastSeenAlt ;
let waypoint = { } ;
routeInfo . up = 0 ;
routeInfo . down = 0 ;
2023-05-12 08:13:01 +00:00
2022-09-21 19:33:14 +00:00
let size = getApproxFileSize ( filename ) ;
while ( ( scanOffset = getEntry ( filename , scanOffset , waypoint ) ) > 0 ) {
if ( routeInfo . count % 5 == 0 ) progressMonitor ( scanOffset , "Loading" , size ) ;
if ( lastSeenWaypoint ) {
routeInfo . length += distance ( lastSeenWaypoint , waypoint ) ;
let diff = waypoint . alt - lastSeenAlt ;
//print("Distance", routeInfo.length, "alt", lastSeenAlt, waypoint.alt, diff);
if ( waypoint . alt && lastSeenAlt && diff > 3 ) {
if ( lastSeenAlt < waypoint . alt ) {
//print("Up", diff);
routeInfo . up += diff ;
} else {
//print("Down", diff);
routeInfo . down += diff ;
}
}
}
routeInfo . count ++ ;
routeInfo . refs . push ( waypoint . fileOffset ) ;
lastSeenWaypoint = waypoint ;
if ( ! isNaN ( waypoint . alt ) ) lastSeenAlt = waypoint . alt ;
waypoint = { } ;
}
set ( routeInfo , 0 ) ;
return routeInfo ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2023-05-14 13:37:54 +00:00
let hasPrev = function ( route , index ) {
if ( ! index ) index = route . index ;
2022-09-21 19:33:14 +00:00
if ( route . mirror ) return route . index < ( route . count - 1 ) ;
return route . index > 0 ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2023-05-14 13:37:54 +00:00
let hasNext = function ( route , index ) {
if ( ! index ) index = route . index ;
2022-09-21 19:33:14 +00:00
if ( route . mirror ) return route . index > 0 ;
2023-05-14 20:38:40 +00:00
return index < ( route . count - 1 ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2023-05-14 13:37:54 +00:00
let getNext = function ( route , index ) {
if ( ! index ) index = route . index ;
if ( ! hasNext ( route , index ) ) return ;
if ( route . mirror ) -- index ;
if ( ! route . mirror ) ++ index ;
let result = { } ;
getEntry ( route . filename , route . refs [ index ] , result ) ;
return result ;
} ;
2023-05-16 17:48:30 +00:00
let getPrev = function ( route , index ) {
if ( ! index ) index = route . index ;
if ( ! hasPrev ( route , index ) ) return ;
if ( route . mirror ) ++ index ;
if ( ! route . mirror ) -- index ;
let result = { } ;
getEntry ( route . filename , route . refs [ index ] , result ) ;
return result ;
} ;
2022-10-13 17:43:56 +00:00
let next = function ( route ) {
2022-09-21 19:33:14 +00:00
if ( ! hasNext ( route ) ) return ;
if ( route . mirror ) set ( route , -- route . index ) ;
if ( ! route . mirror ) set ( route , ++ route . index ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let set = function ( route , index ) {
2023-05-16 17:48:30 +00:00
if ( ! route ) return ;
2022-09-21 19:33:14 +00:00
route . currentWaypoint = { } ;
route . index = index ;
getEntry ( route . filename , route . refs [ index ] , route . currentWaypoint ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let prev = function ( route ) {
2022-09-21 19:33:14 +00:00
if ( ! hasPrev ( route ) ) return ;
if ( route . mirror ) set ( route , ++ route . index ) ;
if ( ! route . mirror ) set ( route , -- route . index ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
let lastMirror ;
let cachedLast ;
2022-10-13 17:43:56 +00:00
let getLast = function ( route ) {
2022-09-21 19:33:14 +00:00
let wp = { } ;
if ( lastMirror != route . mirror ) {
if ( route . mirror ) getEntry ( route . filename , route . refs [ 0 ] , wp ) ;
if ( ! route . mirror ) getEntry ( route . filename , route . refs [ route . count - 1 ] , wp ) ;
lastMirror = route . mirror ;
cachedLast = wp ;
}
return cachedLast ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let removeMenu = function ( ) {
2022-09-21 19:33:14 +00:00
E . showMenu ( ) ;
switchNav ( ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let showProgress = function ( progress , title , max ) {
2022-09-21 19:33:14 +00:00
//print("Progress",progress,max)
let message = title ? title : "Loading" ;
if ( max ) {
message += " " + E . clip ( ( progress / max * 100 ) , 0 , 100 ) . toFixed ( 0 ) + "%" ;
} else {
let dots = progress % 4 ;
for ( let i = 0 ; i < dots ; i ++ ) message += "." ;
for ( let i = dots ; i < 4 ; i ++ ) message += " " ;
}
E . showMessage ( message ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let handleLoading = function ( c ) {
2022-09-21 19:33:14 +00:00
E . showMenu ( ) ;
2022-10-13 17:43:56 +00:00
WIDGETS . gpstrek . getState ( ) . route = parseRouteData ( c , showProgress ) ;
WIDGETS . gpstrek . getState ( ) . waypoint = null ;
WIDGETS . gpstrek . getState ( ) . route . mirror = false ;
2022-10-21 15:04:53 +00:00
removeMenu ( ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let showRouteSelector = function ( ) {
2022-10-21 15:04:53 +00:00
var menu = {
2022-09-21 19:33:14 +00:00
"" : {
back : showRouteMenu ,
}
} ;
2022-11-02 21:50:00 +00:00
STORAGE . list ( /\.trf$/ ) . forEach ( ( file ) => {
2023-05-12 08:13:01 +00:00
menu [ file ] = ( ) => { handleLoading ( file ) ; } ;
2022-11-02 21:50:00 +00:00
} ) ;
2022-09-21 19:33:14 +00:00
E . showMenu ( menu ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let showRouteMenu = function ( ) {
2022-10-21 15:04:53 +00:00
var menu = {
2022-09-21 19:33:14 +00:00
"" : {
"title" : "Route" ,
back : showMenu ,
} ,
"Select file" : showRouteSelector
} ;
2022-10-13 17:43:56 +00:00
if ( WIDGETS . gpstrek . getState ( ) . route ) {
2022-09-21 19:33:14 +00:00
menu . Mirror = {
2022-10-13 17:43:56 +00:00
value : WIDGETS . gpstrek . getState ( ) && WIDGETS . gpstrek . getState ( ) . route && ! ! WIDGETS . gpstrek . getState ( ) . route . mirror || false ,
2022-09-21 19:33:14 +00:00
onchange : v => {
2022-10-13 17:43:56 +00:00
WIDGETS . gpstrek . getState ( ) . route . mirror = v ;
2022-09-21 19:33:14 +00:00
}
} ;
menu [ 'Select closest waypoint' ] = function ( ) {
2022-10-13 17:43:56 +00:00
if ( WIDGETS . gpstrek . getState ( ) . currentPos && WIDGETS . gpstrek . getState ( ) . currentPos . lat ) {
setClosestWaypoint ( WIDGETS . gpstrek . getState ( ) . route , null , showProgress ) ; removeMenu ( ) ;
2022-09-21 19:33:14 +00:00
} else {
E . showAlert ( "No position" ) . then ( ( ) => { E . showMenu ( menu ) ; } ) ;
}
} ;
menu [ 'Select closest waypoint (not visited)' ] = function ( ) {
2022-10-13 17:43:56 +00:00
if ( WIDGETS . gpstrek . getState ( ) . currentPos && WIDGETS . gpstrek . getState ( ) . currentPos . lat ) {
setClosestWaypoint ( WIDGETS . gpstrek . getState ( ) . route , WIDGETS . gpstrek . getState ( ) . route . index , showProgress ) ; removeMenu ( ) ;
2022-09-21 19:33:14 +00:00
} else {
E . showAlert ( "No position" ) . then ( ( ) => { E . showMenu ( menu ) ; } ) ;
}
} ;
menu [ 'Select waypoint' ] = {
2022-10-13 17:43:56 +00:00
value : WIDGETS . gpstrek . getState ( ) . route . index ,
min : 1 , max : WIDGETS . gpstrek . getState ( ) . route . count , step : 1 ,
2022-10-21 15:04:53 +00:00
onchange : v => { set ( WIDGETS . gpstrek . getState ( ) . route , v - 1 ) ; }
2022-09-21 19:33:14 +00:00
} ;
menu [ 'Select waypoint as current position' ] = function ( ) {
2022-10-13 17:43:56 +00:00
WIDGETS . gpstrek . getState ( ) . currentPos . lat = WIDGETS . gpstrek . getState ( ) . route . currentWaypoint . lat ;
WIDGETS . gpstrek . getState ( ) . currentPos . lon = WIDGETS . gpstrek . getState ( ) . route . currentWaypoint . lon ;
WIDGETS . gpstrek . getState ( ) . currentPos . alt = WIDGETS . gpstrek . getState ( ) . route . currentWaypoint . alt ;
2022-09-21 19:33:14 +00:00
removeMenu ( ) ;
} ;
}
2022-10-13 17:43:56 +00:00
if ( WIDGETS . gpstrek . getState ( ) . route && hasPrev ( WIDGETS . gpstrek . getState ( ) . route ) )
2022-10-21 15:04:53 +00:00
menu [ 'Previous waypoint' ] = function ( ) { prev ( WIDGETS . gpstrek . getState ( ) . route ) ; removeMenu ( ) ; } ;
2022-10-13 17:43:56 +00:00
if ( WIDGETS . gpstrek . getState ( ) . route && hasNext ( WIDGETS . gpstrek . getState ( ) . route ) )
2022-10-21 15:04:53 +00:00
menu [ 'Next waypoint' ] = function ( ) { next ( WIDGETS . gpstrek . getState ( ) . route ) ; removeMenu ( ) ; } ;
2022-09-21 19:33:14 +00:00
E . showMenu ( menu ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let showWaypointSelector = function ( ) {
2022-09-21 19:33:14 +00:00
let waypoints = require ( "waypoints" ) . load ( ) ;
2022-10-21 15:04:53 +00:00
var menu = {
2022-09-21 19:33:14 +00:00
"" : {
back : showWaypointMenu ,
}
} ;
2022-11-02 21:23:37 +00:00
waypoints . forEach ( ( wp , c ) => {
2022-09-21 19:33:14 +00:00
menu [ waypoints [ c ] . name ] = function ( ) {
2022-10-21 15:04:53 +00:00
WIDGETS . gpstrek . getState ( ) . waypoint = waypoints [ c ] ;
WIDGETS . gpstrek . getState ( ) . waypointIndex = c ;
WIDGETS . gpstrek . getState ( ) . route = null ;
2022-09-21 19:33:14 +00:00
removeMenu ( ) ;
} ;
2022-11-02 21:23:37 +00:00
} ) ;
2022-09-21 19:33:14 +00:00
E . showMenu ( menu ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let showCalibrationMenu = function ( ) {
2022-09-21 19:33:14 +00:00
let menu = {
"" : {
"title" : "Calibration" ,
back : showMenu ,
} ,
"Barometer (GPS)" : ( ) => {
2022-10-13 17:43:56 +00:00
if ( ! WIDGETS . gpstrek . getState ( ) . currentPos || isNaN ( WIDGETS . gpstrek . getState ( ) . currentPos . alt ) ) {
2022-09-21 19:33:14 +00:00
E . showAlert ( "No GPS altitude" ) . then ( ( ) => { E . showMenu ( menu ) ; } ) ;
} else {
2022-10-13 17:43:56 +00:00
WIDGETS . gpstrek . getState ( ) . calibAltDiff = WIDGETS . gpstrek . getState ( ) . altitude - WIDGETS . gpstrek . getState ( ) . currentPos . alt ;
E . showAlert ( "Calibrated Altitude Difference: " + WIDGETS . gpstrek . getState ( ) . calibAltDiff . toFixed ( 0 ) ) . then ( ( ) => { removeMenu ( ) ; } ) ;
2022-09-21 19:33:14 +00:00
}
} ,
"Barometer (Manual)" : {
2022-10-13 17:43:56 +00:00
value : Math . round ( WIDGETS . gpstrek . getState ( ) . currentPos && ( WIDGETS . gpstrek . getState ( ) . currentPos . alt != undefined && ! isNaN ( WIDGETS . gpstrek . getState ( ) . currentPos . alt ) ) ? WIDGETS . gpstrek . getState ( ) . currentPos . alt : WIDGETS . gpstrek . getState ( ) . altitude ) ,
2022-09-21 19:33:14 +00:00
min : - 2000 , max : 10000 , step : 1 ,
2022-10-21 15:04:53 +00:00
onchange : v => { WIDGETS . gpstrek . getState ( ) . calibAltDiff = WIDGETS . gpstrek . getState ( ) . altitude - v ; }
2022-09-21 19:33:14 +00:00
} ,
"Reset Compass" : ( ) => { Bangle . resetCompass ( ) ; removeMenu ( ) ; } ,
} ;
E . showMenu ( menu ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let showWaypointMenu = function ( ) {
2022-09-21 19:33:14 +00:00
let menu = {
"" : {
"title" : "Waypoint" ,
back : showMenu ,
} ,
"Select waypoint" : showWaypointSelector ,
} ;
E . showMenu ( menu ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let showBackgroundMenu = function ( ) {
2022-10-13 18:36:47 +00:00
let menu = {
"" : {
"title" : "Background" ,
back : showMenu ,
} ,
2022-10-13 17:43:56 +00:00
"Start" : ( ) => { E . showPrompt ( "Start?" ) . then ( ( v ) => { if ( v ) { WIDGETS . gpstrek . start ( true ) ; removeMenu ( ) ; } else { showMenu ( ) ; } } ) . catch ( ( ) => { showMenu ( ) ; } ) ; } ,
"Stop" : ( ) => { E . showPrompt ( "Stop?" ) . then ( ( v ) => { if ( v ) { WIDGETS . gpstrek . stop ( true ) ; removeMenu ( ) ; } else { showMenu ( ) ; } } ) . catch ( ( ) => { showMenu ( ) ; } ) ; } ,
2022-10-13 18:36:47 +00:00
} ;
E . showMenu ( menu ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-10-13 18:36:47 +00:00
2022-10-13 17:43:56 +00:00
let showMenu = function ( ) {
2022-10-21 15:04:53 +00:00
var mainmenu = {
2022-09-21 19:33:14 +00:00
"" : {
"title" : "Main" ,
back : removeMenu ,
} ,
"Route" : showRouteMenu ,
"Waypoint" : showWaypointMenu ,
2022-10-13 18:36:47 +00:00
"Background" : showBackgroundMenu ,
2022-09-21 19:33:14 +00:00
"Calibration" : showCalibrationMenu ,
2022-10-21 15:04:53 +00:00
"Reset" : ( ) => { E . showPrompt ( "Do Reset?" ) . then ( ( v ) => { if ( v ) { WIDGETS . gpstrek . resetState ( ) ; removeMenu ( ) ; } else { E . showMenu ( mainmenu ) ; } } ) . catch ( ( ) => { E . showMenu ( mainmenu ) ; } ) ; } ,
2022-10-30 17:31:31 +00:00
"Info rows" : {
2022-10-13 17:43:56 +00:00
value : WIDGETS . gpstrek . getState ( ) . numberOfSlices ,
2022-09-21 19:33:14 +00:00
min : 1 , max : 6 , step : 1 ,
2022-10-21 15:04:53 +00:00
onchange : v => { WIDGETS . gpstrek . getState ( ) . numberOfSlices = v ; }
2022-09-21 19:33:14 +00:00
} ,
} ;
E . showMenu ( mainmenu ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let switchMenu = function ( ) {
2022-10-21 15:04:53 +00:00
stopDrawing ( ) ;
2022-10-13 17:43:56 +00:00
showMenu ( ) ;
} ;
2022-09-21 19:33:14 +00:00
2022-10-21 15:04:53 +00:00
let stopDrawing = function ( ) {
if ( drawTimeout ) clearTimeout ( drawTimeout ) ;
scheduleDraw = false ;
} ;
2022-10-13 17:43:56 +00:00
let drawInTimeout = function ( ) {
if ( global . drawTimeout ) clearTimeout ( drawTimeout ) ;
drawTimeout = setTimeout ( ( ) => {
drawTimeout = undefined ;
2022-09-21 19:33:14 +00:00
draw ( ) ;
2023-05-17 21:47:57 +00:00
} , 250 ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let switchNav = function ( ) {
2022-09-21 19:33:14 +00:00
if ( ! screen ) screen = 1 ;
setButtons ( ) ;
scheduleDraw = true ;
2022-10-21 15:04:53 +00:00
firstDraw = true ;
2022-09-21 19:33:14 +00:00
drawInTimeout ( ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let nextScreen = function ( ) {
2022-09-21 19:33:14 +00:00
screen ++ ;
if ( screen > maxScreens ) {
screen = 1 ;
}
2022-10-13 17:43:56 +00:00
drawInTimeout ( ) ;
} ;
2022-09-21 19:33:14 +00:00
2022-10-13 17:43:56 +00:00
let setClosestWaypoint = function ( route , startindex , progress ) {
if ( startindex >= WIDGETS . gpstrek . getState ( ) . route . count ) startindex = WIDGETS . gpstrek . getState ( ) . route . count - 1 ;
if ( ! WIDGETS . gpstrek . getState ( ) . currentPos . lat ) {
2022-09-21 19:33:14 +00:00
set ( route , startindex ) ;
return ;
}
let minDist = 100000000000000 ;
let minIndex = 0 ;
for ( let i = startindex ? startindex : 0 ; i < route . count - 1 ; i ++ ) {
if ( progress && ( i % 5 == 0 ) ) progress ( i - ( startindex ? startindex : 0 ) , "Searching" , route . count ) ;
let wp = { } ;
getEntry ( route . filename , route . refs [ i ] , wp ) ;
2022-10-13 17:43:56 +00:00
let curDist = distance ( WIDGETS . gpstrek . getState ( ) . currentPos , wp ) ;
2022-09-21 19:33:14 +00:00
if ( curDist < minDist ) {
minDist = curDist ;
minIndex = i ;
} else {
if ( startindex ) break ;
}
}
set ( route , minIndex ) ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
2022-11-03 20:24:51 +00:00
const finishIcon = atob ( "CggB//meZmeZ+Z5n/w==" ) ;
2022-09-21 19:33:14 +00:00
const waypointData = {
icon : atob ( "EBCBAAAAAAAAAAAAcIB+zg/uAe4AwACAAAAAAAAAAAAAAAAA" ) ,
getProgress : function ( ) {
2022-10-13 17:43:56 +00:00
return ( WIDGETS . gpstrek . getState ( ) . route . index + 1 ) + "/" + WIDGETS . gpstrek . getState ( ) . route . count ;
2022-09-21 19:33:14 +00:00
} ,
getTarget : function ( ) {
2022-10-13 17:43:56 +00:00
return WIDGETS . gpstrek . getState ( ) . route . currentWaypoint ;
2022-09-21 19:33:14 +00:00
} ,
getStart : function ( ) {
2022-10-13 17:43:56 +00:00
return WIDGETS . gpstrek . getState ( ) . currentPos ;
2022-09-21 19:33:14 +00:00
}
} ;
const finishData = {
icon : atob ( "EBABAAA/4DmgJmAmYDmgOaAmYD/gMAAwADAAMAAwAAAAAAA=" ) ,
getTarget : function ( ) {
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
if ( s . route ) return getLast ( s . route ) ;
if ( s . waypoint ) return s . waypoint ;
2022-09-21 19:33:14 +00:00
} ,
getStart : function ( ) {
2022-10-13 17:43:56 +00:00
return WIDGETS . gpstrek . getState ( ) . currentPos ;
2022-09-21 19:33:14 +00:00
}
} ;
2022-10-13 17:43:56 +00:00
let getSliceHeight = function ( number ) {
return Math . floor ( Bangle . appRect . h / WIDGETS . gpstrek . getState ( ) . numberOfSlices ) ;
} ;
2022-09-21 19:33:14 +00:00
2023-05-18 14:50:45 +00:00
let compassSlice = getCompassSlice ( ) ;
2023-05-16 16:49:05 +00:00
let mapSlice = getMapSlice ( ) ;
2022-09-21 19:33:14 +00:00
let waypointSlice = getTargetSlice ( waypointData ) ;
let finishSlice = getTargetSlice ( finishData ) ;
let eleSlice = getDoubleLineSlice ( "Up" , "Down" , ( ) => {
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
return loc . distance ( s . up , 3 ) + "/" + ( s . route ? loc . distance ( s . route . up , 3 ) : "---" ) ;
2022-09-21 19:33:14 +00:00
} , ( ) => {
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
return loc . distance ( s . down , 3 ) + "/" + ( s . route ? loc . distance ( s . route . down , 3 ) : "---" ) ;
2022-09-21 19:33:14 +00:00
} ) ;
let statusSlice = getDoubleLineSlice ( "Speed" , "Alt" , ( ) => {
let speed = 0 ;
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
if ( s . currentPos && s . currentPos . speed ) speed = s . currentPos . speed ;
2022-09-21 19:33:14 +00:00
return loc . speed ( speed , 2 ) ;
} , ( ) => {
let alt = Infinity ;
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
if ( ! isNaN ( s . altitude ) ) {
alt = isNaN ( s . calibAltDiff ) ? s . altitude : ( s . altitude - s . calibAltDiff ) ;
2022-09-21 19:33:14 +00:00
}
2023-05-16 16:49:05 +00:00
if ( s . currentPos && s . currentPos . alt ) alt = s . currentPos . alt ;
2022-10-13 17:43:56 +00:00
if ( isNaN ( alt ) ) return "---" ;
2022-09-21 19:33:14 +00:00
return loc . distance ( alt , 3 ) ;
} ) ;
let status2Slice = getDoubleLineSlice ( "Compass" , "GPS" , ( ) => {
2022-11-01 23:09:34 +00:00
return getAveragedCompass ( ) + "°" ;
2022-09-21 19:33:14 +00:00
} , ( ) => {
let course = "---°" ;
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
if ( s . currentPos && s . currentPos . course ) course = s . currentPos . course + "°" ;
2022-09-21 19:33:14 +00:00
return course ;
2023-05-16 16:15:52 +00:00
} ) ;
2022-09-21 19:33:14 +00:00
let healthSlice = getDoubleLineSlice ( "Heart" , "Steps" , ( ) => {
2022-10-13 17:43:56 +00:00
return WIDGETS . gpstrek . getState ( ) . bpm || "---" ;
2022-09-21 19:33:14 +00:00
} , ( ) => {
2022-10-21 15:04:53 +00:00
return ! isNaN ( WIDGETS . gpstrek . getState ( ) . steps ) ? WIDGETS . gpstrek . getState ( ) . steps : "---" ;
2022-09-21 19:33:14 +00:00
} ) ;
let system2Slice = getDoubleLineSlice ( "Bat" , "" , ( ) => {
2022-11-01 23:31:06 +00:00
return ( Bangle . isCharging ( ) ? "+" : "" ) + E . getBattery ( ) . toFixed ( 0 ) + "% " + ( analogRead ( D3 ) * 4.2 / BAT _FULL ) . toFixed ( 2 ) + "V" ;
2022-09-21 19:33:14 +00:00
} , ( ) => {
return "" ;
} ) ;
let systemSlice = getDoubleLineSlice ( "RAM" , "Storage" , ( ) => {
let ram = process . memory ( false ) ;
return ( ( ram . blocksize * ram . free ) / 1024 ) . toFixed ( 0 ) + "kB" ;
} , ( ) => {
return ( STORAGE . getFree ( ) / 1024 ) . toFixed ( 0 ) + "kB" ;
} ) ;
2022-10-13 17:43:56 +00:00
let clear = function ( ) {
g . clearRect ( Bangle . appRect ) ;
} ;
2022-09-21 19:33:14 +00:00
2023-05-12 08:19:23 +00:00
let minimumDistance = Number . MAX _VALUE ;
let lastSearch = 0 ;
let updateRouting = function ( ) {
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
if ( s . route && s . currentPos . lat ) {
let currentDistanceToTarget = distance ( s . currentPos , s . route . currentWaypoint ) ;
2023-05-12 08:19:23 +00:00
if ( currentDistanceToTarget < minimumDistance ) {
minimumDistance = currentDistanceToTarget ;
}
2023-05-16 16:49:05 +00:00
let nextAvailable = hasNext ( s . route ) ;
2023-05-12 08:19:23 +00:00
if ( currentDistanceToTarget < 30 && nextAvailable ) {
2023-05-16 16:49:05 +00:00
next ( s . route ) ;
2023-05-12 08:19:23 +00:00
minimumDistance = Number . MAX _VALUE ;
} else if ( lastSearch + 15000 < Date . now ( ) && minimumDistance < currentDistanceToTarget - 30 ) {
stopDrawing ( ) ;
Bangle . buzz ( 1000 ) ;
2023-05-16 16:49:05 +00:00
setClosestWaypoint ( s . route , s . route . index , showProgress ) ;
2023-05-12 08:19:23 +00:00
minimumDistance = Number . MAX _VALUE ;
lastSearch = Date . now ( ) ;
switchNav ( ) ;
}
}
} ;
2023-05-18 19:40:20 +00:00
let updateSlices = function ( ) {
let s = WIDGETS . gpstrek . getState ( ) ;
slices = [ ] ;
if ( s . currentPos && s . currentPos . lat && s . route && s . route . currentWaypoint && s . route . index < s . route . count - 1 ) {
slices . push ( waypointSlice ) ;
}
if ( s . currentPos && s . currentPos . lat && ( s . route || s . waypoint ) ) {
slices . push ( finishSlice ) ;
}
if ( ( s . route && s . route . down !== undefined ) || s . down != undefined ) {
slices . push ( eleSlice ) ;
}
slices . push ( statusSlice ) ;
slices . push ( status2Slice ) ;
slices . push ( healthSlice ) ;
slices . push ( systemSlice ) ;
slices . push ( system2Slice ) ;
maxScreens = Math . ceil ( slices . length / s . numberOfSlices ) + 1 ;
} ;
2022-10-13 17:43:56 +00:00
let draw = function ( ) {
if ( ! global . screen ) return ;
let ypos = Bangle . appRect . y ;
2023-05-16 16:49:05 +00:00
let s = WIDGETS . gpstrek . getState ( ) ;
2022-09-21 19:33:14 +00:00
2023-05-18 19:40:20 +00:00
let firstSlice = ( screen - 2 ) * s . numberOfSlices ;
2022-09-21 19:33:14 +00:00
let force = lastDrawnScreen != screen || firstDraw ;
if ( force ) {
clear ( ) ;
2022-11-05 22:45:40 +00:00
}
2022-10-13 17:43:56 +00:00
if ( firstDraw ) Bangle . drawWidgets ( ) ;
2022-09-21 19:33:14 +00:00
lastDrawnScreen = screen ;
2023-05-18 19:40:20 +00:00
updateSlices ( ) ;
2022-09-21 19:33:14 +00:00
2023-05-18 19:40:20 +00:00
if ( global . screen == 1 ) {
let split = s . route ? ( Bangle . appRect . h / 4 ) : Bangle . appRect . h ;
2023-05-18 21:36:43 +00:00
g . reset ( ) ;
2023-05-18 19:40:20 +00:00
compassSlice . draw ( g , Bangle . appRect . x , ypos , split , Bangle . appRect . w ) ;
ypos += split + 1 ;
2023-05-18 21:36:43 +00:00
if ( s . route ) {
g . reset ( ) ;
mapSlice . draw ( g , 0 , ypos , Bangle . appRect . h - split , Bangle . appRect . w ) ;
}
2023-05-18 19:40:20 +00:00
} else {
let sliceHeight = getSliceHeight ( ) ;
let slicesToDraw = slices . slice ( firstSlice , firstSlice + s . numberOfSlices ) ;
for ( let slice of slicesToDraw ) {
g . reset ( ) ;
if ( ! slice . refresh || slice . refresh ( ) || force ) slice . draw ( g , 0 , ypos , sliceHeight , g . getWidth ( ) ) ;
ypos += sliceHeight + 1 ;
g . drawLine ( 0 , ypos - 1 , g . getWidth ( ) , ypos - 1 ) ;
}
2022-09-21 19:33:14 +00:00
}
2023-05-12 08:13:01 +00:00
2023-05-12 08:19:23 +00:00
updateRouting ( ) ;
2022-11-05 22:45:40 +00:00
if ( scheduleDraw ) {
drawInTimeout ( ) ;
}
2022-09-21 19:33:14 +00:00
firstDraw = false ;
2022-10-13 17:43:56 +00:00
} ;
2022-09-21 19:33:14 +00:00
switchNav ( ) ;
2022-10-13 17:43:56 +00:00
clear ( ) ;
}
2023-05-12 08:19:23 +00:00