Merge branch 'espruino:master' into score

pull/3638/head
Aleix 2024-11-02 04:04:33 +01:00 committed by GitHub
commit e8e70ea3f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
73 changed files with 2078 additions and 745 deletions

View File

@ -39,3 +39,4 @@
Allow `calendar-` to take an array of items to remove Allow `calendar-` to take an array of items to remove
0.37: Support Gadgetbridge canned responses 0.37: Support Gadgetbridge canned responses
0.38: Don't rewrite settings file on every boot! 0.38: Don't rewrite settings file on every boot!
0.39: Move GB message handling into a library to reduce boot time from 40ms->13ms

View File

@ -1,349 +1,24 @@
/* global GB */ /* global GB */
{ {
let gbSend = function(message) { // settings var is deleted after this executes to save memory
Bluetooth.println("");
Bluetooth.println(JSON.stringify(message));
}
let lastMsg; // for music messages - may not be needed now...
let actInterval; // Realtime activity reporting interval when `act` is true
let actHRMHandler; // For Realtime activity reporting
let gpsState = {}; // keep information on GPS via Gadgetbridge
// this settings var is deleted after this executes to save memory
let settings = Object.assign({rp:true,as:true,vibrate:".."}, let settings = Object.assign({rp:true,as:true,vibrate:".."},
require("Storage").readJSON("android.settings.json",1)||{} require("Storage").readJSON("android.settings.json",1)||{}
); );
let _GB = global.GB; let _GB = global.GB;
let fetchRecInterval; global.GB = e => {
global.GB = (event) => {
// feed a copy to other handlers if there were any // feed a copy to other handlers if there were any
if (_GB) setTimeout(_GB,0,Object.assign({},event)); if (_GB) setTimeout(_GB,0,Object.assign({},e));
Bangle.emit("GB",e);
/* TODO: Call handling, fitness */ require("android").gbHandler(e);
var HANDLERS = {
// {t:"notify",id:int, src,title,subject,body,sender,tel:string} add
"notify" : function() {
Object.assign(event,{t:"add",positive:true, negative:true});
// Detect a weird GadgetBridge bug and fix it
// For some reason SMS messages send two GB notifications, with different sets of info
if (lastMsg && event.body == lastMsg.body && lastMsg.src == undefined && event.src == "Messages") {
// Mutate the other message
event.id = lastMsg.id;
}
lastMsg = event;
require("messages").pushMessage(event);
},
// {t:"notify~",id:int, title:string} // modified
"notify~" : function() { event.t="modify";require("messages").pushMessage(event); },
// {t:"notify-",id:int} // remove
"notify-" : function() { event.t="remove";require("messages").pushMessage(event); },
// {t:"find", n:bool} // find my phone
"find" : function() {
if (Bangle.findDeviceInterval) {
clearInterval(Bangle.findDeviceInterval);
delete Bangle.findDeviceInterval;
}
if (event.n) // Ignore quiet mode: we always want to find our watch
Bangle.findDeviceInterval = setInterval(_=>Bangle.buzz(),1000);
},
// {t:"musicstate", state:"play/pause",position,shuffle,repeat}
"musicstate" : function() {
require("messages").pushMessage({t:"modify",id:"music",title:"Music",state:event.state});
},
// {t:"musicinfo", artist,album,track,dur,c(track count),n(track num}
"musicinfo" : function() {
require("messages").pushMessage(Object.assign(event, {t:"modify",id:"music",title:"Music"}));
},
// {"t":"call","cmd":"incoming/end","name":"Bob","number":"12421312"})
"call" : function() {
Object.assign(event, {
t:event.cmd=="incoming"?"add":"remove",
id:"call", src:"Phone",
positive:true, negative:true,
title:event.name||/*LANG*/"Call", body:/*LANG*/"Incoming call\n"+event.number});
require("messages").pushMessage(event);
},
"canned_responses_sync" : function() {
require("Storage").writeJSON("replies.json", event.d);
},
// {"t":"alarm", "d":[{h:int,m:int,rep:int},... }
"alarm" : function() {
//wipe existing GB alarms
var sched;
try { sched = require("sched"); } catch (e) {}
if (!sched) return; // alarms may not be installed
var gbalarms = sched.getAlarms().filter(a=>a.appid=="gbalarms");
for (var i = 0; i < gbalarms.length; i++)
sched.setAlarm(gbalarms[i].id, undefined);
var alarms = sched.getAlarms();
var time = new Date();
var currentTime = time.getHours() * 3600000 +
time.getMinutes() * 60000 +
time.getSeconds() * 1000;
for (var j = 0; j < event.d.length; j++) {
// prevents all alarms from going off at once??
var dow = event.d[j].rep;
var rp = false;
if (!dow) {
dow = 127; //if no DOW selected, set alarm to all DOW
} else {
rp = true;
}
var last = (event.d[j].h * 3600000 + event.d[j].m * 60000 < currentTime) ? (new Date()).getDate() : 0;
var a = require("sched").newDefaultAlarm();
a.id = "gb"+j;
a.appid = "gbalarms";
a.on = event.d[j].on !== undefined ? event.d[j].on : true;
a.t = event.d[j].h * 3600000 + event.d[j].m * 60000;
a.dow = ((dow&63)<<1) | (dow>>6); // Gadgetbridge sends DOW in a different format
a.rp = rp;
a.last = last;
alarms.push(a);
}
sched.setAlarms(alarms);
sched.reload();
},
//TODO perhaps move those in a library (like messages), used also for viewing events?
//add and remove events based on activity on phone (pebble-like)
// {t:"calendar", id:int, type:int, timestamp:seconds, durationInSeconds, title:string, description:string,location:string,calName:string.color:int,allDay:bool
"calendar" : function() {
var cal = require("Storage").readJSON("android.calendar.json",true);
if (!cal || !Array.isArray(cal)) cal = [];
var i = cal.findIndex(e=>e.id==event.id);
if(i<0)
cal.push(event);
else
cal[i] = event;
require("Storage").writeJSON("android.calendar.json", cal);
},
// {t:"calendar-", id:int}
"calendar-" : function() {
var cal = require("Storage").readJSON("android.calendar.json",true);
//if any of those happen we are out of sync!
if (!cal || !Array.isArray(cal)) cal = [];
if (Array.isArray(event.id))
cal = cal.filter(e=>!event.id.includes(e.id));
else
cal = cal.filter(e=>e.id!=event.id);
require("Storage").writeJSON("android.calendar.json", cal);
},
//triggered by GB, send all ids
// { t:"force_calendar_sync_start" }
"force_calendar_sync_start" : function() {
var cal = require("Storage").readJSON("android.calendar.json",true);
if (!cal || !Array.isArray(cal)) cal = [];
gbSend({t:"force_calendar_sync", ids: cal.map(e=>e.id)});
},
// {t:"http",resp:"......",[id:"..."]}
"http":function() {
//get the promise and call the promise resolve
if (Bangle.httpRequest === undefined) return;
var request=Bangle.httpRequest[event.id];
if (request === undefined) return; //already timedout or wrong id
delete Bangle.httpRequest[event.id];
clearTimeout(request.t); //t = timeout variable
if(event.err!==undefined) //if is error
request.j(event.err); //r = reJect function
else
request.r(event); //r = resolve function
},
// {t:"gps", lat, lon, alt, speed, course, time, satellites, hdop, externalSource:true }
"gps": function() {
if (!settings.overwriteGps) return;
// modify event for using it as Bangle GPS event
delete event.t;
if (!isFinite(event.satellites)) event.satellites = NaN;
if (!isFinite(event.course)) event.course = NaN;
event.fix = 1;
if (event.long!==undefined) { // for earlier Gadgetbridge implementations
event.lon = event.long;
delete event.long;
}
if (event.time){
event.time = new Date(event.time);
}
if (!gpsState.lastGPSEvent) {
// this is the first event, save time of arrival and deactivate internal GPS
Bangle.moveGPSPower(0);
} else {
// this is the second event, store the intervall for expecting the next GPS event
gpsState.interval = Date.now() - gpsState.lastGPSEvent;
}
gpsState.lastGPSEvent = Date.now();
// in any case, cleanup the GPS state in case no new events arrive
if (gpsState.timeoutGPS) clearTimeout(gpsState.timeoutGPS);
gpsState.timeoutGPS = setTimeout(()=>{
// reset state
gpsState.lastGPSEvent = undefined;
gpsState.timeoutGPS = undefined;
gpsState.interval = undefined;
// did not get an expected GPS event but have GPS clients, switch back to internal GPS
if (Bangle.isGPSOn()) Bangle.moveGPSPower(1);
}, (gpsState.interval || 10000) + 1000);
Bangle.emit('GPS', event);
},
// {t:"is_gps_active"}
"is_gps_active": function() {
gbSend({ t: "gps_power", status: Bangle.isGPSOn() });
},
// {t:"act", hrm:bool, stp:bool, int:int}
"act": function() {
if (actInterval) clearInterval(actInterval);
actInterval = undefined;
if (actHRMHandler)
actHRMHandler = undefined;
Bangle.setHRMPower(event.hrm,"androidact");
if (!(event.hrm || event.stp)) return;
if (!isFinite(event.int)) event.int=1;
var lastSteps = Bangle.getStepCount();
var lastBPM = 0;
actHRMHandler = function(e) {
lastBPM = e.bpm;
};
Bangle.on('HRM',actHRMHandler);
actInterval = setInterval(function() {
var steps = Bangle.getStepCount();
gbSend({ t: "act", stp: steps-lastSteps, hrm: lastBPM, rt:1 });
lastSteps = steps;
}, event.int*1000);
},
// {t:"actfetch", ts:long}
"actfetch": function() {
gbSend({t: "actfetch", state: "start"});
var actCount = 0;
var actCb = function(r) {
// The health lib saves the samples at the start of the 10-minute block
// However, GB expects them at the end of the block, so let's offset them
// here to keep a consistent API in the health lib
var sampleTs = r.date.getTime() + 600000;
if (sampleTs >= event.ts) {
gbSend({
t: "act",
ts: sampleTs,
stp: r.steps,
hrm: r.bpm,
mov: r.movement
});
actCount++;
}
}
if (event.ts != 0) {
require("health").readAllRecordsSince(new Date(event.ts - 600000), actCb);
} else {
require("health").readFullDatabase(actCb);
}
gbSend({t: "actfetch", state: "end", count: actCount});
},
//{t:"listRecs", id:"20230616a"}
"listRecs": function() {
let recs = require("Storage").list(/^recorder\.log.*\.csv$/,{sf:true}).map(s => s.slice(12, 21));
if (event.id.length > 2) { // Handle if there was no id supplied. Then we send a list all available recorder logs back.
let firstNonsyncedIdx = recs.findIndex((logId) => logId > event.id);
if (-1 == firstNonsyncedIdx) {
recs = []
} else {
recs = recs.slice(firstNonsyncedIdx);
}
}
gbSend({t:"actTrksList", list: recs}); // TODO: split up in multiple transmissions?
},
//{t:"fetchRec", id:"20230616a"}
"fetchRec": function() {
// TODO: Decide on what names keys should have.
if (fetchRecInterval) {
clearInterval(fetchRecInterval);
fetchRecInterval = undefined;
}
if (event.id=="stop") {
return
} else {
let log = require("Storage").open("recorder.log"+event.id+".csv","r");
let lines = "init";// = log.readLine();
let pkgcnt = 0;
gbSend({t:"actTrk", log:event.id, lines:"erase", cnt:pkgcnt}); // "erase" will prompt Gadgetbridge to erase the contents of a already fetched log so we can rewrite it without keeping lines from the previous (probably failed) fetch.
let sendlines = ()=>{
lines = log.readLine();
for (var i = 0; i < 3; i++) {
let line = log.readLine();
if (line) lines += line;
}
pkgcnt++;
gbSend({t:"actTrk", log:event.id, lines:lines, cnt:pkgcnt});
if (!lines && fetchRecInterval) {
clearInterval(fetchRecInterval);
fetchRecInterval = undefined;
}
}
fetchRecInterval = setInterval(sendlines, 50)
}
},
"nav": function() {
event.id="nav";
if (event.instr) {
event.t="add";
event.src="maps"; // for the icon
event.title="Navigation";
if (require("messages").getMessages().find(m=>m.id=="nav"))
event.t = "modify";
} else {
event.t="remove";
}
require("messages").pushMessage(event);
},
"cards" : function() {
// we receive all, just override what we have
if (Array.isArray(event.d))
require("Storage").writeJSON("android.cards.json", event.d);
},
"accelsender": function () {
require("Storage").writeJSON("accelsender.json", {enabled: event.enable, interval: event.interval});
load();
}
};
var h = HANDLERS[event.t];
if (h) h(); else console.log("GB Unknown",event);
}; };
// HTTP request handling - see the readme // HTTP request handling - see the readme
// options = {id,timeout,xpath} Bangle.http = (url,options)=>require("android").httpHandler(url,options);
Bangle.http = (url,options)=>{
options = options||{};
if (!NRF.getSecurityStatus().connected)
return Promise.reject(/*LANG*/"Not connected to Bluetooth");
if (Bangle.httpRequest === undefined)
Bangle.httpRequest={};
if (options.id === undefined) {
// try and create a unique ID
do {
options.id = Math.random().toString().substr(2);
} while( Bangle.httpRequest[options.id]!==undefined);
}
//send the request
var req = {t: "http", url:url, id:options.id};
if (options.xpath) req.xpath = options.xpath;
if (options.return) req.return = options.return; // for xpath
if (options.method) req.method = options.method;
if (options.body) req.body = options.body;
if (options.headers) req.headers = options.headers;
gbSend(req);
//create the promise
var promise = new Promise(function(resolve,reject) {
//save the resolve function in the dictionary and create a timeout (30 seconds default)
Bangle.httpRequest[options.id]={r:resolve,j:reject,t:setTimeout(()=>{
//if after "timeoutMillisec" it still hasn't answered -> reject
delete Bangle.httpRequest[options.id];
reject("Timeout");
},options.timeout||30000)};
});
return promise;
};
// Battery monitor // Battery monitor
let sendBattery = function() { gbSend({ t: "status", bat: E.getBattery(), chg: Bangle.isCharging()?1:0 }); } let sendBattery = function() { require("android").gbSend({ t: "status", bat: E.getBattery(), chg: Bangle.isCharging()?1:0 }); }
Bangle.on("charging", sendBattery); Bangle.on("charging", sendBattery);
NRF.on("connect", () => setTimeout(function() { NRF.on("connect", () => setTimeout(function() {
sendBattery(); sendBattery();
gbSend({t: "ver", fw: process.env.VERSION, hw: process.env.HWVERSION}); require("android").gbSend({t: "ver", fw: process.env.VERSION, hw: process.env.HWVERSION});
GB({t:"force_calendar_sync_start"}); // send a list of our calendar entries to start off the sync process GB({t:"force_calendar_sync_start"}); // send a list of our calendar entries to start off the sync process
}, 2000)); }, 2000));
NRF.on("disconnect", () => { NRF.on("disconnect", () => {
@ -357,81 +32,24 @@
setInterval(sendBattery, 10*60*1000); setInterval(sendBattery, 10*60*1000);
// Health tracking - if 'realtime' data is sent with 'rt:1', but let's still send our activity log every 10 mins // Health tracking - if 'realtime' data is sent with 'rt:1', but let's still send our activity log every 10 mins
Bangle.on('health', h=>{ Bangle.on('health', h=>{
gbSend({ t: "act", stp: h.steps, hrm: h.bpm, mov: h.movement }); require("android").gbSend({ t: "act", stp: h.steps, hrm: h.bpm, mov: h.movement });
}); });
// Music control // Music control
Bangle.musicControl = cmd => { Bangle.musicControl = cmd => {
// play/pause/next/previous/volumeup/volumedown // play/pause/next/previous/volumeup/volumedown
gbSend({ t: "music", n:cmd }); require("android").gbSend({ t: "music", n:cmd });
}; };
// Message response // Message response
Bangle.messageResponse = (msg,response) => { Bangle.messageResponse = (msg,response) => {
if (msg.id=="call") return gbSend({ t: "call", n:response?"ACCEPT":"REJECT" }); if (msg.id=="call") return require("android").gbSend({ t: "call", n:response?"ACCEPT":"REJECT" });
if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id }); if (isFinite(msg.id)) return require("android").gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id });
// error/warn here? // error/warn here?
}; };
Bangle.messageIgnore = msg => { Bangle.messageIgnore = msg => {
if (isFinite(msg.id)) return gbSend({ t: "notify", n:"MUTE", id: msg.id }); if (isFinite(msg.id)) return require("android").gbSend({ t: "notify", n:"MUTE", id: msg.id });
}; };
// GPS overwrite logic // GPS overwrite logic
if (settings.overwriteGps) { // if the overwrite option is set.. if (settings.overwriteGps) require("android").overwriteGPS();
const origSetGPSPower = Bangle.setGPSPower;
Bangle.moveGPSPower = (state) => {
if (Bangle.isGPSOn()){
let orig = Bangle._PWR.GPS;
delete Bangle._PWR.GPS;
origSetGPSPower(state);
Bangle._PWR.GPS = orig;
}
};
// work around Serial1 for GPS not working when connected to something
let serialTimeout;
let wrap = function(f){
return (s)=>{
if (serialTimeout) clearTimeout(serialTimeout);
origSetGPSPower(1, "androidgpsserial");
f(s);
serialTimeout = setTimeout(()=>{
serialTimeout = undefined;
origSetGPSPower(0, "androidgpsserial");
}, 10000);
};
};
Serial1.println = wrap(Serial1.println);
Serial1.write = wrap(Serial1.write);
// replace set GPS power logic to suppress activation of gps (and instead request it from the phone)
Bangle.setGPSPower = ((isOn, appID) => {
let pwr;
if (!this.lastGPSEvent){
// use internal GPS power function if no gps event has arrived from GadgetBridge
pwr = origSetGPSPower(isOn, appID);
} else {
// we are currently expecting the next GPS event from GadgetBridge, keep track of GPS state per app
if (!Bangle._PWR) Bangle._PWR={};
if (!Bangle._PWR.GPS) Bangle._PWR.GPS=[];
if (!appID) appID="?";
if (isOn && !Bangle._PWR.GPS.includes(appID)) Bangle._PWR.GPS.push(appID);
if (!isOn && Bangle._PWR.GPS.includes(appID)) Bangle._PWR.GPS.splice(Bangle._PWR.GPS.indexOf(appID),1);
pwr = Bangle._PWR.GPS.length>0;
// stop internal GPS, no clients left
if (!pwr) origSetGPSPower(0);
}
// always update Gadgetbridge on current power state
gbSend({ t: "gps_power", status: pwr });
return pwr;
}).bind(gpsState);
// allow checking for GPS via GadgetBridge
Bangle.isGPSOn = () => {
return !!(Bangle._PWR && Bangle._PWR.GPS && Bangle._PWR.GPS.length>0);
};
// stop GPS on boot if not activated
setTimeout(()=>{
if (!Bangle.isGPSOn()) gbSend({ t: "gps_power", status: false });
},3000);
}
// remove settings object so it's not taking up RAM // remove settings object so it's not taking up RAM
delete settings; delete settings;
} }

388
apps/android/lib.js Normal file
View File

@ -0,0 +1,388 @@
exports.gbSend = function(message) {
Bluetooth.println("");
Bluetooth.println(JSON.stringify(message));
}
let lastMsg, // for music messages - may not be needed now...
gpsState = {}, // keep information on GPS via Gadgetbridge
settings = Object.assign({rp:true,as:true,vibrate:".."},
require("Storage").readJSON("android.settings.json",1)||{}
);
exports.gbHandler = (event) => {
var HANDLERS = {
// {t:"notify",id:int, src,title,subject,body,sender,tel:string} add
"notify" : function() {
print("notify",event);
Object.assign(event,{t:"add",positive:true, negative:true});
// Detect a weird GadgetBridge bug and fix it
// For some reason SMS messages send two GB notifications, with different sets of info
if (lastMsg && event.body == lastMsg.body && lastMsg.src == undefined && event.src == "Messages") {
// Mutate the other message
event.id = lastMsg.id;
}
lastMsg = event;
require("messages").pushMessage(event);
},
// {t:"notify~",id:int, title:string} // modified
"notify~" : function() { event.t="modify";require("messages").pushMessage(event); },
// {t:"notify-",id:int} // remove
"notify-" : function() { event.t="remove";require("messages").pushMessage(event); },
// {t:"find", n:bool} // find my phone
"find" : function() {
if (Bangle.findDeviceInterval) {
clearInterval(Bangle.findDeviceInterval);
delete Bangle.findDeviceInterval;
}
if (event.n) // Ignore quiet mode: we always want to find our watch
Bangle.findDeviceInterval = setInterval(_=>Bangle.buzz(),1000);
},
// {t:"musicstate", state:"play/pause",position,shuffle,repeat}
"musicstate" : function() {
require("messages").pushMessage({t:"modify",id:"music",title:"Music",state:event.state});
},
// {t:"musicinfo", artist,album,track,dur,c(track count),n(track num}
"musicinfo" : function() {
require("messages").pushMessage(Object.assign(event, {t:"modify",id:"music",title:"Music"}));
},
// {"t":"call","cmd":"incoming/end","name":"Bob","number":"12421312"})
"call" : function() {
Object.assign(event, {
t:event.cmd=="incoming"?"add":"remove",
id:"call", src:"Phone",
positive:true, negative:true,
title:event.name||/*LANG*/"Call", body:/*LANG*/"Incoming call\n"+event.number});
require("messages").pushMessage(event);
},
"canned_responses_sync" : function() {
require("Storage").writeJSON("replies.json", event.d);
},
// {"t":"alarm", "d":[{h:int,m:int,rep:int},... }
"alarm" : function() {
//wipe existing GB alarms
var sched;
try { sched = require("sched"); } catch (e) {}
if (!sched) return; // alarms may not be installed
var gbalarms = sched.getAlarms().filter(a=>a.appid=="gbalarms");
for (var i = 0; i < gbalarms.length; i++)
sched.setAlarm(gbalarms[i].id, undefined);
var alarms = sched.getAlarms();
var time = new Date();
var currentTime = time.getHours() * 3600000 +
time.getMinutes() * 60000 +
time.getSeconds() * 1000;
for (var j = 0; j < event.d.length; j++) {
// prevents all alarms from going off at once??
var dow = event.d[j].rep;
var rp = false;
if (!dow) {
dow = 127; //if no DOW selected, set alarm to all DOW
} else {
rp = true;
}
var last = (event.d[j].h * 3600000 + event.d[j].m * 60000 < currentTime) ? (new Date()).getDate() : 0;
var a = require("sched").newDefaultAlarm();
a.id = "gb"+j;
a.appid = "gbalarms";
a.on = event.d[j].on !== undefined ? event.d[j].on : true;
a.t = event.d[j].h * 3600000 + event.d[j].m * 60000;
a.dow = ((dow&63)<<1) | (dow>>6); // Gadgetbridge sends DOW in a different format
a.rp = rp;
a.last = last;
alarms.push(a);
}
sched.setAlarms(alarms);
sched.reload();
},
//TODO perhaps move those in a library (like messages), used also for viewing events?
//add and remove events based on activity on phone (pebble-like)
// {t:"calendar", id:int, type:int, timestamp:seconds, durationInSeconds, title:string, description:string,location:string,calName:string.color:int,allDay:bool
"calendar" : function() {
var cal = require("Storage").readJSON("android.calendar.json",true);
if (!cal || !Array.isArray(cal)) cal = [];
var i = cal.findIndex(e=>e.id==event.id);
if(i<0)
cal.push(event);
else
cal[i] = event;
require("Storage").writeJSON("android.calendar.json", cal);
},
// {t:"calendar-", id:int}
"calendar-" : function() {
var cal = require("Storage").readJSON("android.calendar.json",true);
//if any of those happen we are out of sync!
if (!cal || !Array.isArray(cal)) cal = [];
if (Array.isArray(event.id))
cal = cal.filter(e=>!event.id.includes(e.id));
else
cal = cal.filter(e=>e.id!=event.id);
require("Storage").writeJSON("android.calendar.json", cal);
},
//triggered by GB, send all ids
// { t:"force_calendar_sync_start" }
"force_calendar_sync_start" : function() {
var cal = require("Storage").readJSON("android.calendar.json",true);
if (!cal || !Array.isArray(cal)) cal = [];
exports.gbSend({t:"force_calendar_sync", ids: cal.map(e=>e.id)});
},
// {t:"http",resp:"......",[id:"..."]}
"http":function() {
//get the promise and call the promise resolve
if (Bangle.httpRequest === undefined) return;
var request=Bangle.httpRequest[event.id];
if (request === undefined) return; //already timedout or wrong id
delete Bangle.httpRequest[event.id];
clearTimeout(request.t); //t = timeout variable
if(event.err!==undefined) //if is error
request.j(event.err); //r = reJect function
else
request.r(event); //r = resolve function
},
// {t:"gps", lat, lon, alt, speed, course, time, satellites, hdop, externalSource:true }
"gps": function() {
if (!settings.overwriteGps) return;
// modify event for using it as Bangle GPS event
delete event.t;
if (!isFinite(event.satellites)) event.satellites = NaN;
if (!isFinite(event.course)) event.course = NaN;
event.fix = 1;
if (event.long!==undefined) { // for earlier Gadgetbridge implementations
event.lon = event.long;
delete event.long;
}
if (event.time){
event.time = new Date(event.time);
}
if (!gpsState.lastGPSEvent) {
// this is the first event, save time of arrival and deactivate internal GPS
Bangle.moveGPSPower(0);
} else {
// this is the second event, store the intervall for expecting the next GPS event
gpsState.interval = Date.now() - gpsState.lastGPSEvent;
}
gpsState.lastGPSEvent = Date.now();
// in any case, cleanup the GPS state in case no new events arrive
if (gpsState.timeoutGPS) clearTimeout(gpsState.timeoutGPS);
gpsState.timeoutGPS = setTimeout(()=>{
// reset state
gpsState.lastGPSEvent = undefined;
gpsState.timeoutGPS = undefined;
gpsState.interval = undefined;
// did not get an expected GPS event but have GPS clients, switch back to internal GPS
if (Bangle.isGPSOn()) Bangle.moveGPSPower(1);
}, (gpsState.interval || 10000) + 1000);
Bangle.emit('GPS', event);
},
// {t:"is_gps_active"}
"is_gps_active": function() {
exports.gbSend({ t: "gps_power", status: Bangle.isGPSOn() });
},
// {t:"act", hrm:bool, stp:bool, int:int}
"act": function() {
if (exports.actInterval) clearInterval(exports.actInterval);
exports.actInterval = undefined;
if (exports.actHRMHandler)
exports.actHRMHandler = undefined;
Bangle.setHRMPower(event.hrm,"androidact");
if (!(event.hrm || event.stp)) return;
if (!isFinite(event.int)) event.int=1;
var lastSteps = Bangle.getStepCount();
var lastBPM = 0;
exports.actHRMHandler = function(e) {
lastBPM = e.bpm;
};
Bangle.on('HRM',exports.actHRMHandler);
exports.actInterval = setInterval(function() {
var steps = Bangle.getStepCount();
exports.gbSend({ t: "act", stp: steps-lastSteps, hrm: lastBPM, rt:1 });
lastSteps = steps;
}, event.int*1000);
},
// {t:"actfetch", ts:long}
"actfetch": function() {
exports.gbSend({t: "actfetch", state: "start"});
var actCount = 0;
var actCb = function(r) {
// The health lib saves the samples at the start of the 10-minute block
// However, GB expects them at the end of the block, so let's offset them
// here to keep a consistent API in the health lib
var sampleTs = r.date.getTime() + 600000;
if (sampleTs >= event.ts) {
exports.gbSend({
t: "act",
ts: sampleTs,
stp: r.steps,
hrm: r.bpm,
mov: r.movement
});
actCount++;
}
}
if (event.ts != 0) {
require("health").readAllRecordsSince(new Date(event.ts - 600000), actCb);
} else {
require("health").readFullDatabase(actCb);
}
exports.gbSend({t: "actfetch", state: "end", count: actCount});
},
//{t:"listRecs", id:"20230616a"}
"listRecs": function() {
let recs = require("Storage").list(/^recorder\.log.*\.csv$/,{sf:true}).map(s => s.slice(12, 21));
if (event.id.length > 2) { // Handle if there was no id supplied. Then we send a list all available recorder logs back.
let firstNonsyncedIdx = recs.findIndex((logId) => logId > event.id);
if (-1 == firstNonsyncedIdx) {
recs = []
} else {
recs = recs.slice(firstNonsyncedIdx);
}
}
exports.gbSend({t:"actTrksList", list: recs}); // TODO: split up in multiple transmissions?
},
//{t:"fetchRec", id:"20230616a"}
"fetchRec": function() {
// TODO: Decide on what names keys should have.
if (exports.fetchRecInterval) {
clearInterval(exports.fetchRecInterval);
exports.fetchRecInterval = undefined;
}
if (event.id=="stop") {
return;
} else {
let log = require("Storage").open("recorder.log"+event.id+".csv","r");
let lines = "init";// = log.readLine();
let pkgcnt = 0;
exports.gbSend({t:"actTrk", log:event.id, lines:"erase", cnt:pkgcnt}); // "erase" will prompt Gadgetbridge to erase the contents of a already fetched log so we can rewrite it without keeping lines from the previous (probably failed) fetch.
let sendlines = ()=>{
lines = log.readLine();
for (var i = 0; i < 3; i++) {
let line = log.readLine();
if (line) lines += line;
}
pkgcnt++;
exports.gbSend({t:"actTrk", log:event.id, lines:lines, cnt:pkgcnt});
if (!lines && exports.fetchRecInterval) {
clearInterval(exports.fetchRecInterval);
exports.fetchRecInterval = undefined;
}
};
exports.fetchRecInterval = setInterval(sendlines, 50);
}
},
"nav": function() {
event.id="nav";
if (event.instr) {
event.t="add";
event.src="maps"; // for the icon
event.title="Navigation";
if (require("messages").getMessages().find(m=>m.id=="nav"))
event.t = "modify";
} else {
event.t="remove";
}
require("messages").pushMessage(event);
},
"cards" : function() {
// we receive all, just override what we have
if (Array.isArray(event.d))
require("Storage").writeJSON("android.cards.json", event.d);
},
"accelsender": function () {
require("Storage").writeJSON("accelsender.json", {enabled: event.enable, interval: event.interval});
load();
}
};
var h = HANDLERS[event.t];
if (h) h(); else console.log("GB Unknown",event);
};
// HTTP request handling - see the readme
// options = {id,timeout,xpath}
exports.httpHandler = (url,options) => {
options = options||{};
if (!NRF.getSecurityStatus().connected)
return Promise.reject(/*LANG*/"Not connected to Bluetooth");
if (Bangle.httpRequest === undefined)
Bangle.httpRequest={};
if (options.id === undefined) {
// try and create a unique ID
do {
options.id = Math.random().toString().substr(2);
} while( Bangle.httpRequest[options.id]!==undefined);
}
//send the request
var req = {t: "http", url:url, id:options.id};
if (options.xpath) req.xpath = options.xpath;
if (options.return) req.return = options.return; // for xpath
if (options.method) req.method = options.method;
if (options.body) req.body = options.body;
if (options.headers) req.headers = options.headers;
exports.gbSend(req);
//create the promise
var promise = new Promise(function(resolve,reject) {
//save the resolve function in the dictionary and create a timeout (30 seconds default)
Bangle.httpRequest[options.id]={r:resolve,j:reject,t:setTimeout(()=>{
//if after "timeoutMillisec" it still hasn't answered -> reject
delete Bangle.httpRequest[options.id];
reject("Timeout");
},options.timeout||30000)};
});
return promise;
};
exports.overwriteGPS = () => { // if the overwrite option is set, call this on init..
const origSetGPSPower = Bangle.setGPSPower;
Bangle.moveGPSPower = (state) => {
if (Bangle.isGPSOn()){
let orig = Bangle._PWR.GPS;
delete Bangle._PWR.GPS;
origSetGPSPower(state);
Bangle._PWR.GPS = orig;
}
};
// work around Serial1 for GPS not working when connected to something
let serialTimeout;
let wrap = function(f){
return (s)=>{
if (serialTimeout) clearTimeout(serialTimeout);
origSetGPSPower(1, "androidgpsserial");
f(s);
serialTimeout = setTimeout(()=>{
serialTimeout = undefined;
origSetGPSPower(0, "androidgpsserial");
}, 10000);
};
};
Serial1.println = wrap(Serial1.println);
Serial1.write = wrap(Serial1.write);
// replace set GPS power logic to suppress activation of gps (and instead request it from the phone)
Bangle.setGPSPower = ((isOn, appID) => {
let pwr;
if (!this.lastGPSEvent){
// use internal GPS power function if no gps event has arrived from GadgetBridge
pwr = origSetGPSPower(isOn, appID);
} else {
// we are currently expecting the next GPS event from GadgetBridge, keep track of GPS state per app
if (!Bangle._PWR) Bangle._PWR={};
if (!Bangle._PWR.GPS) Bangle._PWR.GPS=[];
if (!appID) appID="?";
if (isOn && !Bangle._PWR.GPS.includes(appID)) Bangle._PWR.GPS.push(appID);
if (!isOn && Bangle._PWR.GPS.includes(appID)) Bangle._PWR.GPS.splice(Bangle._PWR.GPS.indexOf(appID),1);
pwr = Bangle._PWR.GPS.length>0;
// stop internal GPS, no clients left
if (!pwr) origSetGPSPower(0);
}
// always update Gadgetbridge on current power state
require("android").gbSend({ t: "gps_power", status: pwr });
return pwr;
}).bind(gpsState);
// allow checking for GPS via GadgetBridge
Bangle.isGPSOn = () => {
return !!(Bangle._PWR && Bangle._PWR.GPS && Bangle._PWR.GPS.length>0);
};
// stop GPS on boot if not activated
setTimeout(()=>{
if (!Bangle.isGPSOn()) require("android").gbSend({ t: "gps_power", status: false });
},3000);
};

View File

@ -2,7 +2,7 @@
"id": "android", "id": "android",
"name": "Android Integration", "name": "Android Integration",
"shortName": "Android", "shortName": "Android",
"version": "0.38", "version": "0.39",
"description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.",
"icon": "app.png", "icon": "app.png",
"tags": "tool,system,messages,notifications,gadgetbridge", "tags": "tool,system,messages,notifications,gadgetbridge",
@ -13,7 +13,8 @@
{"name":"android.app.js","url":"app.js"}, {"name":"android.app.js","url":"app.js"},
{"name":"android.settings.js","url":"settings.js"}, {"name":"android.settings.js","url":"settings.js"},
{"name":"android.img","url":"app-icon.js","evaluate":true}, {"name":"android.img","url":"app-icon.js","evaluate":true},
{"name":"android.boot.js","url":"boot.js"} {"name":"android.boot.js","url":"boot.js"},
{"name":"android","url":"lib.js"}
], ],
"data": [{"name":"android.settings.json"}, {"name":"android.calendar.json"}, {"name":"android.cards.json"}], "data": [{"name":"android.settings.json"}, {"name":"android.calendar.json"}, {"name":"android.cards.json"}],
"sortorder": -8 "sortorder": -8

View File

@ -4,3 +4,4 @@
0.04: Now turns GPS off after upload 0.04: Now turns GPS off after upload
0.05: Fix regression in 0.04 that caused AGPS data not to get loaded 0.05: Fix regression in 0.04 that caused AGPS data not to get loaded
0.06: Auto-set GPS output sentences - newer Bangle.js 2 don't include RMC (GPS direction + time) by default 0.06: Auto-set GPS output sentences - newer Bangle.js 2 don't include RMC (GPS direction + time) by default
0.07: Bangle.js 2 now gets estimated time + lat/lon from the browser (~3x faster fix)

