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