Style: Apply deno lint and deno fmt across codebase

This commit is contained in:
lifeadventurer
2024-10-31 19:56:47 +08:00
parent df772b0bde
commit 778cb316c0
20 changed files with 882 additions and 702 deletions

View File

@@ -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`.

View File

@@ -1,11 +1,14 @@
# List of Generators
### [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.

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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) |
|------------------------------------------------|----------------------------------------------|
| ---------------------------------------------- | -------------------------------------------- |
| ![Good Fortune](./good_fortune_statistics.png) | ![Bad Fortune](./bad_fortune_statistics.png) |
[Statistics code](../dev/main.js)

View File

@@ -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;

View File

@@ -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>

View File

@@ -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,18 +200,21 @@ 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;
@@ -167,35 +227,51 @@ function Appear() {
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);
}
@@ -213,7 +289,8 @@ function Appear() {
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;
}
@@ -224,13 +301,21 @@ function Appear() {
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
@@ -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 {

View File

@@ -1,10 +1,11 @@
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;

View File

@@ -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, () => {

View File

@@ -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,7 +37,7 @@ 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) {
@@ -47,44 +47,47 @@ const is_in_array = (str, array) => {
}
return array.indexOf(path) > -1;
}
};
// install
self.addEventListener('install', event => {
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
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());
@@ -92,11 +95,10 @@ self.addEventListener('fetch', event => {
}
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);
})
)
}),
);
}
});

View File

@@ -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>
</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>

View File

@@ -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 {

View File

@@ -1,15 +1,23 @@
<!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">
<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">
<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">
<link
href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css"
rel="stylesheet"
/>
<link rel="stylesheet" href="./css/styles.css" />
</head>
<body>
@@ -20,7 +28,7 @@
<p id="author"></p>
</div>
<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>
</div>

View File

@@ -1,10 +1,11 @@
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;

View File

@@ -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";

View File

@@ -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");
};

View File

@@ -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;
.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`)
})
$(`#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");
};