Add Four Twenty Clock app

pull/1152/head
The Dod 2021-12-21 01:01:10 +02:00
parent d9d5926416
commit 964fa27bfb
9 changed files with 699 additions and 0 deletions

View File

@ -5062,5 +5062,23 @@
{"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.app.js","url":"app.js"},
{"name":"ltherm.img","url":"icon.js","evaluate":true} {"name":"ltherm.img","url":"icon.js","evaluate":true}
] ]
},
{
"id": "ftclock",
"name": "Four Twenty Clock",
"version": "0.01",
"description": "A clock that tells when and where it's going to be 4:20 next",
"icon": "app.png",
"screenshots": [{"url":"screenshot.png"}],
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"storage": [
{"name":"ftclock.app.js","url":"app.js"},
{"name":"fourTwenty","url":"fourTwenty.js"},
{"name":"fourTwentyTz","url":"fourTwentyTz.js"},
{"name":"ftclock.img","url":"app-icon.js","evaluate":true}
]
} }
] ]

1
apps/ftclock/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: first release

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

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwghC/AH4A/AH4A/AAMHu4ACuwHBs4HDsEGBIQLCsADBgwPDCAQGEuwXFBwI0GEAMHuAGCCoMHC4pMHEAIXEAgIGEBwI9BC4wSCC8IVCMAwIBs4XKUQJfITQgXCDwp8EHAqaECoLFEu4cDBIggBs6uFZozuGBAVmC4g+FMgZQEZQ5vGC4iRIC5IrDN4h5EC5J3BCoIKGgyaEC44VBC46yEDgoeDgxqLC5SCMAgoTFY47GFC4xFBdwwPBD4oWFAH4A/AH4A/AH4AjA=="))

52
apps/ftclock/app.js Normal file
View File

@ -0,0 +1,52 @@
let getNextFourTwenty = require("fourTwenty").getNextFourTwenty;
require("FontTeletext10x18Ascii").add(Graphics);
let leaf_img = "\x17\x18\x81\x00\x00\x10\x00\x00 \x00\x00@\x00\x01\xc0\x00\x03\x80\x00\x0f\x80\x00\x1f\x00\x00>\x00\x00|\x00\xc0\xf8\x19\xe1\xf0\xf1\xe3\xe3\xc3\xf7\xdf\x83\xff\xfe\x03\xff\xf8\x03\xff\xe0\x03\xff\x80\x03\xfe\x00\x7f\xff\xc0\xff\xff\xc0\x06\xe0\x00\x18\xc0\x00 \x80\x00\x00\x00";
// timeout used to update every minute
let drawTimeout;
// schedule a draw for the next minute
function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
draw();
}, 60000 - (Date.now() % 60000));
}
function draw() {
g.reset();
g.setBgColor("#ffffff");
let date = new Date();
let timeStr = require("locale").time(date,1);
let next420 = getNextFourTwenty();
g.clearRect(0,26,g.getWidth(),g.getHeight());
g.setColor("#00ff00").setFontAlign(0,-1).setFont("Teletext10x18Ascii",2);
g.drawString(next420.minutes? timeStr: `\0${leaf_img}${timeStr}\0${leaf_img}`, g.getWidth()/2, 28);
g.setColor("#000000");
g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii");
g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60);
// queue draw in one minute
queueDraw();
}
// Clear the screen once, at startup
g.clear();
// Load widgets
Bangle.loadWidgets();
Bangle.drawWidgets();
// draw immediately at first, queue update
draw();
// Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{
if (on) {
draw(); // draw immediately, queue redraw
} else { // stop draw timer
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
}
});
// Show launcher when middle button pressed
Bangle.setUI("clock");

BIN
apps/ftclock/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,45 @@
let timezones = require("fourTwentyTz").timezones;
function get420offset() {
let current_time = Math.floor((Date.now()%(24*3600*1000))/60000);
let current_min = current_time%60;
if (current_min>20 && current_min<25) {
current_time -= current_min-20; // 5 minutes grace period
}
let offset = 16*60+20-current_time;
if (offset<0) {
offset += 24*60;
}
return offset;
}
function makeFourTwentyText(minutes, places) {
//let plural = minutes==1? "": "s";
//let msgprefix = minutes? `${minutes} minute${plural} to`: "It is now";
let msgprefix = minutes? `${minutes}m to`: "It is now";
let msgsuffix = places.length>1? ", and other fine places": "";
let msgplace = places[Math.floor(Math.random()*places.length)];
return `${msgprefix} 4:20 at ${msgplace}${msgsuffix}.`;
}
function getNextFourTwenty() {
let offs = get420offset();
for (let i=0; i<timezones.length; i++) {
if (timezones[i][0]<=offs) {
let minutes = offs-timezones[i][0];
let places = timezones[i][1];
return {
minutes: minutes,
places: places,
text: makeFourTwentyText(minutes, places)
};
}
}
return {
minutes: 666,
places: ["Snafu (Yes. It's a bug)"],
text: "Snafu (Yes. It's a bug)"
};
}
exports.getNextFourTwenty = getNextFourTwenty;