View File

@ -60,6 +60,7 @@
<script> <script>
var isB1; // is Bangle.js 1? var isB1; // is Bangle.js 1?
var isB2; // is Bangle.js 2? var isB2; // is Bangle.js 2?
var currentPosition;
// When the 'upload' button is clicked... // When the 'upload' button is clicked...
document.getElementById("upload").addEventListener("click", function() { document.getElementById("upload").addEventListener("click", function() {
@ -120,6 +121,7 @@
} }
// =================================================== Bangle.js 2 CASIC // =================================================== Bangle.js 2 CASIC
// https://www.espruino.com/Bangle.js2+Technical#gps
function CASIC_CHECKSUM(cmd) { function CASIC_CHECKSUM(cmd) {
var cs = 0; var cs = 0;
@ -128,6 +130,61 @@
return cmd+"*"+cs.toString(16).toUpperCase().padStart(2, '0'); return cmd+"*"+cs.toString(16).toUpperCase().padStart(2, '0');
} }
// Send a binary CASIC packet, eg: {classId:6, messageId:0, payload:[]}
function CASIC_PKT(pkt) {
pkt.payload = pkt.payload || [];
var plen = pkt.payload.length;
var msg = new Uint8Array(10+pkt.payload.length);
msg.set([0xBA,0xCE,
plen, // LENGTH
0x00,
pkt.classId, // CLASS ID
pkt.messageId]); // MESSAGE ID
msg.set(pkt.payload, 6);
var dv = new DataView(msg.buffer);
// checksum
var ckSum = 0;
for (i = -4; i < plen; i+=4)
ckSum = 0|(ckSum+dv.getUint32(6+i, true));
dv.setUint32(6+plen, ckSum, true);
return msg;
}
// Send AID_INI message, {lat,lon,alt}
function AID_INI(pos) {
var msg = new Uint8Array(56);
var dv = new DataView(msg.buffer);
/*
double xOrLat, yOrLon, zOrAlt;
double tow; // 24
float df; // 32
float posAcc; // 36
float tAcc; // 40
float fAcc; // 44
unsigned int res; // 48
unsigned short int wn; // 52
unsigned char timeSource; // 54
unsigned char flags; // 55
*/
var ms = Date.now();
var wk = (ms-new Date("1980-01-06T00:00:00Z")) / 604800000;
var wn = Math.floor(wk); // week number
var tow = (wk-wn) * 604800; // seconds in week
dv.setFloat64(0, pos.lat, true); // xOrLat
dv.setFloat64(8, pos.lon, true); // yOrLon
dv.setFloat64(16, pos.alt, true); // zOrAlt
dv.setFloat64(24, tow, true); // tow
dv.setFloat32(32, 0, true); // df
dv.setFloat32(36, 0, true); // posAcc
dv.setFloat32(40, 0, true); // tAcc
dv.setFloat32(44, 0, true); // fAcc
dv.setUint32(48, 0, true); // res
dv.setUint16(52, wn, true); // wn
dv.setUint8(54,0); // timeSource
dv.setUint8(55, 0x23); // flags ( lat/lon and clock valid, no drift data )
return CASIC_PKT({classId:0x0B, messageId:0x01, payload:msg});
}
// =================================================== // ===================================================
function jsFromBase64(b64) { function jsFromBase64(b64) {
@ -140,7 +197,6 @@
js += `\x10Serial1.write(atob("${btoa(String.fromCharCode.apply(null,UBX_MGA_INI_TIME_UTC()))}"))\n`; // set GPS time js += `\x10Serial1.write(atob("${btoa(String.fromCharCode.apply(null,UBX_MGA_INI_TIME_UTC()))}"))\n`; // set GPS time
} }
if (isB2) { // CASIC if (isB2) { // CASIC
// Select what GNSS System to use for decreased fix time. // Select what GNSS System to use for decreased fix time.
var radios = document.getElementsByName('gnss_select'); var radios = document.getElementsByName('gnss_select');
var gnss_select="1"; var gnss_select="1";
@ -150,11 +206,11 @@
js += `\x10var t=getTime()+0.5;while (getTime()<t);\n`; // This is nasty - but we just wait here until the GPS has had time to boot js += `\x10var t=getTime()+0.5;while (getTime()<t);\n`; // This is nasty - but we just wait here until the GPS has had time to boot
js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS04,"+gnss_select)}")\n`; // set GNSS mode js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS04,"+gnss_select)}")\n`; // set GNSS mode
js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS03,1,0,0,1,1,0,0,0")}")\n`; // enable GGA,GSV,RMC packets (new Bangle.js 2 GPS firmwares don't include RMC by default!) js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS03,1,0,0,1,1,0,0,0")}")\n`; // enable GGA,GSV,RMC packets (new Bangle.js 2 GPS firmwares don't include RMC by default!)
// If the browser let us have the current location, give it to the GPS chip to get a faster fix
if (currentPosition) {
js += `\x10Serial1.write([${AID_INI(currentPosition).join(",")}])\n`;
}
// Serial1.println("$PCAS06,0*1B") gets the current firmware version // Serial1.println("$PCAS06,0*1B") gets the current firmware version
// What about:
// NAV-TIMEUTC (0x01 0x10)
// NAV-PV (0x01 0x03)
// or AGPS.zip uses AID-INI (0x0B 0x01)
} }
for (var i=0;i<bin.length;i+=chunkSize) { for (var i=0;i<bin.length;i+=chunkSize) {
@ -184,7 +240,19 @@
document.getElementById("banglejs1-info").style = isB1?"":"display:none"; document.getElementById("banglejs1-info").style = isB1?"":"display:none";
document.getElementById("banglejs2-info").style = isB2?"":"display:none"; document.getElementById("banglejs2-info").style = isB2?"":"display:none";
document.getElementById("upload-wrap").style = ""; document.getElementById("upload-wrap").style = "";
if (isB2) {
// get current position for AGPS improvement
navigator.geolocation.getCurrentPosition(function(position) {
currentPosition = {
lat : position.coords.latitude,
lon : position.coords.longitude,
alt : 0|position.coords.altitude
};
});
} }
}
</script> </script>
</body> </body>

View File

@ -2,7 +2,7 @@
"id": "assistedgps", "id": "assistedgps",
"name": "Assisted GPS Updater (AGPS)", "name": "Assisted GPS Updater (AGPS)",
"shortName": "AGPS", "shortName": "AGPS",
"version": "0.06", "version": "0.07",
"description": "Downloads assisted GPS (AGPS) data to Bangle.js for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", "description": "Downloads assisted GPS (AGPS) data to Bangle.js for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.",
"sortorder": -1, "sortorder": -1,
"icon": "app.png", "icon": "app.png",

View File

@ -1,2 +1,3 @@
0.01: New app! 0.01: New app!
0.02: Minor code improvements 0.02: Minor code improvements
0.03: Remove clearing of the screen (will break running apps) and fix lint errors

View File

@ -2,8 +2,8 @@
"id": "banglebridge", "id": "banglebridge",
"name": "BangleBridge", "name": "BangleBridge",
"shortName": "BangleBridge", "shortName": "BangleBridge",
"version": "0.02", "version": "0.03",
"description": "Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App", "description": "Widget that allows Bangle.js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App (**Note:** this has nothing to do with Gadgetbridge)",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",
"tags": "widget", "tags": "widget",

View File

@ -35,8 +35,7 @@
}); });
setInterval(function () { setInterval(function () {
//acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag;
acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag;
data[3] = accelN; data[3] = accelN;
}, 2 * 1000); }, 2 * 1000);
@ -45,8 +44,7 @@
function btt() { function btt() {
setInterval(function () { setInterval(function () {
//bttS = E.getBattery(); //return String
bttS = E.getBattery(); //return String
data[2] = E.getBattery(); data[2] = E.getBattery();
}, 15 * 1000); }, 15 * 1000);
@ -65,9 +63,9 @@
setInterval(function () { setInterval(function () {
compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + /*compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" +
"B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" +
"C: " + compssN.heading; //return String "C: " + compssN.heading; *///return String
data[4] = compssN; data[4] = compssN;
}, 2 * 1000); }, 2 * 1000);
@ -86,8 +84,8 @@
setInterval(function () { setInterval(function () {
gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + /*gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" +
"C: " + gpsN.satellites + " ## " + gpsN.fix; //return String "C: " + gpsN.satellites + " ## " + gpsN.fix; *///return String
// work out how to display the current time // work out how to display the current time
var d = new Date(); var d = new Date();
var year = d.getFullYear(); var year = d.getFullYear();
@ -150,7 +148,7 @@
//console.log("Index ==> "+ index); //console.log("Index ==> "+ index);
msr[indexFinal] = nueva; msr[indexFinal] = nueva;
item = nueva; //item = nueva;
lastInsert = indexFinal; lastInsert = indexFinal;
} }
@ -180,7 +178,7 @@
hrmN = normalize(hrmN); hrmN = normalize(hrmN);
var roundedRate = parseFloat(hrmN).toFixed(2); var roundedRate = parseFloat(hrmN).toFixed(2);
hrmS = String.valueOf(roundedRate); //return String //hrmS = String.valueOf(roundedRate); //return String
//console.log("array----->" + msr); //console.log("array----->" + msr);
data[0] = roundedRate; data[0] = roundedRate;
@ -205,7 +203,7 @@
setInterval(function () { setInterval(function () {
stepS = String.valueOf(stepN); //return String //stepS = String.valueOf(stepN); //return String
data[1] = stepN; data[1] = stepN;
}, 2 * 1000); }, 2 * 1000);
@ -243,7 +241,6 @@
flip = 0; flip = 0;
//Bangle.buzz(1000); //Bangle.buzz(1000);
g.clear();
} else { //when on } else { //when on
flip = 1; flip = 1;
@ -283,7 +280,7 @@
com: data[4], com: data[4],
gps: data[5] gps: data[5]
}; };
/* g.clear(); /*
g.drawString(compssS,100,200); g.drawString(compssS,100,200);
*/ */

View File

@ -72,3 +72,7 @@
0.61: Instead of breaking execution with an Exception when updating boot, just use if..else (fix 'Uncaught undefined') 0.61: Instead of breaking execution with an Exception when updating boot, just use if..else (fix 'Uncaught undefined')
0.62: Handle setting for configuring BLE privacy 0.62: Handle setting for configuring BLE privacy
0.63: Only set BLE `display:1` if we have a passkey 0.63: Only set BLE `display:1` if we have a passkey
0.64: Automatically create .widcache and .clkinfocache to speed up loads
Bangle.loadWidgets overwritten with fast version on success
Refuse to work on firmware <2v16 and remove old polyfills
0.65: Only display interpreter errors if log is nonzero

View File

@ -12,14 +12,13 @@ if (DEBUG) {
boot += "var _tm=Date.now()\n"; boot += "var _tm=Date.now()\n";
bootPost += "delete _tm;"; bootPost += "delete _tm;";
} }
if (require('Storage').hash) { // new in 2v11 - helps ensure files haven't changed if (FWVERSION < 216) {
let CRC = E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\.boot\.js/)+E.CRC32(process.env.GIT_COMMIT); E.showMessage(/*LANG*/"Please update Bangle.js firmware\n\nCurrent = "+process.env.VERSION,{title:"ERROR"});
boot += `if(E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\\.boot\\.js/)+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`; throw new Error("Old firmware");
} else {
let CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/))+E.CRC32(process.env.GIT_COMMIT);
boot += `if(E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\\.boot\\.js/))+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`;
} }
boot += `{eval(require('Storage').read('bootupdate.js'));print("Storage Updated!")}else{\n`; let CRC = E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\.js$/)+E.CRC32(process.env.GIT_COMMIT);
boot += `if(E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\\.js$/)+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`;
boot += `{eval(require('Storage').read('bootupdate.js'));}else{\n`;
boot += `E.setFlags({pretokenise:1});\n`; boot += `E.setFlags({pretokenise:1});\n`;
boot += `var bleServices = {}, bleServiceOptions = { uart : true};\n`; boot += `var bleServices = {}, bleServiceOptions = { uart : true};\n`;
bootPost += `NRF.setServices(bleServices,bleServiceOptions);delete bleServices,bleServiceOptions;\n`; // executed after other boot code bootPost += `NRF.setServices(bleServices,bleServiceOptions);delete bleServices,bleServiceOptions;\n`; // executed after other boot code
@ -44,7 +43,7 @@ LoopbackA.setConsole(true);\n`;
boot += ` boot += `
Bluetooth.line=""; Bluetooth.line="";
Bluetooth.on('data',function(d) { Bluetooth.on('data',function(d) {
var l = (Bluetooth.line + d).split(/[\\n\\r]/); let l = (Bluetooth.line + d).split(/[\\n\\r]/);
Bluetooth.line = l.pop(); Bluetooth.line = l.pop();
l.forEach(n=>Bluetooth.emit("line",n)); l.forEach(n=>Bluetooth.emit("line",n));
}); });
@ -67,12 +66,12 @@ if (s.ble===false) boot += `if (!NRF.getSecurityStatus().connected) NRF.sleep();
if (s.timeout!==undefined) boot += `Bangle.setLCDTimeout(${s.timeout});\n`; if (s.timeout!==undefined) boot += `Bangle.setLCDTimeout(${s.timeout});\n`;
if (!s.timeout) boot += `Bangle.setLCDPower(1);\n`; if (!s.timeout) boot += `Bangle.setLCDPower(1);\n`;
boot += `E.setTimeZone(${s.timezone});`; boot += `E.setTimeZone(${s.timezone});`;
// Draw out of memory errors onto the screen // Draw out of memory errors onto the screen if logging enabled
boot += `E.on('errorFlag', function(errorFlags) { if (s.log) boot += `E.on('errorFlag', function(errorFlags) {
g.reset(1).setColor("#ff0000").setFont("6x8").setFontAlign(0,1).drawString(errorFlags,g.getWidth()/2,g.getHeight()-1).flip(); g.reset(1).setColor("#ff0000").setFont("6x8").setFontAlign(0,1).drawString(errorFlags,g.getWidth()/2,g.getHeight()-1).flip();
print("Interpreter error:", errorFlags); print("Interpreter error:", errorFlags);
E.getErrorFlags(); // clear flags so we get called next time E.getErrorFlags();
});\n`; });\n`;// E.getErrorFlags() -> clear flags so we get called next time
// stop users doing bad things! // stop users doing bad things!
if (global.save) boot += `global.save = function() { throw new Error("You can't use save() on Bangle.js without overwriting the bootloader!"); }\n`; if (global.save) boot += `global.save = function() { throw new Error("You can't use save() on Bangle.js without overwriting the bootloader!"); }\n`;
// Apply any settings-specific stuff // Apply any settings-specific stuff
@ -86,30 +85,18 @@ if (s.bleprivacy || (s.passkey!==undefined && s.passkey.length==6)) {
if (s.blename === false) boot+=`NRF.setAdvertising({},{showName:false});\n`; if (s.blename === false) boot+=`NRF.setAdvertising({},{showName:false});\n`;
if (s.whitelist && !s.whitelist_disabled) boot+=`NRF.on('connect', function(addr) { if (!NRF.ignoreWhitelist) { let whitelist = (require('Storage').readJSON('setting.json',1)||{}).whitelist; if (NRF.resolveAddress !== undefined) { let resolvedAddr = NRF.resolveAddress(addr); if (resolvedAddr !== undefined) addr = resolvedAddr + " (resolved)"; } if (!whitelist.includes(addr)) NRF.disconnect(); }});\n`; if (s.whitelist && !s.whitelist_disabled) boot+=`NRF.on('connect', function(addr) { if (!NRF.ignoreWhitelist) { let whitelist = (require('Storage').readJSON('setting.json',1)||{}).whitelist; if (NRF.resolveAddress !== undefined) { let resolvedAddr = NRF.resolveAddress(addr); if (resolvedAddr !== undefined) addr = resolvedAddr + " (resolved)"; } if (!whitelist.includes(addr)) NRF.disconnect(); }});\n`;
if (s.rotate) boot+=`g.setRotation(${s.rotate&3},${s.rotate>>2});\n` // screen rotation if (s.rotate) boot+=`g.setRotation(${s.rotate&3},${s.rotate>>2});\n` // screen rotation
boot+=`Bangle.loadWidgets=function(){if(!global.WIDGETS)eval(require("Storage").read(".widcache"))};\n`;
// ================================================== FIXING OLDER FIRMWARES // ================================================== FIXING OLDER FIRMWARES
if (FWVERSION<215.068) // 2v15.68 and before had compass heading inverted.
boot += `Bangle.on('mag',e=>{if(!isNaN(e.heading))e.heading=360-e.heading;});
Bangle.getCompass=(c=>(()=>{e=c();if(!isNaN(e.heading))e.heading=360-e.heading;return e;}))(Bangle.getCompass);`;
// deleting stops us getting confused by our own decl. builtins can't be deleted // deleting stops us getting confused by our own decl. builtins can't be deleted
// this is a polyfill without fastloading capability // this is a polyfill without fastloading capability
delete Bangle.showClock; delete Bangle.showClock;
if (!Bangle.showClock) boot += `Bangle.showClock = ()=>{load(".bootcde")};\n`; if (!Bangle.showClock) boot += `Bangle.showClock = ()=>{load(".bootcde")};\n`;
delete Bangle.load; delete Bangle.load;
if (!Bangle.load) boot += `Bangle.load = load;\n`; if (!Bangle.load) boot += `Bangle.load = load;\n`;
let date = new Date();
delete date.toLocalISOString; // toLocalISOString was only introduced in 2v15
if (!date.toLocalISOString) boot += `Date.prototype.toLocalISOString = function() {
var o = this.getTimezoneOffset();
var d = new Date(this.getTime() - o*60000);
var sign = o>0?"-":"+";
o = Math.abs(o);
return d.toISOString().slice(0,-1)+sign+Math.floor(o/60).toString().padStart(2,0)+(o%60).toString().padStart(2,0);
};\n`;
// show timings // show timings
if (DEBUG) boot += `print(".boot0",0|(Date.now()-_tm),"ms");_tm=Date.now();\n` if (DEBUG) boot += `print(".boot0",0|(Date.now()-_tm),"ms");_tm=Date.now();\n`
// ================================================== BOOT.JS // ================================================== .BOOT0
// Append *.boot.js files. // Append *.boot.js files.
// Name files with a number - eg 'foo.5.boot.js' to enforce order (lowest first). Numbered files get placed before non-numbered // Name files with a number - eg 'foo.5.boot.js' to enforce order (lowest first). Numbered files get placed before non-numbered
// These could change bleServices/bleServiceOptions if needed // These could change bleServices/bleServiceOptions if needed
@ -128,17 +115,47 @@ let bootFiles = require('Storage').list(/\.boot\.js$/).sort((a,b)=>{
}); });
// precalculate file size // precalculate file size
bootPost += "}"; bootPost += "}";
let fileSize = boot.length + bootPost.length; let fileOffset,fileSize;
bootFiles.forEach(bootFile=>{ /* code to output a file, plus preable and postable
// match the size of data we're adding below in bootFiles.forEach when called with dst==undefined it just increments
if (DEBUG) fileSize += 2+bootFile.length+1; // `//${bootFile}\n` comment fileOffset so we can see ho wbig the file has to be */
fileSize += require('Storage').read(bootFile).length+2; // boot code plus ";\n" let outputFile = (dst,src,pre,post) => {"ram";
if (DEBUG) fileSize += 48+E.toJS(bootFile).length; // `print(${E.toJS(bootFile)},0|(Date.now()-_tm),"ms");_tm=Date.now();\n` if (DEBUG) {
}); if (dst) require('Storage').write(dst,`//${src}\n`,fileOffset);
// write file in chunks (so as not to use up all RAM) fileOffset+=2+src.length+1;
require('Storage').write('.boot0',boot,0,fileSize); }
let fileOffset = boot.length; if (pre) {
bootFiles.forEach(bootFile=>{ if (dst) require('Storage').write(dst,pre,fileOffset);
fileOffset+=pre.length;
}
let f = require('Storage').read(src);
if (src.endsWith("clkinfo.js") && f[0]!="(") {
/* we shouldn't have to do this but it seems sometimes (sched 0.28) folks have
used libraries which get added into the clockinfo, and we can't use them directly
to we have to revert back to eval */
f = `eval(require('Storage').read(${E.toJS(src)}))`;
}
if (dst) {
// we can't just write 'f' in one go because it can be too big
let len = f.length;
let offset = 0;
while (len) {
let chunk = Math.min(len, 2048);
require('Storage').write(dst,f.substr(offset, chunk),fileOffset);
fileOffset+=chunk;
offset+=chunk;
len-=chunk;
}
} else
fileOffset+=f.length;
if (dst) require('Storage').write(dst,post,fileOffset);
fileOffset+=post.length;
if (DEBUG) {
if (dst) require('Storage').write(dst,`print(${E.toJS(src)},0|(Date.now()-_tm),"ms");_tm=Date.now();\n`,fileOffset);
fileOffset += 48+E.toJS(src).length;
}
};
let outputFileComplete = (dst,fn) => {
// we add a semicolon so if the file is wrapped in (function(){ ... }() // we add a semicolon so if the file is wrapped in (function(){ ... }()
// with no semicolon we don't end up with (function(){ ... }()(function(){ ... }() // with no semicolon we don't end up with (function(){ ... }()(function(){ ... }()
// which would cause an error! // which would cause an error!
@ -146,31 +163,48 @@ bootFiles.forEach(bootFile=>{
// "//"+bootFile+"\n"+require('Storage').read(bootFile)+";\n"; // "//"+bootFile+"\n"+require('Storage').read(bootFile)+";\n";
// but we need to do this without ever loading everything into RAM as some // but we need to do this without ever loading everything into RAM as some
// boot files seem to be getting pretty big now. // boot files seem to be getting pretty big now.
if (DEBUG) { outputFile(dst,fn,"",";\n");
require('Storage').write('.boot0',`//${bootFile}\n`,fileOffset); };
fileOffset+=2+bootFile.length+1; fileOffset = boot.length + bootPost.length;
} bootFiles.forEach(fn=>outputFileComplete(undefined,fn)); // just get sizes
let bf = require('Storage').read(bootFile); fileSize = fileOffset;
// we can't just write 'bf' in one go because at least in 2v13 and earlier require('Storage').write('.boot0',boot,0,fileSize);
// Espruino wants to read the whole file into RAM first, and on Bangle.js 1 fileOffset = boot.length;
// it can be too big (especially BTHRM). bootFiles.forEach(fn=>outputFileComplete('.boot0',fn));
let bflen = bf.length;
let bfoffset = 0;
while (bflen) {
let bfchunk = Math.min(bflen, 2048);
require('Storage').write('.boot0',bf.substr(bfoffset, bfchunk),fileOffset);
fileOffset+=bfchunk;
bfoffset+=bfchunk;
bflen-=bfchunk;
}
require('Storage').write('.boot0',";\n",fileOffset);
fileOffset+=2;
if (DEBUG) {
require('Storage').write('.boot0',`print(${E.toJS(bootFile)},0|(Date.now()-_tm),"ms");_tm=Date.now();\n`,fileOffset);
fileOffset += 48+E.toJS(bootFile).length
}
});
require('Storage').write('.boot0',bootPost,fileOffset); require('Storage').write('.boot0',bootPost,fileOffset);
delete boot,bootPost,bootFiles;
// ================================================== .WIDCACHE for widgets
let widgetFiles = require("Storage").list(/\.wid\.js$/);
let widget = `// Made by bootupdate.js\nglobal.WIDGETS={};`, widgetPost = `var W=WIDGETS;WIDGETS={};
Object.keys(W).sort((a,b)=>(0|W[b].sortorder)-(0|W[a].sortorder)).forEach(k=>WIDGETS[k]=W[k]);`; // sort
if (DEBUG) widget+="var _tm=Date.now();";
outputFileComplete = (dst,fn) => {
outputFile(dst,fn,"try{",`}catch(e){print(${E.toJS(fn)},e,e.stack)}\n`);
};
fileOffset = widget.length + widgetPost.length;
widgetFiles.forEach(fn=>outputFileComplete(undefined,fn)); // just get sizes
fileSize = fileOffset;
require('Storage').write('.widcache',widget,0,fileSize);
fileOffset = widget.length;
widgetFiles.forEach(fn=>outputFileComplete('.widcache',fn));
require('Storage').write('.widcache',widgetPost,fileOffset);
delete widget,widgetPost,widgetFiles;
// ================================================== .clkinfocache for clockinfos
let ciFiles = require("Storage").list(/\.clkinfo\.js$/);
let ci = `// Made by bootupdate.js\n`;
if (DEBUG) ci+="var _tm=Date.now();";
outputFileComplete = (dst,fn) => {
outputFile(dst,fn,"try{let fn=",`;let a=fn(),b=menu.find(x=>x.name===a.name);if(b)b.items=b.items.concat(a.items)else menu=menu.concat(a);}catch(e){print(${E.toJS(fn)},e,e.stack)}\n`);
};
fileOffset = ci.length;
ciFiles.forEach(fn=>outputFileComplete(undefined,fn)); // just get sizes
fileSize = fileOffset;
require('Storage').write('.clkinfocache',ci,0,fileSize);
fileOffset = ci.length;
ciFiles.forEach(fn=>outputFileComplete('.clkinfocache',fn));
delete ci,ciFiles;
// test with require("clock_info").load()
// ================================================== END
E.showMessage(/*LANG*/"Reloading..."); E.showMessage(/*LANG*/"Reloading...");
} }
// .bootcde should be run automatically after if required, since // .bootcde should be run automatically after if required, since

View File

@ -1,7 +1,7 @@
{ {
"id": "boot", "id": "boot",
"name": "Bootloader", "name": "Bootloader",
"version": "0.63", "version": "0.65",
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
"icon": "bootloader.png", "icon": "bootloader.png",
"type": "bootloader", "type": "bootloader",
@ -11,6 +11,9 @@
{"name":".boot0","url":"boot0.js"}, {"name":".boot0","url":"boot0.js"},
{"name":".bootcde","url":"bootloader.js"}, {"name":".bootcde","url":"bootloader.js"},
{"name":"bootupdate.js","url":"bootupdate.js"} {"name":"bootupdate.js","url":"bootupdate.js"}
],"data": [
{"name":".widcache"},
{"name":".clkinfocache"}
], ],
"sortorder": -10 "sortorder": -10
} }

View File

@ -11,3 +11,5 @@
0.10: Fix focus bug when changing focus between two clock infos 0.10: Fix focus bug when changing focus between two clock infos
0.11: Prepend swipe listener if possible 0.11: Prepend swipe listener if possible
0.12: Add drawFilledImage to allow drawing icons with a separately coloured middle 0.12: Add drawFilledImage to allow drawing icons with a separately coloured middle
0.13: Cache loaded ClockInfos so if we have clockInfoWidget and a clock, we don't load them twice (saves ~300ms)
0.14: Check for .clkinfocache and use that if exists (from boot 0.64)

View File

