From ad7b0df2a15c7a0573129b60d9f7687ef691f6ab Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 28 Jan 2022 11:23:43 +0100 Subject: [PATCH 1/2] settings fixed, first version BangleTestRunner --- apps/timecal/timecal.app.js | 90 +++++++------ apps/timecal/timecal.app.test.js | 216 ++++++++++++++++--------------- apps/timecal/timecal.settings.js | 148 +++++++++++++++++---- 3 files changed, 290 insertions(+), 164 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 090464be1..17daf127a 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -17,19 +17,19 @@ class TimeCalClock{ this._settings = require("Storage").readJSON("timecal.settings.json", 1) || {}; const defaults = { - showDate:"l", //(n)one, (l)ocale, (m)onth short(y)ear(w)eek - - wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, + shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week + + wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - todayNumClr:"#00E", - todayMrker:"r", //(n)one, (c)ircle, (r)ect, (f)illed - todayMrkClr:"#0E0", - todayMrkMrkPxl:3, + tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled + tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkPxl:3, //px - suColor:"#E00", //sunday - phColor:"#E00", //public holiday + suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + //phColor:"#E00", //public holiday - calBorder:true + calBrdr:false }; for (const k in this._settings) if (!defaults.hasOwnProperty(k)) delete this._settings[k]; //remove invalid settings for (const k in defaults) if(!this._settings.hasOwnProperty(k)) this._settings[k] = defaults[k]; //assign missing defaults @@ -39,7 +39,9 @@ class TimeCalClock{ Bangle.loadWidgets(); Bangle.drawWidgets(); - this.center_x = Bangle.appRect.w/2; + this.centerX = Bangle.appRect.w/2; + this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b + this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -64,7 +66,6 @@ class TimeCalClock{ */ drawTime(){ d=this.date ? this.date : new Date(); - console.log("drawTime", d); const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; d=d?d :new Date(); @@ -73,7 +74,7 @@ class TimeCalClock{ g.setFont("Vector", this.TIME_FONT_SIZE()); g.setColor(g.theme.fg); g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); - g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.center_x, Y); + g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); @@ -107,9 +108,9 @@ class TimeCalClock{ const Y=Bangle.appRect.y; var render=false; var dateStr = ""; - console.log(">"+this.settings().showDate+"<"); - if (!(this.settings().showDate==="n")) - for (let c of this.settings().showDate) { //add part as configured + if (this.settings().shwDate>0) { //skip if exactly -none + const dateSttngs = ["","l","M","m.Y #W"]; + for (let c of dateSttngs[this.settings().shwDate]) { //add part as configured switch (c){ case "l":{ //locale render=true; @@ -121,12 +122,26 @@ class TimeCalClock{ dateStr+=require("locale").month(d,1); break; } - case "y":{ //year e.g. 2022 + case "M":{ //month e.g. January + render=true; + dateStr+=require("locale").month(d,0); + break; + } + case "y":{ //year e.g. 22 + render=true; + dateStr+=d.getFullYear().slice(-2); + break; + } + case "Y":{ //year e.g. 2022 render=true; dateStr+=d.getFullYear(); break; } - case "w":{ //week e.g. #02 + case "w":{ //week e.g. #2 + dateStr+=(this.ISO8601calWeek(d)); + break; + } + case "W":{ //week e.g. #02 dateStr+=("0"+this.ISO8601calWeek(d)).slice(-2); break; } @@ -136,12 +151,13 @@ class TimeCalClock{ break; //noop } } + } if (render){ g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); g.setFont("Vector", FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(0, -1); - g.drawString(dateStr,this.center_x,Y); + g.drawString(dateStr,this.centerX,Y); } //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option } @@ -161,19 +177,18 @@ class TimeCalClock{ g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); - var dNames=[]; - if (require("locale") && require("locale").abday) - dNames=require("locale").abday.map((a) => a.length>2 ? a.substr(0, 2) : a ); //retrieve from locale and force max 2 chars - else - dNames=["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]; //fallback - g.setFont("Vector", DAY_NAME_FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(-1, -1); + + const tdyDate=d.getDate(); + const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); + //draw grid & Headline + const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -189,31 +204,30 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const todayDate=d.getDate(); - const days=7+(7+d.getDay()-this.settings().wdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) + const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) var rD=new Date(); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ for(var x=0; xSu, 1->Mo, ... //Issue #1154: weekstart So/Mo, + shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week + + wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - todayNumClr:"#00E", - todayMrker:"r", //(n)one, (c)ircle, (r)ect, (f)illed - todayMrkClr:"#0E0", - todayMrkMrkPxl:3, + tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled + tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkPxl:3, //px - suColor:"#E00", //sunday - phColor:"#E00", //public holiday + suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + //phColor:"#E00", //public holiday - calBorder:true + calBrdr:false }; for (const k in this._settings) if (!defaults.hasOwnProperty(k)) delete this._settings[k]; //remove invalid settings for (const k in defaults) if(!this._settings.hasOwnProperty(k)) this._settings[k] = defaults[k]; //assign missing defaults @@ -39,7 +39,9 @@ class TimeCalClock{ Bangle.loadWidgets(); Bangle.drawWidgets(); - this.center_x = Bangle.appRect.w/2; + this.centerX = Bangle.appRect.w/2; + this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b + this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -64,7 +66,6 @@ class TimeCalClock{ */ drawTime(){ d=this.date ? this.date : new Date(); - console.log("drawTime", d); const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; d=d?d :new Date(); @@ -73,7 +74,7 @@ class TimeCalClock{ g.setFont("Vector", this.TIME_FONT_SIZE()); g.setColor(g.theme.fg); g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); - g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.center_x, Y); + g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); @@ -107,9 +108,9 @@ class TimeCalClock{ const Y=Bangle.appRect.y; var render=false; var dateStr = ""; - console.log(this.settings().showDate); - if (this.settings().showDate!=="n"); - for (let c of this.settings().showDate) { //add part as configured + if (this.settings().shwDate>0) { //skip if exactly -none + const dateSttngs = ["","l","M","m.Y #W"]; + for (let c of dateSttngs[this.settings().shwDate]) { //add part as configured switch (c){ case "l":{ //locale render=true; @@ -121,12 +122,26 @@ class TimeCalClock{ dateStr+=require("locale").month(d,1); break; } - case "y":{ //year e.g. 2022 + case "M":{ //month e.g. January + render=true; + dateStr+=require("locale").month(d,0); + break; + } + case "y":{ //year e.g. 22 + render=true; + dateStr+=d.getFullYear().slice(-2); + break; + } + case "Y":{ //year e.g. 2022 render=true; dateStr+=d.getFullYear(); break; } - case "w":{ //week e.g. #02 + case "w":{ //week e.g. #2 + dateStr+=(this.ISO8601calWeek(d)); + break; + } + case "W":{ //week e.g. #02 dateStr+=("0"+this.ISO8601calWeek(d)).slice(-2); break; } @@ -136,12 +151,13 @@ class TimeCalClock{ break; //noop } } + } if (render){ g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); g.setFont("Vector", FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(0, -1); - g.drawString(dateStr,this.center_x,Y); + g.drawString(dateStr,this.centerX,Y); } //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option } @@ -161,19 +177,18 @@ class TimeCalClock{ g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); - var dNames=[]; - if (require("locale") && require("locale").abday) - dNames=require("locale").abday.map((a) => a.length>2 ? a.substr(0, 2) : a ); //retrieve from locale and force max 2 chars - else - dNames=["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]; //fallback - g.setFont("Vector", DAY_NAME_FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(-1, -1); + + const tdyDate=d.getDate(); + const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); + //draw grid & Headline + const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -189,31 +204,30 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const todayDate=d.getDate(); - const days=7+(7+d.getDay()-this.settings().wdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) + const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) var rD=new Date(); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ for(var x=0; x", - functionNames: ["required, ", "..."], cases: [ { value: "required,", @@ -335,7 +354,10 @@ class TestSetting extends Test{ afterText: "optional,", afterExpression: "optional," } - ] + ], + constructorParams: ["optional: ","|TEST_SETTINGS|","..."], //TEST_SETTINGS will be replcaed with each current {setting: case} + functionNames: ["required, ", "..."], + functionParams: ["optional: ","|TEST_SETTINGS|","..."] } } @@ -344,7 +366,6 @@ class TestSetting extends Test{ this._validate(data); this.setting = data.setting; - this.methodNames = data.functionNames; this.cases = data.cases.map((entry) => { return { value: entry.value, @@ -354,6 +375,9 @@ class TestSetting extends Test{ afterExpression: entry.afterExpression||true }; }); + this.constructorParams = data.constructorParams, + this.functionNames = data.functionNames; + this.functionParams = data.functionParams; } /** @@ -362,11 +386,11 @@ class TestSetting extends Test{ _validate(data){ //validate given config if (!data.setting) throw new EmptyMandatoryError("setting", data, this.TEST_SETTING_SAMPLE()); - if (!data.cases instanceof Array || data.cases.length==0) throw new EmptyMandatoryError("cases", data, this.TEST_SETTING_SAMPLE()); - if (!data.functionNames instanceof Array || data.functionNames==0) throw new EmptyMandatoryError("functionNames", data, this.TEST_SETTING_SAMPLE()); + if (!(data.cases instanceof Array) || data.cases.length==0) throw new EmptyMandatoryError("cases", data, this.TEST_SETTING_SAMPLE()); + if (!(data.functionNames instanceof Array) || data.functionNames==0) throw new EmptyMandatoryError("functionNames", data, this.TEST_SETTING_SAMPLE()); data.cases.forEach((entry,idx) => { - if (!entry.value) throw new EmptyMandatoryError("cases["+idx+"].value", entry, this.TEST_SETTING_SAMPLE()); + if (entry.value === undefined) throw new EmptyMandatoryError("cases["+idx+"].value", entry, this.TEST_SETTING_SAMPLE()); }); } } @@ -398,8 +422,8 @@ class BangleTestRunner{ * add a Setting Test, return instance for chaining * @param {TestSetting} */ - addSetting(test) { - this.tests.push(test); + addTestSettings(sttngs) { + this.tests.push(new TestSetting(sttngs)); return this; } @@ -416,14 +440,14 @@ class BangleTestRunner{ this._afterCase(); } this._afterTest(); - }; + } } /** - * global prepare + * global prepare - before all test */ _init() { - console.log(new Date(),">>init"); + console.log(new Date().getTime(),">>init"); this.currentTestNum=-1; this.currentCaseNum=-1; } @@ -448,45 +472,33 @@ class BangleTestRunner{ } } + /** + * testcase runner + */ _runCase() { console.log(new Date(), ">>running..."); var returns = []; - this.currentTest.methodNames.forEach((methodName) => { - var instance = eval("new " + this.oClass + ""); - console.log(instance); - const method = instance[methodName]; - //console.log(">>"+this.oClass+"["+methodName+"]()"); - //if (typeof method !== "function") - // throw new InvalidMethodName(this.oClass, methodName); - let settings={}; settings[this.currentTest.setting] = this.currentCase.value; - returns.push(new TimeCalClock(new Date(), settings).drawDate()); - //returns.push(method()); - console.log("<<"+this.oClass+"["+methodName+"]()"); - g.dump() + this.currentTest.functionNames.forEach((fName) => { + var settings={}; settings[this.currentTest.setting] = this.currentCase.value; + var cParams = this.currentTest.constructorParams||[]; + cParams = cParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + var fParams = this.currentTest.functionParams||[]; + fParams = fParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + + var creatorFunc = new Function("return new " + this.oClass + "(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9])"); //prepare spwan arguments[0],arguments[1] + let instance = creatorFunc.call(this.oClass, cParams[0], cParams[1], cParams[2], cParams[3], cParams[4], cParams[5], cParams[6], cParams[7], cParams[8], cParams[9]); //spwan + + console.log(">>"+this.oClass+"["+fName+"]()"); + returns.push(instance[fName](fParams[0], fParams[1], fParams[2], fParams[3], fParams[4], fParams[5], fParams[6], fParams[7], fParams[8], fParams[9])); //run method and store result + console.log("<<"+this.oClass+"["+fName+"]()"); + g.dump(); }); - - //this._delay(1).then((result) => console.log(new Date(), "finished")); - //g.dump(); - /*var testCaseNum=0; - test.cases.forEach(testcase => { //execute test - testcase.dates.forEach(date => { //spawn with each date - testCaseNum++; - E.showMessage( - "="+testcase.value+"\n" - +"expected: "+testcase.descr, - "#"+testCaseNum+": "+test.setting - ); - this._delay(TESTCASE_MSG_TIMEOUT).then((r,e) => { - const objUnderTest = new Object.create(this.ObjClass)(date, new Object()[test.setting]=test.value ); - objUnderTest.draw(); - this._delay(TESTCASE_RUN_TIMEOUT).then((r,e) => { - }); - }); - }); - });*/ console.log(new Date(), "<<...running"); } + /** + * after each testcase + */ _afterCase() { if (this.currentTest instanceof TestSetting) { if (this.currentCase.afterTxt.length>0) { @@ -498,10 +510,16 @@ class BangleTestRunner{ console.log(new Date(), "<Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for always focus/center today - function writeSettings() { + tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled + tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkPxl:2, //px + + suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + //phColor:"#E00", //public holiday + + calBrdr:false + }, + require('Storage').readJSON(FILE, true) || {} + ); + + const SETTINGS_AT_START = Object.assign(settings); //hardcopy of current and defaults + + var saveSettings = () => { require('Storage').writeJSON(FILE, settings); }; -}); -var mainmenu = { - "": { - "title": "Time calendar clock" - }, - "< Back": () => back(), - "Cal.Start Day": { - value: settings.wdStrt === undefined ? 1 : settings.wdStrt, //def: 1: mon - min: -1, max: 6, - //render dow from locale or LANG"today" - format: v => (v>=0 ? (require("locale") && require("locale").abday && require("locale").abday[v] ? : && require("locale").abday[v] : DOW_abbr_FB[v]) : /*LANG*/"today"), - onchange: v => { - settings.weekDay = v; - writeSettings(); - } - } -}; \ No newline at end of file + var restoreAndExitSettings = () => { + require('Storage').writeJSON(FILE, SETTINGS_AT_START); + E.showMenu(); + }; + + var showMainMenu = () => { + E.showMenu({ + "": { + "title": /*LANG*/"Time cal clock" + }, + /*LANG*/"< Save": () => save(), + /*LANG*/"Show date": { + value: settings.shwDate, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"locale", /*LANG*/"M", /*LANG*/"m.Y #W"][v], + onchange: v => { + settings.shwDate = v; + saveSettings(); + } + }, + /*LANG*/"Start wday": { + value: settings.wdStrt, + min: -1, max: 6, + format: v => v>=0 ? ABR_DAY[v] : /*LANG*/"today", + onchange: v => { + settings.wdStrt = v; + saveSettings(); + } + }, + /*LANG*/"Su color": { + value: settings.suClr, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], + onchange: v => { + settings.suClr = v; + saveSettings(); + } + }, + /*LANG*/"Border": { + value: settings.calBrdr, + format: v => v ? "show" : "none", + onchange: v => { + settings.calBrdr = v; + saveSettings(); + } + }, + /*LANG*/"Today settings": () => { + showTodayMenu(); + }, + /*LANG*/"< Cancel": () => restoreAndExitSettings() + }); + }; + + var showTodayMenu = () => { + E.showMenu({ + "": { + "title": /*LANG*/"Today settings" + }, + "< Back": () => showMainMenu(), + /*LANG*/"Color": { + value: settings.tdyNumClr, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], + onchange: v => { + settings.tdyNumClr = v; + saveSettings(); + } + }, + /*LANG*/"Marker": { + value: settings.tdyMrkr, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"circle", /*LANG*/"rectangle", /*LANG*/"filled"][v], + onchange: v => { + settings.tdyMrkr = v; + saveSettings(); + } + }, + /*LANG*/"Mrk.Color": { + value: settings.tdyMrkClr, + min: 0, max: 2, + format: v => [/*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], + onchange: v => { + settings.tdyMrkClr = v; + saveSettings(); + } + }, + /*LANG*/"Mrk.Size": { + value: settings.tdyMrkPxl, + min: 0, max: 10, + format: v => v+"px", + onchange: v => { + settings.tdyMrkPxl = v; + saveSettings(); + } + }, + /*LANG*/"< Cancel": () => restoreAndExitSettings() + }); + }; + + showMainMenu(); +}); From 6e054468abe36c60d876d128966fdce0a7f0aaa8 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 1 Feb 2022 23:44:59 +0100 Subject: [PATCH 2/2] 0.03-settings fixed, app 90% automated tested --- apps.json | 2 +- apps/timecal/timecal.app.js | 59 ++++-- apps/timecal/timecal.app.test.js | 347 +++++++++++++++++++++++++------ apps/timecal/timecal.settings.js | 4 +- 4 files changed, 325 insertions(+), 87 deletions(-) diff --git a/apps.json b/apps.json index f9c5b34fb..79bd0b046 100644 --- a/apps.json +++ b/apps.json @@ -4655,7 +4655,7 @@ "name": "TimeCal", "shortName":"TimeCal", "icon": "icon.png", - "version":"0.02", + "version":"0.03", "description": "TimeCal shows the Time along with a 3 week calendar", "tags": "clock", "readme":"README.md", diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 17daf127a..97cd596c8 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -19,14 +19,14 @@ class TimeCalClock{ const defaults = { shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week - wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today + wdStrt:0, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkPxl:3, //px - suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + suClr:1, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E //phColor:"#E00", //public holiday calBrdr:false @@ -41,7 +41,19 @@ class TimeCalClock{ this.centerX = Bangle.appRect.w/2; this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b - this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + + this.ABR_DAY=[]; + if (require("locale") && require("locale").dow) + for (let d=0; d<=6; d++) { + var refDay=new Date(); + refDay.setFullYear(1972); + refDay.setMonth(0); + refDay.setDate(2+d); + this.ABR_DAY.push(require("locale").dow(refDay)); + + } + else + this.ABR_DAY=["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -57,7 +69,10 @@ class TimeCalClock{ **/ draw(){ this.drawTime(); - } + + if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + this.drawDateAndCal(); + } /** * draw given or current time from date @@ -77,10 +92,7 @@ class TimeCalClock{ g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option - setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); - if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) - this.drawDateAndCal(); - this.TZOffset=d.getTimezoneOffset(); + setTimeout(this.draw.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); } /** @@ -90,11 +102,12 @@ class TimeCalClock{ drawDateAndCal(){ d=this.date ? this.date : new Date(); - if (this.tOutD) //abort exisiting - clearTimeout(this.tOutD); - + this.TZOffset=d.getTimezoneOffset(); this.drawDate(); this.drawCal(); + + if (this.tOutD) //abort exisiting + clearTimeout(this.tOutD); this.tOutD=setTimeout(this.drawDateAndCal.bind(this), 86400000-(d.getHours()*24*60*1000)-(d.getMinutes()*60*1000)-d.getSeconds()-d.getMilliseconds()); } @@ -182,13 +195,15 @@ class TimeCalClock{ g.setFontAlign(-1, -1); - const tdyDate=d.getDate(); - const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); - //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; + const dName=dNames[dIdx]; + if (dIdx==0) //sunday colorize txt + g.setColor(this.nrgb[this.settings().suClr]); + else + g.setColor(g.theme.fg); g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names if(dNo>0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -204,8 +219,9 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) - var rD=new Date(); + const tdyDate=d.getDate(); + const days=this.settings().wdStrt>=0 ? 7+((7+d.getDay()-this.settings().wdStrt)%7) : 10;//start day (week before=7 days + days in this week realtive to week start) or fixed 7+3 days + var rD=new Date(d.getTime()); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ @@ -215,7 +231,7 @@ class TimeCalClock{ switch(this.settings().tdyMrkr){ //0:none, 1:circle, 2:rectangle, 3:filled case 1: for(m=1; m<=this.settings().tdyMrkPxl&&mSu, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today + wdStrt:0, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkPxl:3, //px - suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + suClr:1, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E //phColor:"#E00", //public holiday calBrdr:false @@ -41,7 +41,19 @@ class TimeCalClock{ this.centerX = Bangle.appRect.w/2; this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b - this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + + this.ABR_DAY=[]; + if (require("locale") && require("locale").dow) + for (let d=0; d<=6; d++) { + var refDay=new Date(); + refDay.setFullYear(1972); + refDay.setMonth(0); + refDay.setDate(2+d); + this.ABR_DAY.push(require("locale").dow(refDay)); + + } + else + this.ABR_DAY=["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -57,7 +69,10 @@ class TimeCalClock{ **/ draw(){ this.drawTime(); - } + + if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + this.drawDateAndCal(); + } /** * draw given or current time from date @@ -77,10 +92,7 @@ class TimeCalClock{ g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option - setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); - if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) - this.drawDateAndCal(); - this.TZOffset=d.getTimezoneOffset(); + setTimeout(this.draw.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); } /** @@ -90,11 +102,12 @@ class TimeCalClock{ drawDateAndCal(){ d=this.date ? this.date : new Date(); - if (this.tOutD) //abort exisiting - clearTimeout(this.tOutD); - + this.TZOffset=d.getTimezoneOffset(); this.drawDate(); this.drawCal(); + + if (this.tOutD) //abort exisiting + clearTimeout(this.tOutD); this.tOutD=setTimeout(this.drawDateAndCal.bind(this), 86400000-(d.getHours()*24*60*1000)-(d.getMinutes()*60*1000)-d.getSeconds()-d.getMilliseconds()); } @@ -182,13 +195,15 @@ class TimeCalClock{ g.setFontAlign(-1, -1); - const tdyDate=d.getDate(); - const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); - //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; + const dName=dNames[dIdx]; + if (dIdx==0) //sunday colorize txt + g.setColor(this.nrgb[this.settings().suClr]); + else + g.setColor(g.theme.fg); g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names if(dNo>0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -204,8 +219,9 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) - var rD=new Date(); + const tdyDate=d.getDate(); + const days=this.settings().wdStrt>=0 ? 7+((7+d.getDay()-this.settings().wdStrt)%7) : 10;//start day (week before=7 days + days in this week realtive to week start) or fixed 7+3 days + var rD=new Date(d.getTime()); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ @@ -215,7 +231,7 @@ class TimeCalClock{ switch(this.settings().tdyMrkr){ //0:none, 1:circle, 2:rectangle, 3:filled case 1: for(m=1; m<=this.settings().tdyMrkPxl&&m","|TEST_SETTINGS|","..."], //TEST_SETTINGS will be replcaed with each current {setting: case} functionNames: ["required, ", "..."], functionParams: ["optional: ","|TEST_SETTINGS|","..."] - } + }; } constructor(data){ @@ -375,7 +390,7 @@ class TestSetting extends Test{ afterExpression: entry.afterExpression||true }; }); - this.constructorParams = data.constructorParams, + this.constructorParams = data.constructorParams; this.functionNames = data.functionNames; this.functionParams = data.functionParams; } @@ -440,14 +455,16 @@ class BangleTestRunner{ this._afterCase(); } this._afterTest(); + this._firstCase(); } + this._exit(); } /** * global prepare - before all test */ _init() { - console.log(new Date().getTime(),">>init"); + console.log(this._nowTime(), ">>init"); this.currentTestNum=-1; this.currentCaseNum=-1; } @@ -456,72 +473,69 @@ class BangleTestRunner{ * before each test */ _beforeTest() { - console.log(new Date(),">>test #" + this.currentTestNum); + console.log(this._nowTime(), ">>test #" + this.currentTestNum); } /** * befor each testcase */ _beforeCase() { - console.log(new Date(),">>case #" + this.currentTestNum + "." + this.currentCaseNum + "/" + (this.currentTest.cases.length-1)); - if (this.currentTest instanceof TestSetting) { - console.log( - this.currentTest.setting + "="+this.currentCase.value+"\n"+ - this.currentCase.beforeTxt ? "testcase: " + this.currentCase.beforeTxt : "" + console.log(this._nowTime(), ">>case #" + this.currentTestNum + "." + this.currentCaseNum + "/" + (this.currentTest.cases.length-1)); + if (this.currentTest instanceof TestSetting) + console.log(this.currentTest.setting+"="+this.currentCase.value+"\n" + +this.currentCase.beforeTxt ? "testcase:"+this.currentCase.beforeTxt : "" ); - } } /** * testcase runner */ _runCase() { - console.log(new Date(), ">>running..."); + console.log(this._nowTime(), ">>running..."); var returns = []; this.currentTest.functionNames.forEach((fName) => { var settings={}; settings[this.currentTest.setting] = this.currentCase.value; var cParams = this.currentTest.constructorParams||[]; - cParams = cParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + cParams = cParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v);//replace settings in call params var fParams = this.currentTest.functionParams||[]; - fParams = fParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + fParams = fParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v);//replace settings in call params - var creatorFunc = new Function("return new " + this.oClass + "(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9])"); //prepare spwan arguments[0],arguments[1] + var creatorFunc = new Function("console.log('Constructor params:', arguments); return new " + this.oClass + "(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9])"); //prepare spwan arguments[0],arguments[1] let instance = creatorFunc.call(this.oClass, cParams[0], cParams[1], cParams[2], cParams[3], cParams[4], cParams[5], cParams[6], cParams[7], cParams[8], cParams[9]); //spwan console.log(">>"+this.oClass+"["+fName+"]()"); + + console.log('Instance:', instance); + console.log('Function params:', fParams); returns.push(instance[fName](fParams[0], fParams[1], fParams[2], fParams[3], fParams[4], fParams[5], fParams[6], fParams[7], fParams[8], fParams[9])); //run method and store result - console.log("<<"+this.oClass+"["+fName+"]()"); g.dump(); + console.log("<<"+this.oClass+"["+fName+"]()"); }); - console.log(new Date(), "<<...running"); + console.log(this._nowTime(), "<<...running"); } /** * after each testcase */ _afterCase() { - if (this.currentTest instanceof TestSetting) { - if (this.currentCase.afterTxt.length>0) { - console.log( - "--EXPECTED: " + this.currentCase.afterTxt - ); - } - } - console.log(new Date(), "<0) + console.log("++EXPECTED:" + this.currentCase.afterTxt + "EXPECTED++"); + console.log(this._nowTime(), "<=-1 && (this.currentTestNum+1)=-1 && (this.currentCaseNum+1)