Merge branch 'master' into fix/alarm-clkinfo-enable

Conflicts:
	apps/sched/ChangeLog
	apps/sched/clkinfo.js
pull/3620/head
Rob Pilling 2024-10-29 21:25:25 +00:00
commit 43dcbd3207
57 changed files with 1751 additions and 699 deletions

View File

@ -38,4 +38,5 @@
0.36: Move from wrapper function to {} and let - faster execution at boot
Allow `calendar-` to take an array of items to remove
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 */
{
let gbSend = function(message) {
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
// settings var is deleted after this executes to save memory
let settings = Object.assign({rp:true,as:true,vibrate:".."},
require("Storage").readJSON("android.settings.json",1)||{}
);
let _GB = global.GB;
let fetchRecInterval;
global.GB = (event) => {
global.GB = e => {
// feed a copy to other handlers if there were any
if (_GB) setTimeout(_GB,0,Object.assign({},event));
/* TODO: Call handling, fitness */
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);
if (_GB) setTimeout(_GB,0,Object.assign({},e));
Bangle.emit("GB",e);
require("android").gbHandler(e);
};
// HTTP request handling - see the readme
// options = {id,timeout,xpath}
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;
};
Bangle.http = (url,options)=>require("android").httpHandler(url,options);
// 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);
NRF.on("connect", () => setTimeout(function() {
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
}, 2000));
NRF.on("disconnect", () => {
@ -357,81 +32,24 @@
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
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
Bangle.musicControl = cmd => {
// play/pause/next/previous/volumeup/volumedown
gbSend({ t: "music", n:cmd });
require("android").gbSend({ t: "music", n:cmd });
};
// Message response
Bangle.messageResponse = (msg,response) => {
if (msg.id=="call") return gbSend({ t: "call", n:response?"ACCEPT":"REJECT" });
if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id });
if (msg.id=="call") return require("android").gbSend({ t: "call", n:response?"ACCEPT":"REJECT" });
if (isFinite(msg.id)) return require("android").gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id });
// error/warn here?
};
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
if (settings.overwriteGps) { // if the overwrite option is set..
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);
}
if (settings.overwriteGps) require("android").overwriteGPS();
// remove settings object so it's not taking up RAM
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",
"name": "Android Integration",
"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.",
"icon": "app.png",
"tags": "tool,system,messages,notifications,gadgetbridge",
@ -13,7 +13,8 @@
{"name":"android.app.js","url":"app.js"},
{"name":"android.settings.js","url":"settings.js"},
{"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"}],
"sortorder": -8

View File