@ -14,6 +14,8 @@ if (stepGoal == undefined) {
exports.loadCount = 0; exports.loadCount = 0;
/// A list of all the instances returned by addInteractive /// A list of all the instances returned by addInteractive
exports.clockInfos = []; exports.clockInfos = [];
/// A list of loaded clockInfos
exports.clockInfoMenus = undefined;
/// Load the settings, with defaults /// Load the settings, with defaults
exports.loadSettings = function() { exports.loadSettings = function() {
@ -29,6 +31,8 @@ exports.loadSettings = function() {
/// Load a list of ClockInfos - this does not cache and reloads each time /// Load a list of ClockInfos - this does not cache and reloads each time
exports.load = function() { exports.load = function() {
if (exports.clockInfoMenus)
return exports.clockInfoMenus;
var settings = exports.loadSettings(); var settings = exports.loadSettings();
delete settings.apps; // keep just the basic settings in memory delete settings.apps; // keep just the basic settings in memory
// info used for drawing... // info used for drawing...
@ -131,10 +135,14 @@ exports.load = function() {
hide : function() { clearInterval(this.interval); delete this.interval; }, hide : function() { clearInterval(this.interval); delete this.interval; },
}); });
} }
var clkInfoCache = require('Storage').read('.clkinfocache');
if (clkInfoCache!==undefined) {
// note: code below is included in clkinfocache by bootupdate.js
// we use clkinfocache if it exists as it's faster
eval(clkInfoCache);
} else require("Storage").list(/clkinfo\.js$/).forEach(fn => {
// In case there exists already a menu object b with the same name as the next // In case there exists already a menu object b with the same name as the next
// object a, we append the items. Otherwise we add the new object a to the list. // object a, we append the items. Otherwise we add the new object a to the list.
require("Storage").list(/clkinfo.js$/).forEach(fn => {
try{ try{
var a = eval(require("Storage").read(fn))(); var a = eval(require("Storage").read(fn))();
var b = menu.find(x => x.name === a.name); var b = menu.find(x => x.name === a.name);
@ -146,6 +154,7 @@ exports.load = function() {
}); });
// return it all! // return it all!
exports.clockInfoMenus = menu;
return menu; return menu;
}; };
@ -345,6 +354,9 @@ exports.addInteractive = function(menu, options) {
menuHideItem(menu[options.menuA].items[options.menuB]); menuHideItem(menu[options.menuA].items[options.menuB]);
exports.loadCount--; exports.loadCount--;
delete exports.clockInfos[options.index]; delete exports.clockInfos[options.index];
// If nothing loaded now, clear our list of loaded menus
if (exports.loadCount==0)
exports.clockInfoMenus = undefined;
}; };
options.redraw = function() { options.redraw = function() {
drawItem(menu[options.menuA].items[options.menuB]); drawItem(menu[options.menuA].items[options.menuB]);

View File

@ -1,7 +1,7 @@
{ "id": "clock_info", { "id": "clock_info",
"name": "Clock Info Module", "name": "Clock Info Module",
"shortName": "Clock Info", "shortName": "Clock Info",
"version":"0.12", "version":"0.14",
"description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)", "description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)",
"icon": "app.png", "icon": "app.png",
"type": "module", "type": "module",

View File

@ -5,3 +5,4 @@
'Plasma' generative background 'Plasma' generative background
Add a 'view' option in settings menu to view the current background Add a 'view' option in settings menu to view the current background
0.05: Random square+plasma speed improvements (~2x faster) 0.05: Random square+plasma speed improvements (~2x faster)
0.06: 25% speed improvement if Math.randInt exists (2v25 fw)

View File

@ -1,6 +1,7 @@
let settings; let settings;
exports.reload = function() { exports.reload = function() {
//let t = Date.now();
settings = Object.assign({ settings = Object.assign({
style : "randomcolor", style : "randomcolor",
colors : ["#F00","#0F0","#00F"] colors : ["#F00","#0F0","#00F"]
@ -17,7 +18,8 @@ exports.reload = function() {
let bpp = (settings.colors.length>4)?4:2; let bpp = (settings.colors.length>4)?4:2;
let bg = Graphics.createArrayBuffer(11,11,bpp,{msb:true}); let bg = Graphics.createArrayBuffer(11,11,bpp,{msb:true});
let u32 = new Uint32Array(bg.buffer); // faster to do 1/4 of the ops of E.mapInPlace(bg.buffer, bg.buffer, ()=>Math.random()*256); let u32 = new Uint32Array(bg.buffer); // faster to do 1/4 of the ops of E.mapInPlace(bg.buffer, bg.buffer, ()=>Math.random()*256);
E.mapInPlace(u32, u32, function(r,n){"ram";return r()*n}.bind(null,Math.random,0x100000000)); // random pixels if (Math.randInt) E.mapInPlace(u32, u32, Math.randInt); // random pixels
else E.mapInPlace(u32, u32, function(r,n){"ram";return r()*n}.bind(null,Math.random,0x100000000)); // random pixels
bg.buffer[bg.buffer.length-1]=Math.random()*256; // 11x11 isn't a multiple of 4 bytes - we need to set the last one! bg.buffer[bg.buffer.length-1]=Math.random()*256; // 11x11 isn't a multiple of 4 bytes - we need to set the last one!
bg.palette = new Uint16Array(1<<bpp); bg.palette = new Uint16Array(1<<bpp);
bg.palette.set(settings.colors.map(c=>g.toColor(c))); bg.palette.set(settings.colors.map(c=>g.toColor(c)));
@ -28,7 +30,8 @@ exports.reload = function() {
settings.style = "image"; settings.style = "image";
let bg = Graphics.createArrayBuffer(16,16,4,{msb:true}); let bg = Graphics.createArrayBuffer(16,16,4,{msb:true});
let u32 = new Uint32Array(bg.buffer); // faster to do 1/4 of the ops of E.mapInPlace(bg.buffer, bg.buffer, ()=>Math.random()*256); let u32 = new Uint32Array(bg.buffer); // faster to do 1/4 of the ops of E.mapInPlace(bg.buffer, bg.buffer, ()=>Math.random()*256);
E.mapInPlace(u32, u32, function(r,n){"ram";return r()*n}.bind(null,Math.random,0x100000000)); // random pixels if (Math.randInt) E.mapInPlace(u32, u32, Math.randInt); // random pixels
else E.mapInPlace(u32, u32, function(r,n){"ram";return r()*n}.bind(null,Math.random,0x100000000)); // random pixels
bg.filter([ // a gaussian filter to smooth out bg.filter([ // a gaussian filter to smooth out
1, 4, 7, 4, 1, 1, 4, 7, 4, 1,
4,16,26,16, 4, 4,16,26,16, 4,
@ -42,6 +45,7 @@ exports.reload = function() {
settings.imgOpt = {scale:11}; settings.imgOpt = {scale:11};
delete settings.colors; delete settings.colors;
} }
//console.log("bg",Date.now()-t);
}; };
exports.reload(); exports.reload();

View File

@ -1,7 +1,7 @@
{ "id": "clockbg", { "id": "clockbg",
"name": "Clock Backgrounds", "name": "Clock Backgrounds",
"shortName":"Backgrounds", "shortName":"Backgrounds",
"version": "0.05", "version": "0.06",
"description": "Library that allows clocks to include a custom background (generated on demand or uploaded).", "description": "Library that allows clocks to include a custom background (generated on demand or uploaded).",
"icon": "app.png", "icon": "app.png",
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}], "screenshots": [{"url":"screenshot.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}],

View File

@ -5,3 +5,4 @@
0.04: Enhance menu: enable bluetooth, visit settings & visit recovery 0.04: Enhance menu: enable bluetooth, visit settings & visit recovery
0.05: Enhance menu: permit toggling bluetooth 0.05: Enhance menu: permit toggling bluetooth
0.06: Display clock in green when charging, with "charging" text 0.06: Display clock in green when charging, with "charging" text
0.07: Correctly restore full power when the charged threshold is reached

View File

@ -88,7 +88,7 @@ var reload = function () {
}; };
reload(); reload();
Bangle.emit("drained", E.getBattery()); Bangle.emit("drained", E.getBattery());
var _a = require("Storage").readJSON("".concat(app, ".setting.json"), true) || {}, _b = _a.keepStartup, keepStartup = _b === void 0 ? true : _b, _c = _a.restore, restore = _c === void 0 ? 20 : _c, _d = _a.exceptions, exceptions = _d === void 0 ? ["widdst.0"] : _d; var _a = require("Storage").readJSON("".concat(app, ".setting.json"), true) || {}, _b = _a.keepStartup, keepStartup = _b === void 0 ? true : _b, _c = _a.restore, restore = _c === void 0 ? 20 : _c, _d = _a.exceptions, exceptions = _d === void 0 ? ["widdst.0"] : _d, _e = _a.interval, interval = _e === void 0 ? 10 : _e;
function drainedRestore() { function drainedRestore() {
if (!keepStartup) { if (!keepStartup) {
try { try {
@ -110,8 +110,10 @@ var checkCharge = function () {
if (Bangle.isCharging()) if (Bangle.isCharging())
checkCharge(); checkCharge();
Bangle.on("charging", function (charging) { Bangle.on("charging", function (charging) {
if (drainedInterval)
drainedInterval = clearInterval(drainedInterval);
if (charging) if (charging)
checkCharge(); drainedInterval = setInterval(checkCharge, interval * 60 * 1000);
}); });
if (!keepStartup) { if (!keepStartup) {
var storage = require("Storage"); var storage = require("Storage");

View File

@ -115,7 +115,7 @@ reload();
Bangle.emit("drained", E.getBattery()); Bangle.emit("drained", E.getBattery());
// restore normal boot on charge // restore normal boot on charge
const { keepStartup = true, restore = 20, exceptions = ["widdst.0"] }: DrainedSettings const { keepStartup = true, restore = 20, exceptions = ["widdst.0"], interval = 10 }: DrainedSettings
= require("Storage").readJSON(`${app}.setting.json`, true) || {}; = require("Storage").readJSON(`${app}.setting.json`, true) || {};
// re-enable normal boot code when we're above a threshold: // re-enable normal boot code when we're above a threshold:
@ -142,7 +142,10 @@ if (Bangle.isCharging())
checkCharge(); checkCharge();
Bangle.on("charging", charging => { Bangle.on("charging", charging => {
if(charging) checkCharge(); if(drainedInterval)
drainedInterval = clearInterval(drainedInterval) as undefined;
if(charging)
drainedInterval = setInterval(checkCharge, interval * 60 * 1000);
}); });
if(!keepStartup){ if(!keepStartup){

View File

@ -1,7 +1,7 @@
{ {
"id": "drained", "id": "drained",
"name": "Drained", "name": "Drained",
"version": "0.06", "version": "0.07",
"description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals", "description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals",
"readme": "README.md", "readme": "README.md",
"icon": "icon.png", "icon": "icon.png",

View File

@ -30,3 +30,4 @@ when moving pages. Add caching for faster startups.
0.23: Bangle 1: Fix issue with missing icons, added touch screen interactions 0.23: Bangle 1: Fix issue with missing icons, added touch screen interactions
0.24: Add buzz-on-interaction setting 0.24: Add buzz-on-interaction setting
0.25: Minor code improvements 0.25: Minor code improvements
0.26: Bangle 2: Postpone loading icons that are not needed initially.

View File

@ -33,10 +33,10 @@
s.writeJSON("launch.cache.json", launchCache); s.writeJSON("launch.cache.json", launchCache);
} }
let apps = launchCache.apps; let apps = launchCache.apps;
apps.forEach(app=>{ for (let i = 0; i < 4; i++) { // Initially only load icons for the current page.
if (app.icon) if (apps[i].icon)
app.icon = s.read(app.icon); // should just be a link to a memory area apps[i].icon = s.read(apps[i].icon); // should just be a link to a memory area
}); }
let Napps = apps.length; let Napps = apps.length;
let Npages = Math.ceil(Napps/4); let Npages = Math.ceil(Napps/4);
@ -101,6 +101,11 @@
Bangle.loadWidgets(); Bangle.loadWidgets();
drawPage(0); drawPage(0);
for (let i = 4; i < apps.length; i++) { // Load the rest of the app icons that were not initially.
if (apps[i].icon)
apps[i].icon = s.read(apps[i].icon); // should just be a link to a memory area
}
let swipeListenerDt = function(dirLeftRight, dirUpDown){ let swipeListenerDt = function(dirLeftRight, dirUpDown){
updateTimeoutToClock(); updateTimeoutToClock();
selected = -1; selected = -1;

View File

@ -1,7 +1,7 @@
{ {
"id": "dtlaunch", "id": "dtlaunch",
"name": "Desktop Launcher", "name": "Desktop Launcher",
"version": "0.25", "version": "0.26",
"description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.", "description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.",
"screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}], "screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}],
"icon": "icon.png", "icon": "icon.png",

View File

@ -21,3 +21,4 @@
0.34: Fix 'fast load' so clock doesn't always redraw when screen unlocked/locked 0.34: Fix 'fast load' so clock doesn't always redraw when screen unlocked/locked
0.35: Minor code improvements 0.35: Minor code improvements
0.36: Minor code improvements 0.36: Minor code improvements
0.37: Fix settings (show default as '90' not 'off')

View File

@ -2,7 +2,7 @@
"id": "hworldclock", "id": "hworldclock",
"name": "Hanks World Clock", "name": "Hanks World Clock",
"shortName": "Hanks World Clock", "shortName": "Hanks World Clock",
"version": "0.36", "version": "0.37",
"description": "Current time zone plus up to three others", "description": "Current time zone plus up to three others",
"allow_emulator":true, "allow_emulator":true,
"icon": "app.png", "icon": "app.png",

View File

@ -2,6 +2,7 @@
var FILE = "hworldclock.json"; var FILE = "hworldclock.json";
var settings = Object.assign({ var settings = Object.assign({
secondsOnUnlock: false, secondsOnUnlock: false,
rotationTarget: "90",
}, require('Storage').readJSON(FILE, true) || {}); }, require('Storage').readJSON(FILE, true) || {});
function writeSettings() { function writeSettings() {
@ -55,4 +56,4 @@
E.showMenu(mainmenu); E.showMenu(mainmenu);
}); })

View File

@ -1 +1,2 @@
0.01: New App! 0.01: New App!
0.02: Accents and extended mode characters

View File

@ -12,7 +12,14 @@ To display the in app character chart, long press the screen; you can scroll thr
For a full character chart see [EwChart.pdf](EwChart.pdf) For a full character chart see [EwChart.pdf](EwChart.pdf)
**Supported:** Letters (including capitals), numbers, backspace, word backspace, space, punctuation, new line, and some cursor controls (left, right, word left/right, home, end). **Supported:** Letters (including capitals), numbers, backspace, word backspace, space, punctuation, new line, accents, extended mode (if characters are supported by the vector font), and some cursor controls (left, right, word left/right, home, end).
**Unsupported:** Extended mode, accents, and word-level stroking. **Unsupported:** Word-level stroking.
## Settings
Font size can be selected in Settings app > "Apps" > "EdgeWrite Keyboard"
## Author
Woogal [github](https://github.com/retcurve)

View File

@ -193,17 +193,93 @@
"2425": "`", "2425": "`",
"31": " \n", "31": " \n",
"24": " ", "24": " ",
"46": "\xb7",
"432146": "\xb0",
"412346": "\xb0",
"123246": "\xae",
"2123246": "\xae",
"123146": "\xae",
"2123146": "\xae",
"2346": "\xac",
"32146": "\xa9",
"41236": "\xa2",
"24316": "\xd7",
"31246": "\xd7",
"316": "\xf7",
"136": "\xf7",
"232146": "\x80",
"23246": "\x80",
"132146": "\x80",
"412316": "\x80",
"323146": "\x80",
"324146": "\x80",
"24346": "\xa5",
"243416": "\xa5",
"2143416": "\xa5",
"34146": "\xf0",
"342146": "\xf0",
"343146": "\xf0",
"4214346": "\xf0",
"414346": "\xf0",
"434146": "\xf0",
"123416": "\xf0",
"2123416": "\xf0",
"1346": "\xe6",
"1246": "\xe6",
"13416": "\xe6",
"12416": "\xe6",
"3214346": "\xe6",
"21416": "\xdf",
"213416": "\xdf",
"212416": "\xdf",
"141216": "\xdf",
"1341216": "\xdf",
"121416": "\xdf",
"1232416": "\xdf",
"1231416": "\xdf",
"21232416": "\xdf",
"21231416": "\xdf",
"2321416": "\xdf",
"2146": "\xa3",
"21436": "\xb5",
"214346": "\xb5",
"121436": "\xb5",
"1214346": "\xb5",
"3214316": "\xf8",
"3412316": "\xf8",
"4126": "\xbf",
"216": "\xa1",
"346": "\xa6",
"21236": "\xb1",
"212326": "\xb1",
"31426": "\xa4",
"24136": "\xa4",
"3146": "\xab",
"2416": "\xbb",
"32": "#bs", "32": "#bs",
"41": "#wbs", "41": "#wbs",
"12": "#pu-on", "12": "#pu-on",
"43": "#pu-on", "43": "#pu-on",
"325": "#pu-off", "325": "#pu-off",
"415": "#pu-off", "415": "#pu-off",
"42": "#ex-on",
"326": "#ex-off",
"416": "#ex-off",
"323": "#cur-left", "323": "#cur-left",
"232": "#cur-right", "232": "#cur-right",
"414": "#cur-word-left", "414": "#cur-word-left",
"141": "#cur-word-right", "141": "#cur-word-right",
"4141": "#cur-home", "4141": "#cur-home",
"1414": "#cur-end" "1414": "#cur-end",
"242": "#grave",
"313": "#acute",
"431": "#circumflex",
"421": "#circumflex",
"3421": "#tilde",
"43412": "#umlaut",
"43214": "#ring",
"41234": "#ring",
"142": "#cedilla",
"143": "#cedilla"
} }

View File

@ -7,10 +7,20 @@ exports.input = function(options) {
let chartX = 0; let chartX = 0;
let chartY = 0; let chartY = 0;
let settings = Object.assign({
fontSize: 32,
}, require('Storage').readJSON("kbedgewrite.json", true));
let shouldShowWidgetBar = Bangle.appRect.y > 0; let shouldShowWidgetBar = Bangle.appRect.y > 0;
options = options||{}; options = options||{};
let text = options.text; let text = options.text;
// Substring doesn't play well with UTF8
if (E.isUTF8(text)) {
text = E.decodeUTF8(text);
}
let wrappedText = '';
if ('string' != typeof text) text=''; if ('string' != typeof text) text='';
// Colours for number of corner occurrences // Colours for number of corner occurrences
@ -18,40 +28,140 @@ exports.input = function(options) {
const cornerSize = g.getWidth() / 3; const cornerSize = g.getWidth() / 3;
let punctuationMode = false; let punctuationMode = false;
let extendedMode = false;
let path = ''; let path = '';
let cursorPos = text.length; let cursorPos = text.length;
let chartShown = false; let chartShown = false;
let characterSet = Object.assign({}, require('Storage').readJSON('kbedgewrite.charset.json', true) || {}); let characterSet = Object.assign({}, require('Storage').readJSON('kbedgewrite.charset.json', true) || {});
function draw() { const accentedCharacters = {
g.clearRect(Bangle.appRect).setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2); '#grave': {
'a': String.fromCharCode(0xE0),
'A': String.fromCharCode(0xC0),
'e': String.fromCharCode(0xE8),
'E': String.fromCharCode(0xC8),
'i': String.fromCharCode(0xEC),
'I': String.fromCharCode(0xCC),
'o': String.fromCharCode(0xF2),
'O': String.fromCharCode(0xD2),
'u': String.fromCharCode(0xF9),
'U': String.fromCharCode(0xD9)
},
'#acute': {
'a': String.fromCharCode(0xE1),
'A': String.fromCharCode(0xC1),
'e': String.fromCharCode(0xE9),
'E': String.fromCharCode(0xC9),
'i': String.fromCharCode(0xED),
'I': String.fromCharCode(0xCD),
'o': String.fromCharCode(0xF3),
'O': String.fromCharCode(0xD3),
'u': String.fromCharCode(0xFA),
'U': String.fromCharCode(0xDA),
'y': String.fromCharCode(0xFD),
'Y': String.fromCharCode(0xDD)
},
'#circumflex': {
'a': String.fromCharCode(0xE2),
'A': String.fromCharCode(0xC2),
'e': String.fromCharCode(0xEA),
'E': String.fromCharCode(0xCA),
'i': String.fromCharCode(0xEE),
'I': String.fromCharCode(0xCE),
'o': String.fromCharCode(0xF4),
'O': String.fromCharCode(0xD4),
'u': String.fromCharCode(0xFB),
'U': String.fromCharCode(0xDB)
},
'#umlaut': {
'a': String.fromCharCode(0xE4),
'A': String.fromCharCode(0xC4),
'e': String.fromCharCode(0xEB),
'E': String.fromCharCode(0xCB),
'i': String.fromCharCode(0xEF),
'I': String.fromCharCode(0xCF),
'o': String.fromCharCode(0xF6),
'O': String.fromCharCode(0xD6),
'u': String.fromCharCode(0xFC),
'U': String.fromCharCode(0xDC),
'y': String.fromCharCode(0xFF)
},
'#tilde': {
'a': String.fromCharCode(0xE3),
'A': String.fromCharCode(0xC3),
'n': String.fromCharCode(0xF1),
'N': String.fromCharCode(0xD1),
'o': String.fromCharCode(0xF5),
'O': String.fromCharCode(0xD5)
},
'#ring': {
'a': String.fromCharCode(0xE5),
'A': String.fromCharCode(0xC5)
},
'#cedilla': {
'c': String.fromCharCode(0xE7),
'C': String.fromCharCode(0xC7)
},
// Draw the text string };
let l = g.setFont('6x8:4').wrapString(text.substring(0, cursorPos) + '_' + text.substring(cursorPos), g.getWidth());
if (!l) l = []; function wrapText() {
if (l.length>5) { let stringToWrap = text.substring(0, cursorPos) + '_' + text.substring(cursorPos);
let l = [];
let startPos = 0;
g.setFont("Vector", settings.fontSize); // set the font so we can calculate a string width
// Wrap the string into array of lines that will fit the screen width
for (let i = 0; i < stringToWrap.length; i++) {
// wrap if string is too long or we hit a line break
if (stringToWrap.charCodeAt(i) == 10 || g.stringWidth(stringToWrap.substring(startPos, i+1)) > 176) {
l.push(stringToWrap.substring(startPos, i));
// skip the line break
if (stringToWrap.charCodeAt(i) == 10) {
i++;
}
startPos = i;
}
}
// Add the final line
l.push(stringToWrap.substring(startPos));
// Number of lines that can fit on the screen
let numLines = Math.floor(g.getHeight() / g.getFontHeight());
// If too many lines, reposition so the cursor can be seen
if (l.length > numLines) {
let textPos = 0; let textPos = 0;
let lineNum; let lineNum;
for (lineNum = 0; lineNum < l.length; lineNum++) { for (lineNum = 0; lineNum < l.length; lineNum++) {
textPos = textPos + l[lineNum].length - 1; textPos = textPos + l[lineNum].length;
if (textPos >= cursorPos) break; if (textPos >= cursorPos) break;
} }
l=l.slice(lineNum - l.length - 5); l=l.slice(lineNum - l.length - numLines + 1);
} }
g.setColor(g.theme.fg);
g.setFontAlign(-1, -1, 0);
g.drawString(l.join('\n'), Bangle.appRect.x, Bangle.appRect.y);
// Draw punctuation flag wrappedText = l.join('\n');
if (punctuationMode > 0) { }
function draw() {
g.clearRect(Bangle.appRect).setClipRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2);
g.setColor(g.theme.fg);
g.setFont("Vector", settings.fontSize);
g.setFontAlign(-1, -1, 0);
g.drawString(wrappedText, Bangle.appRect.x, Bangle.appRect.y);
// Draw punctuation or extended flags
if (punctuationMode || extendedMode) {
let x = (g.getWidth() / 2) - 12; let x = (g.getWidth() / 2) - 12;
let y = g.getHeight() - 32; let y = g.getHeight() - 32;
g.setColor('#F00'); g.setColor(punctuationMode ? '#F00' : '#0F0');
g.fillRect(x,y,x+24,y+32); g.fillRect(x,y,x+24,y+32);
g.setColor('#FFF'); g.setColor('#FFF');
g.setFont('6x8:4'); g.setFont('6x8:4');
g.drawString('P', x+4, y+4, false); g.drawString(punctuationMode ? 'P' : 'E', x+4, y+4, false);
} }
// Draw corners // Draw corners
@ -69,30 +179,27 @@ exports.input = function(options) {
} }
function processPath() { function processPath() {
let capital = false;
// Punctuation paths end in 5 // Punctuation paths end in 5
if (punctuationMode) { if (punctuationMode) {
path = path + '5'; path = path + '5';
} }
// Extended paths end in 6
// Capital letters end in 2, remove that and set a capital flag if (extendedMode) {
// but only if the path isn't 232 (cursor right) path = path + '6';
if (path != '232' && path.length > 2 && path.slice(-1) == '2') {
path = path.slice(0,-1);
capital = true;
} }
// Find character from path // Find character from path
let char = characterSet[path]; let char = characterSet[path];
// Unknown character, but ends in a 2 so may be a capital letter
if (char == 'undefined' && path.slice(-1) == '2') {
// Remove the 2 and look for a letter
char = characterSet[path.slice(0,-1)];
// Handle capitals // Handle capitals
if (capital && char != 'undefined') { if (char != 'undefined') {
if (char.charCodeAt(0)>96 && char.charCodeAt(0)<123) { if (char.charCodeAt(0)>96 && char.charCodeAt(0)<123) {
char = char.toUpperCase(); char = char.toUpperCase();
} else { }
// Anything that can't be capitalised is an invalid path
char = undefined;
} }
} }
@ -129,6 +236,17 @@ exports.input = function(options) {
punctuationMode = false; punctuationMode = false;
break; break;
} }
// Enable extended mode
case '#ex-on': {
extendedMode = true;
break;
}
// Disable extended mode
case '#ex-off': {
extendedMode = false;
break;
}
// Cursor controls
case '#cur-left': { case '#cur-left': {
if (cursorPos > 0) { if (cursorPos > 0) {
cursorPos--; cursorPos--;
@ -168,6 +286,22 @@ exports.input = function(options) {
cursorPos = text.length; cursorPos = text.length;
break; break;
} }
// Accents
case '#grave':
case '#acute':
case '#circumflex':
case '#umlaut':
case '#tilde':
case '#ring':
case '#cedilla':
// If the previous character can be accented, replace it with the accented version
if (cursorPos > 0) {
char = accentedCharacters[char][text.substring(cursorPos-1, cursorPos)];
if (char != 'undefined') {
text = text.substring(0, cursorPos-1) + char + text.substring(cursorPos);
}
}
break;
// Append character // Append character
default: { default: {
text = text.substring(0, cursorPos) + char + text.substring(cursorPos); text = text.substring(0, cursorPos) + char + text.substring(cursorPos);
@ -184,6 +318,7 @@ exports.input = function(options) {
if (!chartShown) { if (!chartShown) {
if (e.b == 0) { // Finger lifted, process completed path if (e.b == 0) { // Finger lifted, process completed path
processPath(); processPath();
wrapText();
draw(); draw();
} else { } else {
let corner = 0; let corner = 0;
@ -220,6 +355,7 @@ exports.input = function(options) {
// Draw initial string // Draw initial string
require("widget_utils").hide(); require("widget_utils").hide();
g.setBgColor(g.theme.bg); g.setBgColor(g.theme.bg);
wrapText();
draw(); draw();
return new Promise((resolve,reject) => { return new Promise((resolve,reject) => {

View File

@ -1,14 +1,19 @@
{ "id": "kbedgewrite", { "id": "kbedgewrite",
"name": "EdgeWrite keyboard", "name": "EdgeWrite keyboard",
"version":"0.01", "version":"0.02",
"description": "A library for text input via EdgeWrite swipe gestures", "description": "A library for text input via EdgeWrite swipe gestures",
"icon": "app.png", "icon": "app.png",
"type":"textinput", "type":"textinput",
"tags": "keyboard", "tags": "keyboard",
"supports" : ["BANGLEJS2"], "supports" : ["BANGLEJS2"],
"readme": "README.md", "readme": "README.md",
"screenshots" : [ { "url":"screenshot.png" } ],
"storage": [ "storage": [
{"name":"textinput","url":"lib.js"}, {"name":"textinput","url":"lib.js"},
{"name":"kbedgewrite.charset.json","url":"characterset.json"} {"name":"kbedgewrite.charset.json","url":"characterset.json"},
{"name":"kbedgewrite.settings.js","url":"settings.js"}
],
"data": [
{"name":"kbedgewrite.json"}
] ]
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,40 @@
(function(back) {
var FILE = 'kbedgewrite.json';
// Load settings
var settings = Object.assign({
fontSize: 32
}, require('Storage').readJSON(FILE, true) || {});
function setSetting(key,value) {
settings[key] = value;
require('Storage').writeJSON(FILE, settings);
}
// Helper method which uses int-based menu item for set of string values and their labels
function stringItems(key, startvalue, values, labels) {
return {
value: (startvalue === undefined ? 0 : values.indexOf(startvalue)),
format: v => labels[v],
min: 0,
max: values.length - 1,
wrap: true,
step: 1,
onchange: v => {
setSetting(key,values[v]);
}
};
}
// Helper method which breaks string set settings down to local settings object
function stringInSettings(name, values, labels) {
return stringItems(name,settings[name], values, labels);
}
// Show the menu
E.showMenu({
'' : { 'title' : 'EdgeWrite' },
'< Back' : () => back(),
'Font Size': stringInSettings('fontSize', [24, 32, 48], ['Small', 'Medium', 'Large'])
});
})

View File

@ -515,12 +515,6 @@ module.exports = {
"no-undef" "no-undef"
] ]
}, },
"apps/widbt_notify/widget.js": {
"hash": "16372ffcbc6bd1419ca326c7da40c2195f82a4bfceb6f123c15872624c4f0adf",
"rules": [
"no-undef"
]
},
"apps/widbgjs/widget.js": { "apps/widbgjs/widget.js": {
"hash": "9852ce9aafb0a1ca3029d497282c8cdf07438ea36a3323313bad5b7569b1081b", "hash": "9852ce9aafb0a1ca3029d497282c8cdf07438ea36a3323313bad5b7569b1081b",
"rules": [ "rules": [
@ -1157,12 +1151,6 @@ module.exports = {
"no-undef" "no-undef"
] ]
}, },
"apps/banglebridge/widget.js": {
"hash": "4ee8d6749e1d0e28c58ad871fd9f6ccbca2d716bb4fbd3511ba4c34a6a5897e1",
"rules": [
"no-undef"
]
},
"apps/bad/bad.app.js": { "apps/bad/bad.app.js": {
"hash": "d1354613102818190dd4e6e28fd715db7dc4d51b8e618cae61a3135529cc97eb", "hash": "d1354613102818190dd4e6e28fd715db7dc4d51b8e618cae61a3135529cc97eb",
"rules": [ "rules": [

View File

@ -177,7 +177,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mär 2020 // 01.03.20 datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mär 2020 // 01.03.20
abmonth: "Jan,Feb,Mär,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez", abmonth: "Jan,Feb,Mär,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
@ -194,7 +194,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%Y/%m/%d", 1: "%y/%m/%d" }, datePattern: { 0: "%Y/%m/%d", 1: "%y/%m/%d" },
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
@ -210,7 +210,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d %b %Y", 1: "%d-%m-%Y" }, // 28 feb 2020 // 28-02-2020 datePattern: { 0: "%d %b %Y", 1: "%d-%m-%Y" }, // 28 feb 2020 // 28-02-2020
abday: "zo,ma,di,wo,do,vr,za", abday: "zo,ma,di,wo,do,vr,za",
@ -258,7 +258,7 @@ var locales = {
speed: "km/h", speed: "km/h",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%Y" }, // 1 mars 2020 // 01/03/2020 datePattern: { 0: "%d %B %Y", "1": "%d/%m/%Y" }, // 1 mars 2020 // 01/03/2020
abmonth: "janv,févr,mars,avril,mai,juin,juil,août,sept,oct,nov,déc", abmonth: "janv,févr,mars,avril,mai,juin,juil,août,sept,oct,nov,déc",
@ -290,7 +290,7 @@ var locales = {
speed: 'km/h', speed: 'km/h',
distance: { "0": "m", "1": "km" }, distance: { "0": "m", "1": "km" },
temperature: '°C', temperature: '°C',
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%B %d %Y", "1": "%Y-%m-%d" }, // March 1 2020 // 2020-03-01 datePattern: { 0: "%B %d %Y", "1": "%Y-%m-%d" }, // March 1 2020 // 2020-03-01
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
@ -306,7 +306,7 @@ var locales = {
speed: "km/t", speed: "km/t",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d. %b. %Y", 1: "%d/%m %Y" }, // 1. feb. 2020 // 01/02 2020 // a better short ver. is 1/2 2020 but its not supported datePattern: { 0: "%d. %b. %Y", 1: "%d/%m %Y" }, // 1. feb. 2020 // 01/02 2020 // a better short ver. is 1/2 2020 but its not supported
abmonth: "jan,feb,mar,apr,maj,jun,jul,aug,sep,okt,nov,dec", abmonth: "jan,feb,mar,apr,maj,jun,jul,aug,sep,okt,nov,dec",
@ -322,7 +322,7 @@ var locales = {
speed: "km/h", speed: "km/h",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d. %b. %Y", 1: "%d/%m %Y" }, // 1. feb. 2020 // 01/02 2020 // a better short ver. is 1/2 2020 but its not supported datePattern: { 0: "%d. %b. %Y", 1: "%d/%m %Y" }, // 1. feb. 2020 // 01/02 2020 // a better short ver. is 1/2 2020 but its not supported
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
@ -370,7 +370,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%y" }, // Sonntag, 1. März 2020 // 01.03.20 datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%y" }, // Sonntag, 1. März 2020 // 01.03.20
abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez", abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
@ -403,7 +403,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%A, %d de %B de %Y", "1": "%d/%m/%y" }, // domingo, 1 de marzo de 2020 // 01/03/20 datePattern: { 0: "%A, %d de %B de %Y", "1": "%d/%m/%y" }, // domingo, 1 de marzo de 2020 // 01/03/20
abmonth: "ene,feb,mar,abr,may,jun,jul,ago,sept,oct,nov,dic", abmonth: "ene,feb,mar,abr,may,jun,jul,ago,sept,oct,nov,dic",
@ -420,7 +420,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20
abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
@ -484,7 +484,7 @@ var locales = {
speed: 'kmh', speed: 'kmh',
distance: { "0": "m", "1": "km" }, distance: { "0": "m", "1": "km" },
temperature: '°C', temperature: '°C',
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM.%SS", 1: "%HH:%MM" }, // 17:00.00 // 17:00 timePattern: { 0: "%HH:%MM.%SS", 1: "%HH:%MM" }, // 17:00.00 // 17:00
datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020 datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic", abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
@ -500,7 +500,7 @@ var locales = {
speed: 'kmh', speed: 'kmh',
distance: { "0": "m", "1": "km" }, distance: { "0": "m", "1": "km" },
temperature: '°C', temperature: '°C',
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM.%SS", 1: "%HH:%MM" }, // 17:00.00 // 17:00 timePattern: { 0: "%HH:%MM.%SS", 1: "%HH:%MM" }, // 17:00.00 // 17:00
datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020 datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic", abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
@ -516,7 +516,7 @@ var locales = {
speed: 'kmh', speed: 'kmh',
distance: { "0": "m", "1": "km" }, distance: { "0": "m", "1": "km" },
temperature: '°C', temperature: '°C',
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH.%MM.%SS", 1: "%HH.%MM" }, // 17.00.00 // 17.00 timePattern: { 0: "%HH.%MM.%SS", 1: "%HH.%MM" }, // 17.00.00 // 17.00
datePattern: { 0: "%A, %d. %B %Y", "1": "%Y-%m-%d" }, // Sunntag, 1. Märze 2020 // 2020-03-01 datePattern: { 0: "%A, %d. %B %Y", "1": "%Y-%m-%d" }, // Sunntag, 1. Märze 2020 // 2020-03-01
abmonth: "Jen,Hor,Mär,Abr,Mei,Brá,Hei,Öig,Her,Wím,Win,Chr", abmonth: "Jen,Hor,Mär,Abr,Mei,Brá,Hei,Öig,Her,Wím,Win,Chr",
@ -564,7 +564,7 @@ var locales = {
speed: "km/h", speed: "km/h",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%A %d %B de %Y", "1": "%d/%m/%Y" }, // dimenge 1 de març de 2020 // 01/03/2020 datePattern: { 0: "%A %d %B de %Y", "1": "%d/%m/%Y" }, // dimenge 1 de març de 2020 // 01/03/2020
abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.", abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.",
@ -660,7 +660,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2021 // 01.03.2021 datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2021 // 01.03.2021
abmonth: "Sty,Lut,Mar,Kwi,Maj,Cze,Lip,Sie,Wrz,Paź,Lis,Gru", abmonth: "Sty,Lut,Mar,Kwi,Maj,Cze,Lip,Sie,Wrz,Paź,Lis,Gru",
@ -676,7 +676,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20 datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20
abmonth: "Jan,Feb,Mar,Apr,Mai,Jūn,Jūl,Aug,Sep,Okt,Nov,Dec", abmonth: "Jan,Feb,Mar,Apr,Mai,Jūn,Jūl,Aug,Sep,Okt,Nov,Dec",
@ -692,7 +692,7 @@ var locales = {
speed: "kmt", speed: "kmt",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20 datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20
abmonth: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Des", abmonth: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Des",
@ -708,7 +708,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20 datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20
abmonth: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Des", abmonth: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Des",
@ -725,7 +725,7 @@ var locales = {
speed: "kmh", speed: "kmh",
distance: { 0: "m", 1: "km" }, distance: { 0: "m", 1: "km" },
temperature: "°C", temperature: "°C",
ampm: { 0: "", 1: "" }, ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" }, datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" },
abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.", abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.",

View File

@ -4,15 +4,15 @@
*/ */
const datetime_length_map = { const datetime_length_map = {
// %A, %a, %B, %b vary depending on the locale, so they are calculated later // %A, %a, %B, %b vary depending on the locale, so they are calculated later
"%Y": [4, 4], "%Y": [4, 4, "2024", "2024"],
"%y": [2, 2], "%y": [2, 2, "24", "24"],
"%m": [2, 2], "%m": [2, 2, "10", "10"],
"%-m": [1, 2], "%-m": [1, 2, "1", "10"],
"%d": [2, 2], "%d": [2, 2, "10", "10"],
"%-d": [1, 2], "%-d": [1, 2, "1", "10"],
"%HH": [2, 2], "%HH": [2, 2, "10", "10"],
"%MM": [2, 2], "%MM": [2, 2, "10", "10"],
"%SS": [2, 2], "%SS": [2, 2, "10", "10"],
}; };
/** /**
@ -33,17 +33,18 @@ function getLengthOfDatetimeFormat(name, datetimeEspruino, locale, errors) {
]) { ]) {
const length = [Infinity, 0]; const length = [Infinity, 0];
for(const value of values.split(",")){ for(const value of values.split(",")){
if(length[0] > value.length) length[0] = value.length; if(length[0] > value.length) { length[0] = value.length; length[2] = value; }
if(length[1] < value.length) length[1] = value.length; if(length[1] < value.length) { length[1] = value.length; length[3] = value; }
} }
length_map[symbol] = length; length_map[symbol] = length;
} }
// Find the length of the output // Find the length of the output
let formatLength = [0, 0]; let formatLength = [0, 0, "", ""];
let i = 0; let i = 0;
while (i < datetimeEspruino.length) { while (i < datetimeEspruino.length) {
if (datetimeEspruino[i] === "%") { let ch = datetimeEspruino[i];
if (ch === "%") {
let match; let match;
for(const symbolLength of [2, 3]){ for(const symbolLength of [2, 3]){
const length = length_map[datetimeEspruino.substring(i, i+symbolLength)]; const length = length_map[datetimeEspruino.substring(i, i+symbolLength)];
@ -57,16 +58,22 @@ function getLengthOfDatetimeFormat(name, datetimeEspruino, locale, errors) {
if(match){ if(match){
formatLength[0] += match.length[0]; formatLength[0] += match.length[0];
formatLength[1] += match.length[1]; formatLength[1] += match.length[1];
formatLength[2] += match.length[2];
formatLength[3] += match.length[3];
i += match.symbolLength; i += match.symbolLength;
}else{ }else{
errors.push({name, value: datetimeEspruino, lang: locale.lang, error: `uses an unsupported format symbol: ${datetimeEspruino.substring(i, i+3)}`}); errors.push({name, value: datetimeEspruino, lang: locale.lang, error: `uses an unsupported format symbol: ${datetimeEspruino.substring(i, i+3)}`});
formatLength[0]++; formatLength[0]++;
formatLength[1]++; formatLength[1]++;
formatLength[2]+=" ";
formatLength[3]+=" ";
i++; i++;
} }
} else { } else {
formatLength[0]++; formatLength[0]++;
formatLength[1]++; formatLength[1]++;
formatLength[2]+=ch;
formatLength[3]+=ch;
i++; i++;
} }
} }
@ -154,10 +161,10 @@ function checkLocale(locale, {speedUnits, distanceUnits, codePages, CODEPAGE_CON
function checkFormatLength(name, value, min, max) { function checkFormatLength(name, value, min, max) {
const length = getLengthOfDatetimeFormat(name, value, locale, errors); const length = getLengthOfDatetimeFormat(name, value, locale, errors);
if (min && length[0] < min) { if (min && length[0] < min) {
errors.push({name, value, lang: locale.lang, error: `output must be longer than ${min-1} characters`}); errors.push({name, value, lang: locale.lang, error: `output must be longer than ${min-1} characters (${length[2]} -> ${length[0]})`});
} }
if (max && length[1] > max) { if (max && length[1] > max) {
errors.push({name, value, lang: locale.lang, error: `output must be shorter than ${max+1} characters`}); errors.push({name, value, lang: locale.lang, error: `output must be shorter than ${max+1} characters (${length[3]} -> ${length[1]})`});
} }
} }
function checkIsIn(name, value, listName, list) { function checkIsIn(name, value, listName, list) {

View File

@ -148,7 +148,7 @@ function viewDeferredTable(filename) {
//try finding possible sources for the given function, currently does not work because function.toString() not being identical to code in the *.js files. //try finding possible sources for the given function, currently does not work because function.toString() not being identical to code in the *.js files.
/*Puck.eval(`require("Storage").list(/.*.js$/)`, (f)=>{ /*Puck.eval(`require("Storage").list(/.*\.js$/)`, (f)=>{
console.log("Found files:", f, rows[1].func); console.log("Found files:", f, rows[1].func);
for (let file of f){ for (let file of f){
let query = `require("Storage").read('${file}').includes('${rows[1].func}')`; let query = `require("Storage").read('${file}').includes('${rows[1].func}')`;

View File

@ -29,3 +29,4 @@
0.26: Fix hitting snooze on an alarm after when the snooze would've fired 0.26: Fix hitting snooze on an alarm after when the snooze would've fired
0.27: Tapping clkinfo enables/disables the selected alarm 0.27: Tapping clkinfo enables/disables the selected alarm
0.28: Added an icon for disabled events 0.28: Added an icon for disabled events
0.29: Improve clkinfo startup time by 10ms

View File

@ -1,15 +1,7 @@
(function() { (function() {
const alarm = require('sched');
const iconAlarmOn = atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/n+B/n+B/h+B/4+A/+8A//8Af/4AP/wAH/gAB+AAAAAAAAAA==");
const iconAlarmOff = atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/nAB/mAB/geB/5/g/5tg/zAwfzhwPzhwHzAwB5tgAB/gAAeA==");
const iconTimerOn = atob("GBiBAAAAAAAAAAAAAAf/4Af/4AGBgAGBgAGBgAD/AAD/AAB+AAA8AAA8AAB+AADnAADDAAGBgAGBgAGBgAf/4Af/4AAAAAAAAAAAAA==");
const iconTimerOff = atob("GBiBAAAAAAAAAAAAAAf/4Af/4AGBgAGBgAGBgAD/AAD/AAB+AAA8AAA8AAB+AADkeADB/gGBtgGDAwGDhwfzhwfzAwABtgAB/gAAeA==");
const iconEventOn = atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B/++B/8+B/5+B8z+B+H+B/P+B//+B//+B//+A//8AAAAAAAAAAAAA==");
const iconEventOff = atob("GBgBAAAAAAAAAAAAD//wH//4GAAYGAAYGAAYH//4H//4H//4H/74H/wAH/gAHzB4H4H+H8m2H/MDH/OHH/OHD/MDAAG2AAH+AAB4");
//from 0 to max, the higher the closer to fire (as in a progress bar) //from 0 to max, the higher the closer to fire (as in a progress bar)
function getAlarmValue(a) { function getAlarmValue(a) {
let min = Math.round(alarm.getTimeToAlarm(a)/(60*1000)); let min = Math.round(require('sched').getTimeToAlarm(a)/(60*1000));
if(!min) return 0; //not active or more than a day if(!min) return 0; //not active or more than a day
return getAlarmMax(a)-min; return getAlarmMax(a)-min;
} }
@ -23,20 +15,20 @@
function getAlarmIcon(a) { function getAlarmIcon(a) {
if(a.on) { if(a.on) {
if(a.timer) return iconTimerOn; if(a.timer) return atob("GBiBAAAAAAAAAAAAAAf/4Af/4AGBgAGBgAGBgAD/AAD/AAB+AAA8AAA8AAB+AADnAADDAAGBgAGBgAGBgAf/4Af/4AAAAAAAAAAAAA==");
if(a.date) return iconEventOn; if(a.date) return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B/++B/8+B/5+B8z+B+H+B/P+B//+B//+B//+A//8AAAAAAAAAAAAA==");
return iconAlarmOn; return atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/n+B/n+B/h+B/4+A/+8A//8Af/4AP/wAH/gAB+AAAAAAAAAA==");
} else { } else {
if(a.timer) return iconTimerOff; if(a.timer) return atob("GBiBAAAAAAAAAAAAAAf/4Af/4AGBgAGBgAGBgAD/AAD/AAB+AAA8AAA8AAB+AADkeADB/gGBtgGDAwGDhwfzhwfzAwABtgAB/gAAeA==");
if(a.date) return iconEventOff; if(a.date) return atob("GBgBAAAAAAAAAAAAD//wH//4GAAYGAAYGAAYH//4H//4H//4H/74H/wAH/gAHzB4H4H+H8m2H/MDH/OHH/OHD/MDAAG2AAH+AAB4");
return iconAlarmOff; return atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/nAB/mAB/geB/5/g/5tg/zAwfzhwPzhwHzAwB5tgAB/gAAeA==");
} }
} }
function getAlarmText(a){ function getAlarmText(a){
if(a.timer) { if(a.timer) {
if(!a.on) return /*LANG*/"off"; if(!a.on) return /*LANG*/"off";
let time = Math.round(alarm.getTimeToAlarm(a)/(60*1000)); let time = Math.round(require('sched').getTimeToAlarm(a)/(60*1000));
if(time > 60) if(time > 60)
time = Math.round(time / 60) + "h"; time = Math.round(time / 60) + "h";
else else
@ -52,7 +44,7 @@
//workaround for sorting undefined values //workaround for sorting undefined values
function getAlarmOrder(a) { function getAlarmOrder(a) {
let val = alarm.getTimeToAlarm(a); let val = require('sched').getTimeToAlarm(a);
if(typeof val == "undefined") return 86400*1000; if(typeof val == "undefined") return 86400*1000;
return val; return val;
} }
@ -66,7 +58,7 @@
const minute = 60 * 1000; const minute = 60 * 1000;
const halfhour = 30 * minute; const halfhour = 30 * minute;
const hour = 2 * halfhour; const hour = 2 * halfhour;
let msecs = alarm.getTimeToAlarm(a); let msecs = require('sched').getTimeToAlarm(a);
if(typeof msecs == "undefined" || msecs == 0) if(typeof msecs == "undefined" || msecs == 0)
return []; return [];
if(msecs > hour) { //refresh every half an hour if(msecs > hour) { //refresh every half an hour
@ -103,15 +95,15 @@
}, switchTimeout); }, switchTimeout);
} }
var img = iconAlarmOn; // read the file direct here to avoid loading sched library (saves 10ms!)
var all = alarm.getAlarms(); var all = /*require('sched').getAlarms()*/require("Storage").readJSON("sched.json",1)||[];
//get only alarms not created by other apps //get only alarms not created by other apps
var alarmItems = { var alarmItems = {
name: /*LANG*/"Alarms", name: /*LANG*/"Alarms",
img: img, img: getAlarmIcon({on:1}),
dynamic: true, dynamic: true,
items: all.filter(a=>!a.appid) items: all.filter(a=>!a.appid)
//.sort((a,b)=>alarm.getTimeToAlarm(a)-alarm.getTimeToAlarm(b)) //.sort((a,b)=>require('sched').getTimeToAlarm(a)-require('sched').getTimeToAlarm(b))
.sort((a,b)=>getAlarmOrder(a)-getAlarmOrder(b)) .sort((a,b)=>getAlarmOrder(a)-getAlarmOrder(b))
.map(a => ({ .map(a => ({
name: null, name: null,
@ -135,13 +127,12 @@
run: function() { run: function() {
if (a.date) return; // ignore events if (a.date) return; // ignore events
a.on = !a.on; a.on = !a.on;
if(a.on && a.timer) alarm.resetTimer(a); if(a.on && a.timer) require('sched').resetTimer(a);
this.emit("redraw"); this.emit("redraw");
alarm.setAlarms(all); require('sched').setAlarms(all);
alarm.reload(); // schedule/unschedule the alarm require('sched').reload(); // schedule/unschedule the alarm
} }
})), })),
}; };
return alarmItems; return alarmItems;
}) })

View File

@ -173,7 +173,7 @@ function renderAlarm(alarm, exists) {
}; };
} }
} }
tdType.textContent = type; tdType.textContent = type + (alarm.appid ? `\n(${alarm.appid})` : "");
if (!exists) { if (!exists) {
const asterisk = document.createElement('sup'); const asterisk = document.createElement('sup');
asterisk.textContent = '*'; asterisk.textContent = '*';
@ -331,6 +331,10 @@ function getData() {
alarms.sort((a, b) => { alarms.sort((a, b) => {
let x; let x;
// move app specific alarms to the bottom
x = !!a.appid - !!b.appid;
if(x) return x;
x = !!b.date - !!a.date; x = !!b.date - !!a.date;
if(x) return x; if(x) return x;

View File

@ -1,5 +1,6 @@
// Return an array of all alarms // Return an array of all alarms
exports.getAlarms = function() { exports.getAlarms = function() {
// we do this direct in clkinfo.js to avoid loading the library
return require("Storage").readJSON("sched.json",1)||[]; return require("Storage").readJSON("sched.json",1)||[];
}; };
// Write a list of alarms back to storage // Write a list of alarms back to storage

View File

@ -1,7 +1,7 @@
{ {
"id": "sched", "id": "sched",
"name": "Scheduler", "name": "Scheduler",
"version": "0.28", "version": "0.29",
"description": "Scheduling library for alarms and timers", "description": "Scheduling library for alarms and timers",
"icon": "app.png", "icon": "app.png",
"type": "scheduler", "type": "scheduler",

1
apps/sudoku/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: New App!

1
apps/sudoku/app-icon.js Normal file
View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("l0vwQPM/4AI+E4ChEDwYgJhkwgGAgYHChED3cACwM8gHwBYXwn/wCwMLwELBQULgeACxXACwIPBCwotKAIIWIAAIWCn5EJgewFou4CwQpDAYhyCCQJWBgE7BwWDh6gICwgtDCwYtOF4QWIgf8CxMwL4gtFh7OGCwS0CCxABB4AWHnBbJIhc7LZI2DCw4AFwcDTIPw/6lD/gWB3YABhewAgW72CgQW6wWphELhYCBgYEBgYWC+AAHCwIQBAAwtEHgTOHAA+DB4QAGnk7TYYAFwCxCAAzVGAAo"))

163
apps/sudoku/app.js Normal file
View File

@ -0,0 +1,163 @@
var settings = require("Storage").readJSON("sudoku.json",1)||{};
const Layout = require("Layout");
var puzzle = ""; // start puzzle space for blanks, 81 char str
var solution = ""; // the solution for the puzzle 81 char str
var current = ""; // current puzzle state, 81 char str
var sx=4, sy=4; // selected item
var dx=0, dy=0, dmoved=false; // current drag amount
const DRAG = 20;
const CHOOSERFONT = "12x20:2";
const COL_GOOD = "#00F";
const COL_BAD = "#F00";
function saveSettings() {
settings.puzzle = puzzle;
settings.solution = solution;
settings.current = current;
require("Storage").writeJSON("sudoku.json",settings);
}
function startGame(difficulty) {
let file = require("Storage").read("sudoku.easy.txt");
let games = 0|(file.length/163);
let game = Math.floor(Math.random()*games);
let line = file.substr(game*163, 162);
puzzle = line.substr(0,81).replaceAll("-"," ");
current = ""+puzzle; // new string
solution = line.substr(81,81);
showGrid();
}
function draw() {
g.clear(1);
for (var i=0;i<10;i++) {
g.setColor((i%3)?"#888":g.theme.fg);
g.fillRect(7+18*i, 7, 7+18*i, 169);
g.fillRect(7, 7+18*i, 169, 7+18*i);
}
i = 0;
g.setFont("6x8:2").setFontAlign(0,0);
for (var y=0;y<9;y++)
for (var x=0;x<9;x++)
g.setColor(puzzle[i]==" "?((solution[i]==current[i])?COL_GOOD:COL_BAD):g.theme.fg).drawString(current[i++], 16 + 18*x, 16 + 18*y);
}
function drawSq(x,y,sel) {
g.setColor(sel ? g.theme.bgH : g.theme.bg).fillRect(8+x*18,8+y*18,24+x*18,24+y*18);
g.setFont("6x8:2").setFontAlign(0,0).setColor(sel ? g.theme.fgH : g.theme.fg);
var i = x+y*9;
g.setColor(puzzle[i]==" "?((solution[i]==current[i])?COL_GOOD:COL_BAD):g.theme.fg).drawString(current[i++], 16 + 18*x, 16 + 18*y);
}
// precalculate our layout
var choose = function(num) {
if (num!==undefined) {
Bangle.buzz(100);
var i = sx+sy*9;
current = current.substr(0,i)+num+current.substr(i+1);
}
showGrid();
if (current == solution) {
saveSettings();
E.showMessage(/*LANG*/"Well done,\nyou finished!", {
title:"Sudoku",
buttons : {"Ok":true},
img : require("heatshrink").decompress(atob("k8pwcBkmSpICCnVp0IIFAQl27dt2wOJ9On7/582YtOJBws7tv/DoQKCBwubvvmzVp0wCCHAvf9u2DpE8uOn7waEjQdDq1Itv+DQQCB0gZBkMkyPHj1tHAuGAQOJktt/Ubvo4DAQI3ChMcuPHzd5HAeasICBtFOr/kw3fDQe27RhCofH/lx4xxFSQIFBiu/rNhHAp0DyHx447BHAh0Ekt/61YlodFOgaPBDoJWFAQeJrf1yySBDohWCoVJOgUcKw+YyVOrtly0LKw4eBp4dCjytHBwNOrNlyUbDoVpHAYDBo4dH02EFoTpBDoQ7B2MyZALMCHYsGtOOjALDAQQ7CyM6tFkFIgCDDoPBnkT4wLFAQegxP8z/JBxNwp8E+ALHAQMl+V/n4aIAQI4B4McBxU/z/P8gOKjnx4JHJAQP//5WKSoVwDRICBv//FJTRDBxeT/5WLkmR45WLkitLARNIA"))
}).then(showMenu);
}
};
var numberChooser = new Layout( {
type:"v", c: [
{type:"h", c: [
{type:"btn", font:CHOOSERFONT, label:"1", fillx:1, cb:()=>choose(1) },
{type:"btn", font:CHOOSERFONT, label:"2", fillx:1, cb:()=>choose(2) },
{type:"btn", font:CHOOSERFONT, label:"3", fillx:1, cb:()=>choose(3) }
]},
{type:"h", c: [
{type:"btn", font:CHOOSERFONT, label:"4", fillx:1, cb:()=>choose(4) },
{type:"btn", font:CHOOSERFONT, label:"5", fillx:1, cb:()=>choose(5) },
{type:"btn", font:CHOOSERFONT, label:"6", fillx:1, cb:()=>choose(6) }
]},
{type:"h", c: [
{type:"btn", font:CHOOSERFONT, label:"7", fillx:1, cb:()=>choose(7) },
{type:"btn", font:CHOOSERFONT, label:"8", fillx:1, cb:()=>choose(8) },
{type:"btn", font:CHOOSERFONT, label:"9", fillx:1, cb:()=>choose(9) }
]}
], fillx:1
}, {btns:[ {label:/*LANG*/"Back", cb: l=>choose()} ]});
function showGrid() {
Bangle.setUI({mode:"custom", drag:e=>{
if (e.b) {
dx += e.dx;
dy += e.dy;
while (Math.abs(dx) >= DRAG) {
Bangle.buzz(40);
let old = sx;
sx = (sx+9+Math.sign(dx))%9;
dx -= Math.sign(dx)*DRAG;
drawSq(old,sy,0);
drawSq(sx,sy,1);
dmoved = true;
}
while (Math.abs(dy) >= DRAG) {
Bangle.buzz(40);
let old = sy;
sy = (sy+9+Math.sign(dy))%9;
dy -= Math.sign(dy)*DRAG;
drawSq(sx,old,0);
drawSq(sx,sy,1);
dmoved = true;
}
} else {
if (!dmoved && puzzle[sx+sy*9]==" ") {
Bangle.buzz(100);
setTimeout(showSelectNumber, 10);
}
dx = dy = 0;
dmoved = false;
}
}, btn:() => {
saveSettings();
showMenu();
}});
draw();
drawSq(sx,sy,1);
}
function showSelectNumber() {
g.clear();
numberChooser.setUI();
numberChooser.render();
}
function showMenu() {
var menu = { "" : { title: "Sudoku" } };
if (settings.puzzle)
menu["Resume Game"] = () => {
puzzle = settings.puzzle;
solution = settings.solution;
current = settings.current;
showGrid();
};
menu["New Game"] = () => {
E.showMenu({ "" : { title: /*LANG*/"Difficulty", back : showMenu },
"Easy" : () => startGame("easy"),
"Medium" : () => startGame("medium"),
"Hard" : () => startGame("hard")
});
};
menu["Exit"] = () => load();
E.showMenu(menu);
}
if (settings.puzzle) {
puzzle = settings.puzzle;
solution = settings.solution;
current = settings.current;
showGrid();
} else {
showMenu();
}
E.on("kill", saveSettings); // ensure we save the game

BIN
apps/sudoku/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

24
apps/sudoku/gen_sudoku.js Normal file
View File

@ -0,0 +1,24 @@
/*
Call this to generate the data files needed.
npm install sudoku-gen
*/
var getSudoku = require('sudoku-gen').getSudoku;
// (easy, medium, hard, expert)
function gen(difficulty) {
console.log("Generate", difficulty);
// Get a sudoku of specific difficulty
let result = "";
for (let i=0;i<200;i++) {
const sudoku = getSudoku('easy');
result += sudoku.puzzle + sudoku.solution+"\n";
}
require("fs").writeFileSync("sudoku."+difficulty+".txt", result);
}
gen("easy");
gen("medium");
gen("hard");

17
apps/sudoku/metadata.json Normal file
View File

@ -0,0 +1,17 @@
{ "id": "sudoku",
"name": "Sudoku",
"shortName":"Sudoku",
"version":"0.01",
"description": "A Sudoku game that allows you to play one of 600 pre-made puzzles",
"icon": "app.png",
"screenshots" : [ { "url":"screenshot.png" } ],
"tags": "game",
"supports" : ["BANGLEJS2"],
"storage": [
{"name":"sudoku.app.js","url":"app.js"},
{"name":"sudoku.img","url":"app-icon.js","evaluate":true},
{"name":"sudoku.easy.txt","url":"sudoku.easy.txt"},
{"name":"sudoku.medium.txt","url":"sudoku.medium.txt"},
{"name":"sudoku.hard.txt","url":"sudoku.hard.txt"}
]
}

BIN
apps/sudoku/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

200
apps/sudoku/sudoku.easy.txt Normal file
View File

@ -0,0 +1,200 @@
8----47---47----639-5--381-7--46-13219---5---4----2597--13-724--2--46--83-4-----1813694725247581963965273814758469132192735486436812597681357249529146378374928651
6------1-----954-3--94-1----76-3-----18562-94-927-4638--4-5----9--2--1-62-3----47645378219821695473739421865476839521318562794592714638164957382987243156253186947
9-6-----3-186239-----945---3-521--8-4--3---1---189---46--57-1---7--38-9----16-47-946781523518623947237945861365214789489357216721896354694572138172438695853169472
---4-71---895-27637128-3-495-7-8--3--94-31--------96---5--7---------8-959-1---8-6635497128489512763712863549567284931894631257123759684358976412276148395941325876
4-5----97-92-4-------6--2--7---68----89-14763651-324-9---17-9-8-1-4---265---9----465321897192847635873659214734968152289514763651732489326175948917483526548296371
1---23986------154--819-----3-4--8---2-85-6-3--4-3-2-147----3-93--9--5-7-1---7-28147523986293678154568194732639412875721859643854736291476285319382941567915367428
--6-25837-2--891-6-3-74-5-947-21---5---97--8------4---59-8-23-----4--9-2---5974-8946125837725389146138746529473218695651973284289654713594862371867431952312597468
--5---61-4---1-------6-9-25-5349786--84-----9-17-562345--1-43----6-----23-9-68---895742613462315978731689425253497861684231759917856234578124396146973582329568147
3--16-9--------32794-7-5---6-9-2---18-1---459--489-6-27-628319--------68---6-92-3387162945165948327942735816639524781821376459574891632756283194293417568418659273
------1---2---3----8---6-4564--3-28-2938-4--68--6-7493---9--5--358---9729-4--2618436785129529143867781296345647539281293814756815627493162978534358461972974352618
-96--1-521354-6-9---------6974182-632--597--1---6--7--5192---7-3--7-----6-7--4-35496871352135426897728359146974182563263597481851643729519238674342765918687914235
-9127----------562-5-4-89--43----1791--3-98-698---6--4---89-6-582-65349--------83691275348748931562253468917436582179172349856985716234314897625827653491569124783
58----24-----1--8-3-72--9--6435-8-2989-132-67----4--35-7----3-----8-7-9-4-8-91---589763241264915783317284956643578129895132467721649835972456318136827594458391672
2--4-3-756--5----1----6129-3--74----8--6--143-961--82796--8-5-----2-67--1-2--7-68218493675649572381753861294321748956875629143496135827967384512584216739132957468
---5--3-86---34-5235--27--6-49----3--6-31--4----47-28-8-67-391413----7--9----286-492561378687934152351827496749285631268319547513476289826753914134698725975142863
76---9--5142--83--98--31-7--29-7-5-157---2-6-8-1---7--4--187--3----461-92-8-----7763429815142758396985631472629874531574312968831965724496187253357246189218593647
--476-53-9-6-3-4-1-----9------18------295-7-359-473--21-9-2-3-47---9-1-646351---7284761539976835421315249678637182945842956713591473862159627384728394156463518297
-3--9-----29-46--81-82-75-6--4---3---15--2---9---5-461-9--75684--1--49-7-57--921-536891742729546138148237596674918325315462879982753461293175684861324957457689213
-863--2-9--17--6--34-----718-----3-76--47--5--751-3--81295--7-----9--82-538-471--786315249951724683342869571894652317613478952275193468129586734467931825538247196
--13-98--7---21--4----471-692--543---4--38-6-6---9-4-----286---87-----9--34975--8451369827768521934392847156927654381145738269683192475519286743876413592234975618
1--93-46-3-4--1----9---7-83--61493-8-21----5---3526-9-63--84-----76---3-5-271--4-178932465364851279295467183756149328921378654843526791639284517417695832582713946
-1-7-8--5--4-65-2--59-42---9---714---7--3468--4--8--9----619---8-----21---18237-4612798345784365921359142876968271453175934682243586197427619538836457219591823764
9132-5--4874----------439---21-98-5--45--27----9-7--2--68-3---259-6---4--32----67913285674874916235256743918721398456345162789689574321168437592597621843432859167
-8---63--3---42--8-2--816-7--8-975---4-26--9--93-58------734-----4615-826-----4-5581976324376542918429381657268197543745263891193458276852734169934615782617829435
81-64-379----89------7-348-69-524---48---6--75--8-7-94-45---21----371----3-4---68812645379374289156956713482697524831483196527521837694745968213268371945139452768
9--8--4-5----641-94-6-95---713-42----4--8-25-2------3-1-2--85473974----65--726---921873465835264179476195382713542698649387251258619734162938547397451826584726913
2-4--5---75-48---99--73--54-273-8----8-6-4-9--4----18--92-7---1--3----46861-439-2234965718756481329918732654127398465385614297649257183492876531573129846861543972
2---------95-86--3--87-32-5-268-9--1-74------8391--62--679--358--25-79----13-87-2213495876795286143648713295526879431174632589839154627467921358382567914951348762
--6-----2-2-6-791-57--286-4-9-7563-8--78--56---------9--34-2---1-5369--7--258-4-3316945872824637915579128634491756328237894561658213749983472156145369287762581493
-3--27--52----6---496----233-1----788--73-5-----89--316841--3--9-2473-5-7-----412138927645275346189496518723341265978829731564567894231684152397912473856753689412
-617--52-5-74--6--48325--7---9---4-----1--26-634-2---7----7--9-8--34-71-3-25-18-6961783524527419638483256971219867453758134269634925187145678392896342715372591846
98-----71-1---3---5---9-42--27--8----64932-15-9517-2682-------4-5-41-------3-518-983246571412753896576891423127568349864932715395174268231687954758419632649325187
-39-2--16-8--19---164-83---41-3-----79---6-48--8------3-1-75-9-9-62345--84--61-2-539427816287619453164583972412398765793156248658742139321875694976234581845961327
1-8--6---526-73--4-93--18-62345--6-9--9--432---------591-43-2-84-21--57------2--1148956732526873194793241856234587619859614327671329485917435268462198573385762941
----96--8923------6854-79--7-9--4--38---3--4-5-4-82-7-4-6---31-2-1-6-4---781---9-147396258923851764685427931769514823812739546534682179496278315251963487378145692
---264-----1---52-2--5713-8-2--13--969-85----8--49--5---632-8---3-78-41--8-1---6-358264971471938526269571348524613789697852134813497652146325897932786415785149263
------437--524----4--1-9258-9--7-5---1-35-8-9--79--1-476----9-29---2-3-6-4---6-15129685437385247691476139258892471563614352879537968124768513942951724386243896715
-3-8--47-91537------7---9----6--8-34---23--162-364----569--3--27-1-8-345--4725---632859471915374628847162953176598234498237516253641897569413782721986345384725169
-24--13-5--7--84--16-----87-891-7--24---86-9-2-----1-891286-7-------523-735--98--824971365597638421163542987389157642471286593256394178912863754648715239735429816
248-1--65--152---9-9548---3-------579-6-3-481-3-14--96-8-6-4-12------9---2985---4248319765371526849695487123412968357956732481837145296783694512564271938129853674
57-6321----3--5-8-4-6---3-2---3----1---9---3-13--84-9676-24---8--186-27-2-915---3578632149923415687416798352894376521657921834132584796765243918341869275289157463
4-258-7----3---------2635----9---4-26-7--81-55--1-28---7-621-84-1--9-25-24--356-1462589713853417926791263548189356472627948135534172869975621384316894257248735691
679-8-3-5-14-----92-549---1----7------25-6--856892--7-12-64-58--867-3-1-----1---6679182345814365729235497861391874652742536198568921473123649587986753214457218936
-2--6-------9-34-5--4----96--9---5---4-6-2-1--13-97---4-1238-797-2---3--6-8-49251925164738186973425374825196269381547847652913513497862451238679792516384638749251
4-5----6-2-1-397488-94265-33------7--9-14-8--68--53----4---1---9-----3-1---36--97435718269261539748879426513314682975592147836687953124743891652956274381128365497
7-4---85-----6874---8-45--1--32------4-53-1--269---43-982--7--43-6459-1---5---379794123856521968743638745921153294687847536192269871435982317564376459218415682379
--8---9729-6428-5-231-7---47-4---38-----3674---3-84--5162---49--4-8-95----91-----458613972976428153231975864724591386815236749693784215162357498347869521589142637
--46-19-5-5-------2-9-481--5-84-23--6-7------1423---58--31-45-6--59-6--28-62--491784631925351729864269548173598462317637815249142397658923174586415986732876253491
82-43---9-4--6----7-39-1-58---2---6-3--51-----5---482157--4-9824--75-13-2--1---47825437619149865273763921458914278365382516794657394821571643982498752136236189547
------75937-2-----8-4--7321-9--4-2--52--8-1-44--9--8-7--6-7--82-3---45-6----694-3612438759379215648854697321798341265523786194461952837146573982937824516285169473
3--25---7------6137-4-19---27-6---5-85----974-4-78--62----27-36------28-12-8637-5318256497592478613764319528273694851856132974941785362485927136637541289129863745
6---8-3-519----2--3-529-64197--28-5-5---49-87---7--93----4-28-3-5-9-1--4-46-----9627184395194536278385297641971328456532649187468715932719452863853961724246873519
5-------8-1-49--3-23--65----9---4------52-8-11-----45-3-197256-9-6-----27-4-51389549237618617498235238165947895314726473526891162789453381972564956843172724651389
--9--2-84-6-5------72---6-192--6174383-4259-614-7-------4---8---9--86------95--67319672584468519372572348691925861743837425916146793258654137829791286435283954167
-1------279---8-----69--74186-1-45--2--6------57-834-993---6-78-7---13-66--3-9154314765982792418635586932741863194527249657813157283469931546278475821396628379154
9--8317------946-82-3---1--51---2-4--26-1-8-53-8-----114---65--892--3--763--78-1-964831752751294638283567194519782346426319875378645921147926583892153467635478219
--8----7----3-------6-15-4-4-186-7--879--4-166--197-2491-436-8-765928------5----9598642173147389652236715948421863795879254316653197824912436587765928431384571269
674----92-9-3-2-1---26-------8-391------87-595-9----83486-5-9--2-7943--1--3---425674815392895372614132694578728539146361487259549126783486251937257943861913768425
---8-37--687--41---45---2-6---6-8--7--3-79-5--7-23-6-9-16-82-7---8346--1--2-579--921863745687524193345791286259618437163479852874235619516982374798346521432157968
--4-9-57---1458-62-5273-8-418-6--4-7-7-5-46--9-----2-53--------52--671-----3857--834296571791458362652731894185629437273514689946873215367142958528967143419385726
6-8---93--------469436-57-8---7-418248-1--69--9-8-6-7-76---38--5-2-18---------359628471935175389246943625718356794182487152693291836574769543821532918467814267359
-6--7-5-89----523-51----7-66---1---23--82-6-4--16--9-3-9-3-6427--279----------189263179548978465231514238796647913852359827614821654973195386427482791365736542189
4-158-9-------6----294--5-6-3-894-61---72-----4816-3---943--6-2-526----8-8-21-459461582973875936124329471586537894261916723845248165397794358612152649738683217459
61-5-9------6--2---83--7-9-76-43-829---81-5--54897--163----8------7---63-56---7-2617529438495683271283147695761435829932816547548972316379268154824751963156394782
2--3-4-15-1--8-32----2--6-478-4-5---624--97-------21-6-6-9--47194--2-56--5---328-276394815419586327835217694781465932624139758593872146362958471948721563157643289
-68--9153--5-------438---2-3--15---9---9-86349-4-37815-5-78---2-----6-8-8125--7--268479153795312468143865927386154279571928634924637815659781342437296581812543796
39-----57-26--741---4--39---1--7983-8--3-5--4-37-----1--953-1786-1--2-----3--8269398421657526987413174653982415279836862315794937864521249536178681792345753148269
--28-3145-517--8-9-849--2----725139----6-8----253-9--7-185--9-4----9----53-4-2--1972863145651724839384915276467251398193678452825349617718536924246197583539482761
2-3--1----89-2-613------4723---8-5-7-5-2--19----54-3-8--8--42-91-79--8-64--8----1243671985789425613615398472324189567856237194971546328568714239137952846492863751
-4---1-2-31--28-9-2---694---7--53--2--591--6-----72-54---346---9-2187--676----1--649531728317428695258769431476853912825914367193672854581346279932187546764295183
-7-4-9------37-9-61------4--15-6-----24813-79-879-5162-9--3----7----84-186-----95576489213248371956139256847915762384624813579387945162491537628752698431863124795
39742-5-81-----6-3-648132-7-7-3-5-2----64--719-------4-45-----22-91-4-------5--3-397426518182579643564813297471395826853642971926781354745938162239164785618257439
-3-689-2---54-2-631--5-7-4--5-26------71-5-8-61--48--546-----795--82----3--9--652734689521895412763126537948958263417247195386613748295462351879579826134381974652
4-2-583-656--2--97---6--2--658-7-4-1-4-5---68------7--7168-95--23-1------842--1-3492758316561324897873691254658973421347512968129486735716839542235147689984265173
2--68-5--17-23--8--5--7--2---97-8-6--4-91---2---42--958-2347--6---561---46----7--293684517174235689658179423329758164546913872781426395812347956937561248465892731
9-68--4-5-----6---4--93-28-6-57--8-4--36--5-989452---3---15-----62348--77--26-3-8936812475258476931417935286625793814173684529894521763389157642562348197741269358
-8----9-5456-237-13-95812-462-3-8-------7--5-7-3-----2--47-5-2--6------3----39-48281647935456923781379581264625398417198472356743156892834765129962814573517239648
8-67-194337----1--9--2--8-6----142-8-6--37--4-49-----775-12--6-6--47--25-----578-826751943374896152915243876537614298268937514149582637753128469681479325492365781
4-27-869--39-41-8--1--5---------35----4-76----6-1--379--3--712--26-1-938--1-624-7452738691639241785817659243178923564394576812265184379543897126726415938981362457
-----95-29-2--5-368---461793-91--768-76--8--31---------415--8-75----7---2-786-35-764319582912785436835246179359124768476958213128673945641532897583497621297861354
-2--79-5-7--1-------9--5762-4--563--3817-4---65793-4-8--------55364---172----7-83823679154765142839419385762942856371381724596657931428178263945536498217294517683
2---75-968--9-4-13--16-8274---5-----75--83-6-----974------5--8996-84---2---769-45234175896876924513591638274489516327752483961613297458147352689965841732328769145
6-75-8---8---9--4--34--2658---2--8------8-1---8261--791-58--2-42---359-6-639--5-7627548391851396742934172658719254863346789125582613479195867234278435916463921587
--3--85-18-1--49-2259-613---862934--4---862-3----17------8-----9---35-265-8--21-9743928561861354972259761384186293457497586213325417698612849735974135826538672149
---256----6-78491-7-----4-6--1--7--55---691----9-182-7--697--3--1--32--4-53-41---194256378365784912728193456481327695572469183639518247246975831917832564853641729
31----97--7--8----4--3--6-5-4-7-5-------481-76------5--349-7216-2586374--69-1----318526974576489321492371685941735862253648197687192453834957216125863749769214538
-4----372-1-9-346------2----547-1--6-6-4--5-3-93--8---6-9-1-73543--5--8--7539--24946185372512973468387642951254731896768429513193568247629814735431257689875396124
6--18973-9-8---5-1-4--7---9-9-2------21-5469---69-----83-4-1--6--96-78-2--48-531-652189734978342561143576289495268173321754698786913425837421956519637842264895317
---2-76-8------37-1-7638-257-2-8-5--3-5---249--9-238-76---75--229-4-1---------186953247618826159374147638925762984531385716249419523867631875492298461753574392186
---6-814-1---53-296---9---8----162--46-7--9--8-1--2-67-46-8-7123--52----7---6-853293678145187453629654291378975816234462735981831942567546389712318527496729164853
-534-8-7--94-26-1-1829-73--8---42-----9-75-26---6------1-78--49-68294----47-6----653418972794326815182957364876142593439875126521639487215783649368294751947561238
15---84---3-4---8-89-3-6-5-78-----2426-7----83-5-2--1-416---------1-73--973-85--1157298463632451789894376152781563924269714538345829617416932875528147396973685241
-916-25--3--49--1-5-----9-224----69---69----3-532--7-86871----9125-49--6---7---85891672534362495817574318962248537691716984253953261748687153429125849376439726185
2-759-----3------4---3-7-9-4-3--6--917-----26----5--7-8247-196-----2-14-79-64538-217594638936812754548367291453276819179483526682159473824731965365928147791645382
691-8-4----7-----1---2---6815983--4-3-41----6-624---835--91--24----4--7-9-83-26-5691783452827564931435291768159836247384127596762459183576918324213645879948372615
35---29--62--7-154-1---------51-4-7-----27536-3758-412----6-2--492--1--81--2-8-9-354612987629873154718495623265134879841927536937586412583769241492351768176248395
---8-6-4--8----3--1-654----96----21-----5--6-3-8--24--7136-9-2464-235-78----1--39537826941482791356196543782964378215271954863358162497713689524649235178825417639
437---56859--8-123---5--7--3--16-95484539---11-9--483-------2----3-1--97--8-4----437921568596487123281536749372168954845392671169754832914673285623815497758249316
--4267-5--7--5-24-2-------96523-18-4819----32-3-8--56-7---18-2-586-92--3-----5---394267158178953246265184379652371894819546732437829561743618925586792413921435687
7418-356-----4-78--6397512--2------73-4-69------3-26------9-3--2-75----6-38---4-5741823569952146783863975124526481937384769251179352648415698372297534816638217495
--26-13-884-5-91----97-8-54-2---3-----1--2----3597--212-8---5-7-9--6-2--1--285-46752641398846539172319728654927813465681452739435976821268394517594167283173285946
8-23---19--1--7-637--1----8-5-6--38----57--414---1--52------276-13-6-8946-4--8---842356719591287463736194528159642387328579641467813952985431276213765894674928135
------91687--21---9--5-38--4-3---782--78-456-5-86---3--------45----8569-1-54963-8352748916876921453941563827463159782217834569598672134689317245734285691125496378
--9-18-5----3----8587-9-1---2--79-4----84-36264-1-28978-34--7292-6-8---59--------439718256162354978587296134328679541791845362645132897853461729276983415914527683
--9-----4---465219-2--39678-18--6593-369528--5--3-8-62-5-2-------------7-8-6--43-169827354873465219425139678218746593736952841594318762357294186641583927982671435
8-6---5-9-94------25--196489-8--3-54375-42-----2-95-8-5---6--92---35-7-1681------816234579794586123253719648968173254375842916142695387537461892429358761681927435
---1-459---927--8-3-----4---74---8--83-54---------7-2-2934-86-75-----2-1-416259-8627184593459273186318956472974362815832541769165897324293418657586739241741625938
-7-1-42--5--98--1-13-2-7-----9---5-2-5-692-78---345-----35-8--77----93--8--7-69-4978164253524983716136257849649871532351692478287345691493528167762419385815736924
---375---81-649-5-9-5-----63-6-148----7--61--1---58--7--9-23-1-----9127--2-86-5--264375981813649752975182436396714825587236149142958367759423618638591274421867593
94---16-33-1--6---625-897--4----7-29------5--7925--4-6-----21---1479-3-22-71---85948271653371456298625389741453617829186924537792538416539862174814795362267143985
--6-957-1--2-8134--5-2746-8--------33-4--896----7--41-----37184----16-3-8-1-2--76486395721972681345153274698617942853324158967598763412269537184745816239831429576
6-3---4--2--7-3--97-9--21-51--92-3-6------8--9--358---5-7-89-63-26537-1-39--4--7-613895427254713689789462135178924356435671892962358741547189263826537914391246578
----78-598--961-4-2-1----6-51--946--67--5--3-982-1---4-25--6-9336--2-7--1-9-----6436278159857961342291345867513794628674852931982613574725186493368429715149537286
3952----88-7--15-4--48-------25389-----7---8-1839624-773---92-5------7--5491-7--3395246178867391524214875639472538916956714382183962457731689245628453791549127863
--915-8726-2--3-----1--896319----75---4--1--9-36--7-24-17---2--8---154---2-7-9-18349156872682973541751428963198342756274561389536897124917684235863215497425739618
869-3175--45-792182---48------9-254--9-7---836----5----53--7---7-6----25---8--3--869231754345679218217548936138962547592714683674385192953427861786193425421856379
---3-85--49----72-352--41--5--78-26--8--56--9---2-3-5--7--956---3-842-1-12--37--5716328594498561723352974186543789261281456379967213458874195632635842917129637845
2-9---5-715--9---------3-1-42318--9556-94-378--763------2-5--------74-56-4---91-3239418567154796832876523419423187695561942378987635241692351784318274956745869123
395---4-1-4----5-881-95-2---53----1--8743---94---------34-2-9-59-8--61235-1-8-7-6395278461742163598816954237253697814187432659469815372634721985978546123521389746
631----5--4-57162---7--319837-2-8-----47-5-8-85----37-----9--6-4--65---776----912631829754948571623527463198376218549194735286852946371283197465419652837765384912
---9-1-------68-945-942-1689-4--26--1-2734-----3-9641----685---43-----578---4-92-648971235321568794579423168984152673162734589753896412297685341436219857815347926
37--98--5---1-----5-2--71-8--9-325872-8--19--7-5--42-1--475931-----26---9-7-13--4371298465896145723542367198419632587238571946765984231684759312153426879927813654
-6-7-----8-1-6-7-972--93-6545--8-9373-79--5---8----------4--2-624-6--35--9-3-1478569714823831265749724893165456182937317946582982537614173458296248679351695321478
--98-15--7-----6-82-45--1-98-6-592--3-----------3489---2-184-56-1--7-89--6893-4-1639821547751493628284567139846759213395216784172348965927184356413675892568932471
6-3-98-7-7-1-6---2954-3-8--4--973--8----149-653------7-65--72-92-7-5--1-39----7--623198475781465392954732861416973528872514936539286147165347289247859613398621754
-9146--7-7-6----4-3542---18---3-------9-15-2-51294-3--97-65-2-12-5-387-----7---5-891463572726581943354279618487326195639815427512947386978654231245138769163792854
5----6---743-9--26619---538----8-9---25-7-3--4----------7-23689268-17--393-8--2-7582136794743598126619742538371284965825679341496351872157423689268917453934865217
26-4-1-59-5--371-6--15------7-9-8621---7-------6-129----58-429---8---4-53-26--817267481359954237186831569742473958621129746538586312974615874293798123465342695817
75829-1-4-6----5-39-36157-2--7-54-2--8----9-----93-67----4---5-82--69---4-9---2--758293164261748593943615782697854321382176945514932678136427859825369417479581236
625-1-39-381---4577--3-----93468-5----659-14315---46-9-97-6---5----4---12--------625417398381926457749358216934681572876592143152734689497163825568249731213875964
47-2-89---92-6--7-8-39-------1--5398---8-416-3-7--9----69--2-4-7185---3--34-9-58-476258913192463875853971624641725398925834167387619452569382741718546239234197586
6-7-4-8---5-------18-5--467-2--7----5-92--7-473-4-6-28-4--69175----1-3-231--2-68-697142853453687291182593467824971536569238714731456928248369175976815342315724689
-49--2-5--6-----138516-394---3---5-8--831---9-2486----2-7-38-9-43-7-----9---26-37349182756762954813851673942193247568678315429524869371217538694436791285985426137
---7--9288--3596--9761-2--4---6-8-5751-----8676-5--4----32------27-6--4----913-62351746928842359671976182534234698157519437286768521493693274815127865349485913762
-17432-8----856---8-4-----25--2--1----178---52-631-7-----14-95--9--278--4--69--1-617432589329856471854971362578269134931784625246315798762148953193527846485693217
-9------38--5431--1-38---4-5-8--2-6--12-7638563----972-6-93-528----8----3--72---4496217853827543196153869247578392461912476385634158972761934528245681739389725614
-9-523-611---4-------719438--839-6-236---218927-168--3----5-----8----9---2-6-43--894523761137846295652719438418395672365472189279168543743951826586237914921684357
4---5----6-9---34---79--2-897-3-416223--6----18-52947---2----8-----756-47--4-8---428753916659812347317946258975384162234167895186529473542631789891275634763498521
---8--3---6-23--7-37----49825----7-171--95-----6-725--134---2--6--7249-3--7--1854591847326468239175372516498259683741713495682846172539134958267685724913927361854
17-269-38------6-1---1-892-81--2-3--36----8545--68-21--9-31--8-------792-857-4---174269538928537641653148927819425376362971854547683219796312485431856792285794163
53--467-----1-----7-8-3-4-1--6-853478-4-1---63-7-2-1-8--2367-15----98---6-3-512--531846792469172583728539461216985347854713926397624158942367815175298634683451279
--274-6-----29--343-4----27--7---8131-9874--68253--4--598----41-4--17-6---1--5---912743685756298134384156927467529813139874256825361479598632741243917568671485392
---7-39-29376---45-5--8-7--7----6---1---7-----28-19-763-2--8-946-5--71-38-934-6--481753962937621845256984731794536218163872459528419376372168594645297183819345627
7648--53--5--9---4---4-61-74----8---2---4-----19-2784-9-763---88-5--46-26-1--937-764812539158793264392456187473568921286941753519327846927635418835174692641289375
---3----6746---21339--2-4588-9--7-4227349-8--4--81-739--4-8-69---2-7------------5528341976746958213391726458819637542273495861465812739154283697632579184987164325
--5---9-18--7-9--36-4--38-71-983---4--2---------962--8-7--5--8991--287-6-4-69713-735286941821749563694513827169835274382174695457962318276351489913428756548697132
8--5-6-27-7-8-14594--39--16---96-5-------3---9-328---16-1-58-4-----3--68---619-35819546327376821459452397816127964583568173294943285671631758942795432168284619735
18----62-3-56---49--98----14--1-6-878-6---4---7-28-9---543-------1-28764--87--153187493625325617849649852371492136587816975432573284916754361298931528764268749153
---736----7-82154---1---8-7--357-4--4--1----35--24-6-1-4-69---87---15-9-93-48----854736912379821546261954837613578429428169753597243681145692378786315294932487165
6---384-2----2-7--8-54-1-96983-5--2------49-5--7-----3368-152--1-2--3--9-94--25-1679538412431629758825471396983157624216384975547296183368915247152743869794862531
-35-842-----2--8-38-96---4----39-58---8--5--6--3-261-7--4571--8--1----7298-432--5135784269476219853829653741612397584798145326543826197264571938351968472987432615
---3-----2-4--75-3-71-854--9--748-31----26---7-8-319--4-7--93-28---127545-2--3--8685394127294167583371285469956748231143926875728531946467859312839612754512473698
783-16-2---4593--7----8-643-15---47-----7458--78-5---29---6----86-7--2-----13976-783416925624593817159287643315928476296374581478651392937862154861745239542139768
27---1---46-83259-35-79-142--2---6------85-195--96----1-3---97---53---269----8---279451368461832597358796142892147653634285719517963284183624975745319826926578431
-4-8-5--16------2-----29-74564-1283--9257314-7-----95-----8---51-62-7----28----1-247865391619734528385129674564912837892573146731648952973481265156297483428356719
8-6--4--21-3--94-8--2-78163--9132-472-1-479------85---71--263-----4-----3-8--16-4876314592153269478942578163569132847281647935437985216714826359625493781398751624
---524----5-36197-1-----3-5-2873------5-19-8--7-48---32--95-7----967-4-1--71----2793524816852361974146897325628735149435219687971486253214953768589672431367148592
-2968--5--4-2---8---857-4---1-93---83---25-7----81--34-71---2-----749---8-5162--7129684753547293186638571492714936528386425971952817634471358269263749815895162347
34--789-17-1-4--62---1--4--187-2-3-5--37---18------2---384--5-94-95-----2158-67--346278951751943862892165473187629345923754618564381297638417529479532186215896734
-4------9--765--8--18-34---35------178-52143-62--47895--5--6------41-9-7-7----64-546182379237659184918734562354968721789521436621347895495876213862413957173295648
9---8-237-5-4291-6281-----4--51-4-9--19---762-----7--15--94---3-9863-----43---8-9964581237357429186281376954725164398419853762836297541572948613198632475643715829
95---386-6-3--8---8741-92--297-4-58-------4--5----2-97-3592-67-7-2-3--41-----73--951273864623458719874169235297641583318795426546382197135924678782536941469817352
71-4-5-------72-4---2---8--831-67-94-74859-32---1---86-67---91-28--9-4-----5---7-716485329358972641942613857831267594674859132529134786467328915285791463193546278
--------21--4--87-478-2--615-36-----6827-9--471-3---568-4-3-92----8----3-31-47-85396178542125463879478925361543612798682759134719384256864531927257896413931247685
8937514-67--982--1-----4-9--841--2-7--------41624-38--6----9---218--79--4-93--6-2893751426746982531521634798384195267975826314162473859637249185218567943459318672
5341-9--2-684-----7-16--8-4--------3--72--15-152-3-4-767--215-8-25-6-39----5----6534189672268473915791652834946715283387246159152938467679321548425867391813594726
---5-3-12398--------2-64--89-6-271--251---4-74---9-2-6-248796-376-------8-92-6---647583912398712564512964378986427135251638497473195286124879653765341829839256741
1-8-34---------71269--2---3-7-39--6-53-4---79---65-834------95-9-3----2775291-3-6128734695345869712697125483874392561536481279219657834461273958983546127752918346
-3-68-1-7--72196--5--43-8--7---2-3168-1---4-23---96-----3-61----4-35-9--1-59-8--3932685147487219635516437829759824316861573492324196758293761584648352971175948263
---4-2-36491--------658---1-659718-478-------1-98-6---5---9-6-8623---5-79-876-3--857412936491637285236589471365971824782354169149826753574293618623148597918765342
-236------5------98---2-315-3-5--7-8-728---36--827-541-8615-4----9-8----34-7-61-2923615874157438269864927315431569728572841936698273541786152493219384657345796182
---1238-7-27-493---4--8-2-9---465---1-6----32-98--2--5---97----5742-89-62-9-54---965123847827549361341786259732465198156897432498312675683971524574238916219654783
291-6-53-346---1877----3-----2-51863538-42-1-61-8---25-57-2---1----8---69--------291768534346295187785413692472951863538642719619837425857326941124589376963174258
--4---5811-3745-6-529--87---7-41---6--19-----935----178-7----42----32-78--2-746--764329581183745269529168734278413956641957823935286417857691342496532178312874695
---8---5-4--915--21562348-7-18--29-4--------82796-81--9214--5--8-5--67-97--5-----392867451487915362156234897618352974543791628279648135921473586835126749764589213
97-5-36148342-157---69-4-------4-2---85----6772---5-----8--7-------3679-3---5--42972583614834261579156974328619748253485312967723695481598427136241836795367159842
--96-7---4-1---53---2--56949--4-6----3--98-7-8-417-9---9--6124-2--754-6---8-39-1-359647128461982537782315694975426381136598472824173956597861243213754869648239715
4----69-5-92--3----3-49--2898--52-----68----9-1763---27-3-----1--832459---9178--4471286935892513476635497128984752613326841759517639842743965281168324597259178364
----3-8---9--68-4-84----71365----4-242-5-1-----96-45----42--357287---6--9--7461-8512437869793168245846952713651893472428571936379624581164289357287315694935746128
17----8---98-51------7---6-4---67-8----12-54---9---1--94681-3-7--5---6-221-5364-8174693825698251734532784961451967283763128549829345176946812357385479612217536498
75-34----------9239--1-87----56-78-28-7--2--16-1---547---87-2-9-------863-829617-752349618184765923963128754435617892897452361621983547516874239279531486348296175
-94-28--5--2-6---9-15--96------172--2479-5-1-861-------79----63-38-7--9-52-3----1694728135382561749715439628953617284247985316861243957179852463438176592526394871
2-4--1-383----------85-3146--92--481---9--6--4-6--539--9-3-----6-31728591--4892--264791538315648972978523146539267481781934625426815397892356714643172859157489263
4----97---18----9476---85-329-8-4--6--7-91-2---6---8-9354--29-------365-68291-4--423159768518376294769248513295834176847691325136527849354762981971483652682915437
-----6-7---1732--85731486-9382--17----9--7---7-65--9-2--------663-8--2-12986-53--824956173961732458573148629382491765159267834746583912417329586635874291298615347
-7-5---46-9-2-----------3--71---569856-892-7---96-72-5-2--687538-----4-----459821278531946396284517145976382712345698563892174489617235924168753851723469637459821
--2--413--54---8-9-9--8-4-75--9--2-3--371-9-6--9-5---1------5721--82-----2-3-9618782694135654137829391582467517946283243718956869253741938461572176825394425379618
2-65984-19-7-3----5-14-7293-1---596-35----7-44---8----1--6-4------81-34--9------6236598471947132685581467293712345968358926714469781532173654829625819347894273156
25-3--6-78--4----2-93---84-14-8-35----294--1---5---4-3---6---756781----4531-94--8254381697816479352793526841147863529382945716965217483429638175678152934531794268
-274359-----198---9-3-----53--68-2-----32-16--6-5-7-9---297---15-824--7-1---5--2-827435916456198732913762845391684257785329164264517398642973581538241679179856423
-76-8934194----8561-3--69--4--86---2----3-----9-54-6137-43--2---5------43--124-7-576289341942713856183456927435861792621937485897542613714395268259678134368124579
1792-85-----95---7435------5-28----48-137--2---7-4--8-9-8---46-6-3-9-8--72---6-5-179238546286954317435617298592861734841379625367542189958723461613495872724186953
76-2-35---2-196--7-3-8-5-4-----62--5-9-5-48--5--93--64256--1-7-18-----36----29-5-768243591425196387931875642843762915697514823512938764256381479189457236374629158
31927-5---58--32-92--59-83169--2---5----3---8--4------871---356542-8-19---61-----319278564458613279267594831693821745725439618184765923871942356542386197936157482
136---------6-82--298-57-6---23----5-592-1--7-67--53---418---5-72--4---6-85----34136924578574638219298157463412376895359281647867495321941863752723549186685712934
---975--19-812---35----------14-9--23-7--21-46-----9-8-89-514-7-4--6--19-3-79482-463975281978126543512843796851439672397682154624517938289351467745268319136794825
43-65-182-1-7--34--86---5------2573---4-68-2-1-2----6-----9-6-3-4-2-6-97-695-7--4437659182915782346286341579698425731374168925152973468721894653543216897869537214
74516-3-2--6----14-329----5-29-76----7--14-3--1----57-2-1-8----98-7-1--33--6-9-81745168392896235714132947865529376148678514239413892576261483957984751623357629481
--56-3-42--72----1----7159----5-74---79-8-2--5-1--4-78--87--163--346----79-1--854815693742967245381324871596682517439479386215531924678248759163153468927796132854
4632--1-----3--94-529-716---9----5-1-8-71--2-1-26-5--975-----16--61--8--9-85--4-3463298157871356942529471638397824561685719324142635789754983216236147895918562473

200
apps/sudoku/sudoku.hard.txt Normal file
View File

@ -0,0 +1,200 @@
---15962-----2-89-95-86--7-8--9-634---35-81677---1295-12--845------91--6---2-----478159623361427895952863471815976342293548167746312958127684539534791286689235714
29---3---------9456-89--213-2-8--57---7-9--36---47-82-53--6-18-8----469--4--8-3--294513768713628945658947213429836571187295436365471829532769184871354692946182357
-9431827--------98---79-1-3-79--1--2-28---567-5--879-15-764------3-297--------314694318275731452698285796143379561482128934567456287931517643829843129756962875314
4-7--1-322----------3-92157-8--2----1--3784--5-2614389--8-4-713----8-5--7-5--92-8457861932219753846863492157384925671196378425572614389928546713631287594745139268
--58--937-769-------3-156845-4----6-6--3-48-5-8-15--2-9-74--2-6--25--3--35-----41145862937876943512293715684534287169621394875789156423917438256462571398358629741
-65--84-77-8--1--61937-48-------56-46314---8---2-----13-4-57-69---8--2--9--1-35-8265938417748521396193764852879315624631472985452689731384257169517896243926143578
-6-9-372---86-43---3-2---8-3--7-5-1-85-3-1----4--62--54--1296-3---478-----2---14-564983721278614359931257486326795814859341267147862935485129673613478592792536148
---1-72-4-61432-79------31---837-4-1-39---758-17-4-9--------642-2-91---787-6-5---983157264561432879742896315658379421439261758217548936195783642326914587874625193
8--3259-4--5----82---781---76-29-----8-5-46--9--61--2--9--5--7---784---9-4-93--51876325914135469782429781536763298145281574693954613827392156478517842369648937251
--3-----7-9-16--8-----57-94936-781-2--4---5-675-6248-917------83-874---------1-6-583492617497163285612857394936578142824319576751624839179236458368745921245981763
--789--1-5--243-6--9-61--45-8-97--3-7-43-1--99---64-----9-36---4-1----82--5-2-496647895213518243967293617845186972534754381629932564178829436751461759382375128496
--9-568376-8--2-9-7-3--1-629-7-25--1----64-----173925-57--98--3---2-----3-6--7-28129456837658372194743981562967825341235164789481739256572698413894213675316547928
-38-972----2-8493-9-63------9-----75-7-91--2-86-74----62---85--4-----19-5174-96-2138597264752684931946321758291863475374915826865742319629178543483256197517439682
-7--4--36698--1-24--------97--45--9--4---2-----5-9-487362-14---9846-51-31--98-6--571249836698531724423867519736458291849172365215396487362714958984625173157983642
-----4-----678--419--15-----2--98-65-58-4-----49561---2918-63---739-5--8-6541---2712634589536789241984152736127398465658247193349561827291876354473925618865413972
85169-----9--73--16372-1-592---3-746--68------4--263---------3-7139--86---4-6-51-851694273492573681637281459289135746376849125145726398568417932713952864924368517
281---------48-7--7435-6--8-7--1--6--586--1---3627--5--64----91-29-4---65-7--9-8-281937645695481732743526918972815463458693127136274859864752391329148576517369284
8-791-4--5--8--1----146---53--72--1--2--846-----13-25----657---6-3-----8-14398-6-837915426546872193291463785365729814129584637478136259982657341653241978714398562
9-3257-41--8-14-7------935-29--48-------3-2-735--2-1---3286--1-6--4-3----891--63-963257841528314976174689352291748563846531297357926184732865419615493728489172635
3-6-9---75-98--162--2-------6--12-8----98-536-834-6921197-2-4-----5----92---49-7-316295847579834162842761395965312784421987536783456921197623458634578219258149673
-8--14392192-584--3-49--8-1-61-8---4----9---37--------235---946847-3-21-6----2---586714392192358467374926851961283574458197623723465189235871946847639215619542738
-1837---6-9--8----2-65-1-43--7----9--241-----8---4-372--27---85-8-45-637-458--21-518374926493286751276591843357628194924137568861945372632719485189452637745863219
48--75--1--9------7--6-1-9426-------59-7-8--38173--95-3--1-7-699--4-6-8-65-8--417486975231139284675725631894263519748594768123817342956348127569971456382652893417
--634----5--97-3-2-----2---45-23-1--89-6-47--3617-5-8--1--674-574--2----62-453---276341598584976312139582647457238169892614753361795284913867425745129836628453971
--1-6495-5-6-931---925-----7834-92-1-4----79-12---68--26-34----3--97--1-9------38831264957576893124492517386783459261645182793129736845268341579354978612917625438
-2-56--4----7-8-239-------8-86-----44-938---------6-5-3-----7-5-781534-25928-46-1823569147165748923947231568286915374459387216731426859314692785678153492592874631
3--65--7----73-58--5--412----712---88--4--7--4-697-1--2-3-----4-71394-2----286---328659471164732589759841236597123648812465793436978152283517964671394825945286317
8---2-6-1-5-9---4227-----59--7--5-686--1-4-355--7---1---18-9---------487-8--56193894523671156987342273641859417235968628194735539768214341879526965312487782456193
4-2-----5--84-79--9-78--6-328-746-3--94-5--7-7-691-42---9164-----------1--3-892-4432691785568437912917825643281746539394258176756913428829164357645372891173589264
42-16--75-8-5-4-6-651-79-3--943--5-7------2--2154-----9--64-3-15-69----4---75-8--423168975789534162651279438894326517367815249215497683978642351536981724142753896
6-8--259------68-21--7-56344---------35--19--9-6-4-1538-351--292----3----74-2-3-1648132597357496812192785634481359276735261948926847153863514729219673485574928361
-2-6-359-5--489-6---71-2-3-2---96----1-2-7-8-7-983-2----2-68---9-3---41---5--4629428673591531489762697152834284596173316247985759831246142968357963725418875314629
-2-6-4--35--39--7-13-75------124-5---4-58-96--5--6--1----129-----6---72-2--8764-5729614853564398172138752649691247538342581967857963214475129386986435721213876495
-5-8---973781--46--294-78-38-7--9--6--6-139-8----5-7-496--74--1----2----732-----9654832197378195462129467853817249536546713928293658714965374281481926375732581649
-31--246--4---------67-41928--4------2-168--3-94253786---8----9-19--78-4--83--621931582467247916538586734192863479215725168943194253786652841379319627854478395621
--7--3-29-48-----62-9-6458775-----4--2-84--5----65--93----1-9-4--24-531--143-62--167583429548729136239164587756931842923847651481652793375218964692475318814396275
-47---3---91843-76-856-14294----5----1-----65---36-1-21--45--9--6----2--93-7-6---647529381291843576385671429426195738713284965859367142178452693564938217932716854
--1-35-7-364-729------4----9--3---64523---79-47695-8-31----4-87--7---2---8-716-4-891635472364172958752849136918327564523468791476951823135294687647583219289716345
-9--16--3--542--1--81-39---8---549----9--2--8--4-976-2---685----5-27349-2-----3-5492716853635428719781539264826354971379162548514897632943685127158273496267941385
-9-2-------19------24-57-9168-7-41----91-32-6--76-5-481--469-83-7--3-9--9-6---4-5795216834361948527824357691683724159549183276217695348152469783478531962936872415
-84---2--2-9-78------4---1----86-73--3--14-2-9-----8---687513-27-----1-619328-5-4384195267219678453675423918541862739837914625926537841468751392752349186193286574
1893-4---6-71--49---39-6-7--64------7-5---6-939-6-2745----192-8572------9----536-189374526657128493243956871864597132725431689391682745436719258572863914918245367
89--3--21-4-81----72194----4---------17--9----852---471-965---8-7412---32-87936--896537421543812796721946835462375189317489562985261347139654278674128953258793614
8--3912-------68--6-1-85--4-8----5----3--21985-68493721-295---3--5------9--6134-5854391267397426851621785934289137546743562198516849372162954783435278619978613425
416-29--3---7---547536----9--4---9-169-3-14----829--6-84-1--7-5-21---39-3--9----8416529873982713654753648219274865931695371482138294567849136725521487396367952148
--58--743--793----86-4--9522-4--95-8-86-5--1----2-8-9---23-71-9--81--4------84-26195826743427935861863471952274619538986753214351248697542367189638192475719584326
-691--28--17--5-9--2-9--5---9435----1-27----3-83-9-4--246-7--19875-----------274-569137284417825396328964571794356128152748963683291457246573819875419632931682745
-16--78----3---25-4283-56-1-6743-----4-52--1--5-----481---7359-6-59-----79--541--516247839973186254428395671867431925349528716251769348184673592635912487792854163
6-21--4-33-79---589-5-836--531--6-82-2--9-1-----3-15-71--6-----4---1-----7954--16682157493317964258945283671531476982726895134894321567158632749463719825279548316
7--8-6----6157---3-593---76----6-41-62--1--3-19--85---9-61243-8-----9-62--5-38--4732896541461572983859341276587263419624917835193485627976124358348759162215638794
--7-63-5-------4728-59-2----56-4---3-31---985-8--51-64---5-6-47------6-1-6271453-127463859693185472845972316756849123431627985289351764318596247574238691962714538
32-1-----7-42--1-31967-85--567-9-4-14--5---67------9--65--2--89---6--2---42-573-6325149678784265193196738542567893421439512867218476935651324789973681254842957316
8569-2-74------89--79---5-67-83--6-9---4-87136--7-94--9-4--5--7------265-12-37---856912374423576891179843526748321659295468713631759482964285137387194265512637948
8----------73-89416-1--9-784-89567239--1726---2-8-------26--197---2--4--1-4--38-2893417265257368941641529378418956723935172684726834519382645197579281436164793852
---2-4-31764------3---95-7-9-6-381--123---58---5-6-39-6-73-9----98------53-78694-859274631764813259312695478976538124123947586485162397647329815298451763531786942
96-175---13--9----2---6317---651-----7-83-59------9---6523-7--484-6-13--71-95-2--964175823137298465285463179396512748471836592528749631652387914849621357713954286
--8-72-59-9-615-7-3---48-2--8-5-7-----4-83-6-53-26---89----158725-----418--7-6---618372459492615873375948126186597234724183965539264718963421587257839641841756392
4---175---7825--1--1-8-6-----7-412---3-5986--1---6283---16-5----82---49---3--9168426917583378254916519836742867341259234598671195762834941685327682173495753429168
4-5-386--3--174--58---96-2---681--421---629-----4-3--6---3-1-6-9-7----84643--7-5-495238617362174895871596423736819542154762938289453176528341769917625384643987251
-6-93-8----4-27-3--5368----5--74---6--62--5----716-2-92-----4-8-4-812-67---459---762931845984527631153684792529748316816293574437165289291376458345812967678459123
1-27598--5-82--379-7--382-53--82495----391786--9-6--------4----7-------32--6-5--8132759864548216379976438215367824951425391786819567432681943527754182693293675148
-965-8----8-----7---124---652-----9-43-8-162716-3298-5--2--4----1----4-8---98-71-796518234284693571351247986528476193439851627167329845872164359915732468643985712
-7--85-2---69-45---35-72------863----6-4217-94------62--9-17-48--7-4--3-3---96--7974185623826934571135672894792863415563421789481759362659317248217548936348296157
-15-37-8---3-486---6---1-3--9--25--32--81--4-----93-26-49---1-----564---3-8179--4915637482723948651864251937496725813237816549581493726649382175172564398358179264
-4192--6-532-4---9-76-1-8--15-6--2-8-68-5--7-2-4-----6---37-1-24-5---6----34629--841927563532846719976513824157634298368259471294781356689375142425198637713462985
6--8-2-5-----3---29256--8---14-87269---12-347-7-9-6-1---6------3-2-1-9764-72----5631892754748531692925674831514387269869125347273946518186759423352418976497263185
-9-5-----7---8--34---67-52-9371-485--6-3-2---2-57-86135-48------89----65----3-4--892543176756281934413679528937164852168352749245798613574826391389417265621935487
-1--89542--6--21-8-98--136--69--3-----2---7--1---9-2566-43-89-5-7--1-----31-25--4317689542456732198298541367769253481582164739143897256624378915975416823831925674
-671-943513----9---4-8--67-----9586-7---31-5-5-4----1-21-98---7-7-51--28-----21-6867129435135647982942853671321795864786431259594268713213986547679514328458372196
8--------5-463-9-----7583--9-7--62-3--3-256--1-----4-5-458-37-2-2-1--53--9-572-64836249157574631928219758346957416283483925671162387495645893712728164539391572864
5--329-47----81---3-9-475--8-2--36-4---4------37-962--9---783622-3--54-86-8--4--9561329847724581936389647521852713694196452783437896215945178362213965478678234159
--9-5241----7------72--4-9371-495--6----38-----6-71-54294-13--5-37--6-49-5---7-32869352417341769528572184693713495286425638971986271354294813765137526849658947132
----3859-827-------9-1-6-2-27--91---4-1-------69427-8171-9-4--5953----466--7---19146238597827549163395176428278391654431685972569427381712964835953812746684753219
29876---34-5-8-----16-4-5-8963--28-1--1-3-69---------214-6-39-53-9--427-----9---4298765413435281769716349528963572841521438697874916352147623985389154276652897134
81-56-2--4-539-7--7-6142--3--8------97-6--18-15---4---56148-----8-75-----47-2-56-813567294425398716796142853638219475974635182152874639561483927289756341347921568
-7-1-8924--85-276---4-9351----3-----3-9-861------59--21-582--4-----3-85----91523-573168924918542763624793518852371496349286175761459382135827649297634851486915237
8--9--216--6-3-----2-8-6-9-691-875-435746-----4-1-9--7------9----26--75-179-4-63-834975216916234875725816493691387524357462189248159367563721948482693751179548632
83412-5-7156-47----7-3-8--19----415-318-7-46-------3---9-4-2-3-4---6------2--3984834126597156947823279358641927634158318275469645891372591482736483769215762513984
--8-76--44----2-8-2-5-81-6-----9843--3-62--7-9---358---862197-----547---7-9-----2318976254467352189295481367652798431831624975974135826586219743123547698749863512
21-7---8--75-9-6---96---47---1-4--6--63-15-2--82--6--4548----------89--11396-28--214763985375894612896521473751248369463915728982376154548137296627489531139652847
--4-53-29---1-----1-3--26-4--7-192-5----68---91-2457--5----13-6432-965--6-1--74-2784653129269174853153982674847319265325768941916245738578421396432896517691537482
2-7--51-4-54--1---9613-78---89-5--36-----95--52-78-4-9--2--8-97------6--798-6-2-1237895164854621973961347825189254736476139582523786419642518397315972648798463251
5--39--2--3---1-----9-2-543------2--624--731--5--3-68-7--24---6861-73---2436-98-7586394721432751968179826543318465279624987315957132684795248136861573492243619857
96---52-----7---1--81---53-----91-2-13-27------9---6---12657-49643-18-52---3---68967135284354782916281469537476591823138276495529843671812657349643918752795324168
4-31-297617--------69---1-4--4--631-926----------542-8-3-4-1-9--915--74-8453-7---453182976178649532269735184584276319926813457317954268732461895691528743845397621
134-8--26698---5475----6-----1-2467884-7--2-1267-91--4-25-1-4------7-8--3--------134587926698132547572946183951324678843765291267891354725618439419273865386459712
6--9-3-85-3--567-----84---6-9--67-5--4-381--228--946--17-----98---43--6-468-1--2-614973285832156749759842316391267854546381972287594631173625498925438167468719523
8-574-621-125---7-67----945-2-6318---86--2-3-9-------67---69152-6--54--3----2----895743621412596378673218945524631897186972534937485216748369152269154783351827469
---3--4-656-2---7-8-4-67--36----82--4---321-9---45--689-----31-7--8196---567438--271395486563284971894167523615978234487632159329451768948526317732819645156743892
4-----8--5----4296--1-287-47--4-----264-9-5--935-876411-7--6982----7------9-52-67472639815583714296691528734718465329264193578935287641157346982826971453349852167
-817--4-97-49-----5691-2--3613-5-9-8--83--16---------53-6-7-52-87--316-4---6----7281763459734985216569142783613254978458397162927816345396478521872531694145629837
165---3----4-6-295-8-3547-193----4-664-79------843-9--8--1-3-4------21--41----572165927384374861295289354761937218456641795823528436917852173649796542138413689572
---865---49-213-5-3-5---2--9---546----6--2--98-2-91--4----39-67-7-42---5--3-78-9-721865943498213756365947281917354628546782319832691574284539167179426835653178492
--267-13---41--5------54-82--94--765--73-6---48-5--3292-5-3-94--48--9--1---24---3952678134864123597713954682139482765527396418486517329275831946348769251691245873
--8136-455-38----96-15-9--7--749-618-------528-6--7-941-59-3--6------9--46---1-83798136245543872169621549837237495618914368752856217394175983426382654971469721583
328----49-4-----36-9623--7-83----9--56-48---2--4------48--7--239-3-6--516-2--1798328756149745918236196234875837125964569487312214693587481579623973862451652341798
5-67-2493-29-----7--3--1-5634-----2----47--61-5-29--4----8--6-2--5-2418--82-175--516782493429536817873941256347168925298475361651293748134859672765324189982617534
-9---3-4--6--9253-4---869----9-75-1--8-63---7-74-19-----83216-9---548---3-----18-192753846867492531453186972639275418581634297274819365748321659916548723325967184
---2-54--457-86--2923-------4-3---8--62--83---784-9-6--915----86-4-1--2--85----13816235479457986132923741856149362587562178394378459261791523648634817925285694713
8--3-5796-----62-46-4--2-157---------95--8--11-6-7-9582----9---4-958-12--37-2-8-9812345796953716284674892315748951632395268471126473958281639547469587123537124869
-2---1635--7245-98851----4--7--24-6-1-2-96---6-4----21---3---8-7--48-2--2-8---953429871635367245198851963742573124869182596374694738521916352487735489216248617953
937------6--9--45----61-3-81682-4---57---126--4-5-6-7--25------79----5-64-63-5729937458612681923457254617398168274935579831264342596871825769143793142586416385729
8634-5-915-9261-78----3--4635--92-----7---6-----5-7--94-5---1-3----2---567-1--9--863475291549261378721839546354692817917348652286517439495786123138924765672153984
--5912-7-6-3857294-2--6--------2--3-2---7-5193-1--4-629---46351--6------1-7--59-6845912673613857294729463185598621437264378519371594862982746351456139728137285946
-65--97-3-27--814--4871---5--3-9----28--3459---9--5---7945--61-6---8---9---9-72-4165249783927358146348716925573892461286134597419675832794523618652481379831967254
-1---2---925---6317435--28---48-35622869-43--35--6-4-88-14----3---6----5-7-------618392754925748631743516289194873562286954317357261498861425973439687125572139846
--6452--7-75-86-1---8-193--561-2-7---29---8-5---64-1-----56---1--4-31-9--1-8-45-3136452987975386412248719356561928734429173865387645129893567241754231698612894573
9--2--567-4-5891-3521-----8-86---2-94--89---6-9263---------7--1--4-18-9--19---735938241567647589123521763948386174259475892316192635874263957481754318692819426735
264-398--8-3--4-1-51---893-7------4-421-9---8-----519---6-4258-----8-7--9-25-3-61264139875893754216517268934759816342421397658638425197176942583345681729982573461
--135-8-2--58--6--6--19---58-----9-4-9-438-51---962----6754------9-81-7--5-27-4--971356842435827619682194735823715964796438251514962387367549128249681573158273496
-----35-662-1--8-7-------2---4639-188--47--539--51-6-2---32-165---85-2--51--9-38-147283596629145837385967421254639718861472953973518642798324165436851279512796384
3512-4--6-89--5---74---98-5--------1-7---643-463-1-5-79-746-3-8-36-9-12------3--9351284976689175243742639815295347681178956432463812597927461358536798124814523769
--------5-3-451----8-6-39-132--6-4-819------7-6--123--9-6124-8-24-53-19--137---2-471289635639451872582673941325967418198345267764812359956124783247538196813796524
--1-43----78--9-5-6397-814--4-96-----85---6-1-6--7-4-38-4---2--52---7-647---24-15251643789478219356639758142347961528985432671162875493814596237523187964796324815
----83-----6-91-2591-245-6--89--6-42-5---9-78742-18-5---4-572-1---9------97--2-84275683419436791825918245763189576342653429178742318956364857291821964537597132684
-97---21-1-5-9---------3--5----286-18----935--7--1-----2-63----73854-1-96-198-432397854216185296743264173985543728691812469357976315824429631578738542169651987432
-17-2-4------5-6--3--------758-92--4-2--748566-45--7-2243-6--781----8---869---145517826439492753681386419527758692314921374856634581792243165978175948263869237145
-2------59-7-86------9-28---93---7-42-54----8----6-9------7-53--8965412-5713-948-428731695937586241156942873893215764265497318714863952642178539389654127571329486
7-94----243-682----129376-49---1-573-8---3---1-35---9-3----526-------9---4-27938-769451832435682719812937654926814573584793126173526498398145267257368941641279385
-41-26---------792--785-1--8-239751--------83----819-74--13-8-95-3---4611-89----5941726358685413792237859146862397514719542683354681927426135879593278461178964235
8-695----1---32-8---9---7---18643-59-53---6---2419-378--1----92----691-73--2-----876951423145732986239486715718643259953827641624195378561374892482569137397218564
7---3-1596-9--27-8----7---6--8------9-3--581-1---28965-7--8------5197--38-6453271782634159639512748514879326258961437963745812147328965371286594425197683896453271
78-542-63---1---95135-98-72-56-2-7-----4----889----2-16-----5---187-4-------86--7789542163264137895135698472456821739321479658897365241672913584918754326543286917
7462138-5932--6--78------2-6--7392--2----5-----1-285-9--738-9-6--------81-85973--746213895932856417815974623654739281289165734371428569427381956593642178168597342
1-----57--548-71--3--25---4---6---19471-25-8-8964---5-72----8-5--85---3--137--69-162349578954867123387251964235678419471925386896413257729136845648592731513784692
--9--48676-3---1-4--87-5-----2-183--9--5467---8--736-9-1--825--2-635---88--6-7---529134867673829154148765923762918345931546782485273619317482596296351478854697231
-2--319---8-576--4-64-82-1--37---2-6---8-51--618--74----125-6-9-5--19-3----6-8--1725431968189576324364982517537194286942865173618327495871253649456719832293648751
9---36-2--6572---3-3-5-4---3---47-58-8-215-4---6-93-7---8--1534-57----91--34-2---974136825865729413231584769312647958789215346546893172628971534457368291193452687
-1--46237-36--8--1-72--58-6-21-845------69----5-271-84-67--23-8---8-----2-4-137--815946237436728951972135846621384579748569123359271684567492318193857462284613795
--4-5---2-5---4-73--3-28-415-6----94--76--32-4---9--687--4-3219------857-2--79---194357682258164973673928541516832794987641325432795168765483219349216857821579436
----123-73--46-5---1--38--2--2-54-7--7---62---68-294---51----6-2-4691--5---875---846512397329467581517938642932154876475386219168729453751243968284691735693875124
-----1---5--9-76-86-----7139-7--4---8--6--27-2-63-5-8-76--2---43-279--61-89-5-327473861952521937648698542713957284136834619275216375489765123894342798561189456327
1--697-25-6----1-7---431----3--15--2--2--63----5-296-43-8-72-----156--8-2---847--183697425469258137527431968634715892972846351815329674398172546741563289256984713
6-597124-9-83-----1-2-84369-2--1--954--7-----31----48--9----5-----2-7-342---45---635971248948362157172584369826413795459728613317659482794836521561297834283145976
3-51--249-12--9---------167--3--651--97-5-43--6--3-9-----68-32--2-3--78-8---1--95375168249612749853948523167483976512297851436561432978759684321126395784834217695
6-8-12--5--15489-22--------4-21795365--6--817-7----2--8-42-7--9---4--7----78516--648912375731548962259763481482179536593624817176385294864237159315496728927851643
1------98---479-----92185-3-648-5----9-13-6----56-7-8--5---1-4-4--9-3--5-3-5-2-17127356498583479126649218573264895731798134652315627984852761349471983265936542817
-2-3-6-4----5-----3514-89--9---3--15638---49-51469-7-3-4----8----7241-5-2----5-74729316548486579231351428967972834615638157492514692783145763829897241356263985174
--91687---15---6----8457-2989-2-4-----3-8-9--6-153-4--5--97-8-4-7---329-9-4--5---249168753715392648368457129897214536453786912621539487532971864176843295984625371
25-8---9----4---3---7-------845-93--9--134-58315--8-69879-51-4-461283-----2-----1253876194698412537147395826784569312926134758315728469879651243461283975532947681
67-3----81------458524-17-6-4----82--2--54-7-36--12-----713--94-9324---74-6--9---674325918139687245852491736745963821921854673368712459287136594593248167416579382
9-351---27-----------947--5--56-9--12-4--1-568------93-2-49613--39-75-64-6--8-5-9943518672751362948682947315375629481294831756816754293528496137139275864467183529
---4------1------2-8--65--7--127-8-683-6917--76---8219-2-84796-9--5--------932175357429681416783592289165347591274836832691754764358219125847963973516428648932175
6-7-14-5-2----6-1---1-35--28---971------8129--9-56--3-3-8-----6-156483-----723---687214953253976418941835672832497165576381294194562837328159746715648329469723581
-269-85-----7--2-8---6217-93---86951-8--924-3-5-17-6-2-----7----1784---6---21--9-726938514139754268845621739372486951681592473954173682298367145517849326463215897
-52974--6-71-86-5-43--21-9-58---234---3------14-7-----214-37---3---15---7-5-9-21-852974136971386452436521897587162349623849571149753628214637985398215764765498213
----8----815-936--2---14--9--7925--89-----3---2---8-9758964-71--6-1---85143---9-6394786251815293674276514839637925148958471362421368597589642713762139485143857926
-4329--17-7--8-23--6-7315-48------436-15---72--23-7-5----913-2-9--------3-4-52-6-543296817179485236268731594857129643631548972492367158786913425925674381314852769
------4891-3--827678-6-----3--4--81--4--3--6-96--1-32--7---359---5-8-6-1----5473-526371489193548276784629153352496817841732965967815324478163592235987641619254738
---6----4----1---616-48-37-59---1268--67--5--3-8-26-----19-2-8798--7--322-4-6--51859637124743215896162489375597341268426798513318526749631952487985174632274863951
82-6-4--39415-38--65--97--1---7-----5---32-79--4-69---47-956----1-34--5636--7----827614593941523867653897421192785634586432179734169285478956312219348756365271948
-6---5---7--6-91-5-4-321--64287635-9613--42---9-----6-------9--2--93-4-197-152--3169475832732689145845321796428763519613594278597218364351846927286937451974152683
2-7-64-3-1-68-9-5-458-13--7----9-----4-6-8-----13-298-9-4186---6-39-----5--43-16-297564831136879254458213697825791346349658712761342985974186523613925478582437169
73--2--9-2-51----81-8----26---9-17--471-83--9659--------76---8-8-47-5-3-9-3--86--736824591245196378198357426382961745471583269659472813527639184864715932913248657
-9-2134-7---968---3------92--714--386--79---4--43---6--6542------9-375---4-85--2-596213487472968315381574692957146238638792154214385769165429873829637541743851926
----8--1---6-4283-9-23-76-51-----4-------395-425-9---88-7--45--35---879-264-79-8-743685219516942837982317645139856472678423951425791368897134526351268794264579183
8--3---5-7-4-5-3--1-586--7-6-92----55-2----93-78--9-4-281-75--4463---------42-8--896347251724951368135862479619234785542786193378519642281675934463198527957423816
--2-96--1------3824-17-3----4--158-9-19-8-6---65---174-93258-16------59----1-92-8532896741976541382481723965347615829219487653865932174793258416128364597654179238
-23--4--7--9-7--4--75-3--969512--7-3642-----------9-21-867---1-39--2-8---1748----123964587869571342475832196951248763642317958738659421586793214394126875217485639
23---6-8-6-9-5-7--5-7---16-8-37----17-492--3---2-1--7-4253-78-----58---2198------231476589649158723587239164853764291714925638962813475425397816376581942198642357
5--3-4--7---78-5627-2-15384-4-1-8--9----6-8--8394---1---4-------68-7-435-258--9--586324197413789562792615384647138259251967843839452716174593628968271435325846971
1-826-5379-3----4-2-54836-9--6----7--2--31--5-5469------2---1-6----4672--3-1-----148269537963517248275483619316854972829731465754692381492378156581946723637125894
---539-----9--71-4-67----25---9-3-71---81----1-5-748936--3-17-84-8726---7-14--3--214539687589267134367148925846953271973812456125674893652391748438726519791485362
--6-824-9--96-4---7-2359--1--------3--1--825--3-5219-821-86-5-4-6-1-537---5-----6156782439389614725742359681528976143691438257437521968213867594864195372975243816
429586------9----557-132-6-2--754-811-762-4--645--1-72--6----4---2-79-1----3-----429586137361947825578132964293754681187623459645891372956218743832479516714365298
-8--65---627-81----15-3--6245---2-78--8------76-1-----87--26-3-1-6-49-5-5-23179--384265791627981543915734862451692378298473615763158429879526134136849257542317986
7--69-8---5-----1-83-4-5----64----3--295-7168-872634-5-7----5-96----9------35--71742691853956832714831475926564918237329547168187263495473126589615789342298354671
6---9517213-8-----5--7--8632-5----1--7-95--4---16-27-53-82--4-14--5--6---56----29684395172137826594529714863265473918873951246941682735398267451412539687756148329
81----9---4-95-1-----16-2-7--8--74-2-95-----64-26-9518---3---29-39-76-4---4-9137-816723954247958163953164287368517492195482736472639518781345629539276841624891375
17243---5------3---53-1-6-25941687-36--2951-----3---9-7--9-----3-9-4-2-72156----9172436985968752314453819672594168723637295148821374596746923851389541267215687439
-36-582-77-5-3--14---7--3--587-4-6-96--5---78------4--86-3--9-22-39-----9748-15--136458297795236814428719356587142639642593178319687425861375942253964781974821563
------6913-251------9-47-2--27--6--4-48---532-3--82-76---27--69-7196824-------7-8754823691362519487819647325927356814648791532135482976483275169571968243296134758
389-145----4-8569356-9--4-8-7-----------9---68-2-4---5745-6-38-136---952-2---3---389614527214785693567932418673521849451897236892346175745269381136478952928153764
----3--2-8-47-5---35------4--8-----5-9-2-3-4----15--9798254-3-6--7---1-251-6724-9671439528824715963359826714148967235795283641236154897982541376467398152513672489
76-53---8-----6------79-2-----987-62----6--9398--23-1---43-81273--2-9-541--67--89761532948239846571845791236513987462427165893986423715694358127378219654152674389
--7----86--9817--334-296--12-13-96---34-5--9-----6-3-2--26-57-8--3--1--5---42-13-127543986569817423348296571271389654634152897895764312912635748483971265756428139
-96-43-----1---83---3-21-7--679----8-4-----123821-47-67--49--519-531---761---5---896743125271569834453821679167932548549687312382154796738496251925318467614275983
8-6-14--3-178-------3-65-8176-45----4--19--3-1-----24-9245-13-7-5-----1937---6--2896214573517839624243765981762453198485192736139678245924581367658327419371946852
2-194---8-7--82-4-8--1-3---1-9----76--5--6183--83-4---5--461-3---2-78-9--8--39-15251947368973682541846153927139825476425796183768314259597461832312578694684239715
-----37-6--12-4398-73--645--35-8-14994---15----8--------6--9---28--6-9-1-9741--65429853716561274398873196452635782149942631587718945623156329874284567931397418265
2-17-------3-89-72-78-25--3-2----65--5-24--3-81-59----6459-23-19------2413---8--6291734865563189472478625913324817659759246138816593247645972381987361524132458796
--3---21---7-25--929-1-83--5-1---8-2-8---2-7-37---146-648--9-2------4-3613925--8-453697218817325649296148357561473892984562173372981465648739521725814936139256784
1-8--5-4372----59---3--2--72-5---4---6--293--4--5-7-26--729-654-84--1-----2--6781198675243726134598543982167275863419861429375439517826317298654684751932952346781
15-----872-97--64---65--1--5-7-----44--1-735--3-85---6--53--291--1-85473-942-----153462987289713645746598132517639824468127359932854716875346291621985473394271568
712-96-844--2-7--683641------51--86-627-4-31--------7-5--9-17----1-3-----9-7--251712396584459287136836415927945173862627849315183652479568921743271534698394768251
-54--38277---9--4-8-12-7---6-27--3-43---529-8-859--2-1---3--7------7-6---7386--19954613827726598143831247596692781354317452968485936271169324785548179632273865419
-1-6-9--8------571-8453----4--2-87-962----83489---76-----98-1-795-712-86------29-512679348369824571784531962435268719627195834891347625246983157953712486178456293
2--4--95---1--64-84-7---6-1-7--1-2-55---891-31----7--9--215-396-9--62---------782286431957951276438437895621879314265524689173163527849742158396398762514615943782
639---7-4-4----2-927-93---54---------2864-3---96----7-3-2--16579-72--1-8-645--9-3639852714845176239271934865413729586728645391596318472382491657957263148164587923
------1486-1--7---29--1-675---38-9-6--6-9-4-3-3-1---279----82-1--89--7--4-72--5-9375629148681547392294813675742385916816792453539164827953478261128956734467231589
92-64--37--8--5---5-43-1-9--5---73217-24-----1-------8--57-69132--1---656-75--2-4921648537378295146564371892459867321782413659136952478845726913293184765617539284
--91-43--3-17-56--745--912-6--9-723-------81--32--69574-35-17----------35--27-49-869124375321785649745639128658917234974352816132846957493561782217498563586273491
3-65--82-9--6--37-27831--9---516-98----43----16-928-5------6---6-78--23---279-1-8316579824954682371278314596425167983789435612163928457831256749697841235542793168
4--821--7---5---1-2197645-3--------57389-52---25--78-45-1--93-88724--1--3--1-----453821697687593412219764583146382975738945261925617834561279348872436159394158726
53----6-7---416---4--5--82-2-5--8-1-9-8375-----32-195-----29------1-42-56-285-194531982647827416539496537821245698713918375462763241958154729386389164275672853194
-135-4--74-8-1------76-3-14-4----95-38--56----5--42-7-92546-7-86------4287-3----9213594687468217395597683214742138956389756421156942873925461738631879542874325169
6--432-5---198--7--8-57-63---8-25---3-7---49---6-4-5838---53----9-81--2-1-32-78--679432158531986274482571639948325761357168492216749583824653917795814326163297845
19-86--2--3--9--8-8--72---3---48-35---59-2-7--4-51-8--47------9---371---2-86497--194863527732195684856724913921487356685932471347516892473258169569371248218649735
----718---36-54129184-32-67-----69--5-13----2-672-8----5-1-----6-8---39------3-56925671834736854129184932567842516973591347682367298415253169748678425391419783256
231----------9--15985--17-6-16-3---7-786---92--97---3-69-1--4---42--7-5--574-3---231576984764892315985341726516239847378614592429758631693125478842967153157483269

View File

@ -0,0 +1,200 @@
52-9647-1--4---9-5879-216-3--8---2--7--39--1-----5247------3-9--8124----23----1--523964781614837925879521643158476239742398516396152478465713892981245367237689154
-4-9-3--57--28-9--96-5-4-----67-8-4-4----2--68--4-1-32---637----7-12548---2----57248913765753286914961574328326758149415392876897461532584637291679125483132849657
--92---58-1---742--62---17---8-4531---1--65--6---1-89--9-18-7355---79---------964479231658815967423362458179928745316731896542654312897296184735543679281187523964
16-2-4----5-39-6--------572--186-9-7-83---146-96-7---3-2978536--------98---9-67-5167254839852397614934618572241863957783529146596471283429785361675132498318946725
87--541-22----975-6--127-38--9---8-7-5-27-3---16-3-2-5-875-36----4---------7415--873654192241389756695127438329415867458276319716938245187593624534862971962741583
9---851-48-4-129-----4--68--75-----8--983---5---52--163-8----2-7----1-6969-2-8573926785134834612957517493682275164398169837245483529716358976421742351869691248573
---83-69--7-----8---6-245-----4--2--4-8----5-75--98---62758--148-3912-65-9-----23214835697375169482986724531139456278468271359752398146627583914843912765591647823
53-7-91--78-6--9---6-38574-37-9-85--4-5--386---------965---149-------27--1-49-635532749186784612953169385742371968524495123867826574319657231498943856271218497635
3-4-682592----134-58----6--87-1-6--44--8-9-71----7-8-3-92----8--4-58--9----69-13-314768259267951348589243617875136924436829571921475863692317485143582796758694132
-895-4--31--78-9--3------485269---8----6--23-943-78-5---58---1-47----8-5-314---26289564173154783962367192548526931487718645239943278651695827314472316895831459726
82--349----529--3--9-7-8---2--95--4--1-863-7---947-18-9--3-7---48----65-1--6--798821534967745296831693718524278951346514863279369472185956387412487129653132645798
----5--6-93----4-86-4--3----8-2-5---1596-7-344-23-1587-9---4-----1-3-6-5----18-42728459163935176428614823759387245916159687234462391587293564871841732695576918342
91-38----6-8-----1-----6-5--3----7-54598-16-28-72531-4-9------8---7-8-43--456--1-915387426648925371273146859132694785459871632867253194791432568526718943384569217
287-43-1---1--9-839-3--5-725---94-21----36----94271-5----9-----8-9--2-377---182-4287643915651729483943185672576894321128536749394271856432957168819462537765318294
3-6---21-----9--6-48---25------1--436-5249-787416-3-2516-95-------8-6-5---8---4--356478219217395864489162537892517643635249178741683925163954782974826351528731496
--958--1-2--463-7--8-71-26--5-89--3-9-63-18--8---76-----2-4-7866-1---45---8-37---769582314215463978483719265157894632926351847834276591392145786671928453548637129
-----1-----235---43547-2-1-2-38-7--9-98-----7517--46-392-5-834--4516--9------9--5679481532182356974354792816263817459498635127517924683926578341745163298831249765
39----24--584---6-14--9-3--9753-86--621----------69--573--51-8-86---3--25---2--3-396185247258437961147692358975318624621574893483269175732951486869743512514826739
--869--722-1--7----7952---8-2----45-91--65----5--32-8-4352-68-16------2318-9----4548691372261387945379524618823719456914865237756432189435276891697148523182953764
4-7----25--8-7-3-12----6---15---4---93-761-8278-25-149--1----3----6-82-48--32----467139825598472361213586497152894673934761582786253149621945738379618254845327916
7--4-8------27-8-6--1----4-15--6----34-912-7897-8-51638---2------7--94-16-9----85765498312493271856281356947158763294346912578972845163814527639537689421629134785
519----24--2-5-----4-23---8--64-38-----1-6-477-4----36--3---972965--74--2-1349-8-519768324832954761647231598126473859358196247794582136483615972965827413271349685
--5-876--4--2-6--93-64-9-----47----3--81-4-27-3-8-5-4----523----7-----955--97148-925387614487216539316459278194762853658134927732895146849523761271648395563971482
7-1-3---48-365-7--6--4--3---76--21--5-29---3-3-9---24-968-73-1----19---6154------791238564843659721625417389476382195582941637319765248968573412237194856154826973
---91-4---8-5--37-41-3-7596----65-1-1-9-7--6-6-4---83--4812---7-617---282-----1-3735916482986542371412387596823465719159873264674291835348129657561734928297658143
--83-15--6-529----9-------78-----91----6-9-78--3-1----32------641-98-75358-46329-248371569675298134931546827862734915154629378793815642329157486416982753587463291
3--2-4918--2------8-71--3-22-9761534--1538-7--5---2--------5-9-9-84---255----7183365274918412389756897156342289761534641538279753942861136825497978413625524697183
---1-62--1-3-24----6-----8--15---37-----4-1--6-87---2-8395-17-2-214879-6----3-8-5984176253153824697762359481215698374397245168648713529839561742521487936476932815
9----4---2--9------372-8-497-865-4--4-1--925-5-3--7-68859-4--16-1-7--9------9583-986514372245973681137268549728651493461839257593427168859342716314786925672195834
--1--9-269-2--3-47467-82--13---98-14----25----98471--36-9--4-72---9-----7---1648-531749826982163547467582931375698214146325798298471653619854372824937165753216489
------9587---86-----81-2476-1--9---7-2--751-49----18-2-8-3--72---1-6-3-5-39---6-1162743958745986213398152476614298537823675194957431862586314729271869345439527681
7---5832-9--2-146---63-915723-91-7------8-29----53281-----25--158--94-3----8-----741658329953271468826349157238916745615487293479532816364725981587194632192863574
28-7----4--6------1-7428-6-8-9-3724-65-8-4-3---3-----89-127---3---9-3--1--41865-2285769314496351827137428965819537246652814739743692158961275483528943671374186592
--5------2---159639-7--352-5-6437182--3298--7-8--5----8---7-239----8---66-9--18-5135962478248715963967843521596437182413298657782156394851674239324589716679321845
---7-----2---6817---3-41---37-124----9-63-42-64--7----1392-6--542--179--58-4-36--918752364254368179763941258375124896891635427642879531139286745426517983587493612
1------7--2-6-85--95-31----6-3----9-5-24963-14-812-765---9-1-272-----1-8-6--8----186549273324678519957312846613857492572496381498123765845931627239764158761285934
7-6--5219------435-59-1-----136--7-2--7-4-5-6-4-7----1---8-49-78--5--16--9---78-3736485219128976435459213678913658742287341596645792381361824957872539164594167823
----5-9--3-1--6--8-94---7-6----7-14--8961523-1729-468----3-98---3------19-758----726458913351796428894123756563872149489615237172934685215369874638247591947581362
-----5---2497--3-5-759-1--21----29767635-4281----6-5--9276--1--4-----6--5-64-9--3618325497249786315375941862154832976763594281892167534927653148431278659586419723
2-16--9--6-9---52-37---2-8---35---9-9-431--7-8-7-9---5518---------86---3436-798--241658937689731524375942681123587496954316278867294315518423769792865143436179852
9-8-21-----567--8-1-----4--5------16---19-5-4--7--6---85-739-2136--1574872----9--948521367235674189176983452592347816683192574417856293854739621369215748721468935
-9--------15-4-926-231--7----98-1-7-----5-1--1769----82--6-9-4----41-23543--82691894276513715348926623195784549861372382754169176923458251639847968417235437582691
--3-89524-8--571-3-2-46-9-7-----6---64-81---9---74--5----6--7-8---9746-597-5-82--763189524489257163125463987857396412642815379391742856534621798218974635976538241
--945--8---3----2------7---9--215-683218---598-5-932--294361---15-978-3------4--1679452183413689527582137946947215368321846759865793214294361875156978432738524691
--3-456-9------8----5826-----46-1--55-14--3-26-9---7--94-162-3--56-7--1-1-258--96813745629267319854495826173724631985581497362639258741948162537356974218172583496
----8--5323----87---56-----4-312--------3-7--65-8----13-8-95617----642--962-18-34796482153234951876815673492483127965129536748657849321348295617571364289962718534
542-76--3--3--8-648-6--1-52-87523--1----69---1---87-35---8-----2---3457-4-8--5-26542976813913258764876341952687523491354169287129487635765812349291634578438795126
---75--262-----7-9-1---9---1-3----5-4-21853-78-9-72614-2-91-4--7------6-54--37---984753126235861749617429538173694852462185397859372614328916475791548263546237981
---418----726594--4-6----9-9-857---21--9----7--724--1-6--83-7---3--92--4---76-1-3593418276872659431416327895968571342124983567357246918641835729735192684289764153
7-9-35264---96-587--52-4--9-4-3-6--1----8-6--1264---3-4--------68--9-42557-6--1--719835264234961587865274319948326751357189642126457938493512876681793425572648193
1--85--6---3974-2--8-62--93--82-9----5-18--4-9-1-46--83--7--9826-9----578--4-2---192853764563974821487621593748239615256187349931546278314765982629318457875492136
--8-7----95--2387---3--8----67-8--43-94-5-21--254-1--74827--16-6----5--8---84--92218674359956123874743598621167982543894357216325461987482739165679215438531846792
-3-87-495-873--16---65--3-73---8-546-681-------5---2---1345---9-2--3----6-97-18-4132876495587394162946512387391287546268145973475963218713458629824639751659721834
16-2---57-274----198457--2-841-5-2-----6---15-3------4-587-61-9--984--62----2--3-163298457527463981984571623841357296792684315635912874258736149319845762476129538
7--6-34---1-----9-48--12---3---6-----7----1-6---1-8-79-32----8--56-71934-473852-1725693418613854792489712653391467825278539146564128379132946587856271934947385261
94--5--611---4---857---8-4-62-4----3-15-7-2--43-82----3917--45-786-----------1-37948257361162943578573168942629415783815376294437829615391782456786534129254691837
741--58--3-----1529-2831-6-----94-854---836--8-5----34-8-32---62--7-----197----28741265893368947152952831467673194285429583671815672934584329716236718549197456328
8493---5----8---29231-75-4-3-54-12---6-75---3-2----51--17---4-56-21--89-4--5---6-849326751576814329231975648395481276164752983728639514917268435652143897483597162
189-736-5--3---17-5-6-4-9--7------898--1-7-5-6-43-8----5-43-72--67--2---24-78-5--189273645423965178576841932715624389832197456694358217958436721367512894241789563
3-4-----9--713-6--6-1-7-2-547-213-5--63--9-1-1-2-6834---6382-----------8--56-74-3354826179927135684681974235478213956563749812192568347746382591239451768815697423
3--548--94------82-19327--5---2--9-719-6---3-5-7-392--7---624-89---5---6---7-159-326548179475196382819327645638214957192675834547839261753962418981453726264781593
------7---8-72569---63--24--9-6-------7--13566-1-3--7--68249---21-5764-87-5-8---2532964781184725693976318245893657124427891356651432879368249517219576438745183962
-9135----5-7----9------74--8-5643-291425-9-67-3-----48---8-523--1-----5-2--47-9--491358672527164893386927415875643129142589367639712548764895231918236754253471986
1--64-7-24--7--5---5-13---4---352----7----3-9--3967-413---71-8-8-549------428-9--138645792496728513257139864941352678672814359583967241329571486865493127714286935
-4-38271--2--9--6887--562-33-4--16-2--9---8-76--2-8--17-861---4--5---------835--6946382715523197468871456293384971652219563847657248931738619524165724389492835176
6-8----147126----5---3-7--2---7-1-2---392-8--2---34-915-147-2----7163-5---428---9638592714712648935495317682849751326153926847276834591581479263927163458364285179
5821976-37--4581-----3---8-3-8--24-66--8-----4157----81642-3--5------3---53--17-4582197643736458129941326587398512476627834951415769238164273895879645312253981764
-63----71----51-36--1-374----89-----592----833--78---4--7---268-85372-4-129--63--263498571974251836851637492748923615592164783316785924437519268685372149129846357
9-4--78--3-7-2-514--5----------72439-2946-175-4-5-1--25--7-6--8----3-7--178--5-6-914357826387629514265184397651872439829463175743591682532716948496238751178945263
7--2---3--3-54---729-83--5---1-25-4----36-71-6--91-3--46------2---479----536824--745291836138546297296837154381725649529364718674918325467153982812479563953682471
6--92-431--917-6-8--35-47-2-548-92-----4-7-1-----5-----27-91--3-----59-7---7421-5675928431249173658183564792354819276862437519791256384527691843416385927938742165
-19-----23-8294-1----615-------3975--9--67-3-7--8-21---5--2-3---26-438----3-81--5519378462368294517247615983682139754195467238734852196851726349926543871473981625
532-4--964-9--7--217--69--4----76--18----2---2574---6---3-14-25----8--4-6-57-31-9532148796469357812178269534394876251816592473257431968783914625921685347645723189
-2--9-6--9----28-136--8-4-9--5-1--86-7-9--3-5---25-9-7------13271---6---8-91--764128497653954632871367581429495713286271968345683254917546879132712346598839125764
7-18-3---95-6---8------12------793--1-6-54928493-68-71--59-----31----6-2-----6-15761823459952647183834591267528179346176354928493268571685912734317485692249736815
----6---36-1--345--378-16-27---1-86-186--49-7--------496458---12-3-9----87--3-2-9428965713691723458537841692742319865186254937359678124964582371213497586875136249
-8----1--3-5-47------3-8--4----5--61-43712-891596-3-42-36---2-5----7---38-12--4--284569137365147928917328654728954361643712589159683742436891275592476813871235496
-6--43--2------716-295-7---------84----2-46-147-681-2324--1-3--38----2599---281-4768143592534892716129567438612739845893254671475681923246915387381476259957328164
2-6---5-3-------275739-286--5-2-6--8---7-814676---12-582-3--6--------3599-461----246187593189563427573942861451236978392758146768491235825379614617824359934615782
75-8123-9-29374---8-19----7------8----2-6-73--9-78124-2-56---8--4--2------8--5612754812369629374158831956427167243895482569731593781246215637984946128573378495612
7-38---256-94--1-32-8-539----49-------1-4----87-21--49432--9-56---3-42-7-6--8-4--743891625659427183218653974524936718391748562876215349432179856185364297967582431
4----9687-6--2------76-4-9---19-85--253-61---68954-1-3--------9895-1--26-7---6-35412359687968127354537684291741938562253761948689542173326875419895413726174296835
784----------812--5123-9--889---37--35--24-9--2--7--3-2-96---8-64--1---313-----67784256319963781254512349678891563742357124896426978135279635481645817923138492567
---61---856-39-7-------5----2-56-17--9-8-143---49-7682----5-91----17685-71--89-2-473612598562398741981745263328564179697821435154937682846253917239176854715489326
8-3--416---2-----------6532--93-8---5-46-7--16----1-73-7--639--38-7-52-6-4-81-357853274169162539784497186532719348625534627891628951473275463918381795246946812357
15-4-7-2-739--54--28---1--69-5-----2---3-87-13--572--45-7---2--62---9-8--912--6-7156487329739625418284931576975164832462398751318572964547816293623749185891253647
1-967528----9-2-65------9-7--472--967-8---3429-2-6---824-1-3---------6515--89--2-139675284487932165625481937314728596768519342952364718246153879893247651571896423
43-21-6-5-8--542--2516-97--9--42--715-2-9---4---56--8--94-7--56-------3-315-4----437218695689754213251639748968423571572891364143567982894372156726185439315946827
7---14-583---8---6---3-672-6-7--5-39----735--23-9--8--4--15----9---3-614-23-6-975769214358312587496584396721647825139891673542235941867476159283958732614123468975
81247--5--4---8--9---3-218---8---5----6-----893-58-2-64-51-68--3-172-9--2-9--5-17812479653543618729697352184728963541156247398934581276475196832381724965269835417
6------7----3-21-4--271-----2915-648-78936-21-56--4---9-4----152---9-7-6--1--3---613845972897362154542719863329157648478936521156284397934678215285491736761523489
--53--12--2---9-84---6-235-1-8--473-3---6-49---6--38--5-9-8----43-9--578------961695348127723519684814672359158294736372861495946753812569187243431926578287435961
316-47--2-----1----9--83-7-834----272--3--16-1672-83-5-7------4--5769-1-9---1-75-316947582748521639592683471834156927259374168167298345671835294425769813983412756
7------3--3-8-72-4-8613-79--2-76851-8----16-7-------2-6-4275-8-3---1695-5--3-9---745692138931857264286134795429768513853921647167543829694275381378416952512389476
47219------18--69--9----4-----31--25-5---8-1631-56----745--1--392--8-167-6-937---472196538531874692896253471684319725259748316317562849745621983923485167168937254
8-36---29-965----845129--6----3---82--7-----5185-2-6---4-15--36----6--7--129-38-4873641529296537418451298367964315782327486195185729643748152936539864271612973854
6--284-1-58-----4-2--1756-97-65------1-3---96--5-6172--6279----3----2-6-8-4-53-7-679284315581936247243175689726549831418327596935861724162798453357412968894653172
6-5-41--2---385--1--3------56-13-9-8-9--7--15-2-95864-8-24--1-91--5-9--4--7---5-6685741392279385461413296857564132978398674215721958643852467139136529784947813526
6---215---3-----7----7-468--53-78---7-2----5----2--1--4-7819-653165-7-92-8-----14678321549534986271291754683153478926762193458849265137427819365316547892985632714
3------61-9-8-1-2-57---2-894-----------174-9-16-92--5--16-49-78--8-3-91---57182-6382497561694851723571362489429685137853174692167923854216549378748236915935718246
5-932-8---1274-6---4-58--92----6-4------1--6-6-48-351--6---7-8--53---2-69-7652--4579326841812749653346581792138965427795214368624873519261437985453198276987652134
--2-5------32-----17-38--25248--5-69-9-1--2------428-77-4-1--869-5-2-3-48-16-45--682459731453271698179386425248735169597168243316942857724513986965827314831694572
3---154---1-86--9-----3421-6-5-47-8-2----6-4---4-98--29-3-----6-486739-----529---392715468417862395856934217635247189289156743174398652923481576548673921761529834
3------5----46-9-1-6-5-9----9--4----6----85-381-----97-25834-69-869-7312-37-1----349271856258463971761589234593746128672198543814325697125834769486957312937612485
8-63172---27-----1---952----158-3-6---82-6--9-9---1-8-4--16--2--7-4-58-----7-894-856317294927684531134952678715893462348276159692541387483169725279435816561728943
-51-3-7-279---2-8----17--3--4-3-6---9-75--123-2-7--654-1-64-3-8-7-8----5----5791-451938762793462581286175439145326897967584123328791654512649378679813245834257916
--34--1---1-59---3-2471-5---69-----415-674-9----932---8---459----628--1----16-83-593428176718596243624713589369851724152674398487932651871345962936287415245169837
-7384---2-8--5----4-92-61-3---7--5----416-----1---8736--891-46---76--8-9-91-8-327173849652286351974459276183862793541734165298915428736328917465547632819691584327
46-72-1--78-1--42---25-4--------894--7--153---486935-1----4--638-6-57---9-4-6--1-463729158785136429192584637351278946679415382248693571527941863816357294934862715
-4-6-------374-5--612---34--8--37--5----2893-93----87-168--9--342-371-5--7----491547613289893742516612895347284937165756128934931564872168459723429371658375286491
7-643------98-26--3------5-84-----7-12-39-58669-1784-3---7-3-95--8-2----9-----3-2756439218419852637382617954843265179127394586695178423261743895538926741974581362
7-6--8----8957-3----319-7-8-7-----4596--15----5--27--34257-163-1-----2-763-9--4--716238594289574316543196728372869145964315872851427963425781639198643257637952481
-1--684--5247-1---76834-12--9--73--6--75-----3----6798-------6---9--7-428461---75913268457524791683768345129492873516687519234351426798275984361139657842846132975
7-------5-91-857--4-572-86-1---------56--2--82-36581--3-42-6--78--513-96----74--3782461935691385724435729861148937652956142378273658149314296587827513496569874213
2-5--7-----931-7-2-7142---959-1----83-----2-68642-3-9515--34----4--629---2----48-235697814489315762671428539592146378317589246864273195158934627743862951926751483
----1-5-44815---27596------75--9---21----29--82---71-6-17--5-3-24-9-3---63-2--4--372618594481539627596724813754196382163842975829357146917465238245983761638271459
867---------2--61-912--6-5414--38---2-5-6---337---41---2--4-8--65-8---4-49--5-27-867415932534297618912386754146938527285761493379524186723149865651872349498653271
-6-3---9-9--51---623-49--5---7-35-1--8-27-9-----98-67-5-98431-----162---81------3165327498974518326238496751497635812681274935352981674529843167743162589816759243
----625-7--81----6672-4-83-1-59-746--6---4----9-6-----71-32---452---137-84---62-9931862547458173926672549831185937462367284195294615783719328654526491378843756219
---7----592---86--1-5---8-3---3---195-6987-24493-51-6835-67------2---9------25--6834716295927538641165492873278364519516987324493251768351679482682143957749825136
1---62-5-7------8----4-------169853-987--516-6-571---8218937----69541-7----2--9--143862759792153486856479321421698537987325164635714298218937645369541872574286913
17-----824-6--73-5--2--86---6-8-1-9-8-9-72--4-4----7-879418-2-------543-325--98--173654982486297315952318647267841593839572164541936728794183256618725439325469871
-----5--65-86--19--6482-5-3--------14----825-8251--7-4751-92--83-6--7---24---63-7132975486578643192964821573697254831413768259825139764751392648386417925249586317
61-28-75------56---85-6--43--1--8-25------4--258-4-19-5493-28--1-2--697--67--9---613284759724935618985167243471698325396521487258743196549372861132856974867419532
--9--38-4-3--9---5-57-4-9-16---8-54--2-9--6-7---36-2-99-48--152------378-82--5---169573824438192765257648931691287543823954617745361289974836152516429378382715496
-235-4-----56-24---7--98-2---7481-59---763---8-----7-4-5-8--3--3--9-7--5-9-1-58-6123574968985612473674398521237481659549763182816259734451826397368947215792135846
32----8---8-3-5-24--4-216--5--21-4388-7--9---2----457979---3-866----2--5-52---31-325746891186395724974821653569217438847539162213684579791453286638172945452968317
-163-52------8----4-2--15-82-1--98-45-4--8--33--6-41521-38-69-----4-7---9--213-86816345279735982641492761538271539864564128793389674152143856927628497315957213486
2-9--17-3---3--2--3--5--986--89635---3-7-----7-28456319-5--8-67--7------6--1-7829259681743864379215371524986418963572536712498792845631925438167187296354643157829
6---781-93----48-----65--344-6-32--753-8---2----7--6-32--4193--9-----71--532674--642378159315924876789651234496132587537846921821795643278419365964583712153267498
--15--43-24836-1--5-39--82----73-----561829--9--65-21-8--41--62-----5---4-52--38-791528436248367195563941827124739658356182974987654213879413562632895741415276389
9----63-882-4356--7--9-85-429-7--4-618-------654-927--36-5---42--9------4--3-98-5945176328821435697736928514293751486187643259654892731368517942579284163412369875
2357-4--8------4---84--26-58172963-46--5812-----4---1-4-1--75-33--1-----5286----1235764198169358427784912635817296354643581279952473816491827563376145982528639741
5----9762--7-8-----6-7-5--979235-14--1-9-23--843-71---239-1--78-------9---6--7-34581439762927186453364725819792358146615942387843671925239514678478263591156897234
----138--12-8-7-----3----5--41---26-35--6--8----7--1--592-416-8---2--5-4-185769-3975613842124857396683429751841935267357162489269784135592341678736298514418576923
47-3---1-6-------7---17-628--9--1856148-3-7-2---798--4-14--3--5-2591-------54-9-1472386519681259347593174628739421856148635792256798134914863275825917463367542981
--5---7--23-7-6-5-7-9-51-68--2------87-1--6--4-1687-2-9-481-5-----9-54----64728-3165298734238746951749351268692534187873129645451687329924813576387965412516472893
-1-76-3--9--4528----738-4-914--23--7--617-2--7--8-4---43----6-5-9-5--748-7-2-8---814769352963452871527381469149623587386175294752894136438917625291536748675248913
-8----2--3-4-51------48---1-----5--42-87--1--94----7-341-572-8663294--17-----3-92187369245394251678526487931763195824258734169941826753419572386632948517875613492
5--3--46--1--7-------59-8-78-7-53249145-267-3-9--48------4----6-31---97-7-6-3----579382461318674592624591837867153249145926783293748615982417356431265978756839124
75-21936-86935-41---2---79-54-----3--83-25------4----9--8----5-6---94--3---57--26754219368869357412132648795546981237983725641217436589378162954625894173491573826
39---74---14--936-758-36-9-475-6---9-----164--2----7--56-1-38-48---7591-----9--2-396217458214589367758436291475362189983751642621948735569123874842675913137894526
-6-2--49-8---7-2-352----7-8-8--5---4-9--438-1--5--86-9--4-67---6--8-9147------536763281495849675213521394768187956324296743851435128679314567982652839147978412536
23--8-4-5------2--56872---37138496-2--45138-----2---1-1-2-7-5-6--61-----3854----1237981465941635287568724193713849652624513879859267314192378546476152938385496721
--6239-145-3---7----45769---3-49-6-29----814--42--3---46-1-2-----8-6-4---7538-2--786239514593841726214576938831495672957628143642713895469152387328967451175384269
8932-51--641----------13--97-4-3-2--95-7---1-3-2---67-1-5--2--62-8-94-5---9-6--2-893245167641987532527613489784136295956728314312459678135872946268394751479561823
7---9------6--83-14-8----7586-7-514223-819-6715--4----6--3-7------96-7-4--1----3-713596428526478391498123675869735142234819567157642983645387219382961754971254836
-----3-9-78---5-6---2------348-51--65---68349-693---85914---673--7-4----625--98-4156823497783495261492617538348951726571268349269374185914582673837146952625739814
52316---7847---------3-72--3-6----9821--9--7-9-4--3--67-16--8--6-54-2-1---2--8-6-523164987847925631169387254376241598218596473954873126731659842685432719492718365
-64-58--1--1-43-65---6--4-723-----4--1-49--3----38-57---2--571--49---8--1-78-4293964758321871243965523619487238576149715492638496381572682935714349127856157864293
-5-3-4217--48-1-65--2-79-38---9-----9-7-46--3----871-----738-91----9--843-841--2-859364217734821965612579438481953672927146853563287149246738591175692384398415726
--5-9----6--2---182-3---54--624-5371-41-3-----8791265---65-8-------69-351-----8--815694723674253918293871546962485371541736289387912654436528197728169435159347862
-7--6----63-49--8-8-52-3-4121-6--5-35--9---26-6-12-89415-3-------6-1-4599-------7471568932632491785895273641219684573548937126763125894157349268386712459924856317
-1-8-----987---136325-9--4864827---3-93--64-22--34-869-5-----------6-9--1-4-2-3--416837295987452136325691748648279513593186472271345869859713624732564981164928357
1--98-3--932-674--58-2-379-2598-------------56-84---79---7-9--1-936---8--6-3-8-24176984352932567418584213796259876143347192865618435279825749631493621587761358924
-73--48-5--2--63--41-----62-69-42--73--6-1-9-7-----4-694716-2-------578-285--96--673294815592816374418357962869542137324671598751983426947168253136425789285739641
-584----9-49----5326--5--1---63---9--12--93---976-8-2-674-92--1---1-46--831------758413269149286753263957814586321497412579386397648125674892531925134678831765942
---4-56-119----5-465---1-8------64727652-98--4--713-5----3972-5-26-5---8--3--2---238475691197638524654921387319586472765249813482713956841397265926154738573862149
8-62--4717-5--8-3291---4-65--9------38--91--615----7--561----97-9-----58-78-65-4-836259471745618932912734865629587314387491526154326789561843297493172658278965143
4-------6-1-25--9-79--84----5---2------47-6-11-----24-9-153748-5-8-----73-2-41965425793816813256794796184523654912378239478651187365249961537482548629137372841965
9--4--6314-6-1--9--7---6---3-9-5-2--56-782----426935-86----1-82-5-329-76--------9928475631436218795175936824389154267561782943742693518697541382854329176213867459
-84-9-5-73-765-19-9----7----76--5--11-2-4-7654-------------29-32-3--9-165--8-6472684193527327654198951287634876925341192348765435761289768412953243579816519836472
52-6-1---------9363--74--5-4-5-9---78-7---125--285--49------4-86-498357----4-5-93529631784741528936386749251435192867897364125162857349953276418614983572278415693
-8--64-9596--57--8-259-----5-----37-7--51--8-2-674----8-2--6--3--4----511734-58-2387264195961357428425981637518629374749513286236748519852176943694832751173495862
5-2--36-7---6----2--61--4952-79813649--546--1-6-7-----1-5--974-7----------43-7529512493687849675132376128495257981364938546271461732958125869743793254816684317529
--256----15--72--497--4--25-----531--85--1-4--917-6---5-93184-6---9---587--6-4--3842569731153872964976143825267485319385291647491736582529318476634927158718654293
1365----8---1---37725-48--6--7---8-2--948--5-58-6-27---42---68-6--8----997-2--1-3136579428894126537725348916417953862269487351583612794342791685651834279978265143
-98-----5---397---1-42859-----81-36-6--5-4-9--8-67-1----194---3-5712--4--3--5--1-398461725526397481174285936745819362612534897983672154261948573857123649439756218
-1---42786--1583-9489---5--5-7---1-4-6--157--1-4-37-----659--1----2--9--9-1---832315964278672158349489372561537629184268415793194837625826593417743281956951746832
476-58-3--1-7-9-4-92-64-75-8--49-6-37-48--9-----57---1-893--5-7--------22679-----476258139518739246923641758851492673734816925692573481189324567345167892267985314
4-8--61-5---5--8----53--429--96-12841--------3-4--2-91-5-1-----2--4953--8-1273956438926175792514863615387429579631284126849537384752691953168742267495318841273956
-9-185-732--79---173--42--9--9218-3-32------41---6-----6-----9-94-5---185-283-4-7694185273285793641731642859459218736326957184178364925863471592947526318512839467
--34-8---9--13-6---81-62--3-1-39-2----58764--3--24-8-5-28---9-7-5-7--384-3-6-4---673458129942137658581962743814395276295876431367241895428513967156729384739684512
------7---5---6----1---2-8419-2--835--51-862-28-653--1-6-38-172---5243963-----4--942815763758436219613972584196247835435198627287653941564389172871524396329761458
--129-6---8------7-564-8---93-8-176216-32548-42------5-1----89----58--71--2--9---341297658289653147756418923935841762167325489428976315514732896693584271872169534
-----16--9--5--21-51-863-----9--4-5242--75---75-----84--5436--7-9--18523173--2---847291635936547218512863479369184752428375961751629384285436197694718523173952846
-98-5-7-6---8------7--9215--3--182-5----46---8-1527--3-86-3-5-7--2-8-6-9957-61--2298154736615873924473692158734918265529346871861527493186239547342785619957461382
1---7629-79--251--8-29------8756-----5-23--1--2-----54-18--74----6---32-5346-28-1145876293793425186862913547487561932659234718321789654218357469976148325534692871
9-72--54--386--17-4---8736--2439-6-1---4---2-----2--9--85--42372---6---53-17-2---967231548538649172412587369724398651196475823853126794685914237279863415341752986
92-1-6-47----3-8---4--5213-8------5-572-9---3-----179-254-693--36---5-7-1-7--396-923186547615437829748952136891374652572698413436521798254769381369815274187243965
42-3--1788--------79--4---6---2----4614-8-5---8--54-6---7-18-3----43-2979-35-7481426395178835671942791842356579263814614789523382154769247918635158436297963527481
----638-5-------6976-98523-5--62-3--------5873-1-74---63-8----292----143-1-39-6-8192463875853217469764985231579628314246139587381574926635841792928756143417392658
297-5-6-----93-2--346-7--1583--924--7---8-5---145-7-----3-45-----86--15-65---37-4297451638581936247346278915835192476762384591914567382123745869478629153659813724
39---5-8-51-2--7434-----------1---5--4--56--8875--46----3-47--29-263-574---5-2139397415286518269743426873915639128457241756398875394621153947862982631574764582139
5-8--4-31---5-------3-7849---6-59-74----12---95-437--61-5--6-437----5-18384-91--7578924631419563782623178495236859174847612359951437826195786243762345918384291567
-----7-14749-1-3-2618-------932---76-7-3---8--21--8--3-3458----2-71--5---65-3--4-352967814749815362618423795893251476576394281421678953134589627287146539965732148
-3-17--45-9--46-287-4--2-319------6-61-92-5-3-2-----9---278-4193----98---49-51---236178945195346728784592631953817264617924583428635197562783419371469852849251376
2--1659--81----5--6--798-42--82-96-7-9--3-42-7-2-8-----2647----3----62--1-58-37--274165983819342576653798142438219657591637428762584391926471835387956214145823769
82-4-3-69-516--2-46---2----5---------32-4-9--97-5--432----7-8-64---3172578--6-39-827453169351689274694127583548392617132746958976518432213975846469831725785264391
-93--6---1-89--367------9425---9--86-3-1--4-5---25-1-3-64-8-7-1--1--28-9-2--1-6--293476518148925367675831942517394286932168475486257193364589721751642839829713654
--5---49----432---4--915-78-8-5--3---7-18-52---374--8-36-89-----4--57--68--26-9--215678493798432165436915278189526347674183529523749681361894752942357816857261934
87--13--2--972--1--2-6-8-----236--84-4-851-6-7--29--3-4--5--82638-----952--1-6---874913652639725418521648379152367984943851267768294531417539826386472195295186743
-968-7---4--9-3--7-37----69-19---852--413-9------5---1261-----3-4-392-189----6725196827534452963187837541269319674852524138976678259341261785493745392618983416725
1247965-3968--1--4--5----9---16489----9--3---7--9-53-84--56-8-1--------55-78346--124796583968351274375482196231648957859173462746925318492567831683219745517834629
3-67----4--438-5695-92--7-34-587-2-----13------2495-7885-64-9-------7---9-35--6-7386759124274381569519264783435876291798132456162495378857643912641927835923518647
------593-7-25------54-8271-3-8--4-54--97-1-88---3-7--6-3---8-2--8-2-9-65----6-47284617593179253684365498271937861425456972138821534769613749852748325916592186347
--7--4---394---587816-3-42-542-968--6---28354-835--6-272--6---8--1----------5---3257984136394612587816735429542396871679128354183547692725463918431879265968251743
---3---4-7-6-28----83---7-----81-25--5--43-7-6-----8---182945-746578-9-32-----4-1129375648746128395583469712934817256852643179671952834318294567465781923297536481
6--4-2-97-549--632-297634----3-----8---698753-7-32-914-4---982--6---7-----------1638452197754981632129763485593174268412698753876325914347519826261837549985246371
---5-41--6--1739-81-592-4--3--------2-1697-3--792--6--4-----7---837-6-4-5-7-42-69798564123624173958135928476356481297241697835879235614462359781983716542517842369

View File

@ -1,3 +1,4 @@
0.01: New App! 0.01: New App!
0.10: Redesign to make screen updates fast 0.10: Redesign to make screen updates fast
0.11: bugfix (demo mode was enabled by default)

View File

@ -1,6 +1,6 @@
{ "id": "trail", { "id": "trail",
"name": "Trail Rail", "name": "Trail Rail",
"version":"0.10", "version":"0.11",
"description": "Follow a GPX track in car or on bike", "description": "Follow a GPX track in car or on bike",
"icon": "app.png", "icon": "app.png",
"readme": "README.md", "readme": "README.md",

View File

@ -134,7 +134,6 @@ let gps = {
init: function(x) { init: function(x) {
this.emulator = (process.env.BOARD=="EMSCRIPTEN" this.emulator = (process.env.BOARD=="EMSCRIPTEN"
|| process.env.BOARD=="EMSCRIPTEN2")?1:0; || process.env.BOARD=="EMSCRIPTEN2")?1:0;
this.emulator = 1; // FIXME
}, },
state: {}, state: {},
on_gps: function(f) { on_gps: function(f) {
@ -602,7 +601,7 @@ function step_to(pp, pass_all) {
return quiet; return quiet;
} }
var demo_mode = 0; //fixme var demo_mode = 0;
function step() { function step() {
const fast = 0; const fast = 0;
@ -666,7 +665,7 @@ function step() {
drop_last(); drop_last();
let v2 = getTime(); let v2 = getTime();
print("Step took", (v2-v1), "seconds"); print("Step took", (v2-v1), "seconds");
setTimeout(step, 10); /* FIXME! */ setTimeout(step, 1000);
} }
function recover() { function recover() {

View File

@ -17,3 +17,4 @@
Add option to disable vibration when charger connects Add option to disable vibration when charger connects
0.18: Only redraw when values change 0.18: Only redraw when values change
0.19: Match draw() API e.g. to allow wid_edit to alter this widget 0.19: Match draw() API e.g. to allow wid_edit to alter this widget
0.20: Remove clear of the screen on reload (will break currently running app)

View File

@ -2,7 +2,7 @@
"id": "widbatpc", "id": "widbatpc",
"name": "Battery Level Widget (with percentage)", "name": "Battery Level Widget (with percentage)",
"shortName": "Battery Widget", "shortName": "Battery Widget",
"version": "0.19", "version": "0.20",
"description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",

View File

@ -156,7 +156,6 @@
// need to redraw all widgets, because changing the "charger" setting // need to redraw all widgets, because changing the "charger" setting
// can affect the width and mess with the whole widget layout // can affect the width and mess with the whole widget layout
setWidth(); setWidth();
g.clear();
Bangle.drawWidgets(); Bangle.drawWidgets();
} }

View File

@ -14,3 +14,4 @@
0.15: Added option to hide widget when connected 0.15: Added option to hide widget when connected
0.16: Simplify code, add option to disable displaying a message 0.16: Simplify code, add option to disable displaying a message
0.17: Minor display fix 0.17: Minor display fix
0.18: Use notify lib to stop this widget clearing the screen of the running clock/app

View File

@ -1,13 +1,14 @@
{ {
"id": "widbt_notify", "id": "widbt_notify",
"name": "Bluetooth Widget with Notification", "name": "Bluetooth Widget with Notification",
"version": "0.17", "version": "0.18",
"description": "Show the current Bluetooth connection status with some optional features: show message, buzz on connect/loss, hide always/if connected.", "description": "Show the current Bluetooth connection status with some optional features: show message, buzz on connect/loss, hide always/if connected.",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",
"tags": "widget,bluetooth", "tags": "widget,bluetooth",
"provides_widgets" : ["bluetooth"], "provides_widgets" : ["bluetooth"],
"supports": ["BANGLEJS","BANGLEJS2"], "supports": ["BANGLEJS","BANGLEJS2"],
"dependencies" : { "notify":"module" },
"storage": [ "storage": [
{"name":"widbt_notify.wid.js","url":"widget.js"}, {"name":"widbt_notify.wid.js","url":"widget.js"},
{"name":"widbt_notify.settings.js","url":"settings.js"} {"name":"widbt_notify.settings.js","url":"settings.js"}

View File

@ -1,6 +1,6 @@
(function() { {
// load settings // load settings
var settings = Object.assign({ let settings = Object.assign({
showWidget: true, showWidget: true,
buzzOnConnect: true, buzzOnConnect: true,
buzzOnLoss: true, buzzOnLoss: true,
@ -10,7 +10,7 @@
}, require("Storage").readJSON("widbt_notify.json", true) || {}); }, require("Storage").readJSON("widbt_notify.json", true) || {});
// setup widget with to hide if connected and option set // setup widget with to hide if connected and option set
var widWidth = settings.hideConnected && NRF.getSecurityStatus().connected ? 0 : 15; let widWidth = settings.hideConnected && NRF.getSecurityStatus().connected ? 0 : 15;
// write widget with loaded settings // write widget with loaded settings
WIDGETS.bluetooth_notify = Object.assign(settings, { WIDGETS.bluetooth_notify = Object.assign(settings, {
@ -38,17 +38,6 @@
} }
}, },
redrawCurrentApp: function() {
if (typeof(draw) == 'function') {
g.reset().clear();
draw();
Bangle.loadWidgets();
Bangle.drawWidgets();
} else {
load(); // fallback. This might reset some variables
}
},
onNRF: function(connect) { onNRF: function(connect) {
// setup widget with and reload widgets to show/hide if hideConnected is enabled // setup widget with and reload widgets to show/hide if hideConnected is enabled
if (this.hideConnected) { if (this.hideConnected) {
@ -61,10 +50,10 @@
if (this.warningEnabled) { if (this.warningEnabled) {
if (this.showMessage) { if (this.showMessage) {
E.showMessage( /*LANG*/ 'Connection\n' + (connect ? /*LANG*/ 'restored.' : /*LANG*/ 'lost.'), 'Bluetooth'); require("notify").show({id:"widbtnotify", title:"Bluetooth", body:/*LANG*/ 'Connection\n' + (connect ? /*LANG*/ 'restored.' : /*LANG*/ 'lost.')});
setTimeout(() => { setTimeout(() => {
WIDGETS.bluetooth_notify.redrawCurrentApp(); require("notify").hide({id:"widbtnotify"});
}, 3000); // clear message - this will reload the widget, resetting 'warningEnabled'. }, 3000);
} }
this.warningEnabled = 0; this.warningEnabled = 0;
@ -87,4 +76,4 @@
NRF.on('connect', (addr) => WIDGETS.bluetooth_notify.onNRF(addr)); NRF.on('connect', (addr) => WIDGETS.bluetooth_notify.onNRF(addr));
NRF.on('disconnect', () => WIDGETS.bluetooth_notify.onNRF()); NRF.on('disconnect', () => WIDGETS.bluetooth_notify.onNRF());
})() }

View File

@ -5,3 +5,4 @@
0.04: Now shows message icons again (#2416) 0.04: Now shows message icons again (#2416)
0.05: Match draw() API e.g. to allow wid_edit to alter this widget 0.05: Match draw() API e.g. to allow wid_edit to alter this widget
0.06: Fix bug that meant that only one widget was shown (now 3 unless changed in Settings->Apps->Messages->Widget messages) 0.06: Fix bug that meant that only one widget was shown (now 3 unless changed in Settings->Apps->Messages->Widget messages)
0.07: Only load messages module if we have messages (30ms speed improvement)

View File

@ -1,7 +1,7 @@
{ {
"id": "widmessages", "id": "widmessages",
"name": "Message Widget", "name": "Message Widget",
"version": "0.06", "version": "0.07",
"description": "Widget showing new messages", "description": "Widget showing new messages",
"icon": "app.png", "icon": "app.png",
"type": "widget", "type": "widget",

View File

@ -65,7 +65,7 @@ if ((require("Storage").readJSON("messages.settings.json", true) || {}).maxMessa
this.onMsg("show", {}); // reload messages+redraw this.onMsg("show", {}); // reload messages+redraw
} }
}; };
Bangle.on("message", WIDGETS["messages"].onMsg.bind(WIDGETS["messages"])); Bangle.on("message", WIDGETS["messages"].onMsg.bind(WIDGETS["messages"]));
if (require("Storage").read("messages.json")!==undefined) // only call init if we've got messages - otherwise we can avoid loading messages lib (saves 30ms)
WIDGETS["messages"].onMsg("init", {}); // abuse type="init" to prevent Bangle.drawWidgets(); WIDGETS["messages"].onMsg("init", {}); // abuse type="init" to prevent Bangle.drawWidgets();
} }

View File

@ -5,6 +5,12 @@
var fs = require("fs"); var fs = require("fs");
var vm = require("vm"); var vm = require("vm");
var heatshrink = require("../webtools/heatshrink"); var heatshrink = require("../webtools/heatshrink");
/*var apploader = require("../core/lib/apploader.js");
apploader.init({
DEVICEID : "BANGLEJS2"
});*/
var acorn; var acorn;
try { try {
acorn = require("acorn"); acorn = require("acorn");
@ -48,54 +54,56 @@ function WARN(msg, opt) {
} }
/* These are errors that we temporarily allow */ /* These are errors that we temporarily allow */
var KNOWN_ERRORS = [ var KNOWN_ERRORS = [
"In locale en_CA, long date output must be shorter than 15 characters", "In locale en_CA, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)",
"In locale fr_FR, long date output must be shorter than 15 characters", "In locale fr_FR, long date output must be shorter than 15 characters (10 septembre 2024 -> 17)",
"In locale en_SE, long date output must be shorter than 15 characters",
"In locale en_NZ, long date output must be shorter than 15 characters",
"In locale en_AU, long date output must be shorter than 15 characters",
"In locale de_AT, long date output must be shorter than 15 characters",
"In locale en_IL, long date output must be shorter than 15 characters",
"In locale es_ES, long date output must be shorter than 15 characters",
"In locale fr_BE, long date output must be shorter than 15 characters",
"In locale fi_FI, long date output must be shorter than 15 characters",
"In locale de_CH, long date output must be shorter than 15 characters",
"In locale fr_CH, long date output must be shorter than 15 characters",
"In locale wae_CH, long date output must be shorter than 15 characters",
"In locale tr_TR, long date output must be shorter than 15 characters",
"In locale hu_HU, long date output must be shorter than 15 characters",
"In locale oc_FR, long date output must be shorter than 15 characters",
"In locale ca_ES, long date output must be shorter than 15 characters",
"In locale fr_BE, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fr_CH, short month must be shorter than 5 characters",
"In locale oc_FR, short month must be shorter than 5 characters",
"In locale hr_HR, short month must be shorter than 5 characters",
"In locale ca_ES, short month must be shorter than 5 characters",
"In locale de_DE, meridian must be longer than 0 characters",
"In locale en_JP, meridian must be longer than 0 characters",
"In locale nl_NL, meridian must be longer than 0 characters",
"In locale fr_FR, meridian must be longer than 0 characters",
"In locale se_SE, meridian must be longer than 0 characters",
"In locale en_SE, meridian must be longer than 0 characters",
"In locale da_DK, meridian must be longer than 0 characters",
"In locale en_DK, meridian must be longer than 0 characters",
"In locale de_AT, meridian must be longer than 0 characters",
"In locale es_ES, meridian must be longer than 0 characters",
"In locale fr_BE, meridian must be longer than 0 characters",
"In locale it_CH, meridian must be longer than 0 characters",
"In locale it_IT, meridian must be longer than 0 characters",
"In locale wae_CH, meridian must be longer than 0 characters",
"In locale oc_FR, meridian must be longer than 0 characters",
"In locale pl_PL, meridian must be longer than 0 characters",
"In locale lv_LV, meridian must be longer than 0 characters",
"In locale nn_NO, meridian must be longer than 0 characters",
"In locale nb_NO, meridian must be longer than 0 characters",
"In locale ca_ES, meridian must be longer than 0 characters",
"In locale de_CH, meridian must be shorter than 4 characters",
"In locale hr_HR, meridian must be shorter than 4 characters",
"In locale sl_SI, meridian must be shorter than 4 characters",
"In locale fr_FR, short month must be shorter than 5 characters", "In locale fr_FR, short month must be shorter than 5 characters",
"In locale sv_SE, speed must be shorter than 5 characters", "In locale sv_SE, speed must be shorter than 5 characters",
"In locale en_SE, long date output must be shorter than 15 characters (September 10 2024 -> 17)",
"In locale en_NZ, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)",
"In locale en_AU, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)",
"In locale de_AT, long date output must be shorter than 15 characters (Donnerstag, 10. September 2024 -> 30)",
"In locale en_IL, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)",
"In locale es_ES, long date output must be shorter than 15 characters (miércoles, 10 de septiembre de 2024 -> 35)",
"In locale fr_BE, long date output must be shorter than 15 characters (dimanche septembre 10 2024 -> 26)",
"In locale fr_BE, short month must be shorter than 5 characters",
"In locale fr_BE, short month must be shorter than 5 characters",
"In locale fr_BE, short month must be shorter than 5 characters",
"In locale fr_BE, short month must be shorter than 5 characters",
"In locale fr_BE, short month must be shorter than 5 characters",
"In locale fi_FI, long date output must be shorter than 15 characters (keskiviikkona 10. maaliskuuta 2024 -> 34)",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale fi_FI, short month must be shorter than 5 characters",
"In locale de_CH, meridian must be shorter than 4 characters",
"In locale de_CH, meridian must be shorter than 4 characters",
"In locale de_CH, long date output must be shorter than 15 characters (Donnerstag, 10. September 2024 -> 30)",
"In locale fr_CH, long date output must be shorter than 15 characters (dimanche 10 septembre 2024 -> 26)",
"In locale fr_CH, short month must be shorter than 5 characters",
"In locale fr_CH, short month must be shorter than 5 characters",
"In locale fr_CH, short month must be shorter than 5 characters",
"In locale fr_CH, short month must be shorter than 5 characters",
"In locale fr_CH, short month must be shorter than 5 characters",
"In locale wae_CH, long date output must be shorter than 15 characters (Sunntag, 10. Herbštmánet 2024 -> 29)",
"In locale tr_TR, long date output must be shorter than 15 characters (10 Haziran 2024 Pazartesi -> 25)",
"In locale hu_HU, long date output must be shorter than 15 characters (2024 Szep 10, Csütörtök -> 23)",
"In locale oc_FR, long date output must be shorter than 15 characters (divendres 10 setembre de 2024 -> 29)",
"In locale oc_FR, short month must be shorter than 5 characters",
"In locale oc_FR, short month must be shorter than 5 characters",
"In locale hr_HR, meridian must be shorter than 4 characters",
"In locale hr_HR, meridian must be shorter than 4 characters",
"In locale hr_HR, short month must be shorter than 5 characters",
"In locale sl_SI, meridian must be shorter than 4 characters",
"In locale sl_SI, meridian must be shorter than 4 characters",
"In locale ca_ES, long date output must be shorter than 15 characters (10 setembre 2024 -> 16)",
"In locale ca_ES, short month must be shorter than 5 characters",
]; ];
/* These are warnings we know about but don't want in our output */ /* These are warnings we know about but don't want in our output */
var KNOWN_WARNINGS = [ var KNOWN_WARNINGS = [
@ -112,6 +120,104 @@ var KNOWN_WARNINGS = [
`In locale test, long time format might not work in some apps if it is not "%HH:%MM:%SS"`, `In locale test, long time format might not work in some apps if it is not "%HH:%MM:%SS"`,
`In locale wae_CH, short time format might not work in some apps if it is not "%HH:%MM"`, `In locale wae_CH, short time format might not work in some apps if it is not "%HH:%MM"`,
`In locale test, short time format might not work in some apps if it is not "%HH:%MM"`, `In locale test, short time format might not work in some apps if it is not "%HH:%MM"`,
"App a_dndtoggle file a_dndtoggle.settings.js should be evaluated as a function but doesn't end in ')'",
"App activepedom file activepedom.settings.js should be evaluated as a function but doesn't end in ')'",
"App agpsdata file agpsdata.settings.js should be evaluated as a function but doesn't end in ')'",
"App alarm file alarm.settings.js should be evaluated as a function but doesn't end in ')'",
"App andark file andark.settings.js should be evaluated as a function but doesn't end in ')'",
"App antonclkplus file antonclkplus.settings.js should be evaluated as a function but doesn't end in ')'",
"App banglexercise file banglexercise.settings.js should be evaluated as a function but doesn't end in ')'",
"App barclock file barclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App berlinc file berlinc.settings.js should be evaluated as a function but doesn't end in ')'",
"App bikespeedo file bikespeedo.settings.js should be evaluated as a function but doesn't end in ')'",
"App blc file blc.settings.js should be evaluated as a function but doesn't end in ')'",
"App boxclk file boxclk.settings.js should be evaluated as a function but doesn't end in ')'",
"App bthome file bthome.clkinfo.js should be evaluated as a function but doesn't end in ')'",
"App bthrm file bthrm.settings.js should be evaluated as a function but doesn't end in ')'",
"App carcrazy file carcrazy.settings.js should be evaluated as a function but doesn't end in ')'",
"App chimer file chimer.settings.js should be evaluated as a function but doesn't end in ')'",
"App circlesclock file circlesclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App clicompleteclk file clicompleteclk.settings.js should be evaluated as a function but doesn't end in ')'",
"App clkinfocal file clkinfocal.settings.js should be evaluated as a function but doesn't end in ')'",
"App clkinfogps file gps.clkinfo.js should be evaluated as a function but doesn't end in ')'",
"App clkinfogpsspeed file clkinfogpsspeed.clkinfo.js should be evaluated as a function but doesn't end in ')'",
"App clkinfom file ram.clkinfo.js should be evaluated as a function but doesn't end in ')'",
"App clkinfomag file clkinfomag.clkinfo.js should be evaluated as a function but doesn't end in ')'",
"App clkinfostopw file stopw.clkinfo.js should be evaluated as a function but doesn't end in ')'",
"App clockcal file clockcal.settings.js should be evaluated as a function but doesn't end in ')'",
"App cogclock file cogclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App counter2 file counter2.settings.js should be evaluated as a function but doesn't end in ')'",
"App cprassist file cprassist.settings.js should be evaluated as a function but doesn't end in ')'",
"App dane_tcr file dane_tcr.settings.js should be evaluated as a function but doesn't end in ')'",
"App dragboard file dragboard.settings.js should be evaluated as a function but doesn't end in ')'",
"App draguboard file draguboard.settings.js should be evaluated as a function but doesn't end in ')'",
"App drained file drained.settings.js should be evaluated as a function but doesn't end in ')'",
"App drinkcounter file drinkcounter.settings.js should be evaluated as a function but doesn't end in ')'",
"App dtlaunch file dtlaunch.settings.js should be evaluated as a function but doesn't end in ')'",
"App ffcniftyb file ffcniftyb.settings.js should be evaluated as a function but doesn't end in ')'",
"App folderlaunch file folderlaunch.settings.js should be evaluated as a function but doesn't end in ')'",
"App gassist file gassist.settings.js should be evaluated as a function but doesn't end in ')'",
"App gbmusic file gbmusic.settings.js should be evaluated as a function but doesn't end in ')'",
"App getup file getup.settings.js should be evaluated as a function but doesn't end in ')'",
"App gipy file gipy.settings.js should be evaluated as a function but doesn't end in ')'",
"App gpsrec file gpsrec.settings.js should be evaluated as a function but doesn't end in ')'",
"App gpssetup file gpssetup.settings.js should be evaluated as a function but doesn't end in ')'",
"App iconlaunch file iconlaunch.settings.js should be evaluated as a function but doesn't end in ')'",
"App infoclk file infoclk.settings.js should be evaluated as a function but doesn't end in ')'",
"App largeclock file largeclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App launch file launch.settings.js should be evaluated as a function but doesn't end in ')'",
"App messagelist file messagelist.settings.js should be evaluated as a function but doesn't end in ')'",
"App messages file messages.settings.js should be evaluated as a function but doesn't end in ')'",
"App messages_light file messages_light.settings.js should be evaluated as a function but doesn't end in ')'",
"App messagesoverlay file messagesoverlay.settings.js should be evaluated as a function but doesn't end in ')'",
"App metronome file metronome.settings.js should be evaluated as a function but doesn't end in ')'",
"App multitimer file multitimer.settings.js should be evaluated as a function but doesn't end in ')'",
"App nesclock file nesclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App nightwatch file nightwatch.settings.js should be evaluated as a function but doesn't end in ')'",
"App owmweather file owmweather.settings.js should be evaluated as a function but doesn't end in ')'",
"App pebble file pebble.settings.js should be evaluated as a function but doesn't end in ')'",
"App pebbled file pebbled.settings.js should be evaluated as a function but doesn't end in ')'",
"App pongclock file pongclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App popconlaunch file popcon.settings.js should be evaluated as a function but doesn't end in ')'",
"App poweroff file poweroff.settings.js should be evaluated as a function but doesn't end in ')'",
"App puzzle15 file puzzle15.settings.js should be evaluated as a function but doesn't end in ')'",
"App qcenter file qcenter.settings.js should be evaluated as a function but doesn't end in ')'",
"App rebbleagenda file rebbleagenda.settings.js should be evaluated as a function but doesn't end in ')'",
"App recorder file recorder.clkinfo.js should be evaluated as a function but doesn't end in ')'",
"App rep file rep.settings.js should be evaluated as a function but doesn't end in ')'",
"App saclock file saclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App sched file sched.settings.js should be evaluated as a function but doesn't end in ')'",
"App score file score.settings.js should be evaluated as a function but doesn't end in ')'",
"App sensortools file sensortools.settings.js should be evaluated as a function but doesn't end in ')'",
"App shadowclk file shadowclk.settings.js should be evaluated as a function but doesn't end in ')'",
"App shortcuts file shortcuts.settings.js should be evaluated as a function but doesn't end in ')'",
"App simplebgclock file simplebgclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App slomoclock file slomoclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App slopeclockpp file slopeclockpp.settings.js should be evaluated as a function but doesn't end in ')'",
"App smclock file smclock.settings.js should be evaluated as a function but doesn't end in ')'",
"App speedalt file speedalt.settings.js should be evaluated as a function but doesn't end in ')'",
"App speedalt2 file speedalt2.settings.js should be evaluated as a function but doesn't end in ')'",
"App swp2clk file swp2clk.settings.js should be evaluated as a function but doesn't end in ')'",
"App taglaunch file taglaunch.settings.js should be evaluated as a function but doesn't end in ')'",
"App thunder file thunder.settings.js should be evaluated as a function but doesn't end in ')'",
"App timecal file timecal.settings.js should be evaluated as a function but doesn't end in ')'",
"App timerclk file timerclk.settings.js should be evaluated as a function but doesn't end in ')'",
"App timestamplog file timestamplog.settings.js should be evaluated as a function but doesn't end in ')'",
"App toucher file toucher.settings.js should be evaluated as a function but doesn't end in ')'",
"App touchtimer file touchtimer.settings.js should be evaluated as a function but doesn't end in ')'",
"App trex file trex.settings.js should be evaluated as a function but doesn't end in ')'",
"App usgs file usgs.settings.js should be evaluated as a function but doesn't end in ')'",
"App weatherClock file weatherClock.settings.js should be evaluated as a function but doesn't end in ')'",
"App wid_edit file wid_edit.settings.js should be evaluated as a function but doesn't end in ')'",
"App widalarmeta file widalarmeta.settings.js should be evaluated as a function but doesn't end in ')'",
"App widbaroalarm file widbaroalarm.settings.js should be evaluated as a function but doesn't end in ')'",
"App widbatwarn file widbatwarn.settings.js should be evaluated as a function but doesn't end in ')'",
"App widbgjs file widbgjs.settings.js should be evaluated as a function but doesn't end in ')'",
"App widdst file widdst.settings.js should be evaluated as a function but doesn't end in ')'",
"App widgps file widgps.settings.js should be evaluated as a function but doesn't end in ')'",
"App widhrm file widhrm.settings.js should be evaluated as a function but doesn't end in ')'",
"App widmp file widmp.settings.js should be evaluated as a function but doesn't end in ')'",
"App widsleepstatus file widsleepstatus.settings.js should be evaluated as a function but doesn't end in ')'",
]; ];
var apps = []; var apps = [];
@ -181,6 +287,7 @@ const isGlob = f => /[?*]/.test(f)
// All storage+data files in all apps: {app:<appid>,[file:<storage.name> | data:<data.name|data.wildcard>]} // All storage+data files in all apps: {app:<appid>,[file:<storage.name> | data:<data.name|data.wildcard>]}
let allFiles = []; let allFiles = [];
let existingApps = []; let existingApps = [];
let promise = Promise.resolve();
apps.forEach((app,appIdx) => { apps.forEach((app,appIdx) => {
if (!app.id) ERROR(`App ${appIdx} has no id`); if (!app.id) ERROR(`App ${appIdx} has no id`);
var appDirRelative = APPSDIR_RELATIVE+app.id+"/"; var appDirRelative = APPSDIR_RELATIVE+app.id+"/";
@ -306,8 +413,9 @@ apps.forEach((app,appIdx) => {
} }
if (file.name.endsWith(".js")) { if (file.name.endsWith(".js")) {
// TODO: actual lint? // TODO: actual lint?
var ast;
try { try {
acorn.parse(fileContents); ast = acorn.parse(fileContents);
} catch(e) { } catch(e) {
console.log("====================================================="); console.log("=====================================================");
console.log(" PARSE OF "+appDir+file.url+" failed."); console.log(" PARSE OF "+appDir+file.url+" failed.");
@ -337,6 +445,18 @@ apps.forEach((app,appIdx) => {
WARN(`Settings for ${app.id} has a boolean formatter - this is handled automatically, the line can be removed`, {file:appDirRelative+file.url, line: fileContents.substr(0, m.index).split("\n").length}); WARN(`Settings for ${app.id} has a boolean formatter - this is handled automatically, the line can be removed`, {file:appDirRelative+file.url, line: fileContents.substr(0, m.index).split("\n").length});
} }
} }
// something that needs to be evaluated with 'eval(require("Storage").read(fn))'
if (/\.clkinfo\.js$/.test(file.name) ||
/\.settings\.js$/.test(file.name)) {
if (!fileContents.trim().endsWith(")"))
WARN(`App ${app.id} file ${file.name} should be evaluated as a function but doesn't end in ')'`, {file:appDirRelative+file.url});
}
if (/\.clkinfo\.js$/.test(file.name) ||
/\.wid\.js$/.test(file.name)) {
if (fileContents.indexOf("g.clear(")>=0 ||
fileContents.indexOf("g.reset().clear()")>=0)
ERROR(`App ${app.id} widget/clkinfo ${file.name} should never totally clear the screen`, {file:appDirRelative+file.url});
}
} }
for (const key in file) { for (const key in file) {
if (!STORAGE_KEYS.includes(key)) ERROR(`App ${app.id} file ${file.name} has unknown key ${key}`, {file:appDirRelative+file.url}); if (!STORAGE_KEYS.includes(key)) ERROR(`App ${app.id} file ${file.name} has unknown key ${key}`, {file:appDirRelative+file.url});
@ -436,6 +556,18 @@ apps.forEach((app,appIdx) => {
ERROR(`App ${app.id} has provides_modules ${modulename} but it doesn't provide that filename`, {file:metadataFile}); ERROR(`App ${app.id} has provides_modules ${modulename} but it doesn't provide that filename`, {file:metadataFile});
}); });
} }
/*
// We could try to create the files we need to upload for this app to check it all works ok...
promise = promise.then(() => apploader.getAppFiles(app).then(files => {
files.forEach(file => {
if (/\.clkinfo?\.js$/.test(file.name) ||
/\.settings?\.js$/.test(file.name)) {
if (!file.content.startsWith("(")) {
ERROR(`App ${app.id} file ${file.name} should evaluate to a simple fn and doesn't (starts: ${JSON.stringify(file.content.substr(0,30))})`, {file:appDirRelative+file.url});
}
}
});
}));*/
}); });
@ -481,6 +613,7 @@ function sanityCheckLocales(){
} }
} }
promise.then(function() {
console.log("=================================="); console.log("==================================");
console.log(`${errorCount} errors, ${warningCount} warnings (and ${knownErrorCount} known errors, ${knownWarningCount} known warnings)`); console.log(`${errorCount} errors, ${warningCount} warnings (and ${knownErrorCount} known errors, ${knownWarningCount} known warnings)`);
console.log("=================================="); console.log("==================================");
@ -490,3 +623,4 @@ if (errorCount) {
console.log("Running in CI, raising an error from warnings"); console.log("Running in CI, raising an error from warnings");
process.exit(1); process.exit(1);
} }
});

2
core

@ -1 +1 @@
Subproject commit 7e5ac0271f794bcacda3a5a692cfa479457eb4dd Subproject commit cbf53ec34fee9b7d9234a7bbfc276592d9e076a5

View File

@ -235,7 +235,7 @@ Layout.prototype.forgetLazyState = function () {
Layout.prototype.layout = function (l) { Layout.prototype.layout = function (l) {
// l = current layout element // l = current layout element
var cb = { var floor = Math.floor, cb = {
"h" : function(l) {"ram"; "h" : function(l) {"ram";
var acc_w = l.x + (0|l.pad), var acc_w = l.x + (0|l.pad),
accfillx = 0, accfillx = 0,
@ -246,7 +246,7 @@ Layout.prototype.layout = function (l) {
c.x = 0|x; c.x = 0|x;
acc_w += c._w; acc_w += c._w;
accfillx += 0|c.fillx; accfillx += 0|c.fillx;
x = acc_w + 0|(accfillx*(l.w-l._w)/fillx); x = acc_w + floor(accfillx*(l.w-l._w)/fillx);
c.w = 0|(x - c.x); c.w = 0|(x - c.x);
c.h = 0|(c.filly ? l.h - (l.pad<<1) : c._h); c.h = 0|(c.filly ? l.h - (l.pad<<1) : c._h);
c.y = 0|(l.y + (0|l.pad) + ((1+(0|c.valign))*(l.h-(l.pad<<1)-c.h)>>1)); c.y = 0|(l.y + (0|l.pad) + ((1+(0|c.valign))*(l.h-(l.pad<<1)-c.h)>>1));
@ -263,7 +263,7 @@ Layout.prototype.layout = function (l) {
c.y = 0|y; c.y = 0|y;
acc_h += c._h; acc_h += c._h;
accfilly += 0|c.filly; accfilly += 0|c.filly;
y = acc_h + 0|(accfilly*(l.h-l._h)/filly); y = acc_h + floor(accfilly*(l.h-l._h)/filly);
c.h = 0|(y - c.y); c.h = 0|(y - c.y);
c.w = 0|(c.fillx ? l.w - (l.pad<<1) : c._w); c.w = 0|(c.fillx ? l.w - (l.pad<<1) : c._w);
c.x = 0|(l.x + (0|l.pad) + ((1+(0|c.halign))*(l.w-(l.pad<<1)-c.w)>>1)); c.x = 0|(l.x + (0|l.pad) + ((1+(0|c.halign))*(l.w-(l.pad<<1)-c.w)>>1));

28
modules/Layout.min.js vendored
View File

@ -1,14 +1,14 @@
function p(d,k){function c(f){"ram";f.id&&(l[f.id]=f);f.type||(f.type="");f.c&&f.c.forEach(c)}this._l=this.l=d;this.options=k||{};this.lazy=this.options.lazy||!1;this.physBtns=1;let h;if(2!=process.env.HWVERSION){this.physBtns=3;h=[];function f(a){"ram";"btn"==a.type&&h.push(a);a.c&&a.c.forEach(f)}f(d);h.length&&(this.physBtns=0,this.buttons=h,this.selectedButton=-1)}if(this.options.btns)if(d=this.options.btns,this.physBtns>=d.length){this.b=d;let f=Math.floor(Bangle.appRect.h/ function p(c,h){function d(f){"ram";f.id&&(l[f.id]=f);f.type||(f.type="");f.c&&f.c.forEach(d)}this._l=this.l=c;this.options=h||{};this.lazy=this.options.lazy||!1;this.physBtns=1;let e;if(2!=process.env.HWVERSION){this.physBtns=3;e=[];function f(b){"ram";"btn"==b.type&&e.push(b);b.c&&b.c.forEach(f)}f(c);e.length&&(this.physBtns=0,this.buttons=e,this.selectedButton=-1)}if(this.options.btns)if(c=this.options.btns,this.physBtns>=c.length){this.b=c;let f=Math.floor(Bangle.appRect.h/
this.physBtns);for(2<this.physBtns&&1==d.length&&d.unshift({label:""});this.physBtns>d.length;)d.push({label:""});this._l.width=g.getWidth()-8;this._l={type:"h",filly:1,c:[this._l,{type:"v",pad:1,filly:1,c:d.map(a=>(a.type="txt",a.font="6x8",a.height=f,a.r=1,a))}]}}else this._l.width=g.getWidth()-32,this._l={type:"h",c:[this._l,{type:"v",c:d.map(f=>(f.type="btn",f.filly=1,f.width=32,f.r=1,f))}]},h&&h.push.apply(h,this._l.c[1].c);this.setUI();var l=this;c(this._l);this.updateNeeded=!0}function t(d, this.physBtns);for(2<this.physBtns&&1==c.length&&c.unshift({label:""});this.physBtns>c.length;)c.push({label:""});this._l.width=g.getWidth()-8;this._l={type:"h",filly:1,c:[this._l,{type:"v",pad:1,filly:1,c:c.map(b=>(b.type="txt",b.font="6x8",b.height=f,b.r=1,b))}]}}else this._l.width=g.getWidth()-32,this._l={type:"h",c:[this._l,{type:"v",c:c.map(f=>(f.type="btn",f.filly=1,f.width=32,f.r=1,f))}]},e&&e.push.apply(e,this._l.c[1].c);this.setUI();var l=this;d(this._l);this.updateNeeded=!0}function t(c,
k,c,h,l){var f=null==d.bgCol?l:g.toColor(d.bgCol);if(f!=l||"txt"==d.type||"btn"==d.type||"img"==d.type||"custom"==d.type){var a=d.c;delete d.c;var e="H"+E.CRC32(E.toJS(d));a&&(d.c=a);delete k[e]||((h[e]=[d.x,d.y,d.x+d.w-1,d.y+d.h-1]).bg=null==l?g.theme.bg:l,c&&(c.push(d),c=null))}if(d.c)for(var b of d.c)t(b,k,c,h,f)}p.prototype.setUI=function(){Bangle.setUI();let d;this.buttons&&(Bangle.setUI({mode:"updown",back:this.options.back,remove:this.options.remove},k=>{var c=this.selectedButton,h=this.buttons.length; h,d,e,l){var f=null==c.bgCol?l:g.toColor(c.bgCol);if(f!=l||"txt"==c.type||"btn"==c.type||"img"==c.type||"custom"==c.type){var b=c.c;delete c.c;var k="H"+E.CRC32(E.toJS(c));b&&(c.c=b);delete h[k]||((e[k]=[c.x,c.y,c.x+c.w-1,c.y+c.h-1]).bg=null==l?g.theme.bg:l,d&&(d.push(c),d=null))}if(c.c)for(var a of c.c)t(a,h,d,e,f)}p.prototype.setUI=function(){Bangle.setUI();let c;this.buttons&&(Bangle.setUI({mode:"updown",back:this.options.back,remove:this.options.remove},h=>{var d=this.selectedButton,e=this.buttons.length;
if(void 0===k&&this.buttons[c])return this.buttons[c].cb();this.buttons[c]&&(delete this.buttons[c].selected,this.render(this.buttons[c]));c=(c+h+k)%h;this.buttons[c]&&(this.buttons[c].selected=1,this.render(this.buttons[c]));this.selectedButton=c}),d=!0);!this.options.back&&!this.options.remove||d||Bangle.setUI({mode:"custom",back:this.options.back,remove:this.options.remove});if(this.b){function k(c,h){.75<h.time-h.lastTime&&this.b[c].cbl?this.b[c].cbl(h):this.b[c].cb&&this.b[c].cb(h)}Bangle.btnWatches&& if(void 0===h&&this.buttons[d])return this.buttons[d].cb();this.buttons[d]&&(delete this.buttons[d].selected,this.render(this.buttons[d]));d=(d+e+h)%e;this.buttons[d]&&(this.buttons[d].selected=1,this.render(this.buttons[d]));this.selectedButton=d}),c=!0);!this.options.back&&!this.options.remove||c||Bangle.setUI({mode:"custom",back:this.options.back,remove:this.options.remove});if(this.b){function h(d,e){.75<e.time-e.lastTime&&this.b[d].cbl?this.b[d].cbl(e):this.b[d].cb&&this.b[d].cb(e)}Bangle.btnWatches&&
Bangle.btnWatches.forEach(clearWatch);Bangle.btnWatches=[];this.b[0]&&Bangle.btnWatches.push(setWatch(k.bind(this,0),BTN1,{repeat:!0,edge:-1}));this.b[1]&&Bangle.btnWatches.push(setWatch(k.bind(this,1),BTN2,{repeat:!0,edge:-1}));this.b[2]&&Bangle.btnWatches.push(setWatch(k.bind(this,2),BTN3,{repeat:!0,edge:-1}))}if(2==process.env.HWVERSION){function k(c,h){c.cb&&h.x>=c.x&&h.y>=c.y&&h.x<=c.x+c.w&&h.y<=c.y+c.h&&(2==h.type&&c.cbl?c.cbl(h):c.cb&&c.cb(h));c.c&&c.c.forEach(l=>k(l,h))}Bangle.touchHandler= Bangle.btnWatches.forEach(clearWatch);Bangle.btnWatches=[];this.b[0]&&Bangle.btnWatches.push(setWatch(h.bind(this,0),BTN1,{repeat:!0,edge:-1}));this.b[1]&&Bangle.btnWatches.push(setWatch(h.bind(this,1),BTN2,{repeat:!0,edge:-1}));this.b[2]&&Bangle.btnWatches.push(setWatch(h.bind(this,2),BTN3,{repeat:!0,edge:-1}))}if(2==process.env.HWVERSION){function h(d,e){d.cb&&e.x>=d.x&&e.y>=d.y&&e.x<=d.x+d.w&&e.y<=d.y+d.h&&(2==e.type&&d.cbl?d.cbl(e):d.cb&&d.cb(e));d.c&&d.c.forEach(l=>h(l,e))}Bangle.touchHandler=
(c,h)=>k(this._l,h);Bangle.on("touch",Bangle.touchHandler)}};p.prototype.render=function(d){function k(b){"ram";c.reset();void 0!==b.col&&c.setColor(b.col);void 0!==b.bgCol&&c.setBgColor(b.bgCol).clearRect(b.x,b.y,b.x+b.w-1,b.y+b.h-1);h[b.type](b)}d||(d=this._l);this.updateNeeded&&this.update();var c=g,h={"":function(){},txt:function(b){"ram";if(b.wrap){var m=c.setFont(b.font).setFontAlign(0,-1).wrapString(b.label,b.w),n=b.y+(b.h-c.getFontHeight()*m.length>>1);c.drawString(m.join("\n"),b.x+(b.w>> (d,e)=>h(this._l,e);Bangle.on("touch",Bangle.touchHandler)}};p.prototype.render=function(c){function h(a){"ram";d.reset();void 0!==a.col&&d.setColor(a.col);void 0!==a.bgCol&&d.setBgColor(a.bgCol).clearRect(a.x,a.y,a.x+a.w-1,a.y+a.h-1);e[a.type](a)}c||(c=this._l);this.updateNeeded&&this.update();var d=g,e={"":function(){},txt:function(a){"ram";if(a.wrap){var m=d.setFont(a.font).setFontAlign(0,-1).wrapString(a.label,a.w),n=a.y+(a.h-d.getFontHeight()*m.length>>1);d.drawString(m.join("\n"),a.x+(a.w>>
1),n)}else c.setFont(b.font).setFontAlign(0,0,b.r).drawString(b.label,b.x+(b.w>>1),b.y+(b.h>>1))},btn:function(b){"ram";var m=b.x+(0|b.pad),n=b.y+(0|b.pad),q=b.w-(b.pad<<1),r=b.h-(b.pad<<1);m=[m,n+4,m+4,n,m+q-5,n,m+q-1,n+4,m+q-1,n+r-5,m+q-5,n+r-1,m+4,n+r-1,m,n+r-5,m,n+4];n=void 0!==b.btnBorderCol?b.btnBorderCol:c.theme.fg2;q=void 0!==b.btnFaceCol?b.btnFaceCol:c.theme.bg2;b.selected&&(q=c.theme.bgH,n=c.theme.fgH);c.setColor(q).fillPoly(m).setColor(n).drawPoly(m);void 0!==b.col&&c.setColor(b.col);b.src? 1),n)}else d.setFont(a.font).setFontAlign(0,0,a.r).drawString(a.label,a.x+(a.w>>1),a.y+(a.h>>1))},btn:function(a){"ram";var m=a.x+(0|a.pad),n=a.y+(0|a.pad),q=a.w-(a.pad<<1),r=a.h-(a.pad<<1);m=[m,n+4,m+4,n,m+q-5,n,m+q-1,n+4,m+q-1,n+r-5,m+q-5,n+r-1,m+4,n+r-1,m,n+r-5,m,n+4];n=void 0!==a.btnBorderCol?a.btnBorderCol:d.theme.fg2;q=void 0!==a.btnFaceCol?a.btnFaceCol:d.theme.bg2;a.selected&&(q=d.theme.bgH,n=d.theme.fgH);d.setColor(q).fillPoly(m).setColor(n).drawPoly(m);void 0!==a.col&&d.setColor(a.col);a.src?
c.setBgColor(q).drawImage("function"==typeof b.src?b.src():b.src,b.x+b.w/2,b.y+b.h/2,{scale:b.scale||void 0,rotate:.5*Math.PI*(b.r||0)}):c.setFont(b.font||"6x8:2").setFontAlign(0,0,b.r).drawString(b.label,b.x+b.w/2,b.y+b.h/2)},img:function(b){"ram";c.drawImage("function"==typeof b.src?b.src():b.src,b.x+b.w/2,b.y+b.h/2,{scale:b.scale||void 0,rotate:.5*Math.PI*(b.r||0)})},custom:function(b){"ram";b.render(b)},h:function(b){"ram";b.c.forEach(k)},v:function(b){"ram";b.c.forEach(k)}};if(this.lazy){this.rects|| d.setBgColor(q).drawImage("function"==typeof a.src?a.src():a.src,a.x+a.w/2,a.y+a.h/2,{scale:a.scale||void 0,rotate:.5*Math.PI*(a.r||0)}):d.setFont(a.font||"6x8:2").setFontAlign(0,0,a.r).drawString(a.label,a.x+a.w/2,a.y+a.h/2)},img:function(a){"ram";d.drawImage("function"==typeof a.src?a.src():a.src,a.x+a.w/2,a.y+a.h/2,{scale:a.scale||void 0,rotate:.5*Math.PI*(a.r||0)})},custom:function(a){"ram";a.render(a)},h:function(a){"ram";a.c.forEach(h)},v:function(a){"ram";a.c.forEach(h)}};if(this.lazy){this.rects||
(this.rects={});var l=this.rects.clone(),f=[];t(d,l,f,this.rects,null);for(var a in l)delete this.rects[a];d=Object.keys(l).map(b=>l[b]).reverse();for(var e of d)c.setBgColor(e.bg).clearRect.apply(g,e);f.forEach(k)}else k(d)};p.prototype.forgetLazyState=function(){this.rects={}};p.prototype.layout=function(d){var k={h:function(c){"ram";var h=c.x+(0|c.pad),l=0,f=c.c&&c.c.reduce((e,b)=>e+(0|b.fillx),0);f||(h+=c.w-c._w>>1,f=1);var a=h;c.c.forEach(e=>{e.x=0|a;h+=e._w;l+=0|e.fillx;a=h+0|l*(c.w-c._w)/f; (this.rects={});var l=this.rects.clone(),f=[];t(c,l,f,this.rects,null);for(var b in l)delete this.rects[b];c=Object.keys(l).map(a=>l[a]).reverse();for(var k of c)d.setBgColor(k.bg).clearRect.apply(g,k);f.forEach(h)}else h(c)};p.prototype.forgetLazyState=function(){this.rects={}};p.prototype.layout=function(c){var h=Math.floor,d={h:function(e){"ram";var l=e.x+(0|e.pad),f=0,b=e.c&&e.c.reduce((a,m)=>a+(0|m.fillx),0);b||(l+=e.w-e._w>>1,b=1);var k=l;e.c.forEach(a=>{a.x=0|k;l+=a._w;f+=0|a.fillx;k=l+h(f*
e.w=0|a-e.x;e.h=0|(e.filly?c.h-(c.pad<<1):e._h);e.y=0|c.y+(0|c.pad)+((1+(0|e.valign))*(c.h-(c.pad<<1)-e.h)>>1);if(e.c)k[e.type](e)})},v:function(c){"ram";var h=c.y+(0|c.pad),l=0,f=c.c&&c.c.reduce((e,b)=>e+(0|b.filly),0);f||(h+=c.h-c._h>>1,f=1);var a=h;c.c.forEach(e=>{e.y=0|a;h+=e._h;l+=0|e.filly;a=h+0|l*(c.h-c._h)/f;e.h=0|a-e.y;e.w=0|(e.fillx?c.w-(c.pad<<1):e._w);e.x=0|c.x+(0|c.pad)+((1+(0|e.halign))*(c.w-(c.pad<<1)-e.w)>>1);if(e.c)k[e.type](e)})}};if(k[d.type])k[d.type](d)};p.prototype.debug=function(d, (e.w-e._w)/b);a.w=0|k-a.x;a.h=0|(a.filly?e.h-(e.pad<<1):a._h);a.y=0|e.y+(0|e.pad)+((1+(0|a.valign))*(e.h-(e.pad<<1)-a.h)>>1);if(a.c)d[a.type](a)})},v:function(e){"ram";var l=e.y+(0|e.pad),f=0,b=e.c&&e.c.reduce((a,m)=>a+(0|m.filly),0);b||(l+=e.h-e._h>>1,b=1);var k=l;e.c.forEach(a=>{a.y=0|k;l+=a._h;f+=0|a.filly;k=l+h(f*(e.h-e._h)/b);a.h=0|k-a.y;a.w=0|(a.fillx?e.w-(e.pad<<1):a._w);a.x=0|e.x+(0|e.pad)+((1+(0|a.halign))*(e.w-(e.pad<<1)-a.w)>>1);if(a.c)d[a.type](a)})}};if(d[c.type])d[c.type](c)};p.prototype.debug=
k){d||(d=this._l);k=k||1;g.setColor(k&1,k&2,k&4).drawRect(d.x+k-1,d.y+k-1,d.x+d.w-k,d.y+d.h-k);d.pad&&g.drawRect(d.x+d.pad-1,d.y+d.pad-1,d.x+d.w-d.pad,d.y+d.h-d.pad);k++;d.c&&d.c.forEach(c=>this.debug(c,k))};p.prototype.update=function(){function d(a){"ram";l[a.type](a);if(a.r&1){var e=a._w;a._w=a._h;a._h=e}a._w=c(a._w+(a.pad<<1),0|a.width);a._h=c(a._h+(a.pad<<1),0|a.height)}delete this.updateNeeded;var k=g,c=Math.max,h=Math.round,l={txt:function(a){"ram";a.font.endsWith("%")&&(a.font="Vector"+h(k.getHeight()* function(c,h){c||(c=this._l);h=h||1;g.setColor(h&1,h&2,h&4).drawRect(c.x+h-1,c.y+h-1,c.x+c.w-h,c.y+c.h-h);c.pad&&g.drawRect(c.x+c.pad-1,c.y+c.pad-1,c.x+c.w-c.pad,c.y+c.h-c.pad);h++;c.c&&c.c.forEach(d=>this.debug(d,h))};p.prototype.update=function(){function c(b){"ram";l[b.type](b);if(b.r&1){var k=b._w;b._w=b._h;b._h=k}b._w=d(b._w+(b.pad<<1),0|b.width);b._h=d(b._h+(b.pad<<1),0|b.height)}delete this.updateNeeded;var h=g,d=Math.max,e=Math.round,l={txt:function(b){"ram";b.font.endsWith("%")&&(b.font=
a.font.slice(0,-1)/100));if(a.wrap)a._h=a._w=0;else{var e=k.setFont(a.font).stringMetrics(a.label);a._w=e.width;a._h=e.height}},btn:function(a){"ram";a.font&&a.font.endsWith("%")&&(a.font="Vector"+h(k.getHeight()*a.font.slice(0,-1)/100));var e=a.src?k.imageMetrics("function"==typeof a.src?a.src():a.src):k.setFont(a.font||"6x8:2").stringMetrics(a.label);a._h=16+e.height;a._w=20+e.width},img:function(a){"ram";var e=k.imageMetrics("function"==typeof a.src?a.src():a.src),b=a.scale||1;a._w=e.width*b;a._h= "Vector"+e(h.getHeight()*b.font.slice(0,-1)/100));if(b.wrap)b._h=b._w=0;else{var k=h.setFont(b.font).stringMetrics(b.label);b._w=k.width;b._h=k.height}},btn:function(b){"ram";b.font&&b.font.endsWith("%")&&(b.font="Vector"+e(h.getHeight()*b.font.slice(0,-1)/100));var k=b.src?h.imageMetrics("function"==typeof b.src?b.src():b.src):h.setFont(b.font||"6x8:2").stringMetrics(b.label);b._h=16+k.height;b._w=20+k.width},img:function(b){"ram";var k=h.imageMetrics("function"==typeof b.src?b.src():b.src),a=b.scale||
e.height*b},"":function(a){"ram";a._w=0;a._h=0},custom:function(a){"ram";a._w=0;a._h=0},h:function(a){"ram";a.c.forEach(d);a._h=a.c.reduce((e,b)=>c(e,b._h),0);a._w=a.c.reduce((e,b)=>e+b._w,0);null==a.fillx&&a.c.some(e=>e.fillx)&&(a.fillx=1);null==a.filly&&a.c.some(e=>e.filly)&&(a.filly=1)},v:function(a){"ram";a.c.forEach(d);a._h=a.c.reduce((e,b)=>e+b._h,0);a._w=a.c.reduce((e,b)=>c(e,b._w),0);null==a.fillx&&a.c.some(e=>e.fillx)&&(a.fillx=1);null==a.filly&&a.c.some(e=>e.filly)&&(a.filly=1)}},f=this._l; 1;b._w=k.width*a;b._h=k.height*a},"":function(b){"ram";b._w=0;b._h=0},custom:function(b){"ram";b._w=0;b._h=0},h:function(b){"ram";b.c.forEach(c);b._h=b.c.reduce((k,a)=>d(k,a._h),0);b._w=b.c.reduce((k,a)=>k+a._w,0);null==b.fillx&&b.c.some(k=>k.fillx)&&(b.fillx=1);null==b.filly&&b.c.some(k=>k.filly)&&(b.filly=1)},v:function(b){"ram";b.c.forEach(c);b._h=b.c.reduce((k,a)=>k+a._h,0);b._w=b.c.reduce((k,a)=>d(k,a._w),0);null==b.fillx&&b.c.some(k=>k.fillx)&&(b.fillx=1);null==b.filly&&b.c.some(k=>k.filly)&&
d(f);delete l;f.fillx||f.filly?(f.w=Bangle.appRect.w,f.h=Bangle.appRect.h,f.x=Bangle.appRect.x,f.y=Bangle.appRect.y):(f.w=f._w,f.h=f._h,f.x=Bangle.appRect.w-f.w>>1,f.y=Bangle.appRect.y+(Bangle.appRect.h-f.h>>1));this.layout(f)};p.prototype.clear=function(d){d||(d=this._l);g.reset();void 0!==d.bgCol&&g.setBgColor(d.bgCol);g.clearRect(d.x,d.y,d.x+d.w-1,d.y+d.h-1)};exports=p (b.filly=1)}},f=this._l;c(f);delete l;f.fillx||f.filly?(f.w=Bangle.appRect.w,f.h=Bangle.appRect.h,f.x=Bangle.appRect.x,f.y=Bangle.appRect.y):(f.w=f._w,f.h=f._h,f.x=Bangle.appRect.w-f.w>>1,f.y=Bangle.appRect.y+(Bangle.appRect.h-f.h>>1));this.layout(f)};p.prototype.clear=function(c){c||(c=this._l);g.reset();void 0!==c.bgCol&&g.setBgColor(c.bgCol);g.clearRect(c.x,c.y,c.x+c.w-1,c.y+c.h-1)};exports=p

View File

@ -13,18 +13,13 @@
// Note that if a field is undefined then its value is zero. // Note that if a field is undefined then its value is zero.
// //
const ONE_SECOND = 1000;
const ONE_MINUTE = 60 * ONE_SECOND;
const ONE_HOUR = 60 * ONE_MINUTE;
const ONE_DAY = 24 * ONE_HOUR;
/** /**
* @param {object} time {d, h, m, s} * @param {object} time {d, h, m, s}
* @returns the milliseconds contained in the passed time object * @returns the milliseconds contained in the passed time object
*/ */
exports.encodeTime = (time) => { exports.encodeTime = (time) => {
time = safeTime(time); time = safeTime(time);
return time.d * ONE_DAY + time.h * ONE_HOUR + time.m * ONE_MINUTE + time.s * ONE_SECOND; return time.d * 86400000 + time.h * 3600000 + time.m * 60000 + time.s * 1000;
} }
// internal use, set to zero all the undefined fields // internal use, set to zero all the undefined fields
@ -38,13 +33,13 @@ function safeTime(time) {
*/ */
exports.decodeTime = (millis) => { exports.decodeTime = (millis) => {
if (typeof millis !== "number") throw "Only a number can be decoded"; if (typeof millis !== "number") throw "Only a number can be decoded";
var d = Math.floor(millis / ONE_DAY); var d = Math.floor(millis / 86400000);
millis -= d * ONE_DAY; millis -= d * 86400000;
var h = Math.floor(millis / ONE_HOUR); var h = Math.floor(millis / 3600000);
millis -= h * ONE_HOUR; millis -= h * 3600000;
var m = Math.floor(millis / ONE_MINUTE); var m = Math.floor(millis / 60000);
millis -= m * ONE_MINUTE; millis -= m * 60000;
var s = Math.floor(millis / ONE_SECOND); var s = Math.floor(millis / 1000);
return { d: d, h: h, m: m, s: s }; return { d: d, h: h, m: m, s: s };
} }
@ -55,9 +50,9 @@ exports.decodeTime = (millis) => {
*/ */
exports.formatTime = (value) => { exports.formatTime = (value) => {
var time = safeTime(typeof value === "object" ? value : exports.decodeTime(value)); var time = safeTime(typeof value === "object" ? value : exports.decodeTime(value));
if (time.d != 0) throw "days not supported here"; time.h += time.d*24;
if (time.h < 0 || time.h > 23) throw "Invalid value: must be 0 <= h <= 23"; /*if (time.h < 0 || time.h > 23) throw "Invalid value: must be 0 <= h <= 23";
if (time.m < 0 || time.m > 59) throw "Invalid value: must be 0 <= m <= 59"; if (time.m < 0 || time.m > 59) throw "Invalid value: must be 0 <= m <= 59";*/
return time.h + ":" + ("0" + time.m).substr(-2); return time.h + ":" + ("0" + time.m).substr(-2);
} }

@ -1 +1 @@
Subproject commit 41331a6d8d1a544ee063e87b8dcebca0bd4ef0d0 Subproject commit c3ca6c7a5699a4d4f1f643438bf4f5dd979dba82