Style: Apply deno lint and deno fmt across codebase
This commit is contained in:
@@ -5,65 +5,73 @@
|
|||||||
### Fortune Events and Descriptions
|
### Fortune Events and Descriptions
|
||||||
|
|
||||||
1. Fortune Type:
|
1. Fortune Type:
|
||||||
- Good fortunes
|
- Good fortunes
|
||||||
- These should be added under the `"goodFortunes"` section in the JSON file.
|
- These should be added under the `"goodFortunes"` section in the JSON
|
||||||
- Represent positive or beneficial events.
|
file.
|
||||||
- Bad fortunes
|
- Represent positive or beneficial events.
|
||||||
- These should be added under the `"badFortunes"` section in the JSON file.
|
- Bad fortunes
|
||||||
- Represent challenging or less favorable events.
|
- These should be added under the `"badFortunes"` section in the JSON file.
|
||||||
|
- Represent challenging or less favorable events.
|
||||||
|
|
||||||
2. Unique Content:
|
2. Unique Content:
|
||||||
- Ensure your event and descriptions are original and not repeated in existing entries.
|
- Ensure your event and descriptions are original and not repeated in
|
||||||
|
existing entries.
|
||||||
|
|
||||||
3. Event Structure - Each fortune event should be added as new JSON object with the following structure:
|
3. Event Structure - Each fortune event should be added as new JSON object with
|
||||||
```json
|
the following structure:
|
||||||
{
|
```json
|
||||||
"event": "Event Name",
|
{
|
||||||
"description": [
|
"event": "Event Name",
|
||||||
"Description 1",
|
"description": [
|
||||||
"Description 2",
|
"Description 1",
|
||||||
"Description 3",
|
"Description 2",
|
||||||
"Description 4"
|
"Description 3",
|
||||||
]
|
"Description 4"
|
||||||
}
|
]
|
||||||
```
|
}
|
||||||
|
```
|
||||||
|
|
||||||
2. Maintain a positive and encouraging tone.
|
4. Maintain a positive and encouraging tone.
|
||||||
|
|
||||||
### Special Events
|
### Special Events
|
||||||
|
|
||||||
Special events require a more detailed structure.
|
Special events require a more detailed structure.
|
||||||
|
|
||||||
1. Structure:
|
1. Structure:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"event": "Event Name",
|
"event": "Event Name",
|
||||||
"year": "Year",
|
"year": "Year",
|
||||||
"month": "Month",
|
"month": "Month",
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"status_index": "Status Index",
|
"status_index": "Status Index",
|
||||||
"goodFortunes": {
|
"goodFortunes": {
|
||||||
"l_1_event": "Good Fortune 1",
|
"l_1_event": "Good Fortune 1",
|
||||||
"l_1_desc": "Description 1",
|
"l_1_desc": "Description 1",
|
||||||
"l_2_event": "Good Fortune 2",
|
"l_2_event": "Good Fortune 2",
|
||||||
"l_2_desc": "Description 2"
|
"l_2_desc": "Description 2"
|
||||||
},
|
},
|
||||||
"badFortunes": {
|
"badFortunes": {
|
||||||
"r_1_event": "Bad Fortune 1",
|
"r_1_event": "Bad Fortune 1",
|
||||||
"r_1_desc": "Description 1",
|
"r_1_desc": "Description 1",
|
||||||
"r_2_event": "Bad Fortune 2",
|
"r_2_event": "Bad Fortune 2",
|
||||||
"r_2_desc": "Description 2"
|
"r_2_desc": "Description 2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Empty Fields: If there are no fortunes to add, leave the corresponding fields as empty strings (`""`).
|
2. Empty Fields: If there are no fortunes to add, leave the corresponding fields
|
||||||
|
as empty strings (`""`).
|
||||||
|
|
||||||
## Quote Generator
|
## Quote Generator
|
||||||
|
|
||||||
### Quotes
|
### Quotes
|
||||||
|
|
||||||
- Exclude content that includes any unlawful, defamatory, abusive, threatening or obscene text.
|
- Exclude content that includes any unlawful, defamatory, abusive, threatening
|
||||||
- Verify that your contribution meets JSON standards, specifically avoiding trailing comma at the end of a list.
|
or obscene text.
|
||||||
|
- Verify that your contribution meets JSON standards, specifically avoiding
|
||||||
|
trailing comma at the end of a list.
|
||||||
- Ensure that the added quotes are not duplicates of any existing ones.
|
- Ensure that the added quotes are not duplicates of any existing ones.
|
||||||
- Remember to name your pull request properly. For example, if you are adding new quotes, your pull request should be named `Impr(quotes): Add {count} new quotes`.
|
- Remember to name your pull request properly. For example, if you are adding
|
||||||
|
new quotes, your pull request should be named
|
||||||
|
`Impr(quotes): Add {count} new quotes`.
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
# List of Generators
|
# List of Generators
|
||||||
|
|
||||||
### [Quote_Generator](https://lifeadventurer.github.io/generators/quote_generator)
|
### [Quote_Generator](https://lifeadventurer.github.io/generators/quote_generator)
|
||||||
|
|
||||||
- Generate your daily quote with a button.
|
- Generate your daily quote with a button.
|
||||||
- Background with matrix animation when generating.
|
- Background with matrix animation when generating.
|
||||||
- If you want to contribute quotes, check the quote section in [CONTRIBUTING.md](./CONTRIBUTING.md#quote)
|
- If you want to contribute quotes, check the quote section in
|
||||||
|
[CONTRIBUTING.md](./CONTRIBUTING.md#quote)
|
||||||
|
|
||||||
### [Daily_Fortune_Generator](https://lifeadventurer.github.io/generators/fortune_generator)
|
### [Daily_Fortune_Generator](https://lifeadventurer.github.io/generators/fortune_generator)
|
||||||
|
|
||||||
- Generate your daily fortune with a generate button.
|
- Generate your daily fortune with a generate button.
|
||||||
- Background with matrix animation when generating.
|
- Background with matrix animation when generating.
|
||||||
- Testing some features for an online judge.
|
- Testing some features for an online judge.
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -2,16 +2,19 @@
|
|||||||
|
|
||||||
## Generators Gallery
|
## Generators Gallery
|
||||||
|
|
||||||
Visit the [Generators Gallery](https://lifeadventurer.github.io/generators) to explore a collection of generators, each accompanied by a concise description, and with links to generators.
|
Visit the [Generators Gallery](https://lifeadventurer.github.io/generators) to
|
||||||
|
explore a collection of generators, each accompanied by a concise description,
|
||||||
|
and with links to generators.
|
||||||
|
|
||||||
## List of Generators
|
## List of Generators
|
||||||
|
|
||||||
| Generators | Brief Description |
|
| Generators | Brief Description |
|
||||||
|--------------------------------------------------|---------------------------------------------------------------|
|
| ------------------------------------------------ | ------------------------------------------------------------- |
|
||||||
| **[Quote Generator][Quote Generator]** | Generate inspiring and thought-provoking quotes effortlessly. |
|
| **[Quote Generator][Quote Generator]** | Generate inspiring and thought-provoking quotes effortlessly. |
|
||||||
| **[Daily Fortune Generator][Fortune Generator]** | Get your daily fortune with just a click. |
|
| **[Daily Fortune Generator][Fortune Generator]** | Get your daily fortune with just a click. |
|
||||||
|
|
||||||
For more in-depth information about each generator, refer to [LIST_OF_GENERATORS.md](./LIST_OF_GENERATORS.md)
|
For more in-depth information about each generator, refer to
|
||||||
|
[LIST_OF_GENERATORS.md](./LIST_OF_GENERATORS.md)
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
@@ -22,4 +25,5 @@ Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md)
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the GNU General Public License v3.0 (GPL-3.0). See the [LICENSE](./LICENSE) file for more details.
|
This project is licensed under the GNU General Public License v3.0 (GPL-3.0).
|
||||||
|
See the [LICENSE](./LICENSE) file for more details.
|
||||||
|
|||||||
472
dev/main.js
472
dev/main.js
@@ -1,165 +1,165 @@
|
|||||||
const fs = require('fs')
|
const fs = require("fs");
|
||||||
|
|
||||||
const goodFortunes = [
|
const goodFortunes = [
|
||||||
{
|
{
|
||||||
"event": "睡覺",
|
"event": "睡覺",
|
||||||
"description": "品質良好,精神煥發"
|
"description": "品質良好,精神煥發",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "做家務",
|
"event": "做家務",
|
||||||
"description": "整潔使人心情愉悅"
|
"description": "整潔使人心情愉悅",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "冥想",
|
"event": "冥想",
|
||||||
"description": "平靜心靈,緩解焦慮"
|
"description": "平靜心靈,緩解焦慮",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "攝影",
|
"event": "攝影",
|
||||||
"description": "捕捉到美好瞬間"
|
"description": "捕捉到美好瞬間",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "喝咖啡",
|
"event": "喝咖啡",
|
||||||
"description": "精力充沛燃燒脂肪"
|
"description": "精力充沛燃燒脂肪",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "朋友聚會",
|
"event": "朋友聚會",
|
||||||
"description": "充滿歡笑和美好回憶"
|
"description": "充滿歡笑和美好回憶",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "體育鍛鍊",
|
"event": "體育鍛鍊",
|
||||||
"description": "能量滿滿,效果顯著"
|
"description": "能量滿滿,效果顯著",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "出遊" ,
|
"event": "出遊",
|
||||||
"description": "好天氣,好心情"
|
"description": "好天氣,好心情",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "吃大餐",
|
"event": "吃大餐",
|
||||||
"description": "聯絡感情"
|
"description": "聯絡感情",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "逛書店",
|
"event": "逛書店",
|
||||||
"description": "新書上架,打折推銷"
|
"description": "新書上架,打折推銷",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "學新技能",
|
"event": "學新技能",
|
||||||
"description": "快速上手"
|
"description": "快速上手",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "唱歌",
|
"event": "唱歌",
|
||||||
"description": "被星探發掘"
|
"description": "被星探發掘",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "上課",
|
"event": "上課",
|
||||||
"description": "整天不累,100% 消化"
|
"description": "整天不累,100% 消化",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "洗澡",
|
"event": "洗澡",
|
||||||
"description": "重獲能量"
|
"description": "重獲能量",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "請教問題",
|
"event": "請教問題",
|
||||||
"description": "問題皆獲高人指點"
|
"description": "問題皆獲高人指點",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "網購",
|
"event": "網購",
|
||||||
"description": "心儀商品皆促銷"
|
"description": "心儀商品皆促銷",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "放假",
|
"event": "放假",
|
||||||
"description": "休息充電,明日再戰"
|
"description": "休息充電,明日再戰",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "早睡",
|
"event": "早睡",
|
||||||
"description": "好夢連連"
|
"description": "好夢連連",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "早起",
|
"event": "早起",
|
||||||
"description": "朝氣蓬勃,神采飛揚"
|
"description": "朝氣蓬勃,神采飛揚",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "發文章",
|
"event": "發文章",
|
||||||
"description": "瀏覽數暴增"
|
"description": "瀏覽數暴增",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "點外賣",
|
"event": "點外賣",
|
||||||
"description": "準時到達,新鮮好吃"
|
"description": "準時到達,新鮮好吃",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "做善事",
|
"event": "做善事",
|
||||||
"description": "積善成福"
|
"description": "積善成福",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "散步",
|
"event": "散步",
|
||||||
"description": "空氣良好,放鬆身心"
|
"description": "空氣良好,放鬆身心",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const badFortunes = [
|
const badFortunes = [
|
||||||
{
|
{
|
||||||
"event": "體育鍛鍊",
|
"event": "體育鍛鍊",
|
||||||
"description": "不慎受傷"
|
"description": "不慎受傷",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "攝影",
|
"event": "攝影",
|
||||||
"description": "照片全消失"
|
"description": "照片全消失",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "出遊",
|
"event": "出遊",
|
||||||
"description": "天氣不晴朗"
|
"description": "天氣不晴朗",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "吃大餐",
|
"event": "吃大餐",
|
||||||
"description": "被要求請客"
|
"description": "被要求請客",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "學新技能",
|
"event": "學新技能",
|
||||||
"description": "屢試不爽,始終不懂"
|
"description": "屢試不爽,始終不懂",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "唱歌",
|
"event": "唱歌",
|
||||||
"description": "嗓子發炎"
|
"description": "嗓子發炎",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "洗澡",
|
"event": "洗澡",
|
||||||
"description": "水溫不穩"
|
"description": "水溫不穩",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "請教問題",
|
"event": "請教問題",
|
||||||
"description": "疑難雜症,均無解答"
|
"description": "疑難雜症,均無解答",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "網購",
|
"event": "網購",
|
||||||
"description": "錯過促銷"
|
"description": "錯過促銷",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "放假",
|
"event": "放假",
|
||||||
"description": "隔日工作量倍增"
|
"description": "隔日工作量倍增",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "晚睡",
|
"event": "晚睡",
|
||||||
"description": "失眠,明日精神渙散"
|
"description": "失眠,明日精神渙散",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "晚起",
|
"event": "晚起",
|
||||||
"description": "整天都不順"
|
"description": "整天都不順",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "發文章",
|
"event": "發文章",
|
||||||
"description": "搜索枯腸,不知所云"
|
"description": "搜索枯腸,不知所云",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "點外賣",
|
"event": "點外賣",
|
||||||
"description": "路況壅塞,餐點冷掉"
|
"description": "路況壅塞,餐點冷掉",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "喝咖啡",
|
"event": "喝咖啡",
|
||||||
"description": "晚上失眠"
|
"description": "晚上失眠",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"event": "散步",
|
"event": "散步",
|
||||||
"description": "被害蟲咬傷"
|
"description": "被害蟲咬傷",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const badLen = badFortunes.length;
|
const badLen = badFortunes.length;
|
||||||
@@ -172,106 +172,118 @@ let day = 0;
|
|||||||
let run_cnt = 0;
|
let run_cnt = 0;
|
||||||
|
|
||||||
while (run_cnt != 2000) {
|
while (run_cnt != 2000) {
|
||||||
let n1 = parseInt(Math.random() * 255 + 1);
|
let n1 = parseInt(Math.random() * 255 + 1);
|
||||||
let n2 = parseInt(Math.random() * 255 + 1);
|
let n2 = parseInt(Math.random() * 255 + 1);
|
||||||
let n3 = parseInt(Math.random() * 255 + 1);
|
let n3 = parseInt(Math.random() * 255 + 1);
|
||||||
let n4 = parseInt(Math.random() * 255 + 1);
|
let n4 = parseInt(Math.random() * 255 + 1);
|
||||||
|
|
||||||
if (!check_ip_valid(n1, n2, n3, n4)) continue;
|
if (!check_ip_valid(n1, n2, n3, n4)) continue;
|
||||||
|
|
||||||
let index = `${n1}.${n2}.${n3}.${n4}`;
|
let index = `${n1}.${n2}.${n3}.${n4}`;
|
||||||
buckets[index] = [0, 0, 0, 0];
|
buckets[index] = [0, 0, 0, 0];
|
||||||
for (let i = 1; i <= 12; i++) {
|
for (let i = 1; i <= 12; i++) {
|
||||||
for (let j = 1; j <= dates[i - 1]; j++) {
|
for (let j = 1; j <= dates[i - 1]; j++) {
|
||||||
day %= 7;
|
day %= 7;
|
||||||
run(2023, i, j, day, [n1, n2, n3, n4]);
|
run(2023, i, j, day, [n1, n2, n3, n4]);
|
||||||
day++;
|
day++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
run_cnt++;
|
run_cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFile('./res.txt', JSON.stringify(buckets), err => {
|
fs.writeFile("./res.txt", JSON.stringify(buckets), (err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
function check_ip_valid(n1, n2, n3, n4) {
|
function check_ip_valid(n1, n2, n3, n4) {
|
||||||
if (n1 > 255 || n2 > 255 || n3 > 255 || n4 > 255) return false;
|
if (n1 > 255 || n2 > 255 || n3 > 255 || n4 > 255) return false;
|
||||||
|
|
||||||
// private network
|
// private network
|
||||||
if (n1 === 10) return false;
|
if (n1 === 10) return false;
|
||||||
|
|
||||||
// Carrier-grade NAT
|
// Carrier-grade NAT
|
||||||
if (n1 == 100 && n2 == 64) return false;
|
if (n1 == 100 && n2 == 64) return false;
|
||||||
|
|
||||||
// localhost
|
// localhost
|
||||||
if (n1 === 127 && n2 === 0 && n3 === 0) return false;
|
if (n1 === 127 && n2 === 0 && n3 === 0) return false;
|
||||||
|
|
||||||
// link-local address
|
// link-local address
|
||||||
if (n1 == 169 && n2 == 254) return false;
|
if (n1 == 169 && n2 == 254) return false;
|
||||||
|
|
||||||
// private network
|
// private network
|
||||||
if (n1 === 172) if (n2 >= 16 && n2 <= 31) return false;
|
if (n1 === 172) { if (n2 >= 16 && n2 <= 31) return false; }
|
||||||
|
|
||||||
if (n1 === 192) {
|
if (n1 === 192) {
|
||||||
if (n2 === 168) return false; // private network
|
if (n2 === 168) return false; // private network
|
||||||
if (n2 === 0 && n3 === 0) return false; // IANA RFC 5735
|
if (n2 === 0 && n3 === 0) return false; // IANA RFC 5735
|
||||||
if (n2 === 0 && n3 === 2) return false; // TEST-NET-1 RFC 5735
|
if (n2 === 0 && n3 === 2) return false; // TEST-NET-1 RFC 5735
|
||||||
if (n2 === 88 && n3 === 99) return false; // 6to4
|
if (n2 === 88 && n3 === 99) return false; // 6to4
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n1 == 198) {
|
if (n1 == 198) {
|
||||||
if (n2 == 18) return false; // RFC 2544
|
if (n2 == 18) return false; // RFC 2544
|
||||||
if (n2 == 51 && n3 == 100) return false; // TEST-NET-2 RFC 5735
|
if (n2 == 51 && n3 == 100) return false; // TEST-NET-2 RFC 5735
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n1 == 203 && n3 == 113) return false; // TEST-NET-3 RFC 5735
|
if (n1 == 203 && n3 == 113) return false; // TEST-NET-3 RFC 5735
|
||||||
|
|
||||||
// class D network
|
// class D network
|
||||||
if (n1 == 224) return false;
|
if (n1 == 224) return false;
|
||||||
|
|
||||||
// class E network
|
// class E network
|
||||||
if (n1 == 255) return false;
|
if (n1 == 255) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate hash and write result
|
// calculate hash and write result
|
||||||
function run(year, month, date, day, ip) {
|
function run(year, month, date, day, ip) {
|
||||||
let num = ip;
|
let num = ip;
|
||||||
let index = `${ip[0]}.${ip[1]}.${ip[2]}.${ip[3]}`;
|
let index = `${ip[0]}.${ip[1]}.${ip[2]}.${ip[3]}`;
|
||||||
|
|
||||||
// original hash function
|
// original hash function
|
||||||
let hashDate = Math.round(Math.log10(year * ((month << (Math.log10(num[3]) + day - 1)) * (date << Math.log10(num[2] << day)))));
|
let hashDate = Math.round(
|
||||||
let seed1 = (num[0] >> hashDate) * (num[1] >> Math.min(hashDate, 2)) + (num[2] << 1) * (num[3] >> 3) + (date << 3) * (month << hashDate) + ((year * day) >> 2);
|
Math.log10(
|
||||||
let seed2 = (num[0] << (hashDate + 2)) * (num[1] << hashDate) + (num[2] << 1) * (num[3] << 3) + (date << (hashDate - 1)) * (month << 4) + (year >> hashDate) + ((date * day) >> 1);
|
year *
|
||||||
|
((month << (Math.log10(num[3]) + day - 1)) *
|
||||||
|
(date << Math.log10(num[2] << day))),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let seed1 = (num[0] >> hashDate) * (num[1] >> Math.min(hashDate, 2)) +
|
||||||
|
(num[2] << 1) * (num[3] >> 3) + (date << 3) * (month << hashDate) +
|
||||||
|
((year * day) >> 2);
|
||||||
|
let seed2 = (num[0] << (hashDate + 2)) * (num[1] << hashDate) +
|
||||||
|
(num[2] << 1) * (num[3] << 3) + (date << (hashDate - 1)) * (month << 4) +
|
||||||
|
(year >> hashDate) + ((date * day) >> 1);
|
||||||
|
|
||||||
// make sure the events won't collide
|
// make sure the events won't collide
|
||||||
let set = new Set();
|
let set = new Set();
|
||||||
let l1 = (seed1 % goodLen + goodLen) % goodLen;
|
let l1 = (seed1 % goodLen + goodLen) % goodLen;
|
||||||
let l2 = (((seed1 << 1) + date) % goodLen + goodLen) % goodLen;
|
let l2 = (((seed1 << 1) + date) % goodLen + goodLen) % goodLen;
|
||||||
|
|
||||||
while (l1 == l2) {
|
while (l1 == l2) {
|
||||||
l2 = (l2 + 1) % goodLen;
|
l2 = (l2 + 1) % goodLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
set.add(goodFortunes[l1].event);
|
set.add(goodFortunes[l1].event);
|
||||||
set.add(goodFortunes[l2].event);
|
set.add(goodFortunes[l2].event);
|
||||||
|
|
||||||
let r1 = (((seed1 >> 1) + (month << 3)) % badLen + badLen) % badLen;
|
let r1 = (((seed1 >> 1) + (month << 3)) % badLen + badLen) % badLen;
|
||||||
while (set.has(badFortunes[r1].event)) {
|
while (set.has(badFortunes[r1].event)) {
|
||||||
r1 = (r1 + 2) % badLen;
|
r1 = (r1 + 2) % badLen;
|
||||||
}
|
}
|
||||||
set.add(badFortunes[r1].event);
|
set.add(badFortunes[r1].event);
|
||||||
let r2 = ((((((seed1 << 3) + (year >> 5) * (date << 2)) % badLen) * seed2) >> 6) % badLen + badLen) % badLen;
|
let r2 =
|
||||||
while (set.has(badFortunes[r2].event)) {
|
((((((seed1 << 3) + (year >> 5) * (date << 2)) % badLen) * seed2) >> 6) %
|
||||||
r2 = (r2 + 1) % badLen;
|
badLen + badLen) % badLen;
|
||||||
}
|
while (set.has(badFortunes[r2].event)) {
|
||||||
|
r2 = (r2 + 1) % badLen;
|
||||||
|
}
|
||||||
|
|
||||||
// write l1, l2, r1, r2
|
// write l1, l2, r1, r2
|
||||||
buckets[index][0] = l1;
|
buckets[index][0] = l1;
|
||||||
buckets[index][1] = l2;
|
buckets[index][1] = l2;
|
||||||
buckets[index][2] = r1;
|
buckets[index][2] = r1;
|
||||||
buckets[index][3] = r2;
|
buckets[index][3] = r2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
### 2000 IPs for 365 days, two groups in total
|
### 2000 IPs for 365 days, two groups in total
|
||||||
|
|
||||||
| Fortune Status | Percentage (1st time) | Percentage (2nd time) |
|
| Fortune Status | Percentage (1st time) | Percentage (2nd time) |
|
||||||
|----------------|-----------------------|-----------------------|
|
| -------------- | --------------------- | --------------------- |
|
||||||
| 大吉 | 20.33% | 20.30% |
|
| 大吉 | 20.33% | 20.30% |
|
||||||
| 中吉 | 14.37% | 14.34% |
|
| 中吉 | 14.37% | 14.34% |
|
||||||
| 小吉 | 10.57% | 10.59% |
|
| 小吉 | 10.57% | 10.59% |
|
||||||
@@ -17,12 +17,13 @@
|
|||||||
|
|
||||||
## Distribution statistics of daily fortune events
|
## Distribution statistics of daily fortune events
|
||||||
|
|
||||||
Statistical method: The sum of the number of fortune events that occurred for 2,000 random IPs on the same day.
|
Statistical method: The sum of the number of fortune events that occurred for
|
||||||
|
2,000 random IPs on the same day.
|
||||||
|
|
||||||
The x-axis is the index value and the y-axis is the number of times.
|
The x-axis is the index value and the y-axis is the number of times.
|
||||||
|
|
||||||
| 宜 (Good Fortune) | 忌 (Bad Fortune) |
|
| 宜 (Good Fortune) | 忌 (Bad Fortune) |
|
||||||
|------------------------------------------------|----------------------------------------------|
|
| ---------------------------------------------- | -------------------------------------------- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
[Statistics code](../dev/main.js)
|
[Statistics code](../dev/main.js)
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
:root {
|
:root {
|
||||||
--button-color: #73a3eb;
|
--button-color: #73a3eb;
|
||||||
--button-hover-color: #459aef;
|
--button-hover-color: #459aef;
|
||||||
--bg-color: #FFFFFF;
|
--bg-color: #ffffff;
|
||||||
--good-fortune-color: #e74c3c;
|
--good-fortune-color: #e74c3c;
|
||||||
--bad-fortune-color: #000000bf;
|
--bad-fortune-color: #000000bf;
|
||||||
--middle-fortune-color: #5eb95e;
|
--middle-fortune-color: #5eb95e;
|
||||||
--desc-color: #7f7f7f;
|
--desc-color: #7f7f7f;
|
||||||
--date-color: #096e1bC9;
|
--date-color: #096e1bc9;
|
||||||
--special-event-color: #3e4fbb;
|
--special-event-color: #3e4fbb;
|
||||||
--title-color: #000000CC;
|
--title-color: #000000cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-mode {
|
.dark-mode {
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
--title-color: #cdcdcd;
|
--title-color: #cdcdcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -1,113 +1,136 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Daily Fortune Generator</title>
|
<title>Daily Fortune Generator</title>
|
||||||
<link rel="icon" href="../images/lifeadventurer_rounded_logo.png">
|
<link rel="icon" href="../images/lifeadventurer_rounded_logo.png" />
|
||||||
<link rel="manifest" href="./manifest.json">
|
<link rel="manifest" href="./manifest.json" />
|
||||||
<!-- bootstrap -->
|
<!-- bootstrap -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
<link
|
||||||
<!-- box icons -->
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
|
||||||
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
|
rel="stylesheet"
|
||||||
<!-- jquery -->
|
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
crossorigin="anonymous"
|
||||||
|
/>
|
||||||
|
<!-- box icons -->
|
||||||
|
<link
|
||||||
|
href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<!-- jquery -->
|
||||||
|
<script
|
||||||
|
src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"
|
||||||
|
></script>
|
||||||
|
|
||||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet">
|
<link
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.11/html-to-image.min.js" integrity="sha512-7tWCgq9tTYS/QkGVyKrtLpqAoMV9XIUxoou+sPUypsaZx56cYR/qio84fPK9EvJJtKvJEwt7vkn6je5UVzGevw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
|
||||||
<link rel="stylesheet" href="./css/styles.css">
|
rel="stylesheet"
|
||||||
<script>
|
/>
|
||||||
if ('serviceWorker' in navigator) {
|
<script
|
||||||
navigator.serviceWorker.register('./js/service-worker.js');
|
src="https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.11/html-to-image.min.js"
|
||||||
}
|
integrity="sha512-7tWCgq9tTYS/QkGVyKrtLpqAoMV9XIUxoou+sPUypsaZx56cYR/qio84fPK9EvJJtKvJEwt7vkn6je5UVzGevw=="
|
||||||
</script>
|
crossorigin="anonymous"
|
||||||
</head>
|
referrerpolicy="no-referrer"
|
||||||
<body>
|
></script>
|
||||||
<div class="container">
|
<link rel="stylesheet" href="./css/styles.css" />
|
||||||
<div class="row">
|
<script>
|
||||||
<p id="title"></p>
|
if ("serviceWorker" in navigator) {
|
||||||
</div>
|
navigator.serviceWorker.register("./js/service-worker.js");
|
||||||
<!-- init page start -->
|
}
|
||||||
<div id="init-page">
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-3">
|
<p id="title"></p>
|
||||||
<p id="month"></p>
|
</div>
|
||||||
|
<!-- init page start -->
|
||||||
|
<div id="init-page">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-3">
|
||||||
|
<p id="month"></p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<p id="date"></p>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<p id="weekday"></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="row">
|
||||||
<p id="date"></p>
|
<div class="col">
|
||||||
|
<p id="special-day"></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="row">
|
||||||
<p id="weekday"></p>
|
<p id="upcoming-event-1"></p>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<p id="upcoming-event-2"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<!-- init page end -->
|
||||||
<div class="col">
|
<!-- page after button clicked start -->
|
||||||
<p id="special-day"></p>
|
<div id="result-page">
|
||||||
|
<div class="row">
|
||||||
|
<p id="ip-to-fortune"></p>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<p id="l-1-event"></p>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<p id="l-1-desc"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<p id="r-1-event"></p>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<p id="r-1-desc"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<p id="l-2-event"></p>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<p id="l-2-desc"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<p id="r-2-event"></p>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<p id="r-2-desc"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- page after button click end -->
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<p id="upcoming-event-1"></p>
|
<i class="col-2 bx bx-moon" id="dark-mode-icon"></i>
|
||||||
</div>
|
<button class="col-4 offset-2 bi bi-files" id="btn" onclick="getLuck()">
|
||||||
<div class="row">
|
點擊打卡
|
||||||
<p id="upcoming-event-2"></p>
|
</button>
|
||||||
|
<i
|
||||||
|
class="col-2 offset-2 fas fa-clone d-none"
|
||||||
|
id="copy-result"
|
||||||
|
onclick="copyResultImageToClipboard()"
|
||||||
|
></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- init page end -->
|
|
||||||
<!-- page after button clicked start -->
|
|
||||||
<div id="result-page">
|
|
||||||
<div class="row">
|
|
||||||
<p id="ip-to-fortune"></p>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="row">
|
|
||||||
<p id="l-1-event"></p>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<p id="l-1-desc"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="row">
|
|
||||||
<p id="r-1-event"></p>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<p id="r-1-desc"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="row">
|
|
||||||
<p id="l-2-event"></p>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<p id="l-2-desc"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="row">
|
|
||||||
<p id="r-2-event"></p>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<p id="r-2-desc"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- page after button click end -->
|
|
||||||
|
|
||||||
<div class="row">
|
<canvas id="Matrix"></canvas>
|
||||||
<i class="col-2 bx bx-moon" id="dark-mode-icon"></i>
|
<script src="./js/scripts.js"></script>
|
||||||
<button class="col-4 offset-2 bi bi-files" id="btn" onclick="getLuck()">點擊打卡</button>
|
<script src="./js/fortune.js"></script>
|
||||||
<i class="col-2 offset-2 fas fa-clone d-none" id="copy-result" onclick="copyResultImageToClipboard()"></i>
|
<script src="./js/matrix.js"></script>
|
||||||
</div>
|
</body>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<canvas id="Matrix"></canvas>
|
|
||||||
<script src="./js/scripts.js"></script>
|
|
||||||
<script src="./js/fortune.js"></script>
|
|
||||||
<script src="./js/matrix.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
let ip = null;
|
let ip = null;
|
||||||
fetch("https://api.ipify.org?format=json").then(response => {
|
fetch("https://api.ipify.org?format=json").then((response) => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Network response was not ok.");
|
throw new Error("Network response was not ok.");
|
||||||
}).then(res => {
|
}).then((res) => {
|
||||||
ip = res.ip;
|
ip = res.ip;
|
||||||
|
}).catch((_error) => {
|
||||||
}).catch(_error => {
|
if ("caches" in window) {
|
||||||
if ('caches' in window) {
|
caches.match("https://api.ipify.org?format=json").then((response) => {
|
||||||
caches.match('https://api.ipify.org?format=json').then(response => {
|
|
||||||
if (response) {
|
if (response) {
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
}).then(data => {
|
}).then((data) => {
|
||||||
if (ip === null && data !== undefined) {
|
if (ip === null && data !== undefined) {
|
||||||
ip = JSON.parse(data).ip;
|
ip = JSON.parse(data).ip;
|
||||||
}
|
}
|
||||||
@@ -22,7 +21,6 @@ fetch("https://api.ipify.org?format=json").then(response => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let goodFortunes = [];
|
let goodFortunes = [];
|
||||||
let badFortunes = [];
|
let badFortunes = [];
|
||||||
let special_events = [];
|
let special_events = [];
|
||||||
@@ -31,27 +29,61 @@ let fortune_generated = false;
|
|||||||
// using async and await to prevent fetching the data too late...
|
// using async and await to prevent fetching the data too late...
|
||||||
async function fetch_data() {
|
async function fetch_data() {
|
||||||
await fetch("./json/fortune.json")
|
await fetch("./json/fortune.json")
|
||||||
.then(response => response.json())
|
.then((response) => response.json())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
goodFortunes = data.goodFortunes;
|
goodFortunes = data.goodFortunes;
|
||||||
badFortunes = data.badFortunes;
|
badFortunes = data.badFortunes;
|
||||||
})
|
});
|
||||||
|
|
||||||
await fetch("./json/special.json")
|
await fetch("./json/special.json")
|
||||||
.then(response => response.json())
|
.then((response) => response.json())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
special_events = data.special_events;
|
special_events = data.special_events;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const textColorClass = ["good-fortune", "good-fortune", "good-fortune", "good-fortune", "good-fortune", "middle-fortune", "bad-fortune", "bad-fortune"];
|
const textColorClass = [
|
||||||
const fortuneStatus = ["大吉", "中吉", "小吉", "吉", "末吉", "中平", "凶", "大凶"];
|
"good-fortune",
|
||||||
const chineseMonth = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"];
|
"good-fortune",
|
||||||
const week = ['日', '一', '二', '三', '四', '五', '六'];
|
"good-fortune",
|
||||||
|
"good-fortune",
|
||||||
|
"good-fortune",
|
||||||
|
"middle-fortune",
|
||||||
|
"bad-fortune",
|
||||||
|
"bad-fortune",
|
||||||
|
];
|
||||||
|
const fortuneStatus = [
|
||||||
|
"大吉",
|
||||||
|
"中吉",
|
||||||
|
"小吉",
|
||||||
|
"吉",
|
||||||
|
"末吉",
|
||||||
|
"中平",
|
||||||
|
"凶",
|
||||||
|
"大凶",
|
||||||
|
];
|
||||||
|
const chineseMonth = [
|
||||||
|
"一",
|
||||||
|
"二",
|
||||||
|
"三",
|
||||||
|
"四",
|
||||||
|
"五",
|
||||||
|
"六",
|
||||||
|
"七",
|
||||||
|
"八",
|
||||||
|
"九",
|
||||||
|
"十",
|
||||||
|
"十一",
|
||||||
|
"十二",
|
||||||
|
];
|
||||||
|
const week = ["日", "一", "二", "三", "四", "五", "六"];
|
||||||
|
|
||||||
const title = `<span class="title" style="font-size:8vmin;"><b>今日運勢</b></span>`;
|
const title =
|
||||||
const allGood = `<span class="bad-fortune" style="font-size:6vmin;"><b>萬事皆宜</b></span>`;
|
`<span class="title" style="font-size:8vmin;"><b>今日運勢</b></span>`;
|
||||||
const allBad = `<span class="good-fortune" style="font-size:6vmin;"><b>諸事不宜</b></span>`;
|
const allGood =
|
||||||
|
`<span class="bad-fortune" style="font-size:6vmin;"><b>萬事皆宜</b></span>`;
|
||||||
|
const allBad =
|
||||||
|
`<span class="good-fortune" style="font-size:6vmin;"><b>諸事不宜</b></span>`;
|
||||||
|
|
||||||
// date
|
// date
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
@@ -63,7 +95,11 @@ const year = d.getFullYear();
|
|||||||
function daysDiff(eventIndex) {
|
function daysDiff(eventIndex) {
|
||||||
// define the date right now and the special event date
|
// define the date right now and the special event date
|
||||||
const startDate = new Date(year, month - 1, date);
|
const startDate = new Date(year, month - 1, date);
|
||||||
const endDate = new Date(special_events[eventIndex].year, special_events[eventIndex].month - 1, special_events[eventIndex].date);
|
const endDate = new Date(
|
||||||
|
special_events[eventIndex].year,
|
||||||
|
special_events[eventIndex].month - 1,
|
||||||
|
special_events[eventIndex].date,
|
||||||
|
);
|
||||||
|
|
||||||
// calculate the difference in milliseconds and convert it to days
|
// calculate the difference in milliseconds and convert it to days
|
||||||
const timeDiff = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24));
|
const timeDiff = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24));
|
||||||
@@ -71,15 +107,15 @@ function daysDiff(eventIndex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pre-search jquery - save to a variable to improve performance
|
// pre-search jquery - save to a variable to improve performance
|
||||||
const J_l_1_event = $('#l-1-event');
|
const J_l_1_event = $("#l-1-event");
|
||||||
const J_l_1_desc = $('#l-1-desc');
|
const J_l_1_desc = $("#l-1-desc");
|
||||||
const J_l_2_event= $('#l-2-event');
|
const J_l_2_event = $("#l-2-event");
|
||||||
const J_l_2_desc = $('#l-2-desc');
|
const J_l_2_desc = $("#l-2-desc");
|
||||||
const J_r_1_event = $('#r-1-event');
|
const J_r_1_event = $("#r-1-event");
|
||||||
const J_r_1_desc = $('#r-1-desc');
|
const J_r_1_desc = $("#r-1-desc");
|
||||||
const J_r_2_event= $('#r-2-event');
|
const J_r_2_event = $("#r-2-event");
|
||||||
const J_r_2_desc = $('#r-2-desc');
|
const J_r_2_desc = $("#r-2-desc");
|
||||||
const J_ip_to_fortune = $('#ip-to-fortune');
|
const J_ip_to_fortune = $("#ip-to-fortune");
|
||||||
|
|
||||||
let special = false;
|
let special = false;
|
||||||
let special_events_index = 0;
|
let special_events_index = 0;
|
||||||
@@ -90,23 +126,34 @@ async function init_page() {
|
|||||||
await fetch_data();
|
await fetch_data();
|
||||||
|
|
||||||
// hide the elements of show fortune page
|
// hide the elements of show fortune page
|
||||||
$('#result-page').hide();
|
$("#result-page").hide();
|
||||||
|
|
||||||
// show date before button pressed
|
// show date before button pressed
|
||||||
const showMonth = `<span class="date-color" style="font-size:10vmin; -webkit-writing-mode:vertical-lr;"><b>${chineseMonth[month - 1] + "月"}</b></span>`;
|
const showMonth =
|
||||||
const showDate = `<span class="date-color" style="font-size:25vmin;"><b>${("0" + date).slice(-2)}</b></span>`;
|
`<span class="date-color" style="font-size:10vmin; -webkit-writing-mode:vertical-lr;"><b>${
|
||||||
const showDay = `<span class="date-color" style="font-size:10vmin; -webkit-writing-mode:vertical-lr; margin-right:10%;"><b>${"星期" + week[day]}</b></span>`;
|
chineseMonth[month - 1] + "月"
|
||||||
|
}</b></span>`;
|
||||||
|
const showDate = `<span class="date-color" style="font-size:25vmin;"><b>${
|
||||||
|
("0" + date).slice(-2)
|
||||||
|
}</b></span>`;
|
||||||
|
const showDay =
|
||||||
|
`<span class="date-color" style="font-size:10vmin; -webkit-writing-mode:vertical-lr; margin-right:10%;"><b>${
|
||||||
|
"星期" + week[day]
|
||||||
|
}</b></span>`;
|
||||||
|
|
||||||
$('#month').html(showMonth);
|
$("#month").html(showMonth);
|
||||||
$('#date').html(showDate);
|
$("#date").html(showDate);
|
||||||
$('#weekday').html(showDay);
|
$("#weekday").html(showDay);
|
||||||
|
|
||||||
const showSpecialEventCount = 2;
|
const showSpecialEventCount = 2;
|
||||||
let eventIndexPtr = 0, eventIndexList = Array(showSpecialEventCount).fill(-1);
|
let eventIndexPtr = 0, eventIndexList = Array(showSpecialEventCount).fill(-1);
|
||||||
// check if there is special event today
|
// check if there is special event today
|
||||||
for (let i = 0; i < special_events.length; i++) {
|
for (let i = 0; i < special_events.length; i++) {
|
||||||
if (daysDiff(i) > 0) {
|
if (daysDiff(i) > 0) {
|
||||||
if (eventIndexPtr < showSpecialEventCount && eventIndexList[eventIndexPtr] == -1) {
|
if (
|
||||||
|
eventIndexPtr < showSpecialEventCount &&
|
||||||
|
eventIndexList[eventIndexPtr] == -1
|
||||||
|
) {
|
||||||
eventIndexList[eventIndexPtr] = i;
|
eventIndexList[eventIndexPtr] = i;
|
||||||
eventIndexPtr++;
|
eventIndexPtr++;
|
||||||
}
|
}
|
||||||
@@ -119,23 +166,33 @@ async function init_page() {
|
|||||||
for (let eventIndex = 0; eventIndex < showSpecialEventCount; eventIndex++) {
|
for (let eventIndex = 0; eventIndex < showSpecialEventCount; eventIndex++) {
|
||||||
if (eventIndexList[eventIndex] != -1) {
|
if (eventIndexList[eventIndex] != -1) {
|
||||||
const days = daysDiff(eventIndexList[eventIndex]);
|
const days = daysDiff(eventIndexList[eventIndex]);
|
||||||
const upcoming_event = `<span class="desc" style="font-size:5vmin;">距離<b class="special-event">${special_events[eventIndexList[eventIndex]].event}</b>還剩<b class="special-event">${days}</b>天</span>`;
|
const upcoming_event =
|
||||||
$(`#upcoming-event-${eventIndex + 1}`).html(upcoming_event)
|
`<span class="desc" style="font-size:5vmin;">距離<b class="special-event">${
|
||||||
|
special_events[eventIndexList[eventIndex]].event
|
||||||
|
}</b>還剩<b class="special-event">${days}</b>天</span>`;
|
||||||
|
$(`#upcoming-event-${eventIndex + 1}`).html(upcoming_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// show special event if today is a special day
|
// show special event if today is a special day
|
||||||
if (special) {
|
if (special) {
|
||||||
const special_event_today = `<span class="desc" style="font-size:9vmin;">今日是<b class="good-fortune">${special_events[special_events_index].event}</b></span>`;
|
const special_event_today =
|
||||||
$('#special-day').html(special_event_today);
|
`<span class="desc" style="font-size:9vmin;">今日是<b class="good-fortune">${
|
||||||
|
special_events[special_events_index].event
|
||||||
|
}</b></span>`;
|
||||||
|
$("#special-day").html(special_event_today);
|
||||||
}
|
}
|
||||||
|
|
||||||
const last_date_str = localStorage.getItem('last_date');
|
const last_date_str = localStorage.getItem("last_date");
|
||||||
if (last_date_str !== null && last_date_str !== undefined) {
|
if (last_date_str !== null && last_date_str !== undefined) {
|
||||||
const now_date = new Date();
|
const now_date = new Date();
|
||||||
const last_date = new Date(last_date_str);
|
const last_date = new Date(last_date_str);
|
||||||
|
|
||||||
if (now_date.getFullYear() === last_date.getFullYear() && now_date.getMonth() === last_date.getMonth() && now_date.getDate() === last_date.getDate()) {
|
if (
|
||||||
|
now_date.getFullYear() === last_date.getFullYear() &&
|
||||||
|
now_date.getMonth() === last_date.getMonth() &&
|
||||||
|
now_date.getDate() === last_date.getDate()
|
||||||
|
) {
|
||||||
fortune_generated = true;
|
fortune_generated = true;
|
||||||
Appear();
|
Appear();
|
||||||
}
|
}
|
||||||
@@ -143,18 +200,21 @@ async function init_page() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// event bar
|
// event bar
|
||||||
const good_span = event => `<span class="good-fortune" style="font-size:5.6vmin;"><b>宜: </b>${event}</span>`;
|
const good_span = (event) =>
|
||||||
const bad_span = event => `<span class="bad-fortune" style="font-size:5.6vmin;"><b>忌: </b>${event}</span>`;
|
`<span class="good-fortune" style="font-size:5.6vmin;"><b>宜: </b>${event}</span>`;
|
||||||
const desc_span = desc => `<span class="desc" style="font-size:3.5vmin;">${desc}</span>`;
|
const bad_span = (event) =>
|
||||||
|
`<span class="bad-fortune" style="font-size:5.6vmin;"><b>忌: </b>${event}</span>`;
|
||||||
|
const desc_span = (desc) =>
|
||||||
|
`<span class="desc" style="font-size:3.5vmin;">${desc}</span>`;
|
||||||
|
|
||||||
function Appear() {
|
function Appear() {
|
||||||
$('#title').html(title);
|
$("#title").html(title);
|
||||||
$('#btn').html('打卡成功');
|
$("#btn").html("打卡成功");
|
||||||
// disable the btn
|
// disable the btn
|
||||||
$('#btn').attr("disabled", "disabled");
|
$("#btn").attr("disabled", "disabled");
|
||||||
//change page
|
//change page
|
||||||
$('#init-page').hide();
|
$("#init-page").hide();
|
||||||
$('#result-page').show();
|
$("#result-page").show();
|
||||||
|
|
||||||
// some lengths
|
// some lengths
|
||||||
const goodLen = goodFortunes.length;
|
const goodLen = goodFortunes.length;
|
||||||
@@ -167,35 +227,51 @@ function Appear() {
|
|||||||
|
|
||||||
if (!fortune_generated) {
|
if (!fortune_generated) {
|
||||||
// transform ip to four numbers
|
// transform ip to four numbers
|
||||||
const num = ip.split(".").map(num => parseInt(num));
|
const num = ip.split(".").map((num) => parseInt(num));
|
||||||
|
|
||||||
// TODO: improve the hash process
|
// TODO: improve the hash process
|
||||||
const hashDate = Math.round(Math.log10(year * ((month << (Math.log10(num[3]) + day - 1)) * (date << Math.log10(num[2] << day)))));
|
const hashDate = Math.round(
|
||||||
seed1 = (num[0] >> hashDate) * (num[1] >> Math.min(hashDate, 2)) + (num[2] << 1) * (num[3] >> 3) + (date << 3) * (month << hashDate) + (year * day) >> 2;
|
Math.log10(
|
||||||
seed2 = (num[0] << (hashDate + 2)) * (num[1] << hashDate) + (num[2] << 1) * (num[3] << 2) + (date << (hashDate - 1)) * (month << 4) + year >> hashDate + (date * day) >> 1;
|
year *
|
||||||
|
((month << (Math.log10(num[3]) + day - 1)) *
|
||||||
|
(date << Math.log10(num[2] << day))),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
seed1 = (num[0] >> hashDate) * (num[1] >> Math.min(hashDate, 2)) +
|
||||||
|
(num[2] << 1) * (num[3] >> 3) + (date << 3) * (month << hashDate) +
|
||||||
|
(year * day) >> 2;
|
||||||
|
seed2 = (num[0] << (hashDate + 2)) * (num[1] << hashDate) +
|
||||||
|
(num[2] << 1) * (num[3] << 2) +
|
||||||
|
(date << (hashDate - 1)) * (month << 4) + year >>
|
||||||
|
hashDate + (date * day) >> 1;
|
||||||
|
|
||||||
// decide the status
|
// decide the status
|
||||||
status_index = ((seed1 + seed2) % statusLen + statusLen) % statusLen;
|
status_index = ((seed1 + seed2) % statusLen + statusLen) % statusLen;
|
||||||
|
|
||||||
// update last record
|
// update last record
|
||||||
localStorage.setItem('last_date', d.toISOString());
|
localStorage.setItem("last_date", d.toISOString());
|
||||||
localStorage.setItem('last_status_index', status_index.toString());
|
localStorage.setItem("last_status_index", status_index.toString());
|
||||||
localStorage.setItem('last_seed1', seed1.toString());
|
localStorage.setItem("last_seed1", seed1.toString());
|
||||||
localStorage.setItem('last_seed2', seed2.toString());
|
localStorage.setItem("last_seed2", seed2.toString());
|
||||||
} else {
|
} else {
|
||||||
status_index = parseInt(localStorage.getItem('last_status_index'));
|
status_index = parseInt(localStorage.getItem("last_status_index"));
|
||||||
seed1 = parseInt(localStorage.getItem('last_seed1'));
|
seed1 = parseInt(localStorage.getItem("last_seed1"));
|
||||||
seed2 = parseInt(localStorage.getItem('last_seed2'));
|
seed2 = parseInt(localStorage.getItem("last_seed2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = `<span class=${textColorClass[status_index]} style="font-size:12vmin;"><b>§ ${fortuneStatus[status_index]} §</b></span>`;
|
const status = `<span class=${
|
||||||
|
textColorClass[status_index]
|
||||||
|
} style="font-size:12vmin;"><b>§ ${fortuneStatus[status_index]} §</b></span>`;
|
||||||
|
|
||||||
if (special) {
|
if (special) {
|
||||||
status_index = special_events[special_events_index].status_index;
|
status_index = special_events[special_events_index].status_index;
|
||||||
const special_status = `<span class=${textColorClass[status_index]} style="font-size:12vmin;"><b>§ ${fortuneStatus[status_index]} §</b></span>`;
|
const special_status = `<span class=${
|
||||||
|
textColorClass[status_index]
|
||||||
|
} style="font-size:12vmin;"><b>§ ${
|
||||||
|
fortuneStatus[status_index]
|
||||||
|
} §</b></span>`;
|
||||||
J_ip_to_fortune.html(special_status);
|
J_ip_to_fortune.html(special_status);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
J_ip_to_fortune.html(status);
|
J_ip_to_fortune.html(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +289,8 @@ function Appear() {
|
|||||||
r1 = (r1 + 2) % badLen;
|
r1 = (r1 + 2) % badLen;
|
||||||
}
|
}
|
||||||
set.add(badFortunes[r1].event);
|
set.add(badFortunes[r1].event);
|
||||||
let r2 = ((((((seed1 << 3) + (d.getFullYear() >> 5) * (date << 2)) % badLen) * seed2) >> 6) % badLen + badLen) % badLen;
|
let r2 = ((((((seed1 << 3) + (d.getFullYear() >> 5) * (date << 2)) % badLen) *
|
||||||
|
seed2) >> 6) % badLen + badLen) % badLen;
|
||||||
while (set.has(badFortunes[r2].event)) {
|
while (set.has(badFortunes[r2].event)) {
|
||||||
r2 = (r2 + 1) % badLen;
|
r2 = (r2 + 1) % badLen;
|
||||||
}
|
}
|
||||||
@@ -224,13 +301,21 @@ function Appear() {
|
|||||||
const r1_desc_list = badFortunes[r1].description;
|
const r1_desc_list = badFortunes[r1].description;
|
||||||
const r2_desc_list = badFortunes[r2].description;
|
const r2_desc_list = badFortunes[r2].description;
|
||||||
const l_1_event = good_span(goodFortunes[l1].event);
|
const l_1_event = good_span(goodFortunes[l1].event);
|
||||||
const l_1_desc = desc_span(l1_desc_list[Math.abs(seed1) % l1_desc_list.length]);
|
const l_1_desc = desc_span(
|
||||||
|
l1_desc_list[Math.abs(seed1) % l1_desc_list.length],
|
||||||
|
);
|
||||||
const l_2_event = good_span(goodFortunes[l2].event);
|
const l_2_event = good_span(goodFortunes[l2].event);
|
||||||
const l_2_desc = desc_span(l2_desc_list[Math.abs(seed2) % l2_desc_list.length]);
|
const l_2_desc = desc_span(
|
||||||
|
l2_desc_list[Math.abs(seed2) % l2_desc_list.length],
|
||||||
|
);
|
||||||
const r_1_event = bad_span(badFortunes[r1].event);
|
const r_1_event = bad_span(badFortunes[r1].event);
|
||||||
const r_1_desc = desc_span(r1_desc_list[Math.abs(seed1) % r1_desc_list.length]);
|
const r_1_desc = desc_span(
|
||||||
|
r1_desc_list[Math.abs(seed1) % r1_desc_list.length],
|
||||||
|
);
|
||||||
const r_2_event = bad_span(badFortunes[r2].event);
|
const r_2_event = bad_span(badFortunes[r2].event);
|
||||||
const r_2_desc = desc_span(r2_desc_list[Math.abs(seed2) % r2_desc_list.length]);
|
const r_2_desc = desc_span(
|
||||||
|
r2_desc_list[Math.abs(seed2) % r2_desc_list.length],
|
||||||
|
);
|
||||||
|
|
||||||
if (special) {
|
if (special) {
|
||||||
// instead clear variable name, use short variable name for here... cuz it's too repetitive
|
// instead clear variable name, use short variable name for here... cuz it's too repetitive
|
||||||
@@ -269,8 +354,7 @@ function Appear() {
|
|||||||
J_l_2_desc.html(l_2_desc);
|
J_l_2_desc.html(l_2_desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
if (status_index == 0) {
|
if (status_index == 0) {
|
||||||
J_r_1_event.html(allGood);
|
J_r_1_event.html(allGood);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const canvas = document.getElementById("Matrix")
|
const canvas = document.getElementById("Matrix");
|
||||||
const context = canvas.getContext("2d")
|
const context = canvas.getContext("2d");
|
||||||
|
|
||||||
canvas.height = window.innerHeight + 100;
|
canvas.height = globalThis.innerHeight + 100;
|
||||||
canvas.width = window.innerWidth + 5;
|
canvas.width = globalThis.innerWidth + 5;
|
||||||
|
|
||||||
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./*-+#$%^@!~?><:;[]{}=_αβΓγΔδεζηΘθικΛλμΞξΠπρΣσςτυΦφχΨψΩω×≦≧≠∞≒≡~∩∠∪∟⊿∫∮∵∴$¥〒¢£℃€℉╩◢ⅩⅨⅧⅦⅥⅤⅣⅢⅡⅠあいうえおがぎぐげござじずぜぞだぢつでづどにぬのばひぴぶへぺぼみゃょァゐゎè";
|
const chars =
|
||||||
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./*-+#$%^@!~?><:;[]{}=_αβΓγΔδεζηΘθικΛλμΞξΠπρΣσςτυΦφχΨψΩω×≦≧≠∞≒≡~∩∠∪∟⊿∫∮∵∴$¥〒¢£℃€℉╩◢ⅩⅨⅧⅦⅥⅤⅣⅢⅡⅠあいうえおがぎぐげござじずぜぞだぢつでづどにぬのばひぴぶへぺぼみゃょァゐゎè";
|
||||||
|
|
||||||
const fontSize = 16;
|
const fontSize = 16;
|
||||||
const columns = canvas.width / fontSize;
|
const columns = canvas.width / fontSize;
|
||||||
|
|||||||
@@ -1,49 +1,50 @@
|
|||||||
let darkModeIcon = document.querySelector('#dark-mode-icon');
|
let darkModeIcon = document.querySelector("#dark-mode-icon");
|
||||||
|
|
||||||
darkModeIcon.onclick = () => {
|
darkModeIcon.onclick = () => {
|
||||||
darkModeIcon.classList.toggle('bx-sun');
|
darkModeIcon.classList.toggle("bx-sun");
|
||||||
document.body.classList.toggle('dark-mode');
|
document.body.classList.toggle("dark-mode");
|
||||||
};
|
};
|
||||||
|
|
||||||
function copyResultImageToClipboard() {
|
function copyResultImageToClipboard() {
|
||||||
try {
|
try {
|
||||||
const $title = $('#title').clone().wrap('<div class="row"></div>');
|
const $title = $("#title").clone().wrap('<div class="row"></div>');
|
||||||
$('#result-page').prepend($title.parent());
|
$("#result-page").prepend($title.parent());
|
||||||
|
|
||||||
const backgroundColor = getComputedStyle($('.container')[0]).backgroundColor;
|
const backgroundColor =
|
||||||
htmlToImage.toBlob($('#result-page')[0], {
|
getComputedStyle($(".container")[0]).backgroundColor;
|
||||||
|
htmlToImage.toBlob($("#result-page")[0], {
|
||||||
skipFonts: true,
|
skipFonts: true,
|
||||||
preferredFontFormat: 'woff2',
|
preferredFontFormat: "woff2",
|
||||||
backgroundColor: backgroundColor, // Set background color dynamically
|
backgroundColor: backgroundColor, // Set background color dynamically
|
||||||
}).then(blob => {
|
}).then((blob) => {
|
||||||
navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
|
navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
|
||||||
showCopiedNotice();
|
showCopiedNotice();
|
||||||
$title.parent().remove();
|
$title.parent().remove();
|
||||||
}).catch(error => {
|
}).catch((error) => {
|
||||||
console.error('Error converting result page to image:', error);
|
console.error("Error converting result page to image:", error);
|
||||||
$title.parent().remove();
|
$title.parent().remove();
|
||||||
});
|
});
|
||||||
} catch(error) {
|
} catch (error) {
|
||||||
console.error('Error copying result image to clipboard:', error);
|
console.error("Error copying result image to clipboard:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCopiedNotice() {
|
function showCopiedNotice() {
|
||||||
const notice = $('<div>', {
|
const notice = $("<div>", {
|
||||||
text: 'Copied to clipboard!',
|
text: "Copied to clipboard!",
|
||||||
css: {
|
css: {
|
||||||
position: 'fixed',
|
position: "fixed",
|
||||||
bottom: '20px',
|
bottom: "20px",
|
||||||
right: '20px',
|
right: "20px",
|
||||||
padding: '10px 20px',
|
padding: "10px 20px",
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
||||||
color: '#fff',
|
color: "#fff",
|
||||||
borderRadius: '5px',
|
borderRadius: "5px",
|
||||||
zIndex: 1000,
|
zIndex: 1000,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
$('body').append(notice);
|
$("body").append(notice);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notice.fadeOut(300, () => {
|
notice.fadeOut(300, () => {
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
const pre_cache_file_version = 'pre-v1.1.0';
|
const pre_cache_file_version = "pre-v1.1.0";
|
||||||
const auto_cache_file_version = 'auto-v1.1.0'
|
const auto_cache_file_version = "auto-v1.1.0";
|
||||||
|
|
||||||
const ASSETS = [
|
const ASSETS = [
|
||||||
'/images/lifeadventurer-192x192.png',
|
"/images/lifeadventurer-192x192.png",
|
||||||
'/images/lifeadventurer-512x512.png',
|
"/images/lifeadventurer-512x512.png",
|
||||||
'/images/lifeadventurer-180x180.png',
|
"/images/lifeadventurer-180x180.png",
|
||||||
'/images/lifeadventurer-270x270.png',
|
"/images/lifeadventurer-270x270.png",
|
||||||
'/images/lifeadventurer.jpg',
|
"/images/lifeadventurer.jpg",
|
||||||
|
|
||||||
'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css',
|
"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
|
||||||
'https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js'
|
"https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js",
|
||||||
];
|
];
|
||||||
|
|
||||||
const NEED_UPDATE = [
|
const NEED_UPDATE = [
|
||||||
'/fortune_generator/',
|
"/fortune_generator/",
|
||||||
'/fortune_generator/index.html',
|
"/fortune_generator/index.html",
|
||||||
'/fortune_generator/css/styles.css',
|
"/fortune_generator/css/styles.css",
|
||||||
'/fortune_generator/js/fortune.js',
|
"/fortune_generator/js/fortune.js",
|
||||||
'/fortune_generator/js/matrix.js',
|
"/fortune_generator/js/matrix.js",
|
||||||
'/fortune_generator/json/special.json',
|
"/fortune_generator/json/special.json",
|
||||||
'/fortune_generator/json/fortune.json',
|
"/fortune_generator/json/fortune.json",
|
||||||
'/fortune_generator/json/manifest.json',
|
"/fortune_generator/json/manifest.json",
|
||||||
'https://api.ipify.org/?format=json',
|
"https://api.ipify.org/?format=json",
|
||||||
]
|
];
|
||||||
|
|
||||||
const limit_cache_size = (name, size) => {
|
const limit_cache_size = (name, size) => {
|
||||||
caches.open(name).then(cache => {
|
caches.open(name).then((cache) => {
|
||||||
cache.keys().then(keys => {
|
cache.keys().then((keys) => {
|
||||||
if (keys.length > size) {
|
if (keys.length > size) {
|
||||||
cache.delete(keys[0]).then(() => {
|
cache.delete(keys[0]).then(() => {
|
||||||
limit_cache_size(name, size)
|
limit_cache_size(name, size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -37,7 +37,7 @@ const limit_cache_size = (name, size) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const is_in_array = (str, array) => {
|
const is_in_array = (str, array) => {
|
||||||
let path = '';
|
let path = "";
|
||||||
|
|
||||||
// Check the request's domain is the same as the current domain.
|
// Check the request's domain is the same as the current domain.
|
||||||
if (str.indexOf(self.origin) === 0) {
|
if (str.indexOf(self.origin) === 0) {
|
||||||
@@ -47,44 +47,47 @@ const is_in_array = (str, array) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return array.indexOf(path) > -1;
|
return array.indexOf(path) > -1;
|
||||||
}
|
};
|
||||||
|
|
||||||
// install
|
// install
|
||||||
self.addEventListener('install', event => {
|
self.addEventListener("install", (event) => {
|
||||||
self.skipWaiting();
|
self.skipWaiting();
|
||||||
|
|
||||||
//pre-cache files
|
//pre-cache files
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
caches.open(pre_cache_file_version).then(cache => {
|
caches.open(pre_cache_file_version).then((cache) => {
|
||||||
cache.addAll(ASSETS);
|
cache.addAll(ASSETS);
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// activate
|
// activate
|
||||||
self.addEventListener('activate', event => {
|
self.addEventListener("activate", (event) => {
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
caches.keys().then(keys => {
|
caches.keys().then((keys) => {
|
||||||
return Promise.all(keys.map(key => {
|
return Promise.all(keys.map((key) => {
|
||||||
if (pre_cache_file_version.indexOf(key) === -1 && auto_cache_file_version.indexOf(key) === -1) {
|
if (
|
||||||
|
pre_cache_file_version.indexOf(key) === -1 &&
|
||||||
|
auto_cache_file_version.indexOf(key) === -1
|
||||||
|
) {
|
||||||
return caches.delete(key);
|
return caches.delete(key);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
})
|
}),
|
||||||
)
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// fetch event
|
// fetch event
|
||||||
self.addEventListener('fetch', event => {
|
self.addEventListener("fetch", (event) => {
|
||||||
if (is_in_array(event.request.url, ASSETS)) {
|
if (is_in_array(event.request.url, ASSETS)) {
|
||||||
// cache only strategy
|
// cache only strategy
|
||||||
|
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
caches.match(event.request.url)
|
caches.match(event.request.url),
|
||||||
);
|
);
|
||||||
} else if (is_in_array(event.request.url, NEED_UPDATE)) {
|
} else if (is_in_array(event.request.url, NEED_UPDATE)) {
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
fetch(event.request.url).then(async response => {
|
fetch(event.request.url).then(async (response) => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const cache = await caches.open(auto_cache_file_version);
|
const cache = await caches.open(auto_cache_file_version);
|
||||||
cache.put(event.request.url, response.clone());
|
cache.put(event.request.url, response.clone());
|
||||||
@@ -92,11 +95,10 @@ self.addEventListener('fetch', event => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Network response was not ok.");
|
throw new Error("Network response was not ok.");
|
||||||
|
}).catch(async (_error) => {
|
||||||
}).catch(async _error => {
|
|
||||||
const cache = await caches.open(auto_cache_file_version);
|
const cache = await caches.open(auto_cache_file_version);
|
||||||
return cache.match(event.request.url);
|
return cache.match(event.request.url);
|
||||||
})
|
}),
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
145
index.html
145
index.html
@@ -1,66 +1,99 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Generators</title>
|
<title>Generators</title>
|
||||||
<link rel="icon" href="./images/lifeadventurer_rounded_logo.png">
|
<link rel="icon" href="./images/lifeadventurer_rounded_logo.png" />
|
||||||
<!-- bootstrap 5.3.2 -->
|
<!-- bootstrap 5.3.2 -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
<link
|
||||||
<!-- jquery 3.7.1 -->
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
rel="stylesheet"
|
||||||
<!-- box icons -->
|
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
||||||
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
|
crossorigin="anonymous"
|
||||||
<link rel="stylesheet" href="./styles.css">
|
/>
|
||||||
</head>
|
<!-- jquery 3.7.1 -->
|
||||||
<body>
|
<script
|
||||||
<header>
|
src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"
|
||||||
<div class="row">
|
></script>
|
||||||
<h1 class="col-md-4 col-sm-6 offset-md-4 offset-sm-3">Generators Gallery</h1>
|
<!-- box icons -->
|
||||||
<div class="col-md-1 col-sm-1 offset-md-3 offset-sm-2 bx bx-moon" id="dark-mode-icon"></div>
|
<link
|
||||||
</div>
|
href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css"
|
||||||
</header>
|
rel="stylesheet"
|
||||||
<section>
|
/>
|
||||||
<div class="container">
|
<link rel="stylesheet" href="./styles.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<h1 class="col-md-4 col-sm-6 offset-md-4 offset-sm-3">
|
||||||
<div class="card mb-3 border-0">
|
Generators Gallery
|
||||||
<img class="card-img-top" src="./images/fortune_generator_example.png" alt="fortune generator example">
|
</h1>
|
||||||
<div class="card-body">
|
<div
|
||||||
<h4 class="card-title">Fortune Generator</h4>
|
class="col-md-1 col-sm-1 offset-md-3 offset-sm-2 bx bx-moon"
|
||||||
<p class="card-text">Get your daily fortune with just a click.</p>
|
id="dark-mode-icon"
|
||||||
<a class="btn" href="./fortune_generator/">Check this out</a>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
</div>
|
||||||
<div id="last-update-1"></div>
|
</header>
|
||||||
|
<section>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card mb-3 border-0">
|
||||||
|
<img
|
||||||
|
class="card-img-top"
|
||||||
|
src="./images/fortune_generator_example.png"
|
||||||
|
alt="fortune generator example"
|
||||||
|
/>
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="card-title">Fortune Generator</h4>
|
||||||
|
<p class="card-text">
|
||||||
|
Get your daily fortune with just a click.
|
||||||
|
</p>
|
||||||
|
<a class="btn" href="./fortune_generator/">Check this out</a>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div id="last-update-1"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-md-6">
|
||||||
<div class="col-md-6">
|
<div class="card mb-3 border-0">
|
||||||
<div class="card mb-3 border-0">
|
<img
|
||||||
<img class="card-img-top" src="./images/quote_generator_example_(2).png" alt="quote generator example">
|
class="card-img-top"
|
||||||
<div class="card-body">
|
src="./images/quote_generator_example_(2).png"
|
||||||
<h4 class="card-title">Quote Generator</h4>
|
alt="quote generator example"
|
||||||
<p class="card-text">Generate inspiring and thought-provoking quotes effortlessly.</p>
|
/>
|
||||||
<a class="btn" href="./quote_generator/">Check this out</a>
|
<div class="card-body">
|
||||||
</div>
|
<h4 class="card-title">Quote Generator</h4>
|
||||||
<div class="card-footer">
|
<p class="card-text">
|
||||||
<div id="last-update-2"></div>
|
Generate inspiring and thought-provoking quotes effortlessly.
|
||||||
|
</p>
|
||||||
|
<a class="btn" href="./quote_generator/">Check this out</a>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div id="last-update-2"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
<footer>
|
||||||
<footer>
|
<div class="row text-muted py-3 me-3 float-end" id="footer-author">
|
||||||
<div class="row text-muted py-3 me-3 float-end" id="footer-author">
|
<h5>
|
||||||
<h5> Copyright © 2023-2024 LifeAdventurer | All Rights Reserved.
|
Copyright © 2023-2024 LifeAdventurer | All Rights Reserved.
|
||||||
<a href="https://github.com/LifeAdventurer">
|
<a href="https://github.com/LifeAdventurer">
|
||||||
<img id="footer-author-icon" src="./images/lifeadventurer_rounded_logo.png" alt="footer image">
|
<img
|
||||||
</a>
|
id="footer-author-icon"
|
||||||
</h5>
|
src="./images/lifeadventurer_rounded_logo.png"
|
||||||
</div>
|
alt="footer image"
|
||||||
</footer>
|
/>
|
||||||
<script src="./scripts.js"></script>
|
</a>
|
||||||
</body>
|
</h5>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<script src="./scripts.js"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
:root {
|
:root {
|
||||||
--button-color: #9DC4FF;
|
--button-color: #9dc4ff;
|
||||||
--button-hover-color: #5ca8f3;
|
--button-hover-color: #5ca8f3;
|
||||||
--bg-color: #ffffffd7;
|
--bg-color: #ffffffd7;
|
||||||
--text-color: #000000;
|
--text-color: #000000;
|
||||||
@@ -18,7 +18,7 @@ html {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: Georgia, 'Times New Roman', Times, serif;
|
font-family: Georgia, "Times New Roman", Times, serif;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ button {
|
|||||||
padding: 17px 20px;
|
padding: 17px 20px;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title> Quote Generator </title>
|
<title>Quote Generator</title>
|
||||||
<link rel="icon" href="../images/lifeadventurer_rounded_logo.png">
|
<link rel="icon" href="../images/lifeadventurer_rounded_logo.png" />
|
||||||
<!-- bootstrap -->
|
<!-- bootstrap -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
<link
|
||||||
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
/>
|
||||||
<!-- box icons -->
|
<!-- box icons -->
|
||||||
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
|
<link
|
||||||
<link rel="stylesheet" href="./css/styles.css">
|
href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="./css/styles.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -20,7 +28,7 @@
|
|||||||
<p id="author"></p>
|
<p id="author"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<button class="col-4 offset-4" onclick="getQuote()">Generate </button>
|
<button class="col-4 offset-4" onclick="getQuote()">Generate</button>
|
||||||
<div class="col-2 offset-2 bx bx-moon" id="dark-mode-icon"></div>
|
<div class="col-2 offset-2 bx bx-moon" id="dark-mode-icon"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const canvas = document.getElementById("Matrix")
|
const canvas = document.getElementById("Matrix");
|
||||||
const context = canvas.getContext("2d")
|
const context = canvas.getContext("2d");
|
||||||
|
|
||||||
canvas.height = window.innerHeight + 100;
|
canvas.height = globalThis.innerHeight + 100;
|
||||||
canvas.width = window.innerWidth + 5;
|
canvas.width = globalThis.innerWidth + 5;
|
||||||
|
|
||||||
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./*-+#$%^@!~?><:;[]{}=_αβΓγΔδεζηΘθικΛλμΞξΠπρΣσςτυΦφχΨψΩω×≦≧≠∞≒≡~∩∠∪∟⊿∫∮∵∴$¥〒¢£℃€℉╩◢ⅩⅨⅧⅦⅥⅤⅣⅢⅡⅠあいうえおがぎぐげござじずぜぞだぢつでづどにぬのばひぴぶへぺぼみゃょァゐゎè";
|
const chars =
|
||||||
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./*-+#$%^@!~?><:;[]{}=_αβΓγΔδεζηΘθικΛλμΞξΠπρΣσςτυΦφχΨψΩω×≦≧≠∞≒≡~∩∠∪∟⊿∫∮∵∴$¥〒¢£℃€℉╩◢ⅩⅨⅧⅦⅥⅤⅣⅢⅡⅠあいうえおがぎぐげござじずぜぞだぢつでづどにぬのばひぴぶへぺぼみゃょァゐゎè";
|
||||||
|
|
||||||
const fontSize = 16;
|
const fontSize = 16;
|
||||||
const columns = canvas.width / fontSize;
|
const columns = canvas.width / fontSize;
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ const buttonElement = document.querySelector("button");
|
|||||||
let quotes = [];
|
let quotes = [];
|
||||||
|
|
||||||
fetch("./json/quotes.json")
|
fetch("./json/quotes.json")
|
||||||
.then(response => response.json())
|
.then((response) => response.json())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
quotes = data.quotes;
|
quotes = data.quotes;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function Appear() {
|
function Appear() {
|
||||||
const index = Math.floor(Math.random() * quotes.length);
|
const index = Math.floor(Math.random() * quotes.length);
|
||||||
@@ -24,7 +23,6 @@ function Appear() {
|
|||||||
const numDarkImages = 0;
|
const numDarkImages = 0;
|
||||||
const numLightImages = 0;
|
const numLightImages = 0;
|
||||||
|
|
||||||
|
|
||||||
if (numDarkImages && numLightImages) {
|
if (numDarkImages && numLightImages) {
|
||||||
const isDark = Math.random() < 0.5;
|
const isDark = Math.random() < 0.5;
|
||||||
let randomIndex, randomImage;
|
let randomIndex, randomImage;
|
||||||
@@ -33,7 +31,7 @@ function Appear() {
|
|||||||
if (isDark) {
|
if (isDark) {
|
||||||
randomIndex = Math.floor(Math.random() * numDarkImages) + 1;
|
randomIndex = Math.floor(Math.random() * numDarkImages) + 1;
|
||||||
randomImage = folderPath + "dark/" + randomIndex + ".jpg";
|
randomImage = folderPath + "dark/" + randomIndex + ".jpg";
|
||||||
darkModeIcon.onclick()
|
darkModeIcon.onclick();
|
||||||
} else {
|
} else {
|
||||||
randomIndex = Math.floor(Math.random() * numLightImages) + 1;
|
randomIndex = Math.floor(Math.random() * numLightImages) + 1;
|
||||||
randomImage = folderPath + "light/" + randomIndex + ".jpg";
|
randomImage = folderPath + "light/" + randomIndex + ".jpg";
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
const darkModeIcon = document.querySelector('#dark-mode-icon');
|
const darkModeIcon = document.querySelector("#dark-mode-icon");
|
||||||
|
|
||||||
darkModeIcon.onclick = () => {
|
darkModeIcon.onclick = () => {
|
||||||
darkModeIcon.classList.toggle('bx-sun');
|
darkModeIcon.classList.toggle("bx-sun");
|
||||||
document.body.classList.toggle('dark-mode');
|
document.body.classList.toggle("dark-mode");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
61
scripts.js
61
scripts.js
@@ -1,33 +1,36 @@
|
|||||||
// fetch all folder paths of the generators from `folders.json`
|
// fetch all folder paths of the generators from `folders.json`
|
||||||
let folderPaths = []
|
let folderPaths = [];
|
||||||
|
|
||||||
async function fetch_folders() {
|
async function fetch_folders() {
|
||||||
await fetch('./folders.json')
|
await fetch("./folders.json")
|
||||||
.then(response => response.json())
|
.then((response) => response.json())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
folderPaths = data.folder_paths;
|
folderPaths = data.folder_paths;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function get_generator_card_footer() {
|
async function get_generator_card_footer() {
|
||||||
await fetch_folders()
|
await fetch_folders();
|
||||||
const repoOwner = 'LifeAdventurer';
|
const repoOwner = "LifeAdventurer";
|
||||||
const repoName = 'generators';
|
const repoName = "generators";
|
||||||
for (let folderIndex = 1; folderIndex <= folderPaths.length; folderIndex++) {
|
for (let folderIndex = 1; folderIndex <= folderPaths.length; folderIndex++) {
|
||||||
const folderPath = folderPaths[folderIndex - 1];
|
const folderPath = folderPaths[folderIndex - 1];
|
||||||
const apiUrl = `https://api.github.com/repos/${repoOwner}/${repoName}/commits?path=${folderPath}`;
|
const apiUrl =
|
||||||
|
`https://api.github.com/repos/${repoOwner}/${repoName}/commits?path=${folderPath}`;
|
||||||
|
|
||||||
fetch(apiUrl)
|
fetch(apiUrl)
|
||||||
.then(response => response.json())
|
.then((response) => response.json())
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
// the latest commit will be at the top of the list
|
// the latest commit will be at the top of the list
|
||||||
const lastCommit = data[0].commit.author.date;
|
const lastCommit = data[0].commit.author.date;
|
||||||
const commitTimeStamp = new Date(lastCommit).getTime() / 1000;
|
const commitTimeStamp = new Date(lastCommit).getTime() / 1000;
|
||||||
const currentTimeStamp = Math.floor(new Date().getTime() / 1000);
|
const currentTimeStamp = Math.floor(new Date().getTime() / 1000);
|
||||||
const timeDifference = currentTimeStamp - commitTimeStamp;
|
const timeDifference = currentTimeStamp - commitTimeStamp;
|
||||||
|
|
||||||
$(`#last-update-${folderIndex}`).html(`Last updated ${format_time_difference(timeDifference)} ago`)
|
$(`#last-update-${folderIndex}`).html(
|
||||||
})
|
`Last updated ${format_time_difference(timeDifference)} ago`,
|
||||||
|
);
|
||||||
|
});
|
||||||
// .catch(error => console.error('Error fetching data:', error));
|
// .catch(error => console.error('Error fetching data:', error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,21 +42,21 @@ function format_time_difference(seconds) {
|
|||||||
const days = Math.floor(hours / 24);
|
const days = Math.floor(hours / 24);
|
||||||
|
|
||||||
if (days > 0) {
|
if (days > 0) {
|
||||||
return `${days} day${days > 1 ? 's' : ''}`;
|
return `${days} day${days > 1 ? "s" : ""}`;
|
||||||
} else if(hours > 0) {
|
} else if (hours > 0) {
|
||||||
return `${hours} hour${hours > 1 ? 's' : ''}`;
|
return `${hours} hour${hours > 1 ? "s" : ""}`;
|
||||||
} else if(minutes > 0) {
|
} else if (minutes > 0) {
|
||||||
return `${minutes} minute${minutes > 1 ? 's' : ''}`;
|
return `${minutes} minute${minutes > 1 ? "s" : ""}`;
|
||||||
} else {
|
} else {
|
||||||
return `${seconds} second${seconds > 1 ? 's' : ''}`;
|
return `${seconds} second${seconds > 1 ? "s" : ""}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get_generator_card_footer()
|
get_generator_card_footer();
|
||||||
|
|
||||||
const darkModeIcon = document.querySelector('#dark-mode-icon');
|
const darkModeIcon = document.querySelector("#dark-mode-icon");
|
||||||
|
|
||||||
darkModeIcon.onclick = () => {
|
darkModeIcon.onclick = () => {
|
||||||
darkModeIcon.classList.toggle('bx-sun');
|
darkModeIcon.classList.toggle("bx-sun");
|
||||||
document.body.classList.toggle('dark-mode');
|
document.body.classList.toggle("dark-mode");
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user