@ -3,4 +3,5 @@
0.03: Select GNSS systems to use for Bangle.js 2
0.04: Now turns GPS off after upload
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>
var isB1; // is Bangle.js 1?
var isB2; // is Bangle.js 2?
var currentPosition;
// When the 'upload' button is clicked...
document.getElementById("upload").addEventListener("click", function() {
@ -120,6 +121,7 @@
}
// =================================================== Bangle.js 2 CASIC
// https://www.espruino.com/Bangle.js2+Technical#gps
function CASIC_CHECKSUM(cmd) {
var cs = 0;
@ -128,6 +130,61 @@
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) {
@ -140,7 +197,6 @@
js += `\x10Serial1.write(atob("${btoa(String.fromCharCode.apply(null,UBX_MGA_INI_TIME_UTC()))}"))\n`; // set GPS time
}
if (isB2) { // CASIC
// Select what GNSS System to use for decreased fix time.
var radios = document.getElementsByName('gnss_select');
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 += `\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!)
// 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
// 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) {
@ -184,8 +240,20 @@
document.getElementById("banglejs1-info").style = isB1?"":"display:none";
document.getElementById("banglejs2-info").style = isB2?"":"display:none";
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>
</body>
</html>

View File

@ -2,7 +2,7 @@
"id": "assistedgps",
"name": "Assisted GPS Updater (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.",
"sortorder": -1,
"icon": "app.png",

View File

@ -1,2 +1,3 @@
0.01: New app!
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",
"name": "BangleBridge",
"shortName": "BangleBridge",
"version": "0.02",
"description": "Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App",
"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 (**Note:** this has nothing to do with Gadgetbridge)",
"icon": "widget.png",
"type": "widget",
"tags": "widget",

View File

@ -1,10 +1,10 @@
(() => {
/**
* Widget measurements
* Description:
* Description:
* name: connection.wid.js
*icon: conectionIcon.icon
*
*
*/
//Font
@ -24,7 +24,7 @@
//Sensors code
/**
*
*
* @author Jorge
*/
function accel() {
@ -35,8 +35,7 @@
});
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;
}, 2 * 1000);
@ -45,8 +44,7 @@
function btt() {
setInterval(function () {
bttS = E.getBattery(); //return String
//bttS = E.getBattery(); //return String
data[2] = E.getBattery();
}, 15 * 1000);
@ -65,9 +63,9 @@
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" +
"C: " + compssN.heading; //return String
"C: " + compssN.heading; *///return String
data[4] = compssN;
}, 2 * 1000);
@ -86,8 +84,8 @@
setInterval(function () {
gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" +
"C: " + gpsN.satellites + " ## " + gpsN.fix; //return String
/*gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" +
"C: " + gpsN.satellites + " ## " + gpsN.fix; *///return String
// work out how to display the current time
var d = new Date();
var year = d.getFullYear();
@ -150,7 +148,7 @@
//console.log("Index ==> "+ index);
msr[indexFinal] = nueva;
item = nueva;
//item = nueva;
lastInsert = indexFinal;
}
@ -180,7 +178,7 @@
hrmN = normalize(hrmN);
var roundedRate = parseFloat(hrmN).toFixed(2);
hrmS = String.valueOf(roundedRate); //return String
//hrmS = String.valueOf(roundedRate); //return String
//console.log("array----->" + msr);
data[0] = roundedRate;
@ -205,7 +203,7 @@
setInterval(function () {
stepS = String.valueOf(stepN); //return String
//stepS = String.valueOf(stepN); //return String
data[1] = stepN;
}, 2 * 1000);
@ -240,12 +238,11 @@
g.setFont("Vector", 45);
g.drawString(prueba,100,200);*/
if (flip == 1) { //when off
flip = 0;
//Bangle.buzz(1000);
g.clear();
} else { //when on
flip = 1;
g.setFont("Vector", 30);
g.drawString(data[0], 65, 180);
@ -283,7 +280,7 @@
com: data[4],
gps: data[5]
};
/* g.clear();
/*
g.drawString(compssS,100,200);
*/
@ -293,7 +290,7 @@
//draw();
}, 5 * 1000);
WIDGETS["banglebridge"]={
area: "tl",
width: 10,

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.62: Handle setting for configuring BLE privacy
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";
bootPost += "delete _tm;";
}
if (require('Storage').hash) { // new in 2v11 - helps ensure files haven't changed
let CRC = E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\.boot\.js/)+E.CRC32(process.env.GIT_COMMIT);
boot += `if(E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\\.boot\\.js/)+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`;
} 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})`;
if (FWVERSION < 216) {
E.showMessage(/*LANG*/"Please update Bangle.js firmware\n\nCurrent = "+process.env.VERSION,{title:"ERROR"});
throw new Error("Old firmware");
}
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 += `var bleServices = {}, bleServiceOptions = { uart : true};\n`;
bootPost += `NRF.setServices(bleServices,bleServiceOptions);delete bleServices,bleServiceOptions;\n`; // executed after other boot code
@ -44,7 +43,7 @@ LoopbackA.setConsole(true);\n`;
boot += `
Bluetooth.line="";
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();
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) boot += `Bangle.setLCDPower(1);\n`;
boot += `E.setTimeZone(${s.timezone});`;
// Draw out of memory errors onto the screen
boot += `E.on('errorFlag', function(errorFlags) {
// Draw out of memory errors onto the screen if logging enabled
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();
print("Interpreter error:", errorFlags);
E.getErrorFlags(); // clear flags so we get called next time
});\n`;
E.getErrorFlags();
});\n`;// E.getErrorFlags() -> clear flags so we get called next time
// 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`;
// 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.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
boot+=`Bangle.loadWidgets=function(){if(!global.WIDGETS)eval(require("Storage").read(".widcache"))};\n`;
// ================================================== 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
// this is a polyfill without fastloading capability
delete Bangle.showClock;
if (!Bangle.showClock) boot += `Bangle.showClock = ()=>{load(".bootcde")};\n`;
delete Bangle.load;
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
if (DEBUG) boot += `print(".boot0",0|(Date.now()-_tm),"ms");_tm=Date.now();\n`
// ================================================== BOOT.JS
// ================================================== .BOOT0
// 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
// These could change bleServices/bleServiceOptions if needed
@ -128,17 +115,47 @@ let bootFiles = require('Storage').list(/\.boot\.js$/).sort((a,b)=>{
});
// precalculate file size
bootPost += "}";
let fileSize = boot.length + bootPost.length;
bootFiles.forEach(bootFile=>{
// match the size of data we're adding below in bootFiles.forEach
if (DEBUG) fileSize += 2+bootFile.length+1; // `//${bootFile}\n` comment
fileSize += require('Storage').read(bootFile).length+2; // boot code plus ";\n"
if (DEBUG) fileSize += 48+E.toJS(bootFile).length; // `print(${E.toJS(bootFile)},0|(Date.now()-_tm),"ms");_tm=Date.now();\n`
});
// write file in chunks (so as not to use up all RAM)
require('Storage').write('.boot0',boot,0,fileSize);
let fileOffset = boot.length;
bootFiles.forEach(bootFile=>{
let fileOffset,fileSize;
/* code to output a file, plus preable and postable
when called with dst==undefined it just increments
fileOffset so we can see ho wbig the file has to be */
let outputFile = (dst,src,pre,post) => {"ram";
if (DEBUG) {
if (dst) require('Storage').write(dst,`//${src}\n`,fileOffset);
fileOffset+=2+src.length+1;
}
if (pre) {
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(){ ... }()
// with no semicolon we don't end up with (function(){ ... }()(function(){ ... }()
// which would cause an error!
@ -146,31 +163,48 @@ bootFiles.forEach(bootFile=>{
// "//"+bootFile+"\n"+require('Storage').read(bootFile)+";\n";
// but we need to do this without ever loading everything into RAM as some
// boot files seem to be getting pretty big now.
if (DEBUG) {
require('Storage').write('.boot0',`//${bootFile}\n`,fileOffset);
fileOffset+=2+bootFile.length+1;
}
let bf = require('Storage').read(bootFile);
// we can't just write 'bf' in one go because at least in 2v13 and earlier
// Espruino wants to read the whole file into RAM first, and on Bangle.js 1
// it can be too big (especially BTHRM).
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
}
});
outputFile(dst,fn,"",";\n");
};
fileOffset = boot.length + bootPost.length;
bootFiles.forEach(fn=>outputFileComplete(undefined,fn)); // just get sizes
fileSize = fileOffset;
require('Storage').write('.boot0',boot,0,fileSize);
fileOffset = boot.length;
bootFiles.forEach(fn=>outputFileComplete('.boot0',fn));
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...");
}
// .bootcde should be run automatically after if required, since

View File

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

View File

@ -10,4 +10,6 @@
0.09: Save clkinfo settings on kill and remove
0.10: Fix focus bug when changing focus between two clock infos
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;
/// A list of all the instances returned by addInteractive
exports.clockInfos = [];
/// A list of loaded clockInfos
exports.clockInfoMenus = undefined;
/// Load the settings, with defaults
exports.loadSettings = function() {
@ -29,6 +31,8 @@ exports.loadSettings = function() {
/// Load a list of ClockInfos - this does not cache and reloads each time
exports.load = function() {
if (exports.clockInfoMenus)
return exports.clockInfoMenus;
var settings = exports.loadSettings();
delete settings.apps; // keep just the basic settings in memory
// info used for drawing...
@ -131,10 +135,14 @@ exports.load = function() {
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
// object a, we append the items. Otherwise we add the new object a to the list.
require("Storage").list(/clkinfo.js$/).forEach(fn => {
try{
var a = eval(require("Storage").read(fn))();
var b = menu.find(x => x.name === a.name);
@ -146,6 +154,7 @@ exports.load = function() {
});
// return it all!
exports.clockInfoMenus = menu;
return menu;
};
@ -345,6 +354,9 @@ exports.addInteractive = function(menu, options) {
menuHideItem(menu[options.menuA].items[options.menuB]);
exports.loadCount--;
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() {
drawItem(menu[options.menuA].items[options.menuB]);

View File

@ -1,7 +1,7 @@
{ "id": "clock_info",
"name": "Clock Info Module",
"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)",
"icon": "app.png",
"type": "module",

View File

@ -4,4 +4,5 @@
0.04: More options for different background colors
'Plasma' generative 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;
exports.reload = function() {
//let t = Date.now();
settings = Object.assign({
style : "randomcolor",
colors : ["#F00","#0F0","#00F"]
@ -17,7 +18,8 @@ exports.reload = function() {
let bpp = (settings.colors.length>4)?4:2;
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);
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.palette = new Uint16Array(1<<bpp);
bg.palette.set(settings.colors.map(c=>g.toColor(c)));
@ -28,7 +30,8 @@ exports.reload = function() {
settings.style = "image";
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);
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
1, 4, 7, 4, 1,
4,16,26,16, 4,
@ -42,6 +45,7 @@ exports.reload = function() {
settings.imgOpt = {scale:11};
delete settings.colors;
}
//console.log("bg",Date.now()-t);
};
exports.reload();

View File

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

View File

@ -21,3 +21,4 @@
0.34: Fix 'fast load' so clock doesn't always redraw when screen unlocked/locked
0.35: 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",
"name": "Hanks World Clock",
"shortName": "Hanks World Clock",
"version": "0.36",
"version": "0.37",
"description": "Current time zone plus up to three others",
"allow_emulator":true,
"icon": "app.png",

View File

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

View File

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

View File

@ -177,7 +177,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
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",
@ -194,7 +194,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%Y/%m/%d", 1: "%y/%m/%d" },
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
@ -210,7 +210,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d %b %Y", 1: "%d-%m-%Y" }, // 28 feb 2020 // 28-02-2020
abday: "zo,ma,di,wo,do,vr,za",
@ -258,7 +258,7 @@ var locales = {
speed: "km/h",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
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",
@ -290,7 +290,7 @@ var locales = {
speed: 'km/h',
distance: { "0": "m", "1": "km" },
temperature: '°C',
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
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",
@ -306,7 +306,7 @@ var locales = {
speed: "km/t",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "jan,feb,mar,apr,maj,jun,jul,aug,sep,okt,nov,dec",
@ -322,7 +322,7 @@ var locales = {
speed: "km/h",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
@ -370,7 +370,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
@ -403,7 +403,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "ene,feb,mar,abr,may,jun,jul,ago,sept,oct,nov,dic",
@ -420,7 +420,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
@ -484,7 +484,7 @@ var locales = {
speed: 'kmh',
distance: { "0": "m", "1": "km" },
temperature: '°C',
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
@ -500,7 +500,7 @@ var locales = {
speed: 'kmh',
distance: { "0": "m", "1": "km" },
temperature: '°C',
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
@ -516,7 +516,7 @@ var locales = {
speed: 'kmh',
distance: { "0": "m", "1": "km" },
temperature: '°C',
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "Jen,Hor,Mär,Abr,Mei,Brá,Hei,Öig,Her,Wím,Win,Chr",
@ -564,7 +564,7 @@ var locales = {
speed: "km/h",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
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
abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.",
@ -660,7 +660,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
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",
@ -676,7 +676,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
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",
@ -692,7 +692,7 @@ var locales = {
speed: "kmt",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
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",
@ -708,7 +708,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
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",
@ -725,7 +725,7 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
ampm: { 0: "am", 1: "pm" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" },
abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.",

View File

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

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.
/*Puck.eval(`require("Storage").list(/.*.js$/)`, (f)=>{
/*Puck.eval(`require("Storage").list(/.*\.js$/)`, (f)=>{
console.log("Found files:", f, rows[1].func);
for (let file of f){
let query = `require("Storage").read('${file}').includes('${rows[1].func}')`;

View File

@ -29,4 +29,5 @@
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.28: Added an icon for disabled events
0.29: Fix possible bug in toggling an alarm to on, from clkinfo
0.29: Improve clkinfo startup time by 10ms
0.30: Fix possible bug in toggling an alarm to on, from clkinfo

View File

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

View File

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

View File

@ -1,7 +1,7 @@
{
"id": "sched",
"name": "Scheduler",
"version": "0.29",
"version": "0.30",
"description": "Scheduling library for alarms and timers",
"icon": "app.png",
"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.10: Redesign to make screen updates fast
0.11: bugfix (demo mode was enabled by default)

View File

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

View File

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

View File

@ -17,3 +17,4 @@
Add option to disable vibration when charger connects
0.18: Only redraw when values change
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",
"name": "Battery Level Widget (with percentage)",
"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",
"icon": "widget.png",
"type": "widget",

View File

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

View File

@ -13,4 +13,5 @@
0.14: Added configuration option
0.15: Added option to hide widget when connected
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",
"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.",
"icon": "widget.png",
"type": "widget",
"tags": "widget,bluetooth",
"provides_widgets" : ["bluetooth"],
"supports": ["BANGLEJS","BANGLEJS2"],
"dependencies" : { "notify":"module" },
"storage": [
{"name":"widbt_notify.wid.js","url":"widget.js"},
{"name":"widbt_notify.settings.js","url":"settings.js"}

View File

@ -1,6 +1,6 @@
(function() {
{
// load settings
var settings = Object.assign({
let settings = Object.assign({
showWidget: true,
buzzOnConnect: true,
buzzOnLoss: true,
@ -10,7 +10,7 @@
}, require("Storage").readJSON("widbt_notify.json", true) || {});
// 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
WIDGETS.bluetooth_notify = Object.assign(settings, {
@ -31,24 +31,13 @@
g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="), 2 + this.x, 2 + this.y);
}
} else {
// g.setColor(g.theme.dark ? "#666" : "#999");
// g.setColor(g.theme.dark ? "#666" : "#999");
g.setColor("#f00"); // red is easier to distinguish from blue
g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="), 2 + this.x, 2 + this.y);
}
}
},
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) {
// setup widget with and reload widgets to show/hide if hideConnected is enabled
if (this.hideConnected) {
@ -61,10 +50,10 @@
if (this.warningEnabled) {
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(() => {
WIDGETS.bluetooth_notify.redrawCurrentApp();
}, 3000); // clear message - this will reload the widget, resetting 'warningEnabled'.
require("notify").hide({id:"widbtnotify"});
}, 3000);
}
this.warningEnabled = 0;
@ -87,4 +76,4 @@
NRF.on('connect', (addr) => WIDGETS.bluetooth_notify.onNRF(addr));
NRF.on('disconnect', () => WIDGETS.bluetooth_notify.onNRF());
})()
}

View File

@ -4,4 +4,5 @@
0.03: Fix messages not showing if UI auto-open is disabled
0.04: Now shows message icons again (#2416)
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",
"name": "Message Widget",
"version": "0.06",
"version": "0.07",
"description": "Widget showing new messages",
"icon": "app.png",
"type": "widget",

View File

@ -65,7 +65,7 @@ if ((require("Storage").readJSON("messages.settings.json", true) || {}).maxMessa
this.onMsg("show", {}); // reload messages+redraw
}
};
Bangle.on("message", WIDGETS["messages"].onMsg.bind(WIDGETS["messages"]));
WIDGETS["messages"].onMsg("init", {}); // abuse type="init" to prevent Bangle.drawWidgets();
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();
}

View File

@ -5,6 +5,12 @@
var fs = require("fs");
var vm = require("vm");
var heatshrink = require("../webtools/heatshrink");
/*var apploader = require("../core/lib/apploader.js");
apploader.init({
DEVICEID : "BANGLEJS2"
});*/
var acorn;
try {
acorn = require("acorn");
@ -48,54 +54,56 @@ function WARN(msg, opt) {
}
/* These are errors that we temporarily allow */
var KNOWN_ERRORS = [
"In locale en_CA, long date output must be shorter than 15 characters",
"In locale fr_FR, long date output must be shorter than 15 characters",
"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 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 (10 septembre 2024 -> 17)",
"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 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 */
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 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"`,
"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 = [];
@ -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>]}
let allFiles = [];
let existingApps = [];
let promise = Promise.resolve();
apps.forEach((app,appIdx) => {
if (!app.id) ERROR(`App ${appIdx} has no id`);
var appDirRelative = APPSDIR_RELATIVE+app.id+"/";
@ -306,8 +413,9 @@ apps.forEach((app,appIdx) => {
}
if (file.name.endsWith(".js")) {
// TODO: actual lint?
var ast;
try {
acorn.parse(fileContents);
ast = acorn.parse(fileContents);
} catch(e) {
console.log("=====================================================");
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});
}
}
// 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) {
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});
});
}
/*
// 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,12 +613,14 @@ function sanityCheckLocales(){
}
}
console.log("==================================");
console.log(`${errorCount} errors, ${warningCount} warnings (and ${knownErrorCount} known errors, ${knownWarningCount} known warnings)`);
console.log("==================================");
if (errorCount) {
process.exit(1);
} else if ("CI" in process.env && warningCount) {
console.log("Running in CI, raising an error from warnings");
process.exit(1);
}
promise.then(function() {
console.log("==================================");
console.log(`${errorCount} errors, ${warningCount} warnings (and ${knownErrorCount} known errors, ${knownWarningCount} known warnings)`);
console.log("==================================");
if (errorCount) {
process.exit(1);
} else if ("CI" in process.env && warningCount) {
console.log("Running in CI, raising an error from warnings");
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) {
// l = current layout element
var cb = {
var floor = Math.floor, cb = {
"h" : function(l) {"ram";
var acc_w = l.x + (0|l.pad),
accfillx = 0,
@ -246,7 +246,7 @@ Layout.prototype.layout = function (l) {
c.x = 0|x;
acc_w += c._w;
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.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));
@ -263,7 +263,7 @@ Layout.prototype.layout = function (l) {
c.y = 0|y;
acc_h += c._h;
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.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));
@ -363,4 +363,4 @@ Layout.prototype.clear = function(l) {
g.clearRect(l.x,l.y,l.x+l.w-1,l.y+l.h-1);
};
exports = Layout;
exports = Layout;

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/
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,
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;
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&&
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=
(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>>
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?
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||
(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;
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,
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()*
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=
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;
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
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==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,
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===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(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=
(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 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?
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(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-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=
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=
"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||
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)&&
(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.
//
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}
* @returns the milliseconds contained in the passed time object
*/
exports.encodeTime = (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
@ -38,26 +33,26 @@ function safeTime(time) {
*/
exports.decodeTime = (millis) => {
if (typeof millis !== "number") throw "Only a number can be decoded";
var d = Math.floor(millis / ONE_DAY);
millis -= d * ONE_DAY;
var h = Math.floor(millis / ONE_HOUR);
millis -= h * ONE_HOUR;
var m = Math.floor(millis / ONE_MINUTE);
millis -= m * ONE_MINUTE;
var s = Math.floor(millis / ONE_SECOND);
var d = Math.floor(millis / 86400000);
millis -= d * 86400000;
var h = Math.floor(millis / 3600000);
millis -= h * 3600000;
var m = Math.floor(millis / 60000);
millis -= m * 60000;
var s = Math.floor(millis / 1000);
return { d: d, h: h, m: m, s: s };
}
/**
/**
* @param {object|int} value {h, m} object or milliseconds
* @returns an human-readable time string like "10:25"
* @throws an exception if d != 0 or h > 23 or m > 59
*/
exports.formatTime = (value) => {
var time = safeTime(typeof value === "object" ? value : exports.decodeTime(value));
if (time.d != 0) throw "days not supported here";
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";
time.h += time.d*24;
/*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";*/
return time.h + ":" + ("0" + time.m).substr(-2);
}