View File

@ -0,0 +1,536 @@
// Generated by mk420tz.py - see https://github.com/thedod/BangleApps/420clock
// (version: Sat Dec 18 10:17:32 2021)
// Data source: https://timezonedb.com/files/timezonedb.csv.zip
// (version: Sat Oct 16 01:48:14 2021)
exports.timezones = [
[
1380,
[
"Azores, Portugal",
"Cape Verde, Cabo Verde",
"Scoresbysund, Greenland"
]
],
[
1320,
[
"Noronha, Brazil",
"South Georgia, South Georgia and the South Sandwich Islands"
]
],
[
1260,
[
"Araguaina, Brazil",
"Asuncion, Paraguay",
"Bahia, Brazil",
"Belem, Brazil",
"Buenos Aires, Argentina",
"Catamarca, Argentina",
"Cayenne, French Guiana",
"Cordoba, Argentina",
"Fortaleza, Brazil",
"Jujuy, Argentina",
"La Rioja, Argentina",
"Maceio, Brazil",
"Mendoza, Argentina",
"Miquelon, Saint Pierre and Miquelon",
"Montevideo, Uruguay",
"Nuuk, Greenland",
"Palmer, Antarctica",
"Paramaribo, Suriname",
"Punta Arenas, Chile",
"Recife, Brazil",
"Rio Gallegos, Argentina",
"Rothera, Antarctica",
"Salta, Argentina",
"San Juan, Argentina",
"San Luis, Argentina",
"Santarem, Brazil",
"Santiago, Chile",
"Sao Paulo, Brazil",
"Stanley, Falkland Islands (Malvinas)",
"Tucuman, Argentina",
"Ushuaia, Argentina"
]
],
[
1200,
[
"Anguilla, AI",
"Antigua, Antigua and Barbuda",
"Aruba, AW",
"Barbados, BB",
"Bermuda, BM",
"Blanc-Sablon, Canada",
"Boa Vista, Brazil",
"Campo Grande, Brazil",
"Caracas, Venezuela (Bolivarian Republic of)",
"Cuiaba, Brazil",
"Curacao, Cura\u00e7ao",
"Dominica, DM",
"Glace Bay, Canada",
"Goose Bay, Canada",
"Grenada, GD",
"Guadeloupe, GP",
"Guyana, GY",
"Halifax, Canada",
"Kralendijk, Bonaire, Sint Eustatius and Saba",
"La Paz, Bolivia (Plurinational State of)",
"Lower Princes, Sint Maarten (Dutch part)",
"Manaus, Brazil",
"Marigot, Saint Martin (French part)",
"Martinique, MQ",
"Moncton, Canada",
"Montserrat, MS",
"Port of Spain, Trinidad and Tobago",
"Porto Velho, Brazil",
"Puerto Rico, PR",
"Santo Domingo, Dominican Republic",
"St Barthelemy, Saint Barth\u00e9lemy",
"St Kitts, Saint Kitts and Nevis",
"St Lucia, Saint Lucia",
"St Thomas, Virgin Islands (U.S.)",
"St Vincent, Saint Vincent and the Grenadines",
"Thule, Greenland",
"Tortola, Virgin Islands (British)"
]
],
[
1140,
[
"Atikokan, Canada",
"Bogota, Colombia",
"Cancun, Mexico",
"Cayman, Cayman Islands",
"Detroit, United States of America",
"Easter, Chile",
"Eirunepe, Brazil",
"Grand Turk, Turks and Caicos Islands",
"Guayaquil, Ecuador",
"Havana, Cuba",
"Indianapolis, Indiana",
"Iqaluit, Canada",
"Jamaica, JM",
"Lima, Peru",
"Louisville, Kentucky",
"Marengo, Indiana",
"Monticello, Kentucky",
"Nassau, Bahamas",
"New York, United States of America",
"Nipigon, Canada",
"Panama, PA",
"Pangnirtung, Canada",
"Petersburg, Indiana",
"Port-au-Prince, Haiti",
"Rio Branco, Brazil",
"Thunder Bay, Canada",
"Toronto, Canada",
"Vevay, Indiana",
"Vincennes, Indiana",
"Winamac, Indiana"
]
],
[
1080,
[
"Bahia Banderas, Mexico",
"Belize, BZ",
"Beulah, North Dakota",
"Center, North Dakota",
"Chicago, United States of America",
"Costa Rica, CR",
"El Salvador, SV",
"Galapagos, Ecuador",
"Guatemala, GT",
"Knox, Indiana",
"Managua, Nicaragua",
"Matamoros, Mexico",
"Menominee, United States of America",
"Merida, Mexico",
"Mexico City, Mexico",
"Monterrey, Mexico",
"New Salem, North Dakota",
"Rainy River, Canada",
"Rankin Inlet, Canada",
"Regina, Canada",
"Resolute, Canada",
"Swift Current, Canada",
"Tegucigalpa, Honduras",
"Tell City, Indiana",
"Winnipeg, Canada"
]
],
[
1020,
[
"Boise, United States of America",
"Cambridge Bay, Canada",
"Chihuahua, Mexico",
"Creston, Canada",
"Dawson Creek, Canada",
"Dawson, Canada",
"Denver, United States of America",
"Edmonton, Canada",
"Fort Nelson, Canada",
"Hermosillo, Mexico",
"Inuvik, Canada",
"Mazatlan, Mexico",
"Ojinaga, Mexico",
"Phoenix, United States of America",
"Whitehorse, Canada",
"Yellowknife, Canada"
]
],
[
960,
[
"Los Angeles, United States of America",
"Pitcairn, PN",
"Tijuana, Mexico",
"Vancouver, Canada"
]
],
[
900,
[
"Anchorage, United States of America",
"Gambier, French Polynesia",
"Juneau, United States of America",
"Metlakatla, United States of America",
"Nome, United States of America",
"Sitka, United States of America",
"Yakutat, United States of America"
]
],
[
840,
[
"Adak, United States of America",
"Honolulu, United States of America",
"Kiritimati, Kiribati",
"Rarotonga, Cook Islands",
"Tahiti, French Polynesia"
]
],
[
780,
[
"Apia, Samoa",
"Auckland, New Zealand",
"Fakaofo, Tokelau",
"Kanton, Kiribati",
"McMurdo, Antarctica",
"Midway, United States Minor Outlying Islands",
"Niue, NU",
"Pago Pago, American Samoa",
"Tongatapu, Tonga"
]
],
[
720,
[
"Anadyr, Russian Federation",
"Fiji, FJ",
"Funafuti, Tuvalu",
"Kamchatka, Russian Federation",
"Kwajalein, Marshall Islands",
"Majuro, Marshall Islands",
"Nauru, NR",
"Norfolk, Norfolk Island",
"Tarawa, Kiribati",
"Wake, United States Minor Outlying Islands",
"Wallis, Wallis and Futuna"
]
],
[
660,
[
"Bougainville, Papua New Guinea",
"Casey, Antarctica",
"Efate, Vanuatu",
"Guadalcanal, Solomon Islands",
"Hobart, Australia",
"Kosrae, Micronesia (Federated States of)",
"Lord Howe, Australia",
"Macquarie, Australia",
"Magadan, Russian Federation",
"Melbourne, Australia",
"Noumea, New Caledonia",
"Pohnpei, Micronesia (Federated States of)",
"Sakhalin, Russian Federation",
"Srednekolymsk, Russian Federation",
"Sydney, Australia"
]
],
[
600,
[
"Brisbane, Australia",
"Chuuk, Micronesia (Federated States of)",
"DumontDUrville, Antarctica",
"Guam, GU",
"Lindeman, Australia",
"Port Moresby, Papua New Guinea",
"Saipan, Northern Mariana Islands",
"Ust-Nera, Russian Federation",
"Vladivostok, Russian Federation"
]
],
[
540,
[
"Chita, Russian Federation",
"Dili, Timor-Leste",
"Jayapura, Indonesia",
"Khandyga, Russian Federation",
"Palau, PW",
"Pyongyang, Korea (Democratic People's Republic of)",
"Seoul, Korea, Republic of",
"Tokyo, Japan",
"Yakutsk, Russian Federation"
]
],
[
480,
[
"Brunei, Brunei Darussalam",
"Choibalsan, Mongolia",
"Hong Kong, HK",
"Irkutsk, Russian Federation",
"Kuala Lumpur, Malaysia",
"Kuching, Malaysia",
"Macau, Macao",
"Makassar, Indonesia",
"Manila, Philippines",
"Perth, Australia",
"Shanghai, China",
"Singapore, SG",
"Taipei, Taiwan, Province of China",
"Ulaanbaatar, Mongolia"
]
],
[
420,
[
"Bangkok, Thailand",
"Barnaul, Russian Federation",
"Christmas, Christmas Island",
"Davis, Antarctica",
"Ho Chi Minh, Viet Nam",
"Hovd, Mongolia",
"Jakarta, Indonesia",
"Krasnoyarsk, Russian Federation",
"Novokuznetsk, Russian Federation",
"Novosibirsk, Russian Federation",
"Phnom Penh, Cambodia",
"Pontianak, Indonesia",
"Tomsk, Russian Federation",
"Vientiane, Lao People's Democratic Republic"
]
],
[
360,
[
"Almaty, Kazakhstan",
"Bishkek, Kyrgyzstan",
"Chagos, British Indian Ocean Territory",
"Dhaka, Bangladesh",
"Omsk, Russian Federation",
"Qostanay, Kazakhstan",
"Thimphu, Bhutan",
"Urumqi, China",
"Vostok, Antarctica"
]
],
[
300,
[
"Aqtau, Kazakhstan",
"Aqtobe, Kazakhstan",
"Ashgabat, Turkmenistan",
"Atyrau, Kazakhstan",
"Dushanbe, Tajikistan",
"Karachi, Pakistan",
"Kerguelen, French Southern Territories",
"Maldives, MV",
"Mawson, Antarctica",
"Oral, Kazakhstan",
"Qyzylorda, Kazakhstan",
"Samarkand, Uzbekistan",
"Tashkent, Uzbekistan",
"Yekaterinburg, Russian Federation"
]
],
[
240,
[
"Astrakhan, Russian Federation",
"Baku, Azerbaijan",
"Dubai, United Arab Emirates",
"Mahe, Seychelles",
"Mauritius, MU",
"Muscat, Oman",
"Reunion, R\u00e9union",
"Samara, Russian Federation",
"Saratov, Russian Federation",
"Tbilisi, Georgia",
"Ulyanovsk, Russian Federation",
"Yerevan, Armenia"
]
],
[
180,
[
"Addis Ababa, Ethiopia",
"Aden, Yemen",
"Antananarivo, Madagascar",
"Asmara, Eritrea",
"Baghdad, Iraq",
"Bahrain, BH",
"Comoro, Comoros",
"Dar es Salaam, Tanzania, United Republic of",
"Djibouti, DJ",
"Istanbul, Turkey",
"Kampala, Uganda",
"Kirov, Russian Federation",
"Kuwait, KW",
"Mayotte, YT",
"Minsk, Belarus",
"Mogadishu, Somalia",
"Moscow, Russian Federation",
"Nairobi, Kenya",
"Qatar, QA",
"Riyadh, Saudi Arabia",
"Simferopol, Ukraine",
"Syowa, Antarctica",
"Volgograd, Russian Federation"
]
],
[
120,
[
"Amman, Jordan",
"Athens, Greece",
"Beirut, Lebanon",
"Blantyre, Malawi",
"Bucharest, Romania",
"Bujumbura, Burundi",
"Cairo, Egypt",
"Chisinau, Moldova, Republic of",
"Damascus, Syrian Arab Republic",
"Famagusta, Cyprus",
"Gaborone, Botswana",
"Gaza, Palestine, State of",
"Harare, Zimbabwe",
"Hebron, Palestine, State of",
"Helsinki, Finland",
"Jerusalem, Israel",
"Johannesburg, South Africa",
"Juba, South Sudan",
"Kaliningrad, Russian Federation",
"Khartoum, Sudan",
"Kiev, Ukraine",
"Kigali, Rwanda",
"Lubumbashi, Congo, Democratic Republic of the",
"Lusaka, Zambia",
"Maputo, Mozambique",
"Mariehamn, \u00c5land Islands",
"Maseru, Lesotho",
"Mbabane, Eswatini",
"Nicosia, Cyprus",
"Riga, Latvia",
"Sofia, Bulgaria",
"Tallinn, Estonia",
"Tripoli, Libya",
"Uzhgorod, Ukraine",
"Vilnius, Lithuania",
"Windhoek, Namibia",
"Zaporozhye, Ukraine"
]
],
[
60,
[
"Algiers, Algeria",
"Amsterdam, Netherlands",
"Andorra, AD",
"Bangui, Central African Republic",
"Belgrade, Serbia",
"Berlin, Germany",
"Bratislava, Slovakia",
"Brazzaville, Congo",
"Brussels, Belgium",
"Budapest, Hungary",
"Busingen, Germany",
"Casablanca, Morocco",
"Ceuta, Spain",
"Copenhagen, Denmark",
"Douala, Cameroon",
"El Aaiun, Western Sahara",
"Gibraltar, GI",
"Kinshasa, Congo, Democratic Republic of the",
"Lagos, Nigeria",
"Libreville, Gabon",
"Ljubljana, Slovenia",
"Longyearbyen, Svalbard and Jan Mayen",
"Luanda, Angola",
"Luxembourg, LU",
"Madrid, Spain",
"Malabo, Equatorial Guinea",
"Malta, MT",
"Monaco, MC",
"Ndjamena, Chad",
"Niamey, Niger",
"Oslo, Norway",
"Paris, France",
"Podgorica, Montenegro",
"Porto-Novo, Benin",
"Prague, Czechia",
"Rome, Italy",
"San Marino, SM",
"Sarajevo, Bosnia and Herzegovina",
"Skopje, North Macedonia",
"Stockholm, Sweden",
"Tirane, Albania",
"Tunis, Tunisia",
"Vaduz, Liechtenstein",
"Vatican, Holy See",
"Vienna, Austria",
"Warsaw, Poland",
"Zagreb, Croatia",
"Zurich, Switzerland"
]
],
[
0,
[
"Abidjan, C\u00f4te d'Ivoire",
"Accra, Ghana",
"Bamako, Mali",
"Banjul, Gambia",
"Bissau, Guinea-Bissau",
"Canary, Spain",
"Conakry, Guinea",
"Dakar, Senegal",
"Danmarkshavn, Greenland",
"Dublin, Ireland",
"Faroe, Faroe Islands",
"Freetown, Sierra Leone",
"Guernsey, GG",
"Isle of Man, IM",
"Jersey, JE",
"Lisbon, Portugal",
"Lome, Togo",
"London, United Kingdom of Great Britain and Northern Ireland",
"Madeira, Portugal",
"Monrovia, Liberia",
"Nouakchott, Mauritania",
"Ouagadougou, Burkina Faso",
"Reykjavik, Iceland",
"Sao Tome, Sao Tome and Principe",
"St Helena, Saint Helena, Ascension and Tristan da Cunha",
"Troll, Antarctica"
]
]
];

