From bd882648f55602c22eb0a2dae8e0741a04313d72 Mon Sep 17 00:00:00 2001 From: Pablo Gonzalez Date: Thu, 28 Jan 2021 18:07:39 +0100 Subject: [PATCH] planetarium --- apps.json | 2 +- apps/intervals/intervals.app.js | 312 +++++++++++------------ apps/planetarium/planetarium-icon.js | 2 +- apps/planetarium/planetarium.app.csv | 30 --- apps/planetarium/planetarium.app.js | 141 +++++++++++ apps/planetarium/planetarium.data.csv | 343 ++++++++++++++++++++++++++ apps/planetarium/planetarium.js | 167 ------------- apps/planetarium/planetarium.png | Bin 2930 -> 1920 bytes 8 files changed, 645 insertions(+), 352 deletions(-) delete mode 100644 apps/planetarium/planetarium.app.csv create mode 100644 apps/planetarium/planetarium.app.js create mode 100644 apps/planetarium/planetarium.data.csv delete mode 100644 apps/planetarium/planetarium.js diff --git a/apps.json b/apps.json index ce523ded8..f4546d95f 100644 --- a/apps.json +++ b/apps.json @@ -2684,7 +2684,7 @@ "tags": "", "storage": [ {"name":"planetarium.app.js","url":"planetarium.app.js"}, - {"name":"planetarium.app.csv","url":"planetarium.app.csv"}, + {"name":"planetarium.data.csv","url":"planetarium.data.csv"}, {"name":"planetarium.img","url":"planetarium-icon.js","evaluate":true} ] } diff --git a/apps/intervals/intervals.app.js b/apps/intervals/intervals.app.js index da436b104..a158ca967 100644 --- a/apps/intervals/intervals.app.js +++ b/apps/intervals/intervals.app.js @@ -1,164 +1,170 @@ -var counter; -var counterInterval; - -var settings; - -var work=false; //true if training false if resting -var prep=true; //true if we are in prep phase (at the beginning of the session -var setNum; - -var paused; - -function endPart() { - g.clear(); - if (prep){ - prep=false; - work = true; - counter = settings.workseg+settings.workmin*60; - startCounter(); - }else if (work){ - work = false; - counter = settings.restseg+settings.restmin*60; - startCounter(); - } - else{ - if (setNum>1) - { - setNum--; - work = true; - counter = settings.workseg+settings.workmin*60; - startCounter(); - } - else - { - //End session - setWatch(showMenu, BTN2); - E.showMessage("Press BTN2 for\ngoing back\nto the menu","Well done!"); - } - } -} - -function printCounter(counter){ - g.setFontAlign(0,0); // center font - g.setFont("Vector",80); // vector font, 80px - // draw the current counter value - let minutes = Math.floor(counter/60); - let segs = counter % 60; - let textMinutes = minutes.toString().padStart(2, "0"); - let textSegs = segs.toString().padStart(2,"0"); - g.clearRect(0,80,239,160); - g.setFont("Vector",30); - if (prep) - g.setColor(125,125,0); - else if (work) - g.setColor(255,0,0); - else - g.setColor(0,255,0); - g.drawString(setNum,120,50); - if (prep) - g.drawString("PREPARATION",120,190); - else if (work) - g.drawString("WORK",120,190); - else - g.drawString("REST",120,190); - g.setFont("Vector",10); - g.drawString("Touch to pause",120,215); - g.setFont("Vector",80); - g.drawString(textMinutes+":"+textSegs,120,120); -} - -function signal_to_user(le){ - if (settings.buzz) - Bangle.buzz(le); - else - Bangle.beep(le,4000); -} - -function countDown() { - counter--; - if (counter<4 && counter>0) - signal_to_user(200); - if (counter==0) - signal_to_user(600); - - if (counter<0) { - clearInterval(counterInterval); - counterInterval = undefined; - endPart(); - } - else - { - printCounter(counter); - } - g.flip(); -} - -function startCounter(){ - if (!counterInterval) - counterInterval = setInterval(countDown, 1000); -} - -function pause() +/* + * Degrees to radians + */ +function toRadians(degrees) { - if (!paused) - { - clearInterval(counterInterval); - counterInterval = undefined; - setWatch(resume,BTN4); - setWatch(resume,BTN5); - paused=true; - g.clear(); - g.setFont("Vector",60); - g.drawString("PAUSED",120,120); - g.setFont("Vector",20); - g.drawString("Touch to continue",120,180); - } + return Math.PI * degrees / 180; } -function resume(){ - if (paused) - { - g.clear(); - counterInterval = setInterval(countDown, 1000); - setWatch(pause,BTN4); - setWatch(pause,BTN5); - paused=false; - } -} - -function startSession() { - E.showMenu(); - paused=false; - setWatch(pause,BTN4); - setWatch(pause,BTN5); - require('Storage').write('intervals.settings.json',settings); - setNum = settings.sets; - counter = 5;//prep time - prep=true; - work=false; - startCounter(); -} - -function showMenu() +/* + * Julian day number + * Assumes a proleptic gregorian calendar where the year 1 is preceded by the + * year 0. + */ +function toJulianDay(year, month, day, hours, minutes, seconds) { - settings = require('Storage').readJSON('intervals.settings.json',1)|| - { sets:1,workseg:10,workmin:0,restseg:5,restmin:0,buzz:true}; + day += hours / 24 + minutes / 1440 + seconds / 86400; + + if(month <= 2) + { + year -= 1; + month += 12; + } + + var A = Math.floor(year / 100); + var B = 2 - A + Math.floor(A / 4); + return Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + B - 1524.5; +} - var mainmenu = { - "" : { "title" : "-- Main Menu --" }, - "START" : function() { startSession(); }, - "Sets" : { value : settings.sets,min:0,max:20,step:1,onchange : v => { settings.sets=v; } }, - "Work minutes" : { value : settings.workmin,min:0,max:59,step:1,onchange : v => { settings.workmin=v; } }, - "Work seconds" : { value : settings.workseg,min:0,max:59,step:5,onchange : v => { settings.workseg=v; } }, - "Rest minutes" : { value : settings.restmin,min:0,max:59,step:1,onchange : v => { settings.restmin=v; } }, - "Rest seconds" : { value : settings.restseg,min:0,max:59,step:5,onchange : v => { settings.restseg=v; } }, - "Signal type" : { value : settings.buzz,format : v => v?"Buzz":"Beep",onchange : v => { settings.buzz=v; }} - }; +/* + * Sidereal time in Greenwich + */ +function siderealTime(julianDay) +{ + var T = (julianDay - 2451545.0) / 36525; + return toRadians(280.46061837 + 360.98564736629 * (julianDay - 2451545.0) + 0.000387933 * T * T - T * T * T / 38710000); +} + +function binary_search(a, value) { + var lo = 0, hi = a.length - 1, mid; + while (lo <= hi) { + mid = Math.floor((lo+hi)/2); + if (a[mid] > value) + hi = mid - 1; + else if (a[mid] < value) + lo = mid + 1; + else + return mid; + } + return null; +} + +function drawStars(lat,lon){ + var longitude = toRadians(-lon); + var latitude = toRadians(lat); - E.showMenu(mainmenu); + date = new Date(); + + var julianDay = toJulianDay(date.getFullYear(), date.getMonth()+1,date.getDate(), + date.getHours() + date.getTimezoneOffset() / 60, + date.getMinutes(), date.getSeconds()); + var size = 240; + + storage = require('Storage'); + f=storage.read("planetarium.csv","r"); + linestart=0; + g.clear(); + + //Common calculations based only on time + var t = (julianDay - 2451545.0) / 36525; + var zeta = toRadians((2306.2181 * t + 0.30188 * t * t + 0.017998 * t * t * t) / 3600); + var theta = toRadians((2004.3109 * t - 0.42665 * t * t - 0.041833 * t * t * t) / 3600); + var z = toRadians((2306.2181 * t + 1.09468 * t * t + 0.018203 * t * t * t) / 3600); + + + let starNumber = 0; + //Each star has a number (the position on the file (line number)). These are the lines + //joining each star in the constellations. + constelation_lines=[/*Orion*/[7,68],[10,53],[53,56],[28,68],/*Taurus*/[13,172],[13,340],[293,340],[29,293], + /*canis menor*/[155,8]]; + var starPositions = {}; + + for (i=0;i= 0) + { + //Compute azimuth + var azi = Math.atan2(Math.sin(H), Math.cos(H) * Math.sin(latitude) - Math.tan(dec) * Math.cos(latitude)); + var x = size / 2 + size / 2 * Math.cos(alt) * Math.sin(azi); + var y = size / 2 + size / 2 * Math.cos(alt) * Math.cos(azi); + starPositions[starNumber] = [x,y]; + var magnitude = starMag<1.5?2:1; + g.fillCircle(x, y, magnitude); + if (starMag<1) + g.drawString(starInfo[3],x,y+2); + g.flip(); + + } + } + } + + for (i=0;iprevSats || prevSats===0){ + prevSats = gp.satellites; + g.clearRect(0,150,240,180); + g.drawString("Got "+gp.satellites+" satellites",120,160); + } + g.flip(); + } +}); + diff --git a/apps/planetarium/planetarium-icon.js b/apps/planetarium/planetarium-icon.js index d901489c2..215c5aa38 100644 --- a/apps/planetarium/planetarium-icon.js +++ b/apps/planetarium/planetarium-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwg96xAWVhGIwAuWGCoXrCIZfFDZkJyAKTAAOZBaojEzIADGBoOChITEAgIUCGBAhCCwIlFA4YwIhIjCDQYtDAoIMBQhgUCzJMDR5xYGFwSPMHwYRED4KPMCQcIxKtHWApoCEYczmYXCPgYAEGgZGCAgMDC4pEGA4gVBGwIWCF6GqhWgC4kqBYYAGGgegC4QWCC4kKI4oQBC4guEC4wJDC4gtBGoIXDmWqBoQMBBQUwIAQXJKopSDJooXGmQRBBwYLBFgR2EC4QAEC4RIDToRQDC56pESYhHDAAYFBA4YvMD4oOEL5bMGaJIQFC5ZiEAoxRCC5I1KJoIXVBYJ4FEYgAGPAwwHSYIAGJAwwHEA5+HB5AvMZI4XKBwu72ELAQIHCAoQCBchQMCAQIADDgIfEDBYRBAAI5DCxYUDAxYYMAAgWPDIoVSAFAA==")) \ No newline at end of file +require("heatshrink").decompress(atob("AEGIAAgVPhAWFAAOACyoYNCxQYMCxZjKFxgwKB42ClAwNFw+O9AwNH48u8RhMLpHu9xhMLg0ipwXBokiMQwXKCoIADC5JGHlwWDMI5ICC44wEVI4XCZxBfC8jzKBRAuCC66oIC4K9IwPuoUk90YYJAXIwVCSYR3HC5WBAgYvPCggAFDQoXGwhAIwVIC5cuBoohDeQoXGpwNFEIbDFC4uCaJL1BKQgXDiVEdQdCB4WCYIIACokhC4uEBgYABC4YJII4kuBgZhEBJAXEEwi3EBIhgDwEABwYuHGAoHDgAXDwIXJRwIXKHoaoGC4ZHDC4JgCC4MoUAIXF91CBgReDC4iwCkh3EwNCZwQXFPAgAPCwQXYYIYAOIwYwTCwgwRFwowRCwwwPFw4wPCxAwNFxIYMCxYYKCxpjICp4AQ")) \ No newline at end of file diff --git a/apps/planetarium/planetarium.app.csv b/apps/planetarium/planetarium.app.csv deleted file mode 100644 index 0f3938e81..000000000 --- a/apps/planetarium/planetarium.app.csv +++ /dev/null @@ -1,30 +0,0 @@ -1.76779,-0.29175,-1.5,AL CMA -1.67531,-0.91971,-0.7,AL CAR -3.73352,0.33480,-0.0,AL BOO -3.83799,-1.06178,-0.0,AL1 CEN -4.87356,0.67690,0.0,AL LYR -1.38181,0.80282,0.1,AL AUR -1.37243,-0.14315,0.1,BE ORI -2.00408,0.09119,0.4,AL CMI -0.42636,-0.99897,0.5,AL ERI -1.54973,0.12928,0.5,AL ORI -3.68187,-1.05370,0.6,BE CEN -5.19577,0.15478,0.8,AL AQL -1.20393,0.28814,0.8,AL TAU -4.31710,-0.46132,1.0,AL SCO -3.51331,-0.19480,1.0,AL VIR -2.03032,0.48915,1.1,BE GEM -6.01113,-0.51701,1.2,AL PSA -3.34982,-1.04176,1.2,BE CRU -5.41676,0.79029,1.2,AL CYG -3.83799,-1.06178,1.3,AL2 CEN -2.65452,0.20887,1.4,AL LEO -1.82660,-0.50566,1.5,EP CMA -1.98356,0.55656,1.6,AL GEM -3.25765,-1.10128,1.6,AL1 CRU -1.98356,0.55656,1.6,AL GEM -3.27758,-0.99681,1.6,GA CRU -4.59723,-0.64758,1.6,LA SCO -1.41865,0.11082,1.6,GA ORI -1.42372,0.49930,1.6,BE TAU -2.41380,-1.21680,1.7,BE CAR \ No newline at end of file diff --git a/apps/planetarium/planetarium.app.js b/apps/planetarium/planetarium.app.js new file mode 100644 index 000000000..3f4c00297 --- /dev/null +++ b/apps/planetarium/planetarium.app.js @@ -0,0 +1,141 @@ +/* + * Degrees to radians + */ +function toRadians(degrees) +{ + return Math.PI * degrees / 180; +} + +/* + * Julian day number + * Assumes a proleptic gregorian calendar where the year 1 is preceded by the + * year 0. + */ +function toJulianDay(year, month, day, hours, minutes, seconds) +{ + day += hours / 24 + minutes / 1440 + seconds / 86400; + + if(month <= 2) + { + year -= 1; + month += 12; + } + + var A = Math.floor(year / 100); + var B = 2 - A + Math.floor(A / 4); + return Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + B - 1524.5; +} + +/* + * Sidereal time in Greenwich + */ +function siderealTime(julianDay) +{ + var T = (julianDay - 2451545.0) / 36525; + return toRadians(280.46061837 + 360.98564736629 * (julianDay - 2451545.0) + 0.000387933 * T * T - T * T * T / 38710000); +} + +function binary_search(a, value) { + var lo = 0, hi = a.length - 1, mid; + while (lo <= hi) { + mid = Math.floor((lo+hi)/2); + if (a[mid] > value) + hi = mid - 1; + else if (a[mid] < value) + lo = mid + 1; + else + return mid; + } + return null; +} + +var longitudeSign = 1; //1 for west and -1 for east; +var longitudeDegrees = 5; +var longitudeMinutes = 37; +var longitudeSeconds = 27.4; +var longitude = toRadians(longitudeSign * (longitudeDegrees + longitudeMinutes / 60 + longitudeSeconds / 3600)); +var latitudeSign = 1; //1 for north -1 for south; +var latitudeDegrees = 43; +var latitudeMinutes = 25; +var latitudeSeconds = 0.9; +var latitude = toRadians(latitudeSign * (latitudeDegrees + latitudeMinutes / 60 + latitudeSeconds / 3600)); +var year = 2020; +var month = 1; +var day = 27; +var hours = 22; +var minutes = 0; +var seconds = 0; +var timeZone = 1; +var julianDay = toJulianDay(year, month, day, hours - timeZone, minutes, seconds); +var size = 240; + +storage = require('Storage'); +f=storage.read("planetarium.data.csv","r"); +linestart=0; +g.clearRect(0, 0, 240, 240); + +//Common calculations based only on time +var t = (julianDay - 2451545.0) / 36525; +var zeta = toRadians((2306.2181 * t + 0.30188 * t * t + 0.017998 * t * t * t) / 3600); +var theta = toRadians((2004.3109 * t - 0.42665 * t * t - 0.041833 * t * t * t) / 3600); +var z = toRadians((2306.2181 * t + 1.09468 * t * t + 0.018203 * t * t * t) / 3600); + + +let starNumber = 0; +//Each star has a number (the position on the file (line number)). These are the lines +//joining each star in the constellations. +constelation_lines=[/*Orion*/[7,68],[10,53],[53,56],[28,68],/*Taurus*/[13,172],[13,340],[293,340],[29,293], + /*canis menor*/[155,8]]; +var starPositions = {}; + +for (i=0;i= 0) + { + //Compute azimuth + var azi = Math.atan2(Math.sin(H), Math.cos(H) * Math.sin(latitude) - Math.tan(dec) * Math.cos(latitude)); + var x = size / 2 + size / 2 * Math.cos(alt) * Math.sin(azi); + var y = size / 2 + size / 2 * Math.cos(alt) * Math.cos(azi); + starPositions[starNumber] = [x,y]; + var magnitude = starMag<1.5?2:1; + g.fillCircle(x, y, magnitude); + if (starMag<1) + g.drawString(starInfo[3],x,y+2); + g.flip(); + + } + } +} + +for (i=0;i1) - { - setNum--; - work = true; - counter = settings.workseg+settings.workmin*60; - startCounter(); - } - else - { - //End session - setWatch(showMenu, BTN2); - E.showMessage("Press BTN2 for\ngoing back\nto the menu","Well done!"); - } - } -} - -function printCounter(counter){ - g.setFontAlign(0,0); // center font - g.setFont("Vector",80); // vector font, 80px - // draw the current counter value - let minutes = Math.floor(counter/60); - let segs = counter % 60; - let textMinutes = minutes.toString().padStart(2, "0"); - let textSegs = segs.toString().padStart(2,"0"); - g.clearRect(0,80,239,160); - g.setFont("Vector",30); - if (prep) - g.setColor(125,125,0); - else if (work) - g.setColor(255,0,0); - else - g.setColor(0,255,0); - g.drawString(setNum,120,50); - if (prep) - g.drawString("PREPARATION",120,190); - else if (work) - g.drawString("WORK",120,190); - else - g.drawString("REST",120,190); - g.setFont("Vector",10); - g.drawString("Touch to pause",120,215); - g.setFont("Vector",80); - g.drawString(textMinutes+":"+textSegs,120,120); -} - -function signal_to_user(le){ - if (settings.buzz) - Bangle.buzz(le); - else - Bangle.beep(le,4000); -} - -function countDown() { - counter--; - if (counter<4 && counter>0) - signal_to_user(200); - if (counter==0) - signal_to_user(600); - - if (counter<0) { - clearInterval(counterInterval); - counterInterval = undefined; - endPart(); - } - else - { - printCounter(counter); - } - g.flip(); -} - -function startCounter(){ - if (!counterInterval) - counterInterval = setInterval(countDown, 1000); -} - -function pause() -{ - if (!paused) - { - clearInterval(counterInterval); - counterInterval = undefined; - setWatch(resume,BTN4); - setWatch(resume,BTN5); - paused=true; - g.clear(); - g.setFont("Vector",60); - g.drawString("PAUSED",120,120); - g.setFont("Vector",20); - g.drawString("Touch to continue",120,180); - } -} - -function resume(){ - if (paused) - { - g.clear(); - counterInterval = setInterval(countDown, 1000); - setWatch(pause,BTN4); - setWatch(pause,BTN5); - paused=false; - } -} - -function startSession() { - E.showMenu(); - paused=false; - setWatch(pause,BTN4); - setWatch(pause,BTN5); - require('Storage').write('intervals.settings.json',settings); - setNum = settings.sets; - counter = 5;//prep time - prep=true; - work=false; - startCounter(); -} - -function showMenu() -{ - settings = require('Storage').readJSON('intervals.settings.json',1)|| - { sets:1,workseg:10,workmin:0,restseg:5,restmin:0,buzz:true}; - - var mainmenu = { - "" : { "title" : "-- Main Menu --" }, - "START" : function() { startSession(); }, - "Sets" : { value : settings.sets,min:0,max:20,step:1,onchange : v => { settings.sets=v; } }, - "Work minutes" : { value : settings.workmin,min:0,max:59,step:1,onchange : v => { settings.workmin=v; } }, - "Work seconds" : { value : settings.workseg,min:0,max:59,step:5,onchange : v => { settings.workseg=v; } }, - "Rest minutes" : { value : settings.restmin,min:0,max:59,step:1,onchange : v => { settings.restmin=v; } }, - "Rest seconds" : { value : settings.restseg,min:0,max:59,step:5,onchange : v => { settings.restseg=v; } }, - "Signal type" : { value : settings.buzz,format : v => v?"Buzz":"Beep",onchange : v => { settings.buzz=v; }} - }; - - E.showMenu(mainmenu); -} - -showMenu(); - - - - - - diff --git a/apps/planetarium/planetarium.png b/apps/planetarium/planetarium.png index f6ca9ff41f50a570bb66426bc4e93bdc73a4aba0..c40606009a0d707283ec458dc4e249b0f681e8b6 100644 GIT binary patch delta 1888 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