View File

@ -0,0 +1,46 @@
# Generates tz.js[on] from time zone csv files
# get latest files from https://timezonedb.com/download
import csv,json,time,os,math
countries = {}
for r in csv.reader(open("country.csv")):
countries[r[0]] = r[1]
zones = {}
for r in csv.reader(open("zone.csv")):
parts = r[2].replace('_',' ').split('/')
city = parts[-1]
if len(parts)>2: # e.g. America/North_Dakota/New_Salem
country = parts[1] # e.g. North Dakota
else: # e.g. America/Denver
country = countries[r[1]] # e.g. United States
if country==city: # Avoid awkward searches like "Anguilla, Anguilla"
country = r[1] # Use code instead
zones[int(r[0])] = {"name":', '.join((city,country))}
now = int(time.time())
for r in csv.reader(open("timezone.csv")):
code = int(r[0])
if code not in zones:
continue
starttime = int(r[2] or "0") # Bugger. They're feeding us blanks for UTC now
offs = int(r[3])
if offs < 0:
offs += 60*60*24
d = zones[code]
if starttime<now and ("starttime" not in d or d["starttime"]<starttime):
d["starttime"] = starttime
d["offs"] = math.floor(offs/60)
offsdict = {}
for k in zones:
d = zones[k]
if d["offs"]%60: # One a dem funky timezone. Ignore.
continue
offsdict[d["offs"]] = offsdict.get(d["offs"],[])+[d["name"]]
res = sorted([[k,sorted(offsdict[k])] for k in offsdict],key=lambda x:-x[0])
js = open("tz.js","w")
js.write("// Generated by mk420tz.py - see https://github.com/thedod/BangleApps/420clock\n")
js.write("// (version: {0})\n".format(time.ctime(time.time())))
js.write("// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n")
js.write("// (version: {0})\n".format(time.ctime(os.stat("zone.csv").st_mtime)))
js.write("exports.timezones = ")
json.dump(res,js,indent=1)
js.write(";\n")
js.close()

BIN
apps/ftclock/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB