Compare commits
216 Commits
v1.0.0-bet
...
066f1fd060
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
066f1fd060 | ||
|
|
162eaffd1d | ||
|
|
b5a4db5224 | ||
|
|
09b3aeb8c5 | ||
|
|
c83ceef3c4 | ||
|
|
221e5219f0 | ||
|
|
145dfe964d | ||
|
|
bf9702e3a1 | ||
|
|
b3f1e6c9c5 | ||
|
|
960f3137c6 | ||
|
|
e38daf3ebb | ||
|
|
e72d16f811 | ||
|
|
dea6001234 | ||
|
|
67d7584a6e | ||
|
|
417e386412 | ||
|
|
c3d556ed80 | ||
|
|
af24e69848 | ||
|
|
6d2f1df0da | ||
|
|
037db837b2 | ||
|
|
e91fab8a94 | ||
|
|
b65ef06acd | ||
|
|
10527e4480 | ||
|
|
25d1d4f4bc | ||
|
|
b8fcb7203d | ||
|
|
79e21a1156 | ||
|
|
70d0b4460a | ||
|
|
40b1ba3542 | ||
|
|
274290cc5b | ||
|
|
fa6aa9bc7d | ||
|
|
b18c41349d | ||
|
|
b36f20c0d7 | ||
|
|
75a1d3c5aa | ||
|
|
78ab0fee06 | ||
|
|
1b8fe068f7 | ||
|
|
204635a84b | ||
|
|
21d6df56a4 | ||
|
|
514adffb9c | ||
|
|
0006634e5d | ||
|
|
fe79670273 | ||
|
|
f11af0da02 | ||
|
|
fbd56604c0 | ||
|
|
296e2665b5 | ||
|
|
70b6129c6e | ||
|
|
aa84c5f8a2 | ||
|
|
8b0a237ce4 | ||
|
|
6f89bc68fe | ||
|
|
48f7941e64 | ||
|
|
2557e76761 | ||
|
|
b2d556a9f4 | ||
|
|
b1faf87dc0 | ||
|
|
12b5d2d042 | ||
|
|
64dc0a5b1d | ||
|
|
4e63afbfc6 | ||
|
|
f8f863cada | ||
|
|
441e67a462 | ||
|
|
c01cdfd4e6 | ||
|
|
a4e609f927 | ||
|
|
ccb8be24d5 | ||
|
|
8d4cd08e2e | ||
|
|
a40c5e3951 | ||
|
|
06de7417a8 | ||
|
|
b4d1d757e1 | ||
|
|
574df2b670 | ||
|
|
a5c26a8d68 | ||
|
|
866acdb8b2 | ||
|
|
b833713afe | ||
|
|
7db04c03d7 | ||
|
|
b13c6aa488 | ||
|
|
1c1a2315a0 | ||
|
|
38ac352795 | ||
|
|
2c9392de8d | ||
|
|
71507e0164 | ||
|
|
74e8a7b34f | ||
|
|
5031b089ff | ||
|
|
8a265a2e84 | ||
|
|
fb7d78ef83 | ||
|
|
65be1b4f40 | ||
|
|
77f483bd18 | ||
|
|
a52178b5f8 | ||
|
|
1e4670c112 | ||
|
|
ed0a5de025 | ||
|
|
c73d2ebae6 | ||
|
|
f048e0bbc2 | ||
|
|
7654b2a212 | ||
|
|
cf1acb64bf | ||
|
|
6433c737d7 | ||
|
|
1e816faf00 | ||
|
|
e876fc7768 | ||
|
|
a59bce865f | ||
|
|
1003a78a2a | ||
|
|
92d739ce24 | ||
|
|
5754749af2 | ||
|
|
398be68058 | ||
|
|
efcae96a5a | ||
|
|
55caf12417 | ||
|
|
166f3b8a58 | ||
|
|
7330c24635 | ||
|
|
d2f3392722 | ||
|
|
e06139d5c0 | ||
|
|
d72b6c553f | ||
|
|
3727c5077b | ||
|
|
6234612bef | ||
|
|
85ea1c9149 | ||
|
|
44e05a166e | ||
|
|
3a9149e9a4 | ||
|
|
20288a686b | ||
|
|
8d280345ed | ||
|
|
0e22119a38 | ||
|
|
0ba0286d9c | ||
|
|
bbb49741cf | ||
|
|
538bd7caee | ||
|
|
f63bcad8eb | ||
|
|
e420fdf8fd | ||
|
|
418734cfce | ||
|
|
d08efd4d3c | ||
|
|
0e919dcb8a | ||
|
|
31034b064d | ||
|
|
a36ef5953b | ||
|
|
73405837c9 | ||
|
|
aa887b5b08 | ||
|
|
59b8d32232 | ||
|
|
4c0fc07ff8 | ||
|
|
e18c730d1e | ||
|
|
37196e1924 | ||
|
|
96178012d4 | ||
|
|
6e135949fe | ||
|
|
4964b01eac | ||
|
|
40ad57dd93 | ||
|
|
3f3d6dda0f | ||
|
|
476cafdc4a | ||
|
|
01d6cdbff4 | ||
|
|
df6b130b56 | ||
|
|
32d7d4b824 | ||
|
|
3b83c7b9e3 | ||
|
|
e3f93818d6 | ||
|
|
598601cbf2 | ||
|
|
7766ceb607 | ||
|
|
3b20e05769 | ||
|
|
b6bbdde260 | ||
|
|
824a4a229f | ||
|
|
2a3d811187 | ||
|
|
403621be40 | ||
|
|
84785f3e40 | ||
|
|
1b7ae5f1ff | ||
|
|
4a5127fecf | ||
|
|
1c8628bb3d | ||
|
|
160aab5bc2 | ||
|
|
eff286199f | ||
|
|
175f9f869f | ||
|
|
43d621324a | ||
|
|
d60d8bab51 | ||
|
|
b849b6bf7e | ||
|
|
1cf073bc51 | ||
|
|
d86f2330d5 | ||
|
|
ee461384b2 | ||
|
|
6928367884 | ||
|
|
caf08695d1 | ||
|
|
2ec9fc5412 | ||
|
|
156ef662f4 | ||
|
|
16bda15111 | ||
|
|
6789db0997 | ||
|
|
cea157765e | ||
|
|
bcdb452aa3 | ||
|
|
2346935149 | ||
|
|
f730eaa0e6 | ||
|
|
7e808e1bde | ||
|
|
22794d3f71 | ||
|
|
0195c857d5 | ||
|
|
f105be1882 | ||
|
|
313dc29a9a | ||
|
|
ac78231a78 | ||
|
|
b73e547732 | ||
|
|
94781e78b0 | ||
|
|
86126e7444 | ||
|
|
c758f13a10 | ||
|
|
d866dc6d7b | ||
|
|
c358af923a | ||
|
|
666862a6b2 | ||
|
|
325146e161 | ||
|
|
48c1b9a6cc | ||
|
|
2c4b276686 | ||
|
|
dbac251c76 | ||
|
|
0cee643697 | ||
|
|
d3eddf16d3 | ||
|
|
a90f88049b | ||
|
|
af4fca2e71 | ||
|
|
e2fe7ef955 | ||
|
|
59678748a8 | ||
|
|
d719f2fcbf | ||
|
|
f1f8172f4e | ||
|
|
cbe51784ba | ||
|
|
c27bac4ea1 | ||
|
|
da874adcad | ||
|
|
4b1433f22a | ||
|
|
4d22567ad4 | ||
|
|
3c42cfb546 | ||
|
|
b0ef08c0c2 | ||
|
|
a839eb18cd | ||
|
|
dcba35d5ae | ||
|
|
5778ddc0b9 | ||
|
|
bc4244c99a | ||
|
|
5191569e3e | ||
|
|
bb830fa313 | ||
|
|
e7427f564c | ||
|
|
0350ec09c4 | ||
|
|
99d445638f | ||
|
|
6cb60663b6 | ||
|
|
fe761241b3 | ||
|
|
549d9de5ca | ||
|
|
36d8f30fe2 | ||
|
|
a0974704c3 | ||
|
|
177cd4c34e | ||
|
|
b3dd499e17 | ||
|
|
ee5842bb1f | ||
|
|
62acdc845f | ||
|
|
1583a631a5 |
2
.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
31
.github/workflows/node.js.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
|
name: Node.js CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [14.x, 16.x]
|
||||||
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run build --if-present
|
||||||
|
- run: npm test
|
||||||
6
.gitignore
vendored
@@ -103,4 +103,8 @@ dist
|
|||||||
# TernJS port file
|
# TernJS port file
|
||||||
.tern-port
|
.tern-port
|
||||||
|
|
||||||
utils/xlsxTransform-*
|
utils/xlsxTransform-*
|
||||||
|
|
||||||
|
/.idea
|
||||||
|
|
||||||
|
__localStorage.json
|
||||||
11
.vscode/launch.json
vendored
@@ -22,6 +22,15 @@
|
|||||||
"skipFiles": [
|
"skipFiles": [
|
||||||
"<node_internals>/**"
|
"<node_internals>/**"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"name": "Attach by Process ID",
|
||||||
|
"processId": "${command:PickProcess}",
|
||||||
|
"request": "attach",
|
||||||
|
"skipFiles": [
|
||||||
|
"<node_internals>/**"
|
||||||
|
],
|
||||||
|
"type": "node"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
15
Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
FROM node:alpine
|
||||||
|
|
||||||
|
ENV NPM_CONFIG_LOGLEVEL info
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
CMD ["yarn", "dev"]
|
||||||
|
|
||||||
72
README-zh_CN.md
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Life Restart
|
||||||
|
|
||||||
|
<a href="https://discord.gg/U3qrf49NMQ"><img src="https://img.shields.io/discord/883382868427014255?color=%23FEE75C&label=Discord&logo=discord&logoColor=white&style=for-the-badge" /></a>
|
||||||
|
|
||||||
|
[English](./README.md) | 简体中文
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
- Game Life Restart
|
||||||
|
|
||||||
|
## 使用
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>网页版</strong></summary>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
1. 下载项目代码。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/VickScarlet/lifeRestart.git my-project
|
||||||
|
cd my-project
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 进入目录安装依赖。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
或者
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 启动本地服务器。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
或者
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 启动完成后会自动打开浏览器访问 [http://localhost:8081/view/index.html](http://localhost:8081/view/index.html)。
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>控制台版本</strong></summary>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node repl
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 其他版本
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>版本列表</strong></summary>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
- Cocos版:[gameall3d/LifeRestart_Cocos](https://github.com/gameall3d/LifeRestart_Cocos)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
> 更多信息请参考 [官网文档](https://liferestart.syaro.io/)。
|
||||||
73
README.md
@@ -1,2 +1,71 @@
|
|||||||
# lifeRestart
|
# Life Restart
|
||||||
Game Life Restart
|
|
||||||
|
<a href="https://discord.gg/U3qrf49NMQ"><img src="https://img.shields.io/discord/883382868427014255?color=%23FEE75C&label=Discord&logo=discord&logoColor=white&style=for-the-badge" /></a>
|
||||||
|
|
||||||
|
English | [简体中文](./README-zh_CN.md)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
- Game Life Restart
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>Web Version</strong></summary>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
1. Clone project code.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone git@github.com:VickScarlet/lifeRestart.git my-project
|
||||||
|
cd my-project
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Installation dependence.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Start local server.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Or
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
4. After the startup is complete, will automatically open a browser and visit [http://localhost:8081/view/index.html](http://localhost:8081/view/index.html).
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>Command Line Version</strong></summary>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node repl
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Other Version
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>Versions</strong></summary>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
- Cocos Ver: [gameall3d/LifeRestart_Cocos](https://github.com/gameall3d/LifeRestart_Cocos)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
> More instructions at [documentation](https://liferestart.syaro.io/).
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html lang="{{ site.lang | default: "en-US" }}">
|
<html lang="{{ site.lang | default: "en-US" }}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<script data-ad-client="ca-pub-9857163863537600" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||||
{% seo %}
|
{% seo %}
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||||
<link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" as="style" type="text/css" crossorigin>
|
<link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" as="style" type="text/css" crossorigin>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
<h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>
|
<h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>
|
||||||
<h2 class="project-tagline">{{ page.description | default: site.description | default: site.github.project_tagline }}</h2>
|
<h2 class="project-tagline">{{ page.description | default: site.description | default: site.github.project_tagline }}</h2>
|
||||||
<a href="/view/" class="btn">RESTART</a>
|
<a href="/view/" class="btn">RESTART</a>
|
||||||
|
<a href="/view/test.html" class="btn">Source Version</a>
|
||||||
{% if site.github.is_project_page %}
|
{% if site.github.is_project_page %}
|
||||||
<a href="{{ site.github.repository_url }}" class="btn">View on GitHub</a>
|
<a href="{{ site.github.repository_url }}" class="btn">View on GitHub</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
1460
data/achievement.json
Normal file
BIN
data/achievement.xlsx
Normal file
504
data/age.csv
Normal file
39474
data/age.json
BIN
data/age.xlsx
1750
data/events.csv
Normal file
1705
data/events.json
BIN
data/events.xlsx
BIN
data/specialthanks-afd.xlsx
Normal file
BIN
data/specialthanks-dun.xlsx
Normal file
4322
data/specialthanks.json
Normal file
136
data/talents.csv
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
$id,name,description,condition,grade,status,effect:SPR,effect:MNY,effect:CHR,effect:STR,effect:INT,exclusive[],exclusive[],exclusive[],exclusive[],exclusive[],exclusive[]
|
||||||
|
序号,天赋名,括号中的内容,触发条件,稀有度,初始可用属性点,额外快乐,额外家境,额外颜值,额外体质,额外智力,互斥天赋,互斥天赋,互斥天赋,互斥天赋,互斥天赋,互斥天赋
|
||||||
|
1001,随身玉佩,或许有护佑作用,,0,,,,,,,,,,,,
|
||||||
|
1002,红肚兜,小时候死亡率降低,,0,,,,,,,,,,,,
|
||||||
|
1003,生而为男,性别一定为男,,1,,,,,,,1004,1025,1024,1113,,
|
||||||
|
1004,生而为女,性别一定为女,,1,,,,,,,1003,1024,1025,,,
|
||||||
|
1005,动漫高手,入宅的可能性翻6倍,,2,,,,,,,,,,,,
|
||||||
|
1006,乐观,快乐+1,,0,,1,,,,,,,,,,
|
||||||
|
1007,天赋异禀,初始可用属性点+2,,1,2,,,,,,,,,,,
|
||||||
|
1008,天生抑郁,快乐-3,,0,,-3,,,,,,,,,,
|
||||||
|
1009,网络巨魔,快乐+2,,1,,2,,,,,,,,,,
|
||||||
|
1010,天龙人,你拥有北京户口,,2,,,,,,,1012,1013,1014,,,
|
||||||
|
1011,独生子女,你没有兄弟姐妹,,0,,,,,,,,,,,,
|
||||||
|
1012,乡间微风,你出生在农村,,0,,,,,,,1010,1013,1014,,,
|
||||||
|
1013,城中高楼,你出生在城市,,0,,,,,,,1010,1012,1014,,,
|
||||||
|
1014,美籍华人,你有美国国籍,,2,,,3,,,,1010,1012,1013,,,
|
||||||
|
1015,家中老大,你最受父母宠爱,,1,,,,,,,,,,,,
|
||||||
|
1016,水性良好,不会被淹死,,0,,,,,,,,,,,,
|
||||||
|
1017,先天免疫,你不会得艾滋病,,0,,,,,,,,,,,,
|
||||||
|
1018,人类进化,所有属性+1,,2,,1,1,1,1,1,,,,,,
|
||||||
|
1019,超凡,初始可用属性点+4,,2,4,,,,,,,,,,,
|
||||||
|
1020,父母美貌,颜值+2,,1,,,,2,,,,,,,,
|
||||||
|
1021,红颜薄命,颜值+2,体质-2,,0,,,,2,-2,,,,,,,
|
||||||
|
1022,属蛇,不会被蛇咬死,,0,,,,,,,,,,,,
|
||||||
|
1023,半神,所有属性+2,,3,,2,2,2,2,2,,,,,,
|
||||||
|
1024,人中龙凤,天生双重性别,,2,,,,,,,1003,1004,1025,,,
|
||||||
|
1025,阴阳之外,天生无性别,,2,,,,,,,1003,1024,1004,1113,,
|
||||||
|
1026,彩虹之下,可能和同性交往,,0,,,,,,,1113,,,,,
|
||||||
|
1027,斩情证道,终生不恋爱结婚,,1,,,,,,,1113,,,,,
|
||||||
|
1028,桃花连连,恋爱机会提升,,0,,,,,,,,,,,,
|
||||||
|
1029,平安童年,12岁前父母都健在,,1,,,,,,,,,,,,
|
||||||
|
1030,宠物大师,宠物不会意外死亡,,0,,,,,,,,,,,,
|
||||||
|
1031,天生残疾,体质-2,,0,,,,,-2,,,,,,,
|
||||||
|
1032,早产儿,所有属性-1,,0,,-1,-1,-1,-1,-1,,,,,,
|
||||||
|
1033,十死无生,体质-10,,0,,,,,-10,,,,,,,
|
||||||
|
1034,家运不顺,家境-2,,0,,,-2,,,,,,,,,
|
||||||
|
1035,头着地,智力-2,,0,,,,,,-2,,,,,,
|
||||||
|
1036,胎教,智力+1,,0,,,,,,1,,,,,,
|
||||||
|
1037,班中红人,和同学容易处好关系,,0,,,,,,,,,,,,
|
||||||
|
1038,骑士,能轻松学会骑车,,0,,,,,,,,,,,,
|
||||||
|
1039,永远的神,电竞天才,,1,,,,,,,,,,,,
|
||||||
|
1040,戒律,赌毒不沾,,0,,,,,,,,,,,,
|
||||||
|
1041,丁克,不生孩子,,1,,,,,,,1113,,,,,
|
||||||
|
1042,少数民族,高考+5分,,0,,,,,,,,,,,,
|
||||||
|
1043,老司机,你和家人不会发生车祸,,0,,,,,,,,,,,,
|
||||||
|
1044,低压,你的家人不会心脏病,,0,,,,,,,,,,,,
|
||||||
|
1045,战功,你退伍后会当官,,0,,,,,,,,,,,,
|
||||||
|
1046,不孕不育,你生不出孩子,,1,,,,,,,1113,,,,,
|
||||||
|
1047,白头偕老,爱人至少能活到70岁,,1,,,,,,,,,,,,
|
||||||
|
1048,神秘的小盒子,100岁时才能开启,,3,,,,,,,,,,,,
|
||||||
|
1049,三十而立,30岁时家境+2,AGE?[30],0,,,2,,,,,,,,,
|
||||||
|
1050,四十不惑,40岁时智力+2,AGE?[40],0,,,,,,2,,,,,,
|
||||||
|
1051,知天命,50岁时智力、快乐+1,AGE?[50],0,,1,,,,1,,,,,,
|
||||||
|
1052,耳顺,60岁时快乐+2,AGE?[60],0,,2,,,,,,,,,,
|
||||||
|
1053,从心所欲,70岁时快乐+3,AGE?[70],0,,3,,,,,,,,,,
|
||||||
|
1054,老当益壮,60岁时体质+2,AGE?[60],1,,,,,2,,,,,,,
|
||||||
|
1055,鹤发童颜,70岁时颜值+3,AGE?[70],0,,,,3,,,,,,,,
|
||||||
|
1056,学前启蒙,5岁时智力+2,AGE?[5],1,,,,,,2,,,,,,
|
||||||
|
1057,十八变,18岁时颜值+2,AGE?[18],1,,,,2,,,,,,,,
|
||||||
|
1058,迟来之财,90岁时家境+4,AGE?[90],0,,,4,,,,,,,,,
|
||||||
|
1059,理财达人,40岁时家境+3,AGE?[40],0,,,3,,,,,,,,,
|
||||||
|
1060,成熟,18岁时智力+2,AGE?[18],1,,,,,,2,,,,,,
|
||||||
|
1061,形象管理,24岁时颜值+2,AGE?[24],1,,,,2,,,,,,,,
|
||||||
|
1062,成年礼,18岁时快乐+1,AGE?[18],0,,1,,,,,,,,,,
|
||||||
|
1063,开光之胎,初始可用属性点+1,,0,1,,,,,,,,,,,
|
||||||
|
1064,天命,初始可用属性点+8,,3,8,,,,,,,,,,,
|
||||||
|
1065,祖传药丸,功能不明,,1,,,,,,,,,,,,
|
||||||
|
1066,精准扶贫,家境为0时家境+1,(MNY<1)&(MNY>-1),0,,,1,,,,,,,,,
|
||||||
|
1067,乐天派,快乐为0时快乐+1,(SPR<1)&(SPR>-1),1,,1,,,,,,,,,,
|
||||||
|
1068,命悬一线,体质为0时体质+1,(STR<1)&(STR>-1),0,,,,,1,,,,,,,
|
||||||
|
1069,智可生财,若20岁时智力>8,家境+2,(AGE?[20])&(INT>8),0,,,2,,,,,,,,,
|
||||||
|
1070,舔狗甚多,若20岁时颜值>8,快乐+2,(AGE?[20])&(CHR>8),0,,2,,,,,,,,,,
|
||||||
|
1071,保胎丸,你不会胎死腹中,,0,,,,,,,,,,,,
|
||||||
|
1072,白化病,你不会遭遇枪击,,0,,,,,,,,,,,,
|
||||||
|
1073,佛宗,考上哈佛大学的几率提高,,0,,,,,,,,,,,,
|
||||||
|
1074,悟道,智力>10时快乐+3,INT>10,1,,3,,,,,,,,,,
|
||||||
|
1075,驻颜,体质>10时颜值+3,STR>10,0,,,,3,,,,,,,,
|
||||||
|
1076,界限突破,体质>10时快乐+3,STR>10,1,,3,,,,,,,,,,
|
||||||
|
1077,倾城,颜值>10时快乐+3,CHR>10,1,,3,,,,,,,,,,
|
||||||
|
1078,训练有方,智力>10时体质+3,INT>10,0,,,,,3,,,,,,,
|
||||||
|
1079,相由心生,智力>10时颜值+3,INT>10,0,,,,3,,,,,,,,
|
||||||
|
1080,智多鑫,智力>10时家境+3,INT>10,0,,,3,,,,,,,,,
|
||||||
|
1081,灵光,快乐>10时其他属性+1,SPR>10,0,,,1,1,1,1,,,,,,
|
||||||
|
1082,天启,快乐>10时其他属性+2,SPR>10,1,,,2,2,2,2,,,,,,
|
||||||
|
1083,神谕,快乐>10时其他属性+3,SPR>10,2,,,3,3,3,3,,,,,,
|
||||||
|
1084,献祭,初始可用属性点-2,快乐+2,,0,-2,2,,,,,1122,,,,,
|
||||||
|
1085,幸运儿,初始可用属性点-3,快乐+5,,1,-3,5,,,,,1122,,,,,
|
||||||
|
1086,挑战者,初始可用点-10,,0,-10,,,,,,1122,,,,,
|
||||||
|
1087,你不懂,家境>10时快乐+3,MNY>10,1,,3,,,,,,,,,,
|
||||||
|
1088,整容,家境>10时颜值+3,MNY>10,0,,,,3,,,,,,,,
|
||||||
|
1089,钻石健身卡,家境>10时体质+3,MNY>10,0,,,,,3,,,,,,,
|
||||||
|
1090,身残志坚,体质<0时其他属性+1,STR<0,0,,1,1,1,,1,,,,,,
|
||||||
|
1091,活死人,体质<0时其他属性+2,STR<0,1,,2,2,2,,2,,,,,,
|
||||||
|
1092,开一扇窗,颜值<0时其他属性+1,CHR<0,0,,1,1,,1,1,,,,,,
|
||||||
|
1093,大额头,颜值-2,智力+2,,0,,,,-2,,2,,,,,,
|
||||||
|
1094,痘痘脸,颜值-1,,0,,,,-1,,,,,,,,
|
||||||
|
1095,潜能,家境<0时其他属性+1,MNY<0,0,,1,,1,1,1,,,,,,
|
||||||
|
1096,哀兵,快乐<0时其他属性+1,SPR<0,0,,,1,1,1,1,,,,,,
|
||||||
|
1097,苦痛侍僧,快乐<-1时其他属性+2,SPR<-1,1,,,2,2,2,2,,,,,,
|
||||||
|
1098,觉醒,家境<-1时其他属性+2,MNY<-1,1,,2,,2,2,2,,,,,,
|
||||||
|
1099,抖M,家境-2,快乐+2,,0,,2,-2,,,,,,,,,
|
||||||
|
1100,海的女儿,颜值-2,初始可用属性点+1,,0,1,,,-2,,,,,,,,
|
||||||
|
1101,进阶,所有属性>5时,所有属性+1,(SPR>5)&(MNY>5)&(CHR>5)&(STR>5)&(INT>5),0,,1,1,1,1,1,,,,,,
|
||||||
|
1102,超进化,所有属性>5时,所有属性+2,(SPR>5)&(MNY>5)&(CHR>5)&(STR>5)&(INT>5),1,,2,2,2,2,2,,,,,,
|
||||||
|
1103,白色胶囊,你10岁时无事发生,AGE?[10],0,,,,,,,,,,,,
|
||||||
|
1104,紫色胶囊,跳过你的40~50岁,"AGE?[40,41,42,43,44,45,46,47,48,49,50]",2,,,,,,,,,,,,
|
||||||
|
1105,蓝色胶囊,你20、30岁时无事发生,"AGE?[20,30]",1,,,,,,,,,,,,
|
||||||
|
1106,健康饮食,你不吃洋快餐,,0,,,,,,,,,,,,
|
||||||
|
1107,不想罢了,你不会上清华大学,,0,,,,,,,,,,,,
|
||||||
|
1108,挑衅,你喜欢没事找事,,0,,,,,,,,,,,,
|
||||||
|
1109,旅行者,你喜欢旅游,,0,,,,,,,,,,,,
|
||||||
|
1110,水仙,你比较自恋,,0,,,,,,,,,,,,
|
||||||
|
1111,缺一门,无效果,,0,,,,,,,,,,,,
|
||||||
|
1112,异界来客,你可能听到一些绝密消息,,2,,,,,,,,,,,,
|
||||||
|
1113,三胎人生,你尽可能生三胎,,1,,,,,,,1003,1025,1026,1027,1041,1046
|
||||||
|
1114,橙色胶囊,跳过你的60~90岁,"AGE?[60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90]",3,,,,,,,,,,,,
|
||||||
|
1115,宙斯,参加奥赛的几率提高,,0,,,,,,,,,,,,
|
||||||
|
1116,为人民服务,考公务员时一定能考上,,0,,,,,,,,,,,,
|
||||||
|
1117,表现良好,入狱会减刑,,0,,,,,,,,,,,,
|
||||||
|
1118,小吉,运气稍微提升,,0,,,,,,,,,,,,
|
||||||
|
1119,天秤座,据说做事很公平,,0,,,,,,,,,,,,
|
||||||
|
1120,万里挑一,你很攻,,0,,,,,,,,,,,,
|
||||||
|
1121,把握不住,你有强迫症,,0,,,,,,,,,,,,
|
||||||
|
1122,急了急了,赶着投胎,不要初始属性了,,1,-20,,,,,,1084,1085,1086,,,
|
||||||
|
1123,不离不弃,你不会离婚,,0,,,,,,,,,,,,
|
||||||
|
1124,足量,身高不矮,,0,,,,,,,,,,,,
|
||||||
|
1125,易胖体质,颜值更容易降低,,0,,,,,,,,,,,,
|
||||||
|
1126,黄帝,种族主义者,,0,,,,,,,,,,,,
|
||||||
|
1127,左撇子,习惯使用左手,,0,,,,,,,,,,,,
|
||||||
|
1128,克苏鲁,&▓▓▓◆▓▓▓¥#▓@■.◆,,2,,,,,,,,,,,,
|
||||||
|
1129,不连续存在,你还拥有其他人格,,1,,,,,,,,,,,,
|
||||||
|
1130,占位符,少一个可选天赋,,0,,,,,,,,,,,,
|
||||||
|
1131,魔法棒,不知道有什么用……,,2,,,,,,,,,,,,
|
||||||
|
1132,返老还童,可能会回到年轻的时候,,1,,,,,,,,,,,,
|
||||||
|
1133,时光倒流,或许时间会倒流,,0,,,,,,,,,,,,
|
||||||
|
1134,转世重修,渡劫失败重生,,2,,,,,,,,,,,,
|
||||||
|
@@ -19,8 +19,7 @@
|
|||||||
"exclusive": [
|
"exclusive": [
|
||||||
"1004",
|
"1004",
|
||||||
"1025",
|
"1025",
|
||||||
"1024",
|
"1024"
|
||||||
1113
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"1004": {
|
"1004": {
|
||||||
@@ -42,7 +41,7 @@
|
|||||||
},
|
},
|
||||||
"1006": {
|
"1006": {
|
||||||
"id": "1006",
|
"id": "1006",
|
||||||
"name": "乐天派",
|
"name": "乐观",
|
||||||
"description": "快乐+1",
|
"description": "快乐+1",
|
||||||
"grade": 0,
|
"grade": 0,
|
||||||
"effect": {
|
"effect": {
|
||||||
@@ -79,6 +78,9 @@
|
|||||||
"name": "天龙人",
|
"name": "天龙人",
|
||||||
"description": "你拥有北京户口",
|
"description": "你拥有北京户口",
|
||||||
"grade": 2,
|
"grade": 2,
|
||||||
|
"effect": {
|
||||||
|
"MNY": 1
|
||||||
|
},
|
||||||
"exclusive": [
|
"exclusive": [
|
||||||
"1012",
|
"1012",
|
||||||
"1013",
|
"1013",
|
||||||
@@ -119,7 +121,7 @@
|
|||||||
"description": "你有美国国籍",
|
"description": "你有美国国籍",
|
||||||
"grade": 2,
|
"grade": 2,
|
||||||
"effect": {
|
"effect": {
|
||||||
"MNY": 3
|
"MNY": 1
|
||||||
},
|
},
|
||||||
"exclusive": [
|
"exclusive": [
|
||||||
"1010",
|
"1010",
|
||||||
@@ -502,31 +504,31 @@
|
|||||||
"1059": {
|
"1059": {
|
||||||
"id": "1059",
|
"id": "1059",
|
||||||
"name": "理财达人",
|
"name": "理财达人",
|
||||||
"description": "30、40、50岁时家境+1",
|
"description": "40岁时家境+3",
|
||||||
"condition": "AGE?[30,40,50]",
|
"condition": "AGE?[40]",
|
||||||
"grade": 0,
|
"grade": 0,
|
||||||
"effect": {
|
"effect": {
|
||||||
"MNY": 1
|
"MNY": 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"1060": {
|
"1060": {
|
||||||
"id": "1060",
|
"id": "1060",
|
||||||
"name": "成熟",
|
"name": "成熟",
|
||||||
"description": "12、18岁时智力+1",
|
"description": "18岁时智力+2",
|
||||||
"condition": "AGE?[12,18]",
|
"condition": "AGE?[18]",
|
||||||
"grade": 1,
|
"grade": 1,
|
||||||
"effect": {
|
"effect": {
|
||||||
"INT": 1
|
"INT": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"1061": {
|
"1061": {
|
||||||
"id": "1061",
|
"id": "1061",
|
||||||
"name": "形象管理",
|
"name": "形象管理",
|
||||||
"description": "16、24岁时颜值+1",
|
"description": "24岁时颜值+2",
|
||||||
"condition": "AGE?[16,24]",
|
"condition": "AGE?[24]",
|
||||||
"grade": 1,
|
"grade": 1,
|
||||||
"effect": {
|
"effect": {
|
||||||
"CHR": 1
|
"CHR": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"1062": {
|
"1062": {
|
||||||
@@ -818,7 +820,7 @@
|
|||||||
"1091": {
|
"1091": {
|
||||||
"id": "1091",
|
"id": "1091",
|
||||||
"name": "活死人",
|
"name": "活死人",
|
||||||
"description": "体质<-1时其他属性+2",
|
"description": "体质<0时其他属性+2",
|
||||||
"condition": "STR<0",
|
"condition": "STR<0",
|
||||||
"grade": 1,
|
"grade": 1,
|
||||||
"effect": {
|
"effect": {
|
||||||
@@ -901,7 +903,7 @@
|
|||||||
},
|
},
|
||||||
"1098": {
|
"1098": {
|
||||||
"id": "1098",
|
"id": "1098",
|
||||||
"name": "觉醒",
|
"name": "艰苦奋斗",
|
||||||
"description": "家境<-1时其他属性+2",
|
"description": "家境<-1时其他属性+2",
|
||||||
"condition": "MNY<-1",
|
"condition": "MNY<-1",
|
||||||
"grade": 1,
|
"grade": 1,
|
||||||
@@ -971,14 +973,14 @@
|
|||||||
"id": "1104",
|
"id": "1104",
|
||||||
"name": "紫色胶囊",
|
"name": "紫色胶囊",
|
||||||
"description": "跳过你的40~50岁",
|
"description": "跳过你的40~50岁",
|
||||||
"condition": "AGE?[40,41,42,43,44,45,46,47,48,49,50]",
|
"condition": "AGE?[40]",
|
||||||
"grade": 2
|
"grade": 2
|
||||||
},
|
},
|
||||||
"1105": {
|
"1105": {
|
||||||
"id": "1105",
|
"id": "1105",
|
||||||
"name": "蓝色胶囊",
|
"name": "蓝色胶囊",
|
||||||
"description": "你20、30岁时无事发生",
|
"description": "你20、30岁时无事发生",
|
||||||
"condition": "AGE?[20,30]",
|
"condition": "AGE?[20]",
|
||||||
"grade": 1
|
"grade": 1
|
||||||
},
|
},
|
||||||
"1106": {
|
"1106": {
|
||||||
@@ -1041,7 +1043,7 @@
|
|||||||
"id": "1114",
|
"id": "1114",
|
||||||
"name": "橙色胶囊",
|
"name": "橙色胶囊",
|
||||||
"description": "跳过你的60~90岁",
|
"description": "跳过你的60~90岁",
|
||||||
"condition": "AGE?[60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90]",
|
"condition": "AGE?[60]",
|
||||||
"grade": 3
|
"grade": 3
|
||||||
},
|
},
|
||||||
"1115": {
|
"1115": {
|
||||||
@@ -1138,7 +1140,7 @@
|
|||||||
"id": "1129",
|
"id": "1129",
|
||||||
"name": "不连续存在",
|
"name": "不连续存在",
|
||||||
"description": "你还拥有其他人格",
|
"description": "你还拥有其他人格",
|
||||||
"grade": 2
|
"grade": 1
|
||||||
},
|
},
|
||||||
"1130": {
|
"1130": {
|
||||||
"id": "1130",
|
"id": "1130",
|
||||||
@@ -1151,5 +1153,183 @@
|
|||||||
"name": "魔法棒",
|
"name": "魔法棒",
|
||||||
"description": "不知道有什么用……",
|
"description": "不知道有什么用……",
|
||||||
"grade": 2
|
"grade": 2
|
||||||
|
},
|
||||||
|
"1132": {
|
||||||
|
"id": 1132,
|
||||||
|
"name": "返老还童",
|
||||||
|
"description": "可能会回到年轻的时候",
|
||||||
|
"grade": 1
|
||||||
|
},
|
||||||
|
"1133": {
|
||||||
|
"id": 1133,
|
||||||
|
"name": "时光倒流",
|
||||||
|
"description": "或许时间会倒流",
|
||||||
|
"grade": 0
|
||||||
|
},
|
||||||
|
"1134": {
|
||||||
|
"id": 1134,
|
||||||
|
"name": "转世重修",
|
||||||
|
"description": "渡劫失败重生",
|
||||||
|
"grade": 2
|
||||||
|
},
|
||||||
|
"1135": {
|
||||||
|
"id": 1135,
|
||||||
|
"name": "轮回之外",
|
||||||
|
"description": "死后可能灵魂离体",
|
||||||
|
"grade": 3
|
||||||
|
},
|
||||||
|
"1136": {
|
||||||
|
"id": 1136,
|
||||||
|
"name": "贪婪",
|
||||||
|
"description": "家境+10",
|
||||||
|
"grade": 0,
|
||||||
|
"effect": {
|
||||||
|
"INT": -5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1137": {
|
||||||
|
"id": 1137,
|
||||||
|
"name": "百岁百世丸",
|
||||||
|
"description": "某条件下所有属性+2",
|
||||||
|
"condition": "(AGE?[100])&(TMS>99)",
|
||||||
|
"grade": 1,
|
||||||
|
"effect": {
|
||||||
|
"SPR": 2,
|
||||||
|
"MNY": 2,
|
||||||
|
"CHR": 2,
|
||||||
|
"STR": 2,
|
||||||
|
"INT": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1138": {
|
||||||
|
"id": 1138,
|
||||||
|
"name": "意外之喜",
|
||||||
|
"description": "随机属性+1",
|
||||||
|
"grade": 0,
|
||||||
|
"effect": {
|
||||||
|
"RDM": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1139": {
|
||||||
|
"id": 1139,
|
||||||
|
"name": "培养爱好",
|
||||||
|
"description": "随机属性+2",
|
||||||
|
"grade": 1,
|
||||||
|
"effect": {
|
||||||
|
"RDM": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1140": {
|
||||||
|
"id": 1140,
|
||||||
|
"name": "觉醒",
|
||||||
|
"description": "随机属性+4",
|
||||||
|
"grade": 2,
|
||||||
|
"effect": {
|
||||||
|
"RDM": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1141": {
|
||||||
|
"id": 1141,
|
||||||
|
"name": "阴间大会员",
|
||||||
|
"description": "随机属性+8",
|
||||||
|
"grade": 3,
|
||||||
|
"effect": {
|
||||||
|
"RDM": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1142": {
|
||||||
|
"id": 1142,
|
||||||
|
"name": "蓝色转盘",
|
||||||
|
"description": "变成随机蓝色天赋",
|
||||||
|
"grade": 0,
|
||||||
|
"replacement": {
|
||||||
|
"grade": [
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclusive": [
|
||||||
|
"1012",
|
||||||
|
"1013",
|
||||||
|
"1014",
|
||||||
|
1110,
|
||||||
|
1003,
|
||||||
|
1004,
|
||||||
|
1124,
|
||||||
|
1125
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"1143": {
|
||||||
|
"id": 1143,
|
||||||
|
"name": "紫色转盘",
|
||||||
|
"description": "变成随机紫色天赋",
|
||||||
|
"grade": 1,
|
||||||
|
"replacement": {
|
||||||
|
"grade": [
|
||||||
|
2
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclusive": [
|
||||||
|
"1012",
|
||||||
|
"1013",
|
||||||
|
"1014",
|
||||||
|
1110,
|
||||||
|
1003,
|
||||||
|
1004,
|
||||||
|
1124,
|
||||||
|
1125
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"1144": {
|
||||||
|
"id": 1144,
|
||||||
|
"name": "橙色转盘",
|
||||||
|
"description": "变成随机橙色天赋",
|
||||||
|
"grade": 2,
|
||||||
|
"replacement": {
|
||||||
|
"grade": [
|
||||||
|
3
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1145": {
|
||||||
|
"id": 1145,
|
||||||
|
"name": "阴间福袋",
|
||||||
|
"description": "可能开出好天赋",
|
||||||
|
"grade": 1,
|
||||||
|
"replacement": {
|
||||||
|
"talent": [
|
||||||
|
1138,
|
||||||
|
1133,
|
||||||
|
1125,
|
||||||
|
1128,
|
||||||
|
1129,
|
||||||
|
1131,
|
||||||
|
1111,
|
||||||
|
1108,
|
||||||
|
1071,
|
||||||
|
1072,
|
||||||
|
1044,
|
||||||
|
1039,
|
||||||
|
1040,
|
||||||
|
1033,
|
||||||
|
1031,
|
||||||
|
1002
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1146": {
|
||||||
|
"id": 1146,
|
||||||
|
"name": "轮盘赌",
|
||||||
|
"description": "1/6几率变橙色天赋",
|
||||||
|
"grade": 1,
|
||||||
|
"replacement": {
|
||||||
|
"talent": [
|
||||||
|
"1141*0.2",
|
||||||
|
"1135*0.2",
|
||||||
|
"1114*0.2",
|
||||||
|
"1023*0.2",
|
||||||
|
"1048*0.2",
|
||||||
|
"1033*5"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2
index.md
@@ -1,3 +1,5 @@
|
|||||||
# Life Restart
|
# Life Restart
|
||||||
|
|
||||||
やり直すんだ。そして、次はうまくやる。[RESTART](view/index.html)
|
やり直すんだ。そして、次はうまくやる。[RESTART](view/index.html)
|
||||||
|
|
||||||
|
<iframe src="https://discord.com/widget?id=883382868427014255&theme=dark" width="350" height="500" allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>
|
||||||
2
lib/dom-to-image.min.js
vendored
Normal file
2
lib/jquery-3.6.0.min.js
vendored
Normal file
19
package.json
@@ -1,12 +1,23 @@
|
|||||||
{
|
{
|
||||||
"name": "xlsx_transform",
|
"name": "life_restart",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": "test/index.js",
|
"bin": "repl/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test",
|
"test": "node test",
|
||||||
"xlsxTransform": "node utils/xlsxTransform.js data"
|
"xlsxTransform": "vt transform data",
|
||||||
|
"dev": "webpack serve --open /view/index.html",
|
||||||
|
"build": "webpack --mode production"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"xlsx": "^0.17.0"
|
"@babel/core": "^7.15.4",
|
||||||
|
"@babel/preset-env": "^7.15.4",
|
||||||
|
"babel-loader": "^8.2.2",
|
||||||
|
"core-js": "^3.17.2",
|
||||||
|
"v-transform": "^1.0.1",
|
||||||
|
"webpack": "^5.64.2",
|
||||||
|
"webpack-dev-server": "^4.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"webpack-cli": "^4.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
public/bundle.js
Normal file
639
repl/app.js
Normal file
@@ -0,0 +1,639 @@
|
|||||||
|
import { summary } from '../src/functions/summary.js'
|
||||||
|
import { readFile } from 'fs/promises';
|
||||||
|
import Life from '../src/life.js';
|
||||||
|
|
||||||
|
globalThis.json = async fileName => JSON.parse(await readFile(`data/${fileName}.json`));
|
||||||
|
|
||||||
|
globalThis.$$eventMap = new Map();
|
||||||
|
globalThis.$$event = (tag, data) => {
|
||||||
|
const listener = $$eventMap.get(tag);
|
||||||
|
if(listener) listener.forEach(fn=>fn(data));
|
||||||
|
}
|
||||||
|
globalThis.$$on = (tag, fn) => {
|
||||||
|
let listener = $$eventMap.get(tag);
|
||||||
|
if(!listener) {
|
||||||
|
listener = new Set();
|
||||||
|
$$eventMap.set(tag, listener);
|
||||||
|
}
|
||||||
|
listener.add(fn);
|
||||||
|
}
|
||||||
|
globalThis.$$off = (tag, fn) => {
|
||||||
|
const listener = $$eventMap.get(tag);
|
||||||
|
if(listener) listener.delete(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
class App {
|
||||||
|
constructor() {
|
||||||
|
this.#life = new Life();
|
||||||
|
}
|
||||||
|
|
||||||
|
Steps= {
|
||||||
|
TALENT: 'talent',
|
||||||
|
PROPERTY: 'property',
|
||||||
|
TRAJECTORY: 'trajectory',
|
||||||
|
SUMMARY: 'summary',
|
||||||
|
};
|
||||||
|
|
||||||
|
#step = this.Steps.SUMMARY;
|
||||||
|
#life;
|
||||||
|
#talentSelected = new Set();
|
||||||
|
#talentExtend = new Set();
|
||||||
|
#input;
|
||||||
|
#auto;
|
||||||
|
#isEnd;
|
||||||
|
#propertyAllocation;
|
||||||
|
#output;
|
||||||
|
#exit;
|
||||||
|
#interval;
|
||||||
|
#style = {
|
||||||
|
warn: ['\x1B[93m', '\x1B[39m'], // Bright Yellow
|
||||||
|
grade1: ['\x1B[94m', '\x1B[39m'], // Bright Blue
|
||||||
|
grade2: ['\x1B[95m', '\x1B[39m'], // Bright Magenta
|
||||||
|
grade3: ['\x1B[93m', '\x1B[39m'], // Bright Yellow
|
||||||
|
grade1b: ['\x1B[94m\x1B[7m', '\x1B[0m'], // Bright Blue BG
|
||||||
|
grade2b: ['\x1B[95m\x1B[7m', '\x1B[0m'], // Bright Magenta BG
|
||||||
|
grade3b: ['\x1B[93m\x1B[7m', '\x1B[0m'], // Bright Yellow BG
|
||||||
|
};
|
||||||
|
#randomTalents;
|
||||||
|
|
||||||
|
style(type, str) {
|
||||||
|
const style = this.#style[type];
|
||||||
|
if(!style) return str;
|
||||||
|
return `${style[0]}${str}${style[1]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async initial() {
|
||||||
|
this.output('Now Loading...');
|
||||||
|
this.#talentExtend = localStorage.talentExtend;
|
||||||
|
await this.#life.initial();
|
||||||
|
this.output(`\rLoading Complete.
|
||||||
|
人生重开模拟器
|
||||||
|
这垃圾人生一秒也不想待了
|
||||||
|
|
||||||
|
键入 \x1B[4m/remake\x1B[24m 开始游戏
|
||||||
|
键入 \x1B[4m/help\x1B[24m 获取帮助`,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
$$on('achievement', ({name})=>this.output(`
|
||||||
|
-------------------------
|
||||||
|
解锁成就【${name}】
|
||||||
|
-------------------------
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
||||||
|
io(input, output, exit) {
|
||||||
|
this.#input = input;
|
||||||
|
this.#output = output;
|
||||||
|
this.#exit = exit;
|
||||||
|
input(command=>{
|
||||||
|
const ret = this.repl(command);
|
||||||
|
if(!ret) return;
|
||||||
|
if(typeof ret == 'string') return this.output(ret, true);
|
||||||
|
if(Array.isArray(ret)) return this.output(...ret);
|
||||||
|
const { message, isRepl } = ret;
|
||||||
|
return this.output(message, isRepl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
output(data, isRepl) {
|
||||||
|
if(!this.#output) return;
|
||||||
|
this.#output(data, isRepl);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(code) {
|
||||||
|
if(this.#exit) this.#exit(code);
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
repl(command) {
|
||||||
|
command = command.split(/\s+/);
|
||||||
|
switch(command.shift()) {
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
case 'remake':
|
||||||
|
case '/remake':return this.remake();
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
case 'select':
|
||||||
|
case '/select': return this.select(...command);
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
case 'unselect':
|
||||||
|
case '/unselect': return this.unselect(...command);
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
case 'next':
|
||||||
|
case '/next':
|
||||||
|
case '': return this.next(true);
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
case 'alloc':
|
||||||
|
case 'allocate':
|
||||||
|
case 'attrib':
|
||||||
|
case 'attribute':
|
||||||
|
case '/alloc':
|
||||||
|
case '/allocate':
|
||||||
|
case '/attrib':
|
||||||
|
case '/attribute': return this.attrib(...command);
|
||||||
|
|
||||||
|
case 'rd':
|
||||||
|
case 'random':
|
||||||
|
case '/random': return this.random();
|
||||||
|
|
||||||
|
case 'at':
|
||||||
|
case 'auto':
|
||||||
|
case '/auto': return this.auto(...command);
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
case 'exit':
|
||||||
|
case '/exit': return this.exit(0);
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
case 'help':
|
||||||
|
case '/?':
|
||||||
|
case '/h':
|
||||||
|
case '/help':
|
||||||
|
default: return this.help(...command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
help(key) {
|
||||||
|
|
||||||
|
switch(key) {
|
||||||
|
case 'x':
|
||||||
|
case 'exit':
|
||||||
|
case '/exit': return `退出
|
||||||
|
x, exit, /exit 命令同等效果`;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
case 'remake':
|
||||||
|
case '/remake': return `重开
|
||||||
|
r, remake, /remake 命令同等效果`;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
case 'select':
|
||||||
|
case '/select': return `选择
|
||||||
|
s, select, /select 命令同等效果
|
||||||
|
|
||||||
|
Example: /select 1 2 3 意味着选择 1 2 3 三个天赋
|
||||||
|
|
||||||
|
/select <id1> [id2] [id3]
|
||||||
|
|
||||||
|
参数解释 <id1> 通常来说要指定至少一个id
|
||||||
|
虽然不指定也可以
|
||||||
|
[id2]
|
||||||
|
[id3] 可以不指定`;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
case 'unselect':
|
||||||
|
case '/unselect': return `取消选择
|
||||||
|
u, unselect,
|
||||||
|
/unselect 命令同等效果
|
||||||
|
|
||||||
|
Example: /unselect 1 2 3
|
||||||
|
意味着取消选择 1 2 3 三个天赋
|
||||||
|
|
||||||
|
参数解释 /unselect <id1> [id2] [id3]
|
||||||
|
|
||||||
|
<id1> 通常来说要指定至少一个id
|
||||||
|
虽然不指定也可以
|
||||||
|
[id2]
|
||||||
|
[id3] 可以不指定`;
|
||||||
|
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
case 'alloc':
|
||||||
|
case 'allocate':
|
||||||
|
case 'attrib':
|
||||||
|
case 'attribute':
|
||||||
|
case '/alloc':
|
||||||
|
case '/allocate':
|
||||||
|
case '/attrib':
|
||||||
|
case '/attribute': return `分配或查看属性点
|
||||||
|
a, alloc, allocate, attrib, attribute
|
||||||
|
/alloc, /allocate, /attrib, /attribute 命令同等效果
|
||||||
|
|
||||||
|
Example: /attribute
|
||||||
|
/allocate STR 1
|
||||||
|
/allocate INT -3
|
||||||
|
/allocate CHR +5
|
||||||
|
|
||||||
|
效果 在属性分配时分配属性点
|
||||||
|
在人生的过程中查看当前属性点
|
||||||
|
|
||||||
|
参数解释 /allocate <TAG> <[+/-]value>
|
||||||
|
|
||||||
|
<TAG> 表示要分配的属性标签
|
||||||
|
可选有
|
||||||
|
CHR, chr, c, C 表示颜值
|
||||||
|
INT, int, i, I 表示智力
|
||||||
|
STR, str, s, S 表示体质
|
||||||
|
MNY, mny, m, M 表示家境
|
||||||
|
必填
|
||||||
|
|
||||||
|
<[+/-]value>
|
||||||
|
表示属性的调整
|
||||||
|
其中
|
||||||
|
+ 表示在当前基础上增加
|
||||||
|
- 表示在当前基础上减少
|
||||||
|
无符号表示直接设置为此值
|
||||||
|
必填`;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
case 'next':
|
||||||
|
case '/next': return `继续
|
||||||
|
n, next, /next 命令同等效果
|
||||||
|
|
||||||
|
效果 通常用于各步骤结束后
|
||||||
|
例如: 选择天赋后
|
||||||
|
分配属性后
|
||||||
|
每个年龄事件后
|
||||||
|
总评后
|
||||||
|
继承天赋后`;
|
||||||
|
|
||||||
|
case 'at':
|
||||||
|
case 'auto':
|
||||||
|
case '/auto': return `自动播放
|
||||||
|
at, auto, /auto 命令同等效果
|
||||||
|
|
||||||
|
效果 用于人生的过程中
|
||||||
|
每个年龄会自动下一年
|
||||||
|
播放速度 1 秒 1 年`;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
case 'help':
|
||||||
|
case '/?':
|
||||||
|
case '/h':
|
||||||
|
case '/help': return `显示帮助
|
||||||
|
?, h, help
|
||||||
|
/?, /h, /help 命令同等效果
|
||||||
|
|
||||||
|
Example: /help
|
||||||
|
/help /select
|
||||||
|
|
||||||
|
参数解释 /help [command]
|
||||||
|
|
||||||
|
[command] 要详细显示帮助的命令
|
||||||
|
可以不填`;
|
||||||
|
}
|
||||||
|
return `Help ---
|
||||||
|
命令 说明 示例
|
||||||
|
x
|
||||||
|
exit
|
||||||
|
/exit 退出 /exit
|
||||||
|
|
||||||
|
r
|
||||||
|
remake
|
||||||
|
/remake 重开 /remake
|
||||||
|
|
||||||
|
s
|
||||||
|
select
|
||||||
|
/select 选择天赋 /select <id1> [id2] [id3]
|
||||||
|
|
||||||
|
u
|
||||||
|
unselect
|
||||||
|
/unselect 取消选择 /unselect <id1> [id2] [id3]
|
||||||
|
|
||||||
|
a
|
||||||
|
alloc
|
||||||
|
allocate
|
||||||
|
attrib
|
||||||
|
attribute
|
||||||
|
/alloc
|
||||||
|
/allocate
|
||||||
|
/attrib
|
||||||
|
/attribute 分配或查看属性点 /allocate <TAG> <[+/-]value>
|
||||||
|
|
||||||
|
n
|
||||||
|
next
|
||||||
|
/next 继续 /next
|
||||||
|
|
||||||
|
at
|
||||||
|
auto
|
||||||
|
/auto 自动播放 /auto
|
||||||
|
|
||||||
|
?
|
||||||
|
h
|
||||||
|
help
|
||||||
|
/?
|
||||||
|
/h
|
||||||
|
/help 显示帮助 /help [command]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto(arg) {
|
||||||
|
this.#auto = arg != 'off';
|
||||||
|
return this.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
remake() {
|
||||||
|
if(this.#talentExtend) {
|
||||||
|
this.#life.talentExtend(this.#talentExtend)
|
||||||
|
dumpLocalStorage();
|
||||||
|
this.#talentExtend = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#isEnd = false;
|
||||||
|
this.#talentSelected.clear();
|
||||||
|
this.#propertyAllocation = {CHR:0,INT:0,STR:0,MNY:0,SPR:5};
|
||||||
|
this.#step = this.Steps.TALENT;
|
||||||
|
this.#randomTalents = this.#life.talentRandom();
|
||||||
|
return this.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
select(...select) {
|
||||||
|
switch(this.#step) {
|
||||||
|
case this.Steps.TALENT: return this.talentSelect(...select);
|
||||||
|
case this.Steps.SUMMARY: return this.talentExtend(...select);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unselect(...select) {
|
||||||
|
switch(this.#step) {
|
||||||
|
case this.Steps.TALENT: return this.talentUnSelect(...select);
|
||||||
|
case this.Steps.SUMMARY: return this.talentExtendCancle(...select);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
talentSelect(...select) {
|
||||||
|
const warn = str => `${this.list()}\n${this.style('warn', str)}`;
|
||||||
|
for(const number of select) {
|
||||||
|
const s = this.#randomTalents[number];
|
||||||
|
if(!s) return warn(`${number} 为未知天赋`);
|
||||||
|
if(this.#talentSelected.has(s)) continue;
|
||||||
|
if(this.#talentSelected.size == 3)
|
||||||
|
return warn('你只能选3个天赋。请使用 \x1B[4m/unselect\x1B[24m 取消选择你不想要的天赋');
|
||||||
|
|
||||||
|
const exclusive = this.#life.exclusive(
|
||||||
|
Array.from(this.#talentSelected).map(({id})=>id),
|
||||||
|
s.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if(exclusive != null)
|
||||||
|
for(const { name, id } of this.#talentSelected)
|
||||||
|
if(id == exclusive)
|
||||||
|
return warn(`天赋【${s.name}】与已选择的天赋【${name}】冲突`);
|
||||||
|
|
||||||
|
this.#talentSelected.add(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
talentUnSelect(...select) {
|
||||||
|
for(const number of select) {
|
||||||
|
const s = this.#randomTalents[number];
|
||||||
|
if(this.#talentSelected.has(s))
|
||||||
|
this.#talentSelected.delete(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
talentExtend(select) {
|
||||||
|
const warn = str => `${this.list()}\n${this.style('warn', str)}`;
|
||||||
|
const list = Array.from(this.#talentSelected);
|
||||||
|
const s = list[select];
|
||||||
|
if(!s) return warn(`${select} 为未知天赋`);
|
||||||
|
this.#talentExtend = s.id;
|
||||||
|
return this.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
talentExtendCancle() {
|
||||||
|
this.#talentExtend = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
list() {
|
||||||
|
let description, list, check;
|
||||||
|
switch(this.#step) {
|
||||||
|
case this.Steps.TALENT:
|
||||||
|
description = '🎉 请选择(\x1B[4m/select\x1B[24m)3 个天赋';
|
||||||
|
list = this.#randomTalents;
|
||||||
|
check = talent=>this.#talentSelected.has(talent);
|
||||||
|
break;
|
||||||
|
case this.Steps.SUMMARY:
|
||||||
|
description = '🎉 你可以选(\x1B[4m/select\x1B[24m)一个天赋继承';
|
||||||
|
list = Array.from(this.#talentSelected);
|
||||||
|
check = ({id})=>this.#talentExtend == id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!list) return '';
|
||||||
|
|
||||||
|
return [description, list.map(
|
||||||
|
(talent, i) =>
|
||||||
|
this.style(
|
||||||
|
`grade${talent.grade}b`,
|
||||||
|
`${check(talent)?'√':' '} ${i} ${talent.name}(${talent.description})`
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
.flat()
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
next(enter) {
|
||||||
|
const warn = (a, b) => `${a}\n${this.style('warn', this.style('warn', b))}`;
|
||||||
|
switch(this.#step) {
|
||||||
|
case this.Steps.TALENT:
|
||||||
|
if(this.#talentSelected.size != 3) return warn(this.list(), `请选择 3 个天赋`);
|
||||||
|
this.#step = this.Steps.PROPERTY;
|
||||||
|
this.#propertyAllocation.total = 20 + this.#life.getTalentAllocationAddition(
|
||||||
|
Array.from(this.#talentSelected).map(({id})=>id)
|
||||||
|
);
|
||||||
|
this.#propertyAllocation.TLT = Array.from(this.#talentSelected).map(({id})=>id);
|
||||||
|
return this.prop();
|
||||||
|
case this.Steps.PROPERTY:
|
||||||
|
const less = this.less();
|
||||||
|
if(less > 0) return warn(this.prop(), `你还有 ${less} 属性点没有分配完`);
|
||||||
|
this.#step = this.Steps.TRAJECTORY;
|
||||||
|
delete this.#propertyAllocation.total;
|
||||||
|
this.#life.restart(this.#propertyAllocation);
|
||||||
|
return this.trajectory(enter);
|
||||||
|
case this.Steps.TRAJECTORY:
|
||||||
|
if(!this.#isEnd) return this.trajectory(enter);
|
||||||
|
this.#step = this.Steps.SUMMARY;
|
||||||
|
return `${
|
||||||
|
this.summary()
|
||||||
|
}\n\n${
|
||||||
|
this.list()
|
||||||
|
}`;
|
||||||
|
case this.Steps.SUMMARY:
|
||||||
|
return this.remake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trajectory(enter) {
|
||||||
|
if(enter) {
|
||||||
|
if(this.#interval) {
|
||||||
|
clearInterval(this.#interval);
|
||||||
|
this.#interval = null;
|
||||||
|
this.#auto = false;
|
||||||
|
} else if(this.#auto) {
|
||||||
|
this.#interval = setInterval(
|
||||||
|
()=>{
|
||||||
|
const trajectory = this.next();
|
||||||
|
if(this.#isEnd && this.#interval) {
|
||||||
|
clearInterval(this.#interval);
|
||||||
|
this.#interval = null;
|
||||||
|
}
|
||||||
|
if(!this.#isEnd) return this.output(`${trajectory}\n`);
|
||||||
|
return this.output(trajectory, true);
|
||||||
|
}
|
||||||
|
, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const trajectory = this.#life.next();
|
||||||
|
const { age, content, isEnd } = trajectory;
|
||||||
|
if(isEnd) this.#isEnd = true;
|
||||||
|
return `${age}岁:\t${
|
||||||
|
content.map(
|
||||||
|
({type, description, grade, name, postEvent}) => {
|
||||||
|
switch(type) {
|
||||||
|
case 'TLT':
|
||||||
|
return `天赋【${name}】发动:${description}`;
|
||||||
|
case 'EVT':
|
||||||
|
return description + (postEvent?`\n\t${postEvent}`:'');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).join('\n\t')
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop() {
|
||||||
|
const { CHR, INT, STR, MNY } = this.#propertyAllocation;
|
||||||
|
return `🎉 属性分配
|
||||||
|
请使用 \x1B[4m/alloc\x1B[24m <TAG> <value> 分配属性
|
||||||
|
剩余点数 ${this.less()}
|
||||||
|
|
||||||
|
属性(TAG) 当前值
|
||||||
|
颜值(CHR) ${CHR}
|
||||||
|
智力(INT) ${INT}
|
||||||
|
体质(STR) ${STR}
|
||||||
|
家境(MNY) ${MNY}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
less() {
|
||||||
|
const { total, CHR, INT, STR, MNY } = this.#propertyAllocation;
|
||||||
|
return total - CHR - INT - STR - MNY;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrib(tag, value) {
|
||||||
|
switch (this.#step) {
|
||||||
|
case this.Steps.PROPERTY:
|
||||||
|
return this.alloc(tag, value);
|
||||||
|
|
||||||
|
case this.Steps.TRAJECTORY:
|
||||||
|
return this.showProperty();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showProperty() {
|
||||||
|
let property = this.#life.getLastRecord();
|
||||||
|
return `当前属性
|
||||||
|
|
||||||
|
属性(TAG) 当前值
|
||||||
|
颜值(CHR) ${property.CHR}
|
||||||
|
智力(INT) ${property.INT}
|
||||||
|
体质(STR) ${property.STR}
|
||||||
|
家境(MNY) ${property.MNY}
|
||||||
|
快乐(SPR) ${property.SPR}`
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc(tag, value) {
|
||||||
|
const warn = str => `${this.prop()}\n${this.style('warn', str)}`
|
||||||
|
if(!value) return warn('⚠ 分配的数值没有给定');
|
||||||
|
const isSet = !(value[0] == '-'|| value[0] == '+');
|
||||||
|
|
||||||
|
value = Number(value);
|
||||||
|
if(isNaN(value)) return warn('⚠ 分配的数值不正确');
|
||||||
|
|
||||||
|
switch(tag) {
|
||||||
|
case 'c':
|
||||||
|
case 'chr':
|
||||||
|
case 'C': tag = 'CHR'; break;
|
||||||
|
case 'i':
|
||||||
|
case 'int':
|
||||||
|
case 'I': tag = 'INT'; break;
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
case 'str': tag = 'STR'; break;
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
case 'mny': tag = 'MNY'; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch(tag) {
|
||||||
|
case 'CHR':
|
||||||
|
case 'INT':
|
||||||
|
case 'STR':
|
||||||
|
case 'MNY':
|
||||||
|
if(isSet) value = value - this.#propertyAllocation[tag];
|
||||||
|
|
||||||
|
const tempLess = this.less() - value;
|
||||||
|
const tempSet = this.#propertyAllocation[tag] + value;
|
||||||
|
|
||||||
|
if(tempLess<0) return warn('⚠ 你没有更多的点数可以分配了');
|
||||||
|
if(
|
||||||
|
tempLess>this.#propertyAllocation.total
|
||||||
|
|| tempSet < 0
|
||||||
|
) return warn('⚠ 不能分配负数属性');
|
||||||
|
if(tempSet>10) return warn('⚠ 单项属性最高分配10点');
|
||||||
|
|
||||||
|
this.#propertyAllocation[tag] += value;
|
||||||
|
|
||||||
|
return this.prop();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return warn('⚠ 未知的tag');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
random() {
|
||||||
|
let t = this.#propertyAllocation.total;
|
||||||
|
const arr = [10, 10, 10, 10];
|
||||||
|
while(t>0) {
|
||||||
|
const sub = Math.round(Math.random() * (Math.min(t, 10) - 1)) + 1;
|
||||||
|
while(true) {
|
||||||
|
const select = Math.floor(Math.random() * 4) % 4;
|
||||||
|
if(arr[select] - sub <0) continue;
|
||||||
|
arr[select] -= sub;
|
||||||
|
t -= sub;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.#propertyAllocation.CHR = 10 - arr[0];
|
||||||
|
this.#propertyAllocation.INT = 10 - arr[1];
|
||||||
|
this.#propertyAllocation.STR = 10 - arr[2];
|
||||||
|
this.#propertyAllocation.MNY = 10 - arr[3];
|
||||||
|
return this.prop();
|
||||||
|
}
|
||||||
|
|
||||||
|
summary() {
|
||||||
|
const summaryData = this.#life.getSummary();
|
||||||
|
const format = (name, type) => {
|
||||||
|
const value = summaryData[type];
|
||||||
|
const { judge, grade } = summary(type, value);
|
||||||
|
return this.style(`grade${grade}b`, `${name}:${value} ${judge}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'🎉 总评',
|
||||||
|
format('颜值', 'CHR'),
|
||||||
|
format('智力', 'INT'),
|
||||||
|
format('体质', 'STR'),
|
||||||
|
format('家境', 'MNY'),
|
||||||
|
format('快乐', 'SPR'),
|
||||||
|
format('享年', 'AGE'),
|
||||||
|
format('总评', 'SUM'),
|
||||||
|
].join('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
32
repl/index.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import App from './app.js';
|
||||||
|
import { readFile, writeFile } from 'fs/promises';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
globalThis.localStorage = JSON.parse(await readFile('__localStorage.json'));
|
||||||
|
} catch (e) {
|
||||||
|
globalThis.localStorage = {};
|
||||||
|
}
|
||||||
|
localStorage.getItem = key => localStorage[key]===void 0? null: localStorage[key];
|
||||||
|
localStorage.setItem = (key, value) => (localStorage[key] = value);
|
||||||
|
|
||||||
|
globalThis.dumpLocalStorage = async ()=>await writeFile('__localStorage.json', JSON.stringify( global.localStorage))
|
||||||
|
|
||||||
|
const app = new App();
|
||||||
|
app.io(
|
||||||
|
repl => process.stdin.on('data', data=>repl(data.toString().trim())),
|
||||||
|
(data, isRepl) => process.stdout.write(`${data}${isRepl?'\n>':''}`),
|
||||||
|
code=>process.exit(code)
|
||||||
|
)
|
||||||
|
await app.initial();
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
// process.stdin.setRawMode(true);
|
||||||
|
|
||||||
|
// process.openStdin().on('keypress', function (chunk, key) {
|
||||||
|
// process.stdout.write('Get Chunk: ' + chunk + '\n');
|
||||||
|
// if (key && key.ctrl && key.name == 'c') process.exit();
|
||||||
|
// });
|
||||||
67
src/achievement.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { clone } from './functions/util.js';
|
||||||
|
import { checkCondition } from './functions/condition.js';
|
||||||
|
|
||||||
|
class Achievement {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
// 时机
|
||||||
|
Opportunity = {
|
||||||
|
START: "START", // 分配完成点数,点击开始新人生后
|
||||||
|
TRAJECTORY: "TRAJECTORY", // 每一年的人生经历中
|
||||||
|
SUMMARY: "SUMMARY", // 人生结束,点击人生总结后
|
||||||
|
END: "END", // 游戏完成,点击重开 重开次数在这之后才会+1
|
||||||
|
};
|
||||||
|
|
||||||
|
#achievements;
|
||||||
|
|
||||||
|
initial({achievements}) {
|
||||||
|
this.#achievements = achievements;
|
||||||
|
}
|
||||||
|
|
||||||
|
count() {
|
||||||
|
return Object.keys(this.#achievements).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
list(property) {
|
||||||
|
return Object
|
||||||
|
.values(this.#achievements)
|
||||||
|
.map(({
|
||||||
|
id, name, opportunity,
|
||||||
|
description, hide, grade,
|
||||||
|
})=>({
|
||||||
|
id, name, opportunity,
|
||||||
|
description, hide, grade,
|
||||||
|
isAchieved: this.isAchieved(id, property),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
get(achievementId) {
|
||||||
|
const achievement = this.#achievements[achievementId];
|
||||||
|
if(!achievement) throw new Error(`[ERROR] No Achievement[${achievementId}]`);
|
||||||
|
return clone(achievement);
|
||||||
|
}
|
||||||
|
|
||||||
|
check(achievementId, property) {
|
||||||
|
const { condition } = this.get(achievementId);
|
||||||
|
return checkCondition(property, condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
isAchieved(achievementId, property) {
|
||||||
|
for(const [achieved] of (property.get(property.TYPES.ACHV)||[]))
|
||||||
|
if(achieved == achievementId) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
achieve(opportunity, property) {
|
||||||
|
this.list(property)
|
||||||
|
.filter(({isAchieved})=>!isAchieved)
|
||||||
|
.filter(({opportunity: o})=>o==opportunity)
|
||||||
|
.filter(({id})=>this.check(id, property))
|
||||||
|
.forEach(({id})=>{
|
||||||
|
property.achieve(property.TYPES.ACHV, id)
|
||||||
|
$$event('achievement', this.get(id))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Achievement;
|
||||||
573
src/app.js
@@ -1,6 +1,7 @@
|
|||||||
import { max, sum } from './functions/util.js';
|
import { summary } from './functions/summary.js';
|
||||||
import { summary } from './functions/summary.js'
|
import { getRate, getGrade } from './functions/addition.js';
|
||||||
import Life from './life.js'
|
import Life from './life.js';
|
||||||
|
|
||||||
class App{
|
class App{
|
||||||
constructor(){
|
constructor(){
|
||||||
this.#life = new Life();
|
this.#life = new Life();
|
||||||
@@ -8,20 +9,35 @@ class App{
|
|||||||
|
|
||||||
#life;
|
#life;
|
||||||
#pages;
|
#pages;
|
||||||
|
#currentPage;
|
||||||
#talentSelected = new Set();
|
#talentSelected = new Set();
|
||||||
#totalMax=20;
|
#totalMax=20;
|
||||||
#isEnd = false;
|
#isEnd = false;
|
||||||
#selectedExtendTalent = null;
|
#selectedExtendTalent = null;
|
||||||
#hintTimeout;
|
#hintTimeout;
|
||||||
|
#specialthanks;
|
||||||
|
#autoTrajectory;
|
||||||
|
|
||||||
async initial() {
|
async initial() {
|
||||||
this.initPages();
|
this.initPages();
|
||||||
this.switch('loading');
|
this.switch('loading');
|
||||||
await this.#life.initial();
|
const [,specialthanks] = await Promise.all([
|
||||||
|
this.#life.initial(),
|
||||||
|
json('specialthanks')
|
||||||
|
]);
|
||||||
|
this.#specialthanks = specialthanks;
|
||||||
this.switch('index');
|
this.switch('index');
|
||||||
window.onerror = (event, source, lineno, colno, error) => {
|
globalThis.onerror = (event, source, lineno, colno, error) => {
|
||||||
this.hint(`[ERROR] at (${source}:${lineno}:${colno})\n\n${error?.stack||error||'unknow Error'}`, 'error');
|
this.hint(`[ERROR] at (${source}:${lineno}:${colno})\n\n${error?.stack||error||'unknow Error'}`, 'error');
|
||||||
}
|
}
|
||||||
|
const keyDownCallback = ({which: w, keyCode: k}) => {
|
||||||
|
if ( w === 13 || k === 13 || w === 32 || k === 32 ) {
|
||||||
|
const pressEnterFunc = this.#pages[this.#currentPage]?.pressEnter;
|
||||||
|
pressEnterFunc && typeof pressEnterFunc === 'function' && pressEnterFunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
globalThis.removeEventListener('keydown', keyDownCallback);
|
||||||
|
globalThis.addEventListener('keydown', keyDownCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
initPages() {
|
initPages() {
|
||||||
@@ -39,31 +55,154 @@ class App{
|
|||||||
// Index
|
// Index
|
||||||
const indexPage = $(`
|
const indexPage = $(`
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="cnt" class="head">已重开1次</div>
|
<button id="achievement">成就</button>
|
||||||
<button id="rank">排行榜</button>
|
<button id="specialthanks">特别感谢</button>
|
||||||
|
<button id="themeToggleBtn">黑</button>
|
||||||
|
<button id="save">Save</button>
|
||||||
|
<button id="load">Load</button>
|
||||||
<div id="title">
|
<div id="title">
|
||||||
人生重开模拟器<br>
|
人生重开模拟器<br>
|
||||||
<div style="font-size:1.5rem; font-weight:normal;">这垃圾人生一秒也不想呆了</div>
|
<div style="font-size:1.5rem; font-weight:normal;">这垃圾人生一秒也不想呆了</div>
|
||||||
</div>
|
</div>
|
||||||
<button id="restart" class="mainbtn"><span class="iconfont"></span>立即重开</button>
|
<button id="restart" class="mainbtn"><span class="iconfont"></span>立即重开</button>
|
||||||
|
<a id="discord" href="https://discord.gg/U3qrf49NMQ" style="z-index: 9999;" aria-label="Chat on Discord"><button class="discord-btn"><svg width="50%" height="55" viewBox="0 0 71 55" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0)"><path d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z" fill="#ffffff"/></g><defs><clipPath id="clip0"><rect width="71" height="55" fill="white"/></clipPath></defs></svg>CHAT</button><style>.discord-btn {position: fixed;bottom: 0.5rem;left: 0.5rem;background-color: #5865F2;padding: 0.7rem;height: auto;color: white;text-align: right;vertical-align: middle;border: none;width: 6.5rem;font-size: 1rem;border-radius: 4px;}.discord-btn svg {height: 1.5rem;position: absolute;top: 50%;left: 0;transform: translateY(-50%);}.discord-btn:hover svg{animation:discord-wave 560ms ease-in-out;}@keyframes discord-wave{0%,100%{transform:translateY(-50%) rotate(0)}20%,60%{transform:translateY(-50%) rotate(-25deg)}40%,80%{transform:translateY(-50%) rotate(10deg)}}@media (max-width:500px){.discord-btn:hover svg{animation:none}.discord-btn svg{animation:discord-wave 560ms ease-in-out}}</style></a>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
// Init theme
|
||||||
|
let date = new Date();
|
||||||
|
if( date.getMonth() == 9 && date.getDate() == 31
|
||||||
|
|| date.getMonth() == 10 && date.getDate() == 1
|
||||||
|
){
|
||||||
|
this.setTheme('halloween');
|
||||||
|
} else {
|
||||||
|
this.setTheme(localStorage.getItem('theme'))
|
||||||
|
}
|
||||||
|
|
||||||
indexPage
|
indexPage
|
||||||
.find('#restart')
|
.find('#restart')
|
||||||
.click(()=>this.switch('talent'));
|
.click(()=>this.switch('talent'));
|
||||||
|
|
||||||
indexPage
|
indexPage
|
||||||
.find('#rank')
|
.find('#achievement')
|
||||||
.click(()=>this.hint('别卷了!没有排行榜'));
|
.click(()=>this.switch('achievement'));
|
||||||
|
|
||||||
|
|
||||||
|
indexPage
|
||||||
|
.find('#save')
|
||||||
|
.click(()=>{
|
||||||
|
const data = {};
|
||||||
|
Object
|
||||||
|
.keys(localStorage)
|
||||||
|
.filter(v=>v.substr(0,4)!='goog')
|
||||||
|
.forEach(key=>data[key] = localStorage[key]);
|
||||||
|
|
||||||
|
let blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
|
||||||
|
const slice = blob.slice || blob.webkitSlice || blob.mozSlice;
|
||||||
|
blob = slice.call(blob, 0, blob.size, 'application/octet-stream');
|
||||||
|
const a = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
|
||||||
|
a.href = URL.createObjectURL(blob);
|
||||||
|
a.download = `Remake_save_${new Date().toISOString().replace(':','.')}.json`;
|
||||||
|
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(a.href);
|
||||||
|
});
|
||||||
|
|
||||||
|
indexPage
|
||||||
|
.find('#load')
|
||||||
|
.click(()=>{
|
||||||
|
const file = $(`<input type="file" name="file" accept="application/json" style="display: none;" />`)
|
||||||
|
file.appendTo('body');
|
||||||
|
file.click();
|
||||||
|
file.on('change', (e)=>{
|
||||||
|
this.switch('loading');
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if(!file) return;
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
const data = JSON.parse(reader.result);
|
||||||
|
for(const key in data) {
|
||||||
|
localStorage[key] = data[key];
|
||||||
|
}
|
||||||
|
this.switch('index');
|
||||||
|
this.setTheme(localStorage.getItem('theme'))
|
||||||
|
if(localStorage.getItem('theme') == 'light') {
|
||||||
|
indexPage.find('#themeToggleBtn').text('黑')
|
||||||
|
} else{
|
||||||
|
indexPage.find('#themeToggleBtn').text('白')
|
||||||
|
}
|
||||||
|
this.hint('加载存档成功', 'success');
|
||||||
|
}
|
||||||
|
reader.readAsText(file);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if(localStorage.getItem('theme') == 'light') {
|
||||||
|
indexPage.find('#themeToggleBtn').text('黑')
|
||||||
|
} else{
|
||||||
|
indexPage.find('#themeToggleBtn').text('白')
|
||||||
|
}
|
||||||
|
|
||||||
|
indexPage
|
||||||
|
.find("#themeToggleBtn")
|
||||||
|
.click(() => {
|
||||||
|
if(localStorage.getItem('theme') == 'light') {
|
||||||
|
localStorage.setItem('theme', 'dark');
|
||||||
|
indexPage.find('#themeToggleBtn').text('白')
|
||||||
|
} else {
|
||||||
|
localStorage.setItem('theme', 'light');
|
||||||
|
indexPage.find('#themeToggleBtn').text('黑')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setTheme(localStorage.getItem('theme'))
|
||||||
|
});
|
||||||
|
|
||||||
|
indexPage
|
||||||
|
.find('#specialthanks')
|
||||||
|
.click(()=>this.switch('specialthanks'));
|
||||||
|
|
||||||
|
const specialThanksPage = $(`
|
||||||
|
<div id="main">
|
||||||
|
<button id="specialthanks">返回</button>
|
||||||
|
<div id="spthx">
|
||||||
|
<ul class="g1"></ul>
|
||||||
|
<ul class="g2"></ul>
|
||||||
|
</div>
|
||||||
|
<button class="sponsor" onclick="globalThis.open('https://afdian.net/@LifeRestart')" style="background: linear-gradient(90deg,#946ce6,#7e5fd9); left:auto; right:50%; transform: translate(-2rem,-50%);">打赏策划(爱发电)</button>
|
||||||
|
<button class="sponsor" onclick="globalThis.open('https://dun.mianbaoduo.com/@vickscarlet')" style="background-color:#c69; left:50%; right:auto; transform: translate(2rem,-50%);">打赏程序(顿顿饭)</button>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
specialThanksPage
|
||||||
|
.find('#specialthanks')
|
||||||
|
.click(()=>this.switch('index'));
|
||||||
|
|
||||||
|
const achievementPage = $(`
|
||||||
|
<div id="main">
|
||||||
|
<button id="specialthanks">返回</button>
|
||||||
|
<span class="title">统计</span>
|
||||||
|
<ul id="total"></ul>
|
||||||
|
<span style="padding:0.25rem; margin: 0.5rem 0; border: none; background: #ccc;"></span>
|
||||||
|
<span class="title">成就<button id="rank">排行榜</button></span>
|
||||||
|
<ul id="achievements"></ul>
|
||||||
|
`)
|
||||||
|
|
||||||
|
achievementPage
|
||||||
|
.find('#specialthanks')
|
||||||
|
.click(()=>this.switch('index'));
|
||||||
|
|
||||||
|
achievementPage
|
||||||
|
.find('#rank')
|
||||||
|
.click(()=>this.hint('别卷了,没有排行榜'));
|
||||||
// Talent
|
// Talent
|
||||||
const talentPage = $(`
|
const talentPage = $(`
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div class="head" style="font-size: 1.6rem">天赋抽卡</div>
|
<div class="head" style="font-size: 1.6rem">天赋抽卡</div>
|
||||||
<button id="random" class="mainbtn" style="top: 50%;">10连抽!</button>
|
<button id="random" class="mainbtn" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);"">10连抽!</button>
|
||||||
<ul id="talents" class="selectlist"></ul>
|
<ul id="talents" class="selectlist"></ul>
|
||||||
<button id="next" class="mainbtn" style="top:auto; bottom:0.1em">请选择3个</button>
|
<button id="next" class="mainbtn">请选择3个</button>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@@ -84,6 +223,9 @@ class App{
|
|||||||
if(li.hasClass('selected')) {
|
if(li.hasClass('selected')) {
|
||||||
li.removeClass('selected')
|
li.removeClass('selected')
|
||||||
this.#talentSelected.delete(talent);
|
this.#talentSelected.delete(talent);
|
||||||
|
if(this.#talentSelected.size<3) {
|
||||||
|
talentPage.find('#next').text('请选择3个')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if(this.#talentSelected.size==3) {
|
if(this.#talentSelected.size==3) {
|
||||||
this.hint('只能选3个天赋');
|
this.hint('只能选3个天赋');
|
||||||
@@ -105,9 +247,13 @@ class App{
|
|||||||
}
|
}
|
||||||
li.addClass('selected');
|
li.addClass('selected');
|
||||||
this.#talentSelected.add(talent);
|
this.#talentSelected.add(talent);
|
||||||
|
if(this.#talentSelected.size==3) {
|
||||||
|
talentPage.find('#next').text('开始新人生')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
talentPage.find('#next').show()
|
||||||
});
|
});
|
||||||
|
|
||||||
talentPage
|
talentPage
|
||||||
@@ -117,23 +263,36 @@ class App{
|
|||||||
this.hint('请选择3个天赋');
|
this.hint('请选择3个天赋');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
talentPage.find('#next').hide()
|
||||||
this.#totalMax = 20 + this.#life.getTalentAllocationAddition(Array.from(this.#talentSelected).map(({id})=>id));
|
this.#totalMax = 20 + this.#life.getTalentAllocationAddition(Array.from(this.#talentSelected).map(({id})=>id));
|
||||||
this.switch('property');
|
this.switch('property');
|
||||||
})
|
})
|
||||||
|
|
||||||
// Property
|
// Property
|
||||||
const propertyPage = $(`
|
// hint of extension tobermory.es6-string-html
|
||||||
|
const propertyPage = $(/*html*/`
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div class="head" style="font-size: 1.6rem">
|
<div class="head" style="font-size: 1.6rem">
|
||||||
调整初始属性<br>
|
<div>调整初始属性</div>
|
||||||
<div id="total" style="font-size:1rem; font-weight:normal;">可用属性点:0</div>
|
<div id="total" style="font-size:1rem; font-weight:normal;">可用属性点:0</div>
|
||||||
</div>
|
</div>
|
||||||
<ul id="propertyAllocation" class="propinitial"></ul>
|
<ul id="propertyAllocation" class="propinitial"></ul>
|
||||||
<button id="random" class="mainbtn" style="top:auto; bottom:7rem">随机分配</button>
|
<ul class="selectlist" id="talentSelectedView"></ul>
|
||||||
<button id="start" class="mainbtn" style="top:auto; bottom:0.1rem">开始新人生</button>
|
<div class="btn-area">
|
||||||
|
<button id="random" class="mainbtn">随机分配</button>
|
||||||
|
<button id="start" class="mainbtn">开始新人生</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
|
propertyPage.mounted = ()=>{
|
||||||
|
propertyPage
|
||||||
|
.find('#talentSelectedView').append(
|
||||||
|
`<li>已选天赋</li>` +
|
||||||
|
Array.from(this.#talentSelected)
|
||||||
|
.map(({name,description})=>`<li class="grade0b">${name}(${description})</li>`)
|
||||||
|
.join('')
|
||||||
|
)
|
||||||
|
}
|
||||||
const groups = {};
|
const groups = {};
|
||||||
const total = ()=>{
|
const total = ()=>{
|
||||||
let t = 0;
|
let t = 0;
|
||||||
@@ -147,7 +306,7 @@ class App{
|
|||||||
const getBtnGroups = (name, min, max)=>{
|
const getBtnGroups = (name, min, max)=>{
|
||||||
const group = $(`<li>${name} </li>`);
|
const group = $(`<li>${name} </li>`);
|
||||||
const btnSub = $(`<span class="iconfont propbtn"></span>`);
|
const btnSub = $(`<span class="iconfont propbtn"></span>`);
|
||||||
const inputBox = $(`<input value="0">`);
|
const inputBox = $(`<input value="0" type="number" />`);
|
||||||
const btnAdd = $(`<span class="iconfont propbtn"></span>`);
|
const btnAdd = $(`<span class="iconfont propbtn"></span>`);
|
||||||
group.append(btnSub);
|
group.append(btnSub);
|
||||||
group.append(inputBox);
|
group.append(inputBox);
|
||||||
@@ -166,8 +325,8 @@ class App{
|
|||||||
freshTotal();
|
freshTotal();
|
||||||
}
|
}
|
||||||
btnAdd.click(()=>{
|
btnAdd.click(()=>{
|
||||||
if(total() == this.#totalMax) {
|
if(total() >= this.#totalMax) {
|
||||||
this.hint('没用可分配的点数了');
|
this.hint('没有可分配的点数了');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
set(get()+1);
|
set(get()+1);
|
||||||
@@ -223,11 +382,14 @@ class App{
|
|||||||
propertyPage
|
propertyPage
|
||||||
.find('#start')
|
.find('#start')
|
||||||
.click(()=>{
|
.click(()=>{
|
||||||
if(total()!=this.#totalMax) {
|
if(total() < this.#totalMax) {
|
||||||
this.hint(`你还有${this.#totalMax-total()}属性点没有分配完`);
|
this.hint(`你还有${this.#totalMax-total()}属性点没有分配完`);
|
||||||
return;
|
return;
|
||||||
|
} else if (total() > this.#totalMax) {
|
||||||
|
this.hint(`你多使用了${total() - this.#totalMax}属性点`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.#life.restart({
|
const contents = this.#life.restart({
|
||||||
CHR: groups.CHR.get(),
|
CHR: groups.CHR.get(),
|
||||||
INT: groups.INT.get(),
|
INT: groups.INT.get(),
|
||||||
STR: groups.STR.get(),
|
STR: groups.STR.get(),
|
||||||
@@ -236,14 +398,28 @@ class App{
|
|||||||
TLT: Array.from(this.#talentSelected).map(({id})=>id),
|
TLT: Array.from(this.#talentSelected).map(({id})=>id),
|
||||||
});
|
});
|
||||||
this.switch('trajectory');
|
this.switch('trajectory');
|
||||||
this.#pages.trajectory.born();
|
this.#pages.trajectory.born(contents);
|
||||||
|
// $(document).keydown(function(event){
|
||||||
|
// if(event.which == 32 || event.which == 13){
|
||||||
|
// $('#lifeTrajectory').click();
|
||||||
|
// }
|
||||||
|
// })
|
||||||
});
|
});
|
||||||
|
|
||||||
// Trajectory
|
// Trajectory
|
||||||
const trajectoryPage = $(`
|
const trajectoryPage = $(`
|
||||||
<div id="main">
|
<div id="main">
|
||||||
|
<ul id="lifeProperty" class="lifeProperty"></ul>
|
||||||
<ul id="lifeTrajectory" class="lifeTrajectory"></ul>
|
<ul id="lifeTrajectory" class="lifeTrajectory"></ul>
|
||||||
<button id="summary" class="mainbtn" style="top:auto; bottom:0.1rem">人生总结</button>
|
<div class="btn-area">
|
||||||
|
<button id="auto" class="mainbtn">自动播放</button>
|
||||||
|
<button id="auto2x" class="mainbtn">自动播放2x</button>
|
||||||
|
<button id="summary" class="mainbtn">人生总结</button>
|
||||||
|
<button id="domToImage" class="mainbtn">人生回放</button>
|
||||||
|
</div>
|
||||||
|
<div class="domToImage2wx">
|
||||||
|
<img src="" id="endImage" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@@ -253,8 +429,7 @@ class App{
|
|||||||
if(this.#isEnd) return;
|
if(this.#isEnd) return;
|
||||||
const trajectory = this.#life.next();
|
const trajectory = this.#life.next();
|
||||||
const { age, content, isEnd } = trajectory;
|
const { age, content, isEnd } = trajectory;
|
||||||
|
const li = $(`<li><span>${age}岁:</span><span>${
|
||||||
const li = $(`<li><span>${age}岁:</span>${
|
|
||||||
content.map(
|
content.map(
|
||||||
({type, description, grade, name, postEvent}) => {
|
({type, description, grade, name, postEvent}) => {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
@@ -265,38 +440,102 @@ class App{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
).join('<br>')
|
).join('<br>')
|
||||||
}</li>`);
|
}</span></li>`);
|
||||||
li.appendTo('#lifeTrajectory');
|
li.appendTo('#lifeTrajectory');
|
||||||
$("#lifeTrajectory").scrollTop($("#lifeTrajectory")[0].scrollHeight);
|
$("#lifeTrajectory").scrollTop($("#lifeTrajectory")[0].scrollHeight);
|
||||||
if(isEnd) {
|
if(isEnd) {
|
||||||
|
$(document).unbind("keydown");
|
||||||
this.#isEnd = true;
|
this.#isEnd = true;
|
||||||
trajectoryPage.find('#summary').show();
|
trajectoryPage.find('#summary').show();
|
||||||
|
trajectoryPage.find('#auto').hide();
|
||||||
|
trajectoryPage.find('#auto2x').hide();
|
||||||
|
// trajectoryPage.find('#domToImage').show();
|
||||||
}
|
}
|
||||||
|
const property = this.#life.getLastRecord();
|
||||||
|
$("#lifeProperty").html(`
|
||||||
|
<li><span>颜值</span><span>${property.CHR}</span></li>
|
||||||
|
<li><span>智力</span><span>${property.INT}</span></li>
|
||||||
|
<li><span>体质</span><span>${property.STR}</span></li>
|
||||||
|
<li><span>家境</span><span>${property.MNY}</span></li>
|
||||||
|
<li><span>快乐</span><span>${property.SPR}</span></li>
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
// html2canvas
|
||||||
|
trajectoryPage
|
||||||
|
.find('#domToImage')
|
||||||
|
.click(()=>{
|
||||||
|
$("#lifeTrajectory").addClass("deleteFixed");
|
||||||
|
const ua = navigator.userAgent.toLowerCase();
|
||||||
|
domtoimage.toJpeg(document.getElementById('lifeTrajectory'))
|
||||||
|
.then(function (dataUrl) {
|
||||||
|
let link = document.createElement('a');
|
||||||
|
link.download = '我的人生回放.jpeg';
|
||||||
|
link.href = dataUrl;
|
||||||
|
link.click();
|
||||||
|
$("#lifeTrajectory").removeClass("deleteFixed");
|
||||||
|
// 微信内置浏览器,显示图片,需要用户单独保存
|
||||||
|
if(ua.match(/MicroMessenger/i)=="micromessenger") {
|
||||||
|
$('#endImage').attr('src', dataUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.hide();
|
||||||
|
|
||||||
trajectoryPage
|
trajectoryPage
|
||||||
.find('#summary')
|
.find('#summary')
|
||||||
.click(()=>{
|
.click(()=>{
|
||||||
|
clearInterval(this.#autoTrajectory);
|
||||||
|
this.#autoTrajectory = null;
|
||||||
this.switch('summary');
|
this.switch('summary');
|
||||||
})
|
});
|
||||||
|
|
||||||
|
const auto = tick=>{
|
||||||
|
if(this.#autoTrajectory) {
|
||||||
|
clearInterval(this.#autoTrajectory);
|
||||||
|
this.#autoTrajectory = null;
|
||||||
|
} else {
|
||||||
|
if(!this.isEnd)
|
||||||
|
trajectoryPage
|
||||||
|
.find('#lifeTrajectory')
|
||||||
|
.click();
|
||||||
|
this.#autoTrajectory = setInterval(()=>{
|
||||||
|
if(this.isEnd) {
|
||||||
|
clearInterval(this.#autoTrajectory);
|
||||||
|
this.#autoTrajectory = null;
|
||||||
|
} else {
|
||||||
|
trajectoryPage
|
||||||
|
.find('#lifeTrajectory')
|
||||||
|
.click();
|
||||||
|
}
|
||||||
|
}, tick);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
trajectoryPage
|
||||||
|
.find('#auto')
|
||||||
|
.click(()=>auto(1000));
|
||||||
|
trajectoryPage
|
||||||
|
.find('#auto2x')
|
||||||
|
.click(()=>auto(500));
|
||||||
|
|
||||||
// Summary
|
// Summary
|
||||||
const summaryPage = $(`
|
const summaryPage = $(`
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div class="head">人生总结</div>
|
<div class="head">人生总结</div>
|
||||||
<ul id="judge" class="judge" style="bottom: calc(35% + 2.5rem)">
|
<ul id="judge" class="judge">
|
||||||
<li class="grade2"><span>颜值:</span>9级 美若天仙</li>
|
<li class="grade2"><span>颜值:</span><span>9级 美若天仙</span></li>
|
||||||
<li><span>智力:</span>4级 智力一般</li>
|
<li class="grade0"><span>智力:</span><span>4级 智力一般</span></li>
|
||||||
<li><span>体质:</span>1级 极度虚弱</li>
|
<li class="grade0"><span>体质:</span><span>1级 极度虚弱</span></li>
|
||||||
<li><span>家境:</span>6级 小康之家</li>
|
<li class="grade0"><span>家境:</span><span>6级 小康之家</span></li>
|
||||||
<li><span>享年:</span>3岁 早夭</li>
|
<li class="grade0"><span>享年:</span><span>3岁 早夭</span></li>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<li class="grade0"><span>快乐:</span><span></span>3级 不太幸福的人生</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="head" style="top:auto; bottom:35%">天赋,你可以选一个,下辈子还能抽到</div>
|
<div class="head" style="height:auto;">天赋,你可以选一个,下辈子还能抽到</div>
|
||||||
<ul id="talents" class="selectlist" style="top:calc(65% + 0.5rem); bottom:8rem">
|
<ul id="talents" class="selectlist" style="flex: 0 1 auto;">
|
||||||
<li class="grade2b">黑幕(面试一定成功)</li>
|
<li class="grade2b">黑幕(面试一定成功)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button id="again" class="mainbtn" style="top:auto; bottom:0.1em"><span class="iconfont"></span>再次重开</button>
|
<button id="again" class="mainbtn"><span class="iconfont"></span>再次重开</button>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@@ -315,34 +554,126 @@ class App{
|
|||||||
this.#pages = {
|
this.#pages = {
|
||||||
loading: {
|
loading: {
|
||||||
page: loadingPage,
|
page: loadingPage,
|
||||||
clear: ()=>{},
|
clear: ()=>{
|
||||||
|
this.#currentPage = 'loading';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
index: {
|
index: {
|
||||||
page: indexPage,
|
page: indexPage,
|
||||||
btnRank: indexPage.find('#rank'),
|
btnAchievement: indexPage.find('#achievement'),
|
||||||
btnRestart: indexPage.find('#restart'),
|
btnRestart: indexPage.find('#restart'),
|
||||||
hint: indexPage.find('.hint'),
|
hint: indexPage.find('.hint'),
|
||||||
cnt: indexPage.find('#cnt'),
|
pressEnter: ()=>{
|
||||||
|
this.#pages.index.btnRestart.click();
|
||||||
|
},
|
||||||
clear: ()=>{
|
clear: ()=>{
|
||||||
|
this.#currentPage = 'index';
|
||||||
indexPage.find('.hint').hide();
|
indexPage.find('.hint').hide();
|
||||||
|
|
||||||
const times = this.times;
|
const times = this.times;
|
||||||
const btnRank = indexPage.find('#rank');
|
const achievement = indexPage.find('#achievement');
|
||||||
const cnt = indexPage.find('#cnt');
|
const discord = indexPage.find('#discord');
|
||||||
|
const specialthanks = indexPage.find('#specialthanks');
|
||||||
|
|
||||||
if(times > 0) {
|
if(times > 0) {
|
||||||
btnRank.show();
|
achievement.show();
|
||||||
cnt.show();
|
discord.show();
|
||||||
cnt.text(`已重开${times}次`);
|
specialthanks.show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
btnRank.hide();
|
achievement.hide();
|
||||||
cnt.hide();
|
discord.hide();
|
||||||
|
specialthanks.hide();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
specialthanks: {
|
||||||
|
page: specialThanksPage,
|
||||||
|
clear: () => {
|
||||||
|
const groups = [
|
||||||
|
specialThanksPage.find('#spthx > ul.g1'),
|
||||||
|
specialThanksPage.find('#spthx > ul.g2'),
|
||||||
|
];
|
||||||
|
groups.forEach(g=>g.empty());
|
||||||
|
this.#specialthanks
|
||||||
|
.sort(()=>0.5-Math.random())
|
||||||
|
.forEach(({group, name, comment, color})=>groups[--group].append(`
|
||||||
|
<li>
|
||||||
|
<span class="name" ${color?('style="color:'+color+'"'):''}>${name}</span>
|
||||||
|
<span class="comment">${comment||''}</span>
|
||||||
|
</li>
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
achievement: {
|
||||||
|
page: achievementPage,
|
||||||
|
clear: () => {
|
||||||
|
const total = achievementPage.find("ul#total");
|
||||||
|
const achievements = achievementPage.find("ul#achievements");
|
||||||
|
total.empty();
|
||||||
|
achievements.empty();
|
||||||
|
|
||||||
|
const formatRate = (type, value) => {
|
||||||
|
const rate = getRate(type, value);
|
||||||
|
let color = Object.keys(rate)[0];
|
||||||
|
switch(parseInt(color)) {
|
||||||
|
case 0: color = '白色'; break;
|
||||||
|
case 1: color = '蓝色'; break;
|
||||||
|
case 2: color = '紫色'; break;
|
||||||
|
case 3: color = '橙色'; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
let r = Object.values(rate)[0];
|
||||||
|
switch(parseInt(r)) {
|
||||||
|
case 1: r = '不变'; break;
|
||||||
|
case 2: r = '翻倍'; break;
|
||||||
|
case 3: r = '三倍'; break;
|
||||||
|
case 4: r = '四倍'; break;
|
||||||
|
case 5: r = '五倍'; break;
|
||||||
|
case 6: r = '六倍'; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return `抽到${color}概率${r}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { times, achievement, talentRate, eventRate } = this.#life.getTotal();
|
||||||
|
total.append(`
|
||||||
|
<li class="achvg${getGrade('times', times)}"><span class="achievementtitle">已重开${times}次</span>${formatRate('times', times)}</li>
|
||||||
|
<li class="achvg${getGrade('achievement', achievement)}"><span class="achievementtitle">成就达成${achievement}个</span>${formatRate('achievement', achievement)}</li>
|
||||||
|
<li class="achvg${getGrade('eventRate', eventRate)}"><span class="achievementtitle">事件收集率</span>${Math.floor(eventRate * 100)}%</li>
|
||||||
|
<li class="achvg${getGrade('talentRate', talentRate)}"><span class="achievementtitle">天赋收集率</span>${Math.floor(talentRate * 100)}%</li>
|
||||||
|
`);
|
||||||
|
|
||||||
|
const achievementsData = this.#life.getAchievements();
|
||||||
|
achievementsData.forEach(({
|
||||||
|
name, description, hide,
|
||||||
|
grade, isAchieved
|
||||||
|
})=>{
|
||||||
|
if(hide && !isAchieved) name = description = '???';
|
||||||
|
achievements.append(
|
||||||
|
`<li class="achvg${grade} ${isAchieved?'':'mask'}"><span class="achievementtitle">${name}</span>${description}</li>`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
talent: {
|
talent: {
|
||||||
page: talentPage,
|
page: talentPage,
|
||||||
|
talentList: talentPage.find('#talents'),
|
||||||
|
btnRandom: talentPage.find('#random'),
|
||||||
|
btnNext: talentPage.find('#next'),
|
||||||
|
pressEnter: ()=>{
|
||||||
|
const talentList = this.#pages.talent.talentList;
|
||||||
|
const btnRandom = this.#pages.talent.btnRandom;
|
||||||
|
const btnNext = this.#pages.talent.btnNext;
|
||||||
|
if (talentList.children().length) {
|
||||||
|
btnNext.click();
|
||||||
|
} else {
|
||||||
|
btnRandom.click();
|
||||||
|
}
|
||||||
|
},
|
||||||
clear: ()=>{
|
clear: ()=>{
|
||||||
|
this.#currentPage = 'talent';
|
||||||
talentPage.find('ul.selectlist').empty();
|
talentPage.find('ul.selectlist').empty();
|
||||||
talentPage.find('#random').show();
|
talentPage.find('#random').show();
|
||||||
this.#totalMax = 20;
|
this.#totalMax = 20;
|
||||||
@@ -350,89 +681,104 @@ class App{
|
|||||||
},
|
},
|
||||||
property: {
|
property: {
|
||||||
page: propertyPage,
|
page: propertyPage,
|
||||||
|
btnStart: propertyPage.find('#start'),
|
||||||
|
pressEnter: ()=>{
|
||||||
|
this.#pages.property.btnStart.click();
|
||||||
|
},
|
||||||
clear: ()=>{
|
clear: ()=>{
|
||||||
|
this.#currentPage = 'property';
|
||||||
freshTotal();
|
freshTotal();
|
||||||
|
propertyPage
|
||||||
|
.find('#talentSelectedView')
|
||||||
|
.empty();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
trajectory: {
|
trajectory: {
|
||||||
page: trajectoryPage,
|
page: trajectoryPage,
|
||||||
|
lifeTrajectory: trajectoryPage.find('#lifeTrajectory'),
|
||||||
|
pressEnter: ()=>{
|
||||||
|
this.#pages.trajectory.lifeTrajectory.click();
|
||||||
|
},
|
||||||
clear: ()=>{
|
clear: ()=>{
|
||||||
|
this.#currentPage = 'trajectory';
|
||||||
trajectoryPage.find('#lifeTrajectory').empty();
|
trajectoryPage.find('#lifeTrajectory').empty();
|
||||||
trajectoryPage.find('#summary').hide();
|
trajectoryPage.find('#summary').hide();
|
||||||
|
trajectoryPage.find('#auto').show();
|
||||||
|
trajectoryPage.find('#auto2x').show();
|
||||||
this.#isEnd = false;
|
this.#isEnd = false;
|
||||||
},
|
},
|
||||||
born: ()=>{
|
born: contents => {
|
||||||
|
if(contents.length > 0)
|
||||||
|
$('#lifeTrajectory')
|
||||||
|
.append(`<li><span>初始:</span><span>${
|
||||||
|
contents.map(
|
||||||
|
({source, target}) => `天赋【${source.name}】发动:替换为天赋【${target.name}】`
|
||||||
|
).join('<br>')
|
||||||
|
}</span></li>`);
|
||||||
|
|
||||||
trajectoryPage.find('#lifeTrajectory').trigger("click");
|
trajectoryPage.find('#lifeTrajectory').trigger("click");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
page: summaryPage,
|
page: summaryPage,
|
||||||
clear: ()=>{
|
clear: ()=>{
|
||||||
|
this.#currentPage = 'summary';
|
||||||
const judge = summaryPage.find('#judge');
|
const judge = summaryPage.find('#judge');
|
||||||
const talents = summaryPage.find('#talents');
|
const talents = summaryPage.find('#talents');
|
||||||
judge.empty();
|
judge.empty();
|
||||||
talents.empty();
|
talents.empty();
|
||||||
this.#talentSelected.forEach(talent=>{
|
const lastExtendTalent = this.#life.getLastExtendTalent();
|
||||||
const li = createTalent(talent);
|
Array
|
||||||
talents.append(li);
|
.from(this.#talentSelected)
|
||||||
li.click(()=>{
|
.sort((
|
||||||
if(li.hasClass('selected')) {
|
{id:a, grade:ag},
|
||||||
this.#selectedExtendTalent = null;
|
{id:b, grade:bg},
|
||||||
li.removeClass('selected');
|
)=>{
|
||||||
} else if(this.#selectedExtendTalent != null) {
|
if(a == lastExtendTalent) return -1;
|
||||||
this.hint('只能继承一个天赋');
|
if(b == lastExtendTalent) return 1;
|
||||||
return;
|
return bg - ag;
|
||||||
} else {
|
})
|
||||||
this.#selectedExtendTalent = talent.id;
|
.forEach((talent, i)=>{
|
||||||
li.addClass('selected');
|
const li = createTalent(talent);
|
||||||
}
|
talents.append(li);
|
||||||
|
li.click(()=>{
|
||||||
|
if(li.hasClass('selected')) {
|
||||||
|
this.#selectedExtendTalent = null;
|
||||||
|
li.removeClass('selected');
|
||||||
|
} else if(this.#selectedExtendTalent != null) {
|
||||||
|
this.hint('只能继承一个天赋');
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.#selectedExtendTalent = talent.id;
|
||||||
|
li.addClass('selected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(!i) li.click();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const records = this.#life.getRecord();
|
const summaryData = this.#life.getSummary();
|
||||||
const s = (type, func)=>{
|
const format = (discription, type)=>{
|
||||||
const value = func(records.map(({[type]:v})=>v));
|
const value = summaryData[type];
|
||||||
const { judge, grade } = summary(type, value);
|
const { judge, grade } = summary(type, value);
|
||||||
return { judge, grade, value };
|
return `<li class="grade${grade}"><span>${discription}:</span><span>${value} ${judge}</span></li>`;
|
||||||
};
|
};
|
||||||
console.table(records);
|
|
||||||
console.debug(records);
|
|
||||||
|
|
||||||
judge.append([
|
judge.append(`
|
||||||
(()=>{
|
${format('颜值', 'CHR')}
|
||||||
const { judge, grade, value } = s('CHR', max);
|
${format('智力', 'INT')}
|
||||||
return `<li class="grade${grade}"><span>颜值:</span>${value} ${judge}</li>`
|
${format('体质', 'STR')}
|
||||||
})(),
|
${format('家境', 'MNY')}
|
||||||
(()=>{
|
${format('快乐', 'SPR')}
|
||||||
const { judge, grade, value } = s('INT', max);
|
${format('享年', 'AGE')}
|
||||||
return `<li class="grade${grade}"><span>智力:</span>${value} ${judge}</li>`
|
${format('总评', 'SUM')}
|
||||||
})(),
|
`);
|
||||||
(()=>{
|
|
||||||
const { judge, grade, value } = s('STR', max);
|
|
||||||
return `<li class="grade${grade}"><span>体质:</span>${value} ${judge}</li>`
|
|
||||||
})(),
|
|
||||||
(()=>{
|
|
||||||
const { judge, grade, value } = s('MNY', max);
|
|
||||||
return `<li class="grade${grade}"><span>家境:</span>${value} ${judge}</li>`
|
|
||||||
})(),
|
|
||||||
(()=>{
|
|
||||||
const { judge, grade, value } = s('SPR', max);
|
|
||||||
return `<li class="grade${grade}"><span>快乐:</span>${value} ${judge}</li>`
|
|
||||||
})(),
|
|
||||||
(()=>{
|
|
||||||
const { judge, grade, value } = s('AGE', max);
|
|
||||||
return `<li class="grade${grade}"><span>享年:</span>${value} ${judge}</li>`
|
|
||||||
})(),
|
|
||||||
(()=>{
|
|
||||||
const m = type=>max(records.map(({[type]: value})=>value));
|
|
||||||
const value = Math.floor(sum(m('CHR'), m('INT'), m('STR'), m('MNY'), m('SPR'))*2 + m('AGE')/2);
|
|
||||||
const { judge, grade } = summary('SUM', value);
|
|
||||||
return `<li class="grade${grade}"><span>总评:</span>${value} ${judge}</li>`
|
|
||||||
})(),
|
|
||||||
].join(''));
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$$on('achievement', ({name})=>{
|
||||||
|
this.hint(`解锁成就【${name}】`, 'success');
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(page) {
|
switch(page) {
|
||||||
@@ -441,6 +787,9 @@ class App{
|
|||||||
$('#main').detach();
|
$('#main').detach();
|
||||||
p.clear();
|
p.clear();
|
||||||
p.page.appendTo('body');
|
p.page.appendTo('body');
|
||||||
|
if(typeof p.page.mounted === 'function'){
|
||||||
|
p.page.mounted()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hint(message, type='info') {
|
hint(message, type='info') {
|
||||||
@@ -459,9 +808,23 @@ class App{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get times() {return JSON.parse(localStorage.times||'0') || 0;}
|
setTheme(theme) {
|
||||||
set times(v) {localStorage.times = JSON.stringify(parseInt(v) || 0)};
|
const themeLink = $(document).find('#themeLink');
|
||||||
|
|
||||||
|
switch(theme){
|
||||||
|
case 'dark':
|
||||||
|
case 'light':
|
||||||
|
case 'halloween':
|
||||||
|
themeLink.attr('href', `${theme}.css`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
themeLink.attr('href', 'dark.css');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get times() {return this.#life?.times || 0;}
|
||||||
|
set times(v) { if(this.#life) this.#life.times = v };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ class Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count() {
|
||||||
|
return Object.keys(this.#events).length;
|
||||||
|
}
|
||||||
|
|
||||||
check(eventId, property) {
|
check(eventId, property) {
|
||||||
const { include, exclude, NoRandom } = this.get(eventId);
|
const { include, exclude, NoRandom } = this.get(eventId);
|
||||||
if(NoRandom) return false;
|
if(NoRandom) return false;
|
||||||
|
|||||||
41
src/functions/addition.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
export function getRate(type, value) {
|
||||||
|
switch(type) {
|
||||||
|
case 'times':
|
||||||
|
if(value >= 100) return {2:6};
|
||||||
|
if(value >= 70) return {2:5};
|
||||||
|
if(value >= 50) return {2:4};
|
||||||
|
if(value >= 30) return {2:3};
|
||||||
|
if(value >= 10) return {2:2};
|
||||||
|
return {2: 1};
|
||||||
|
case 'achievement':
|
||||||
|
if(value >= 100) return {3:6};
|
||||||
|
if(value >= 70) return {3:5};
|
||||||
|
if(value >= 50) return {3:4};
|
||||||
|
if(value >= 30) return {3:3};
|
||||||
|
if(value >= 10) return {3:2};
|
||||||
|
return {3:1};
|
||||||
|
default: return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGrade(type, value) {
|
||||||
|
switch(type) {
|
||||||
|
case 'times':
|
||||||
|
case 'achievement':
|
||||||
|
if(value >= 100) return 3;
|
||||||
|
if(value >= 50) return 2;
|
||||||
|
if(value >= 10) return 1;
|
||||||
|
return 0;
|
||||||
|
case 'talentRate':
|
||||||
|
if(value >= 0.9) return 3;
|
||||||
|
if(value >= 0.6) return 2;
|
||||||
|
if(value >= 0.3) return 1;
|
||||||
|
return 0;
|
||||||
|
case 'eventRate':
|
||||||
|
if(value >= 0.6) return 3;
|
||||||
|
if(value >= 0.4) return 2;
|
||||||
|
if(value >= 0.2) return 1;
|
||||||
|
return 0;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -93,7 +93,7 @@ function checkProp(property, condition) {
|
|||||||
case '!=':
|
case '!=':
|
||||||
if(Array.isArray(propData))
|
if(Array.isArray(propData))
|
||||||
return !propData.includes(conditionData);
|
return !propData.includes(conditionData);
|
||||||
return propData == conditionData;
|
return propData != conditionData;
|
||||||
case '?':
|
case '?':
|
||||||
if(Array.isArray(propData)) {
|
if(Array.isArray(propData)) {
|
||||||
for(const p of propData)
|
for(const p of propData)
|
||||||
@@ -113,4 +113,17 @@ function checkProp(property, condition) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { checkCondition };
|
function extractMaxTriggers(condition) {
|
||||||
|
// Assuming only age related talents can be triggered multiple times.
|
||||||
|
const RE_AGE_CONDITION = /AGE\?\[([0-9\,]+)\]/;
|
||||||
|
const match_object = RE_AGE_CONDITION.exec(condition);
|
||||||
|
if (match_object == null) {
|
||||||
|
// Not age related, single trigger.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const age_list = match_object[1].split(",");
|
||||||
|
return age_list.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { checkCondition, extractMaxTriggers };
|
||||||
@@ -28,4 +28,20 @@ function average(...arr) {
|
|||||||
return s / arr.flat().length;
|
return s / arr.flat().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { clone, max, min, sum, average };
|
function weightRandom(list) {
|
||||||
|
let totalWeights = 0;
|
||||||
|
for(const [, weight] of list)
|
||||||
|
totalWeights += weight;
|
||||||
|
|
||||||
|
let random = Math.random() * totalWeights;
|
||||||
|
for(const [id, weight] of list)
|
||||||
|
if((random-=weight)<0)
|
||||||
|
return id;
|
||||||
|
return list[list.length-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function listRandom(list) {
|
||||||
|
return list[Math.floor(Math.random() * list.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export { clone, max, min, sum, average, weightRandom, listRandom };
|
||||||
31
src/index.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import App from '../src/app.js';
|
||||||
|
|
||||||
|
globalThis.$$eventMap = new Map();
|
||||||
|
globalThis.$$event = (tag, data) => {
|
||||||
|
const listener = $$eventMap.get(tag);
|
||||||
|
if(listener) listener.forEach(fn=>fn(data));
|
||||||
|
}
|
||||||
|
globalThis.$$on = (tag, fn) => {
|
||||||
|
let listener = $$eventMap.get(tag);
|
||||||
|
if(!listener) {
|
||||||
|
listener = new Set();
|
||||||
|
$$eventMap.set(tag, listener);
|
||||||
|
}
|
||||||
|
listener.add(fn);
|
||||||
|
}
|
||||||
|
globalThis.$$off = (tag, fn) => {
|
||||||
|
const listener = $$eventMap.get(tag);
|
||||||
|
if(listener) listener.delete(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
globalThis.json = async fileName => await (await fetch(`../data/${fileName}.json`)).json();
|
||||||
|
|
||||||
|
// Pssst, I've created a github package - https://github.com/brookesb91/dismissible
|
||||||
|
globalThis.hideBanners = (e) => {
|
||||||
|
document
|
||||||
|
.querySelectorAll(".banner.visible")
|
||||||
|
.forEach((b) => b.classList.remove("visible"));
|
||||||
|
};
|
||||||
|
|
||||||
|
const app = new App();
|
||||||
|
app.initial();
|
||||||
153
src/life.js
@@ -1,63 +1,98 @@
|
|||||||
|
import { weightRandom } from './functions/util.js'
|
||||||
import Property from './property.js';
|
import Property from './property.js';
|
||||||
import Event from './event.js';
|
import Event from './event.js';
|
||||||
import Talent from './talent.js';
|
import Talent from './talent.js';
|
||||||
|
import Achievement from './achievement.js';
|
||||||
|
|
||||||
class Life {
|
class Life {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.#property = new Property();
|
this.#property = new Property();
|
||||||
this.#event = new Event();
|
this.#event = new Event();
|
||||||
this.#talent = new Talent();
|
this.#talent = new Talent();
|
||||||
|
this.#achievement = new Achievement();
|
||||||
}
|
}
|
||||||
|
|
||||||
#property;
|
#property;
|
||||||
#event;
|
#event;
|
||||||
#talent;
|
#talent;
|
||||||
|
#achievement;
|
||||||
#triggerTalents;
|
#triggerTalents;
|
||||||
|
|
||||||
async initial() {
|
async initial() {
|
||||||
const age = await json('age');
|
const [age, talents, events, achievements] = await Promise.all([
|
||||||
const talents = await json('talents');
|
json('age'),
|
||||||
const events = await json('events');
|
json('talents'),
|
||||||
|
json('events'),
|
||||||
|
json('achievement'),
|
||||||
|
])
|
||||||
this.#property.initial({age});
|
this.#property.initial({age});
|
||||||
this.#talent.initial({talents});
|
this.#talent.initial({talents});
|
||||||
this.#event.initial({events});
|
this.#event.initial({events});
|
||||||
|
this.#achievement.initial({achievements});
|
||||||
}
|
}
|
||||||
|
|
||||||
restart(allocation) {
|
restart(allocation) {
|
||||||
this.#triggerTalents = new Set();
|
this.#triggerTalents = {};
|
||||||
|
const contents = this.talentReplace(allocation.TLT);
|
||||||
this.#property.restart(allocation);
|
this.#property.restart(allocation);
|
||||||
this.doTalent();
|
this.doTalent()
|
||||||
this.#property.record();
|
this.#property.restartLastStep();
|
||||||
|
this.#achievement.achieve(
|
||||||
|
this.#achievement.Opportunity.START,
|
||||||
|
this.#property
|
||||||
|
)
|
||||||
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTalentAllocationAddition(talents) {
|
getTalentAllocationAddition(talents) {
|
||||||
return this.#talent.allocationAddition(talents);
|
return this.#talent.allocationAddition(talents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTalentCurrentTriggerCount(talentId) {
|
||||||
|
return this.#triggerTalents[talentId] || 0;
|
||||||
|
}
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
const {age, event, talent} = this.#property.ageNext();
|
const {age, event, talent} = this.#property.ageNext();
|
||||||
|
|
||||||
const talentContent = this.doTalent(talent);
|
const talentContent = this.doTalent(talent);
|
||||||
const eventContent = this.doEvent(this.random(event));
|
const eventContent = this.doEvent(this.random(event));
|
||||||
this.#property.record();
|
|
||||||
|
|
||||||
const isEnd = this.#property.isEnd();
|
const isEnd = this.#property.isEnd();
|
||||||
|
|
||||||
const content = [talentContent, eventContent].flat();
|
const content = [talentContent, eventContent].flat();
|
||||||
|
this.#achievement.achieve(
|
||||||
|
this.#achievement.Opportunity.TRAJECTORY,
|
||||||
|
this.#property
|
||||||
|
)
|
||||||
return { age, content, isEnd };
|
return { age, content, isEnd };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
talentReplace(talents) {
|
||||||
|
const result = this.#talent.replace(talents);
|
||||||
|
const contents = [];
|
||||||
|
for(const id in result) {
|
||||||
|
talents.push(result[id]);
|
||||||
|
const source = this.#talent.get(id);
|
||||||
|
const target = this.#talent.get(result[id]);
|
||||||
|
contents.push({
|
||||||
|
type: 'talentReplace',
|
||||||
|
source, target
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
doTalent(talents) {
|
doTalent(talents) {
|
||||||
if(talents) this.#property.change(this.#property.TYPES.TLT, talents);
|
if(talents) this.#property.change(this.#property.TYPES.TLT, talents);
|
||||||
talents = this.#property.get(this.#property.TYPES.TLT)
|
talents = this.#property.get(this.#property.TYPES.TLT)
|
||||||
.filter(talentId=>!this.#triggerTalents.has(talentId));
|
.filter(talentId => this.getTalentCurrentTriggerCount(talentId) < this.#talent.get(talentId).max_triggers);
|
||||||
|
|
||||||
const contents = [];
|
const contents = [];
|
||||||
for(const talentId of talents) {
|
for(const talentId of talents) {
|
||||||
const result = this.#talent.do(talentId, this.#property);
|
const result = this.#talent.do(talentId, this.#property);
|
||||||
if(!result) continue;
|
if(!result) continue;
|
||||||
this.#triggerTalents.add(talentId);
|
this.#triggerTalents[talentId] = this.getTalentCurrentTriggerCount(talentId) + 1;
|
||||||
const { effect, name, description, grade } = result;
|
const { effect, name, description, grade } = result;
|
||||||
contents.push({
|
contents.push({
|
||||||
type: this.#property.TYPES.TLT,
|
type: this.#property.TYPES.TLT,
|
||||||
@@ -85,34 +120,102 @@ class Life {
|
|||||||
}
|
}
|
||||||
|
|
||||||
random(events) {
|
random(events) {
|
||||||
events = events.filter(([eventId])=>this.#event.check(eventId, this.#property));
|
return weightRandom(
|
||||||
|
events.filter(
|
||||||
let totalWeights = 0;
|
([eventId])=>this.#event.check(eventId, this.#property)
|
||||||
for(const [, weight] of events)
|
)
|
||||||
totalWeights += weight;
|
);
|
||||||
|
|
||||||
let random = Math.random() * totalWeights;
|
|
||||||
for(const [eventId, weight] of events)
|
|
||||||
if((random-=weight)<0)
|
|
||||||
return eventId;
|
|
||||||
return events[events.length-1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
talentRandom() {
|
talentRandom() {
|
||||||
return this.#talent.talentRandom(JSON.parse(localStorage.extendTalent||'null'));
|
const times = this.#property.get(this.#property.TYPES.TMS);
|
||||||
|
const achievement = this.#property.get(this.#property.TYPES.CACHV);
|
||||||
|
return this.#talent.talentRandom(this.getLastExtendTalent(), { times, achievement });
|
||||||
}
|
}
|
||||||
|
|
||||||
talentExtend(talentId) {
|
talentExtend(talentId) {
|
||||||
localStorage.extendTalent = JSON.stringify(talentId);
|
this.#property.set(this.#property.TYPES.EXT, talentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecord() {
|
getLastExtendTalent() {
|
||||||
return this.#property.getRecord();
|
return this.#property.get(this.#property.TYPES.EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSummary() {
|
||||||
|
this.#achievement.achieve(
|
||||||
|
this.#achievement.Opportunity.SUMMARY,
|
||||||
|
this.#property
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
AGE: this.#property.get(this.#property.TYPES.HAGE),
|
||||||
|
CHR: this.#property.get(this.#property.TYPES.HCHR),
|
||||||
|
INT: this.#property.get(this.#property.TYPES.HINT),
|
||||||
|
STR: this.#property.get(this.#property.TYPES.HSTR),
|
||||||
|
MNY: this.#property.get(this.#property.TYPES.HMNY),
|
||||||
|
SPR: this.#property.get(this.#property.TYPES.HSPR),
|
||||||
|
SUM: this.#property.get(this.#property.TYPES.SUM),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastRecord() {
|
||||||
|
return this.#property.getLastRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
exclusive(talents, exclusive) {
|
exclusive(talents, exclusive) {
|
||||||
return this.#talent.exclusive(talents, exclusive);
|
return this.#talent.exclusive(talents, exclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAchievements() {
|
||||||
|
const ticks = {};
|
||||||
|
this.#property
|
||||||
|
.get(this.#property.TYPES.ACHV)
|
||||||
|
.forEach(([id, tick]) => ticks[id] = tick);
|
||||||
|
return this
|
||||||
|
.#achievement
|
||||||
|
.list(this.#property)
|
||||||
|
.sort((
|
||||||
|
{id: a, grade: ag, hide: ah},
|
||||||
|
{id: b, grade: bg, hide: bh}
|
||||||
|
)=>{
|
||||||
|
a = ticks[a];
|
||||||
|
b = ticks[b];
|
||||||
|
if(a&&b) return b - a;
|
||||||
|
if(!a&&!b) {
|
||||||
|
if(ah&&bh) return bg - ag;
|
||||||
|
if(ah) return 1;
|
||||||
|
if(bh) return -1;
|
||||||
|
return bg - ag;
|
||||||
|
}
|
||||||
|
if(!a) return 1;
|
||||||
|
if(!b) return -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getTotal() {
|
||||||
|
const TMS = this.#property.get(this.#property.TYPES.TMS);
|
||||||
|
const CACHV = this.#property.get(this.#property.TYPES.CACHV);
|
||||||
|
const CTLT = this.#property.get(this.#property.TYPES.CTLT);
|
||||||
|
const CEVT = this.#property.get(this.#property.TYPES.CEVT);
|
||||||
|
|
||||||
|
const totalTalent = this.#talent.count();
|
||||||
|
const totalEvent = this.#event.count();
|
||||||
|
|
||||||
|
return {
|
||||||
|
times: TMS,
|
||||||
|
achievement: CACHV,
|
||||||
|
talentRate: CTLT / totalTalent,
|
||||||
|
eventRate: CEVT / totalEvent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get times() { return this.#property?.get(this.#property.TYPES.TMS) || 0; }
|
||||||
|
set times(v) {
|
||||||
|
this.#property?.set(this.#property.TYPES.TMS, v) || 0;
|
||||||
|
this.#achievement.achieve(
|
||||||
|
this.#achievement.Opportunity.END,
|
||||||
|
this.#property
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Life;
|
export default Life;
|
||||||
|
|||||||
267
src/property.js
@@ -1,23 +1,67 @@
|
|||||||
import { clone } from './functions/util.js';
|
import { max, min, sum, clone, listRandom } from './functions/util.js';
|
||||||
|
|
||||||
class Property {
|
class Property {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
TYPES = {
|
TYPES = {
|
||||||
AGE: "AGE",
|
// 本局
|
||||||
CHR: "CHR",
|
AGE: "AGE", // 年龄 age AGE
|
||||||
INT: "INT",
|
CHR: "CHR", // 颜值 charm CHR
|
||||||
STR: "STR",
|
INT: "INT", // 智力 intelligence INT
|
||||||
MNY: "MNY",
|
STR: "STR", // 体质 strength STR
|
||||||
SPR: "SPR",
|
MNY: "MNY", // 家境 money MNY
|
||||||
LIF: "LIF",
|
SPR: "SPR", // 快乐 spirit SPR
|
||||||
TLT: "TLT",
|
LIF: "LIF", // 生命 life LIFE
|
||||||
EVT: "EVT",
|
TLT: "TLT", // 天赋 talent TLT
|
||||||
|
EVT: "EVT", // 事件 event EVT
|
||||||
|
TMS: "TMS", // 次数 times TMS
|
||||||
|
|
||||||
|
// Auto calc
|
||||||
|
LAGE: "LAGE", // 最低年龄 Low Age
|
||||||
|
HAGE: "HAGE", // 最高年龄 High Age
|
||||||
|
LCHR: "LCHR", // 最低颜值 Low Charm
|
||||||
|
HCHR: "HCHR", // 最高颜值 High Charm
|
||||||
|
LINT: "LINT", // 最低智力 Low Intelligence
|
||||||
|
HINT: "HINT", // 最高智力 High Intelligence
|
||||||
|
LSTR: "LSTR", // 最低体质 Low Strength
|
||||||
|
HSTR: "HSTR", // 最高体质 High Strength
|
||||||
|
LMNY: "LMNY", // 最低家境 Low Money
|
||||||
|
HMNY: "HMNY", // 最高家境 High Money
|
||||||
|
LSPR: "LSPR", // 最低快乐 Low Spirit
|
||||||
|
HSPR: "HSPR", // 最高快乐 High Spirit
|
||||||
|
|
||||||
|
SUM: "SUM", // 总评 summary SUM
|
||||||
|
|
||||||
|
EXT: "EXT", // 继承天赋
|
||||||
|
|
||||||
|
// 总计
|
||||||
|
// Achievement Total
|
||||||
|
ATLT: "ATLT", // 拥有过的天赋 Achieve Talent
|
||||||
|
AEVT: "AEVT", // 触发过的事件 Achieve Event
|
||||||
|
ACHV: "ACHV", // 达成的成就 Achievement
|
||||||
|
|
||||||
|
CTLT: "RTLT", // 天赋选择数 Count Talent
|
||||||
|
CEVT: "REVT", // 事件收集数 Count Event
|
||||||
|
CACHV: "CACHV", // 成就达成数 Count Achievement
|
||||||
|
|
||||||
|
// SPECIAL
|
||||||
|
RDM: 'RDM', // 随机属性 random RDM
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 特殊类型
|
||||||
|
SPECIAL = {
|
||||||
|
RDM: [ // 随机属性 random RDM
|
||||||
|
this.TYPES.CHR,
|
||||||
|
this.TYPES.INT,
|
||||||
|
this.TYPES.STR,
|
||||||
|
this.TYPES.MNY,
|
||||||
|
this.TYPES.SPR,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
#ageData;
|
#ageData;
|
||||||
#data;
|
#data = {};
|
||||||
#record;
|
|
||||||
|
|
||||||
initial({age}) {
|
initial({age}) {
|
||||||
|
|
||||||
@@ -45,18 +89,49 @@ class Property {
|
|||||||
restart(data) {
|
restart(data) {
|
||||||
this.#data = {
|
this.#data = {
|
||||||
[this.TYPES.AGE]: -1,
|
[this.TYPES.AGE]: -1,
|
||||||
|
|
||||||
[this.TYPES.CHR]: 0,
|
[this.TYPES.CHR]: 0,
|
||||||
[this.TYPES.INT]: 0,
|
[this.TYPES.INT]: 0,
|
||||||
[this.TYPES.STR]: 0,
|
[this.TYPES.STR]: 0,
|
||||||
[this.TYPES.MNY]: 0,
|
[this.TYPES.MNY]: 0,
|
||||||
[this.TYPES.SPR]: 0,
|
[this.TYPES.SPR]: 0,
|
||||||
|
|
||||||
[this.TYPES.LIF]: 1,
|
[this.TYPES.LIF]: 1,
|
||||||
|
|
||||||
[this.TYPES.TLT]: [],
|
[this.TYPES.TLT]: [],
|
||||||
[this.TYPES.EVT]: [],
|
[this.TYPES.EVT]: [],
|
||||||
|
|
||||||
|
[this.TYPES.LAGE]: Infinity,
|
||||||
|
[this.TYPES.LCHR]: Infinity,
|
||||||
|
[this.TYPES.LINT]: Infinity,
|
||||||
|
[this.TYPES.LSTR]: Infinity,
|
||||||
|
[this.TYPES.LSPR]: Infinity,
|
||||||
|
[this.TYPES.LMNY]: Infinity,
|
||||||
|
|
||||||
|
[this.TYPES.HAGE]: -Infinity,
|
||||||
|
[this.TYPES.HCHR]: -Infinity,
|
||||||
|
[this.TYPES.HINT]: -Infinity,
|
||||||
|
[this.TYPES.HSTR]: -Infinity,
|
||||||
|
[this.TYPES.HMNY]: -Infinity,
|
||||||
|
[this.TYPES.HSPR]: -Infinity,
|
||||||
};
|
};
|
||||||
for(const key in data)
|
for(const key in data)
|
||||||
this.change(key, data[key]);
|
this.change(key, data[key]);
|
||||||
this.#record = [];
|
}
|
||||||
|
|
||||||
|
restartLastStep() {
|
||||||
|
this.#data[this.TYPES.LAGE] = this.get(this.TYPES.AGE);
|
||||||
|
this.#data[this.TYPES.LCHR] = this.get(this.TYPES.CHR);
|
||||||
|
this.#data[this.TYPES.LINT] = this.get(this.TYPES.INT);
|
||||||
|
this.#data[this.TYPES.LSTR] = this.get(this.TYPES.STR);
|
||||||
|
this.#data[this.TYPES.LSPR] = this.get(this.TYPES.SPR);
|
||||||
|
this.#data[this.TYPES.LMNY] = this.get(this.TYPES.MNY);
|
||||||
|
this.#data[this.TYPES.HAGE] = this.get(this.TYPES.AGE);
|
||||||
|
this.#data[this.TYPES.HCHR] = this.get(this.TYPES.CHR);
|
||||||
|
this.#data[this.TYPES.HINT] = this.get(this.TYPES.INT);
|
||||||
|
this.#data[this.TYPES.HSTR] = this.get(this.TYPES.STR);
|
||||||
|
this.#data[this.TYPES.HMNY] = this.get(this.TYPES.MNY);
|
||||||
|
this.#data[this.TYPES.HSPR] = this.get(this.TYPES.SPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(prop) {
|
get(prop) {
|
||||||
@@ -71,10 +146,73 @@ class Property {
|
|||||||
case this.TYPES.TLT:
|
case this.TYPES.TLT:
|
||||||
case this.TYPES.EVT:
|
case this.TYPES.EVT:
|
||||||
return clone(this.#data[prop]);
|
return clone(this.#data[prop]);
|
||||||
|
case this.TYPES.LAGE:
|
||||||
|
case this.TYPES.LCHR:
|
||||||
|
case this.TYPES.LINT:
|
||||||
|
case this.TYPES.LSTR:
|
||||||
|
case this.TYPES.LMNY:
|
||||||
|
case this.TYPES.LSPR:
|
||||||
|
return min(
|
||||||
|
this.#data[prop],
|
||||||
|
this.get(this.fallback(prop))
|
||||||
|
);
|
||||||
|
case this.TYPES.HAGE:
|
||||||
|
case this.TYPES.HCHR:
|
||||||
|
case this.TYPES.HINT:
|
||||||
|
case this.TYPES.HSTR:
|
||||||
|
case this.TYPES.HMNY:
|
||||||
|
case this.TYPES.HSPR:
|
||||||
|
return max(
|
||||||
|
this.#data[prop],
|
||||||
|
this.get(this.fallback(prop))
|
||||||
|
);
|
||||||
|
case this.TYPES.SUM:
|
||||||
|
const HAGE = this.get(this.TYPES.HAGE);
|
||||||
|
const HCHR = this.get(this.TYPES.HCHR);
|
||||||
|
const HINT = this.get(this.TYPES.HINT);
|
||||||
|
const HSTR = this.get(this.TYPES.HSTR);
|
||||||
|
const HMNY = this.get(this.TYPES.HMNY);
|
||||||
|
const HSPR = this.get(this.TYPES.HSPR);
|
||||||
|
return Math.floor(sum(HCHR, HINT, HSTR, HMNY, HSPR)*2 + HAGE/2);
|
||||||
|
case this.TYPES.TMS:
|
||||||
|
return this.lsget('times') || 0;
|
||||||
|
case this.TYPES.EXT:
|
||||||
|
return this.lsget('extendTalent') || null;
|
||||||
|
case this.TYPES.ATLT:
|
||||||
|
case this.TYPES.AEVT:
|
||||||
|
case this.TYPES.ACHV:
|
||||||
|
return this.lsget(prop) || [];
|
||||||
|
case this.TYPES.CTLT:
|
||||||
|
case this.TYPES.CEVT:
|
||||||
|
case this.TYPES.CACHV:
|
||||||
|
return this.get(
|
||||||
|
this.fallback(prop)
|
||||||
|
).length;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fallback(prop) {
|
||||||
|
switch(prop) {
|
||||||
|
case this.TYPES.LAGE:
|
||||||
|
case this.TYPES.HAGE: return this.TYPES.AGE;
|
||||||
|
case this.TYPES.LCHR:
|
||||||
|
case this.TYPES.HCHR: return this.TYPES.CHR;
|
||||||
|
case this.TYPES.LINT:
|
||||||
|
case this.TYPES.HINT: return this.TYPES.INT;
|
||||||
|
case this.TYPES.LSTR:
|
||||||
|
case this.TYPES.HSTR: return this.TYPES.STR;
|
||||||
|
case this.TYPES.LMNY:
|
||||||
|
case this.TYPES.HMNY: return this.TYPES.MNY;
|
||||||
|
case this.TYPES.LSPR:
|
||||||
|
case this.TYPES.HSPR: return this.TYPES.SPR;
|
||||||
|
case this.TYPES.CTLT: return this.TYPES.ATLT;
|
||||||
|
case this.TYPES.CEVT: return this.TYPES.AEVT;
|
||||||
|
case this.TYPES.CACHV: return this.TYPES.ACHV;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
set(prop, value) {
|
set(prop, value) {
|
||||||
switch(prop) {
|
switch(prop) {
|
||||||
case this.TYPES.AGE:
|
case this.TYPES.AGE:
|
||||||
@@ -86,14 +224,21 @@ class Property {
|
|||||||
case this.TYPES.LIF:
|
case this.TYPES.LIF:
|
||||||
case this.TYPES.TLT:
|
case this.TYPES.TLT:
|
||||||
case this.TYPES.EVT:
|
case this.TYPES.EVT:
|
||||||
this.#data[prop] = clone(value);
|
this.hl(prop, this.#data[prop] = clone(value));
|
||||||
break;
|
this.achieve(prop, value);
|
||||||
default: return 0;
|
return;
|
||||||
|
case this.TYPES.TMS:
|
||||||
|
this.lsset('times', parseInt(value) || 0);
|
||||||
|
return;
|
||||||
|
case this.TYPES.EXT:
|
||||||
|
this.lsset('extendTalent', value);
|
||||||
|
return
|
||||||
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record() {
|
getLastRecord() {
|
||||||
this.#record.push({
|
return clone({
|
||||||
[this.TYPES.AGE]: this.get(this.TYPES.AGE),
|
[this.TYPES.AGE]: this.get(this.TYPES.AGE),
|
||||||
[this.TYPES.CHR]: this.get(this.TYPES.CHR),
|
[this.TYPES.CHR]: this.get(this.TYPES.CHR),
|
||||||
[this.TYPES.INT]: this.get(this.TYPES.INT),
|
[this.TYPES.INT]: this.get(this.TYPES.INT),
|
||||||
@@ -103,10 +248,6 @@ class Property {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecord() {
|
|
||||||
return clone(this.#record);
|
|
||||||
}
|
|
||||||
|
|
||||||
change(prop, value) {
|
change(prop, value) {
|
||||||
if(Array.isArray(value)) {
|
if(Array.isArray(value)) {
|
||||||
for(const v of value)
|
for(const v of value)
|
||||||
@@ -121,8 +262,8 @@ class Property {
|
|||||||
case this.TYPES.MNY:
|
case this.TYPES.MNY:
|
||||||
case this.TYPES.SPR:
|
case this.TYPES.SPR:
|
||||||
case this.TYPES.LIF:
|
case this.TYPES.LIF:
|
||||||
this.#data[prop] += Number(value);
|
this.hl(prop, this.#data[prop] += Number(value));
|
||||||
break;
|
return;
|
||||||
case this.TYPES.TLT:
|
case this.TYPES.TLT:
|
||||||
case this.TYPES.EVT:
|
case this.TYPES.EVT:
|
||||||
const v = this.#data[prop];
|
const v = this.#data[prop];
|
||||||
@@ -131,14 +272,31 @@ class Property {
|
|||||||
if(index!=-1) v.splice(index,1);
|
if(index!=-1) v.splice(index,1);
|
||||||
}
|
}
|
||||||
if(!v.includes(value)) v.push(value);
|
if(!v.includes(value)) v.push(value);
|
||||||
break;
|
this.achieve(prop, value);
|
||||||
|
return;
|
||||||
|
case this.TYPES.TMS:
|
||||||
|
this.set(
|
||||||
|
prop,
|
||||||
|
this.get(prop) + parseInt(value)
|
||||||
|
);
|
||||||
|
return;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hookSpecial(prop) {
|
||||||
|
switch(prop) {
|
||||||
|
case this.TYPES.RDM: return listRandom(this.SPECIAL.RDM);
|
||||||
|
default: return prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
effect(effects) {
|
effect(effects) {
|
||||||
for(const prop in effects)
|
for(let prop in effects)
|
||||||
this.change(prop, Number(effects[prop]));
|
this.change(
|
||||||
|
this.hookSpecial(prop),
|
||||||
|
Number(effects[prop])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isEnd() {
|
isEnd() {
|
||||||
@@ -156,6 +314,61 @@ class Property {
|
|||||||
return clone(this.#ageData[age]);
|
return clone(this.#ageData[age]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hl(prop, value) {
|
||||||
|
let keys;
|
||||||
|
switch(prop) {
|
||||||
|
case this.TYPES.AGE: keys = [this.TYPES.LAGE, this.TYPES.HAGE]; break;
|
||||||
|
case this.TYPES.CHR: keys = [this.TYPES.LCHR, this.TYPES.HCHR]; break;
|
||||||
|
case this.TYPES.INT: keys = [this.TYPES.LINT, this.TYPES.HINT]; break;
|
||||||
|
case this.TYPES.STR: keys = [this.TYPES.LSTR, this.TYPES.HSTR]; break;
|
||||||
|
case this.TYPES.MNY: keys = [this.TYPES.LMNY, this.TYPES.HMNY]; break;
|
||||||
|
case this.TYPES.SPR: keys = [this.TYPES.LSPR, this.TYPES.HSPR]; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
const [l, h] = keys;
|
||||||
|
this.#data[l] = min(this.#data[l], value);
|
||||||
|
this.#data[h] = max(this.#data[h], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
achieve(prop, newData) {
|
||||||
|
let key;
|
||||||
|
switch(prop) {
|
||||||
|
case this.TYPES.ACHV:
|
||||||
|
const lastData = this.lsget(prop);
|
||||||
|
this.lsset(
|
||||||
|
prop,
|
||||||
|
(lastData || []).concat([[newData, Date.now()]])
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
case this.TYPES.TLT: key = this.TYPES.ATLT; break;
|
||||||
|
case this.TYPES.EVT: key = this.TYPES.AEVT; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
const lastData = this.lsget(key) || [];
|
||||||
|
this.lsset(
|
||||||
|
key,
|
||||||
|
Array.from(
|
||||||
|
new Set(
|
||||||
|
lastData
|
||||||
|
.concat(newData||[])
|
||||||
|
.flat()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
lsget(key) {
|
||||||
|
const data = localStorage.getItem(key);
|
||||||
|
if(data === null) return;
|
||||||
|
return JSON.parse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
lsset(key, value) {
|
||||||
|
localStorage.setItem(
|
||||||
|
key,
|
||||||
|
JSON.stringify(value)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Property;
|
export default Property;
|
||||||
103
src/talent.js
@@ -1,5 +1,6 @@
|
|||||||
import { clone } from './functions/util.js';
|
import { clone, weightRandom } from './functions/util.js';
|
||||||
import { checkCondition } from './functions/condition.js';
|
import { checkCondition, extractMaxTriggers } from './functions/condition.js';
|
||||||
|
import { getRate } from './functions/addition.js';
|
||||||
|
|
||||||
class Talent {
|
class Talent {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
@@ -12,9 +13,24 @@ class Talent {
|
|||||||
const talent = talents[id];
|
const talent = talents[id];
|
||||||
talent.id= Number(id);
|
talent.id= Number(id);
|
||||||
talent.grade = Number(talent.grade);
|
talent.grade = Number(talent.grade);
|
||||||
|
talent.max_triggers = extractMaxTriggers(talent.condition);
|
||||||
|
if(talent.replacement) {
|
||||||
|
for(let key in talent.replacement) {
|
||||||
|
const obj = {};
|
||||||
|
for(let value of talent.replacement[key]) {
|
||||||
|
value = `${value}`.split('*');
|
||||||
|
obj[value[0]||0] = Number(value[1]) || 1;
|
||||||
|
}
|
||||||
|
talent.replacement[key] = obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count() {
|
||||||
|
return Object.keys(this.#talents).length;
|
||||||
|
}
|
||||||
|
|
||||||
check(talentId, property) {
|
check(talentId, property) {
|
||||||
const { condition } = this.get(talentId);
|
const { condition } = this.get(talentId);
|
||||||
return checkCondition(property, condition);
|
return checkCondition(property, condition);
|
||||||
@@ -42,7 +58,29 @@ class Talent {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
talentRandom(include) {
|
talentRandom(include, {times = 0, achievement = 0} = {}) {
|
||||||
|
const rate = { 1:100, 2:10, 3:1, };
|
||||||
|
const rateAddition = { 1:1, 2:1, 3:1, };
|
||||||
|
const timesRate = getRate('times', times);
|
||||||
|
const achievementRate = getRate('achievement', achievement);
|
||||||
|
|
||||||
|
for(const grade in timesRate)
|
||||||
|
rateAddition[grade] += timesRate[grade] - 1;
|
||||||
|
|
||||||
|
for(const grade in achievementRate)
|
||||||
|
rateAddition[grade] += achievementRate[grade] - 1;
|
||||||
|
|
||||||
|
for(const grade in rateAddition)
|
||||||
|
rate[grade] *= rateAddition[grade];
|
||||||
|
|
||||||
|
const randomGrade = () => {
|
||||||
|
let randomNumber = Math.floor(Math.random() * 1000);
|
||||||
|
if((randomNumber -= rate[3]) < 0) return 3;
|
||||||
|
if((randomNumber -= rate[2]) < 0) return 2;
|
||||||
|
if((randomNumber -= rate[1]) < 0) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// 1000, 100, 10, 1
|
// 1000, 100, 10, 1
|
||||||
const talentList = {};
|
const talentList = {};
|
||||||
for(const talentId in this.#talents) {
|
for(const talentId in this.#talents) {
|
||||||
@@ -58,15 +96,8 @@ class Talent {
|
|||||||
return new Array(10)
|
return new Array(10)
|
||||||
.fill(1).map((v, i)=>{
|
.fill(1).map((v, i)=>{
|
||||||
if(!i && include) return include;
|
if(!i && include) return include;
|
||||||
const gradeRandom = Math.random();
|
let grade = randomGrade();
|
||||||
let grade;
|
|
||||||
if(gradeRandom>=0.111) grade = 0;
|
|
||||||
else if(gradeRandom>=0.011) grade = 1;
|
|
||||||
else if(gradeRandom>=0.001) grade = 2;
|
|
||||||
else grade = 3;
|
|
||||||
|
|
||||||
while(talentList[grade].length == 0) grade--;
|
while(talentList[grade].length == 0) grade--;
|
||||||
|
|
||||||
const length = talentList[grade].length;
|
const length = talentList[grade].length;
|
||||||
|
|
||||||
const random = Math.floor(Math.random()*length) % length;
|
const random = Math.floor(Math.random()*length) % length;
|
||||||
@@ -90,6 +121,56 @@ class Talent {
|
|||||||
return null;
|
return null;
|
||||||
return { effect, grade, name, description };
|
return { effect, grade, name, description };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
replace(talents) {
|
||||||
|
const getReplaceList = (talent, talents) => {
|
||||||
|
const { replacement } = this.get(talent);
|
||||||
|
if(!replacement) return null;
|
||||||
|
const list = [];
|
||||||
|
if(replacement.grade) {
|
||||||
|
this.forEach(({id, grade})=>{
|
||||||
|
if(!replacement.grade[grade]) return;
|
||||||
|
if(this.exclusive(talents, id)) return;
|
||||||
|
list.push([id, replacement.grade[grade]]);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(replacement.talent) {
|
||||||
|
for(let id in replacement.talent) {
|
||||||
|
id = Number(id);
|
||||||
|
if(this.exclusive(talents, id)) continue;
|
||||||
|
list.push([id, replacement.talent[id]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replace = (talent, talents) => {
|
||||||
|
const replaceList = getReplaceList(talent, talents);
|
||||||
|
if(!replaceList) return talent;
|
||||||
|
const rand = weightRandom(replaceList);
|
||||||
|
return replace(
|
||||||
|
rand, talents.concat(rand)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTalents = clone(talents);
|
||||||
|
const result = {};
|
||||||
|
for(const talent of talents) {
|
||||||
|
const replaceId = replace(talent, newTalents);
|
||||||
|
if(replaceId != talent) {
|
||||||
|
result[talent] = replaceId;
|
||||||
|
newTalents.push(replaceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
forEach(callback) {
|
||||||
|
if(typeof callback != 'function') return;
|
||||||
|
for(const id in this.#talents)
|
||||||
|
callback(clone(this.#talents[id]), id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Talent;
|
export default Talent;
|
||||||
@@ -1,7 +1,30 @@
|
|||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import Life from '../src/life.js'
|
import Life from '../src/life.js'
|
||||||
|
|
||||||
global.json = async fileName => JSON.parse(await readFile(`data/${fileName}.json`));
|
globalThis.json = async fileName => JSON.parse(await readFile(`data/${fileName}.json`));
|
||||||
|
|
||||||
|
globalThis.localStorage = {};
|
||||||
|
localStorage.getItem = key => localStorage[key]===void 0? null: localStorage[key];
|
||||||
|
localStorage.setItem = (key, value) => (localStorage[key] = value);
|
||||||
|
|
||||||
|
|
||||||
|
globalThis.$$eventMap = new Map();
|
||||||
|
globalThis.$$event = (tag, data) => {
|
||||||
|
const listener = $$eventMap.get(tag);
|
||||||
|
if(listener) listener.forEach(fn=>fn(data));
|
||||||
|
}
|
||||||
|
globalThis.$$on = (tag, fn) => {
|
||||||
|
let listener = $$eventMap.get(tag);
|
||||||
|
if(!listener) {
|
||||||
|
listener = new Set();
|
||||||
|
$$eventMap.set(tag, listener);
|
||||||
|
}
|
||||||
|
listener.add(fn);
|
||||||
|
}
|
||||||
|
globalThis.$$off = (tag, fn) => {
|
||||||
|
const listener = $$eventMap.get(tag);
|
||||||
|
if(listener) listener.delete(fn);
|
||||||
|
}
|
||||||
|
|
||||||
async function debug() {
|
async function debug() {
|
||||||
|
|
||||||
@@ -14,7 +37,8 @@ async function debug() {
|
|||||||
STR: 5, // 体质 strength STR
|
STR: 5, // 体质 strength STR
|
||||||
MNY: 5, // 家境 money MNY
|
MNY: 5, // 家境 money MNY
|
||||||
SPR: 5, // 快乐 spirit SPR
|
SPR: 5, // 快乐 spirit SPR
|
||||||
TLT: [1004, 1005, 1009], // 天赋 talent TLT
|
// AGE: 100,
|
||||||
|
TLT: [1134, 1048, 1114], // 天赋 talent TLT
|
||||||
});
|
});
|
||||||
const lifeTrajectory = [];
|
const lifeTrajectory = [];
|
||||||
let trajectory;
|
let trajectory;
|
||||||
@@ -26,7 +50,7 @@ async function debug() {
|
|||||||
// debugger
|
// debugger
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
lifeTrajectory.push(lifeTrajectory);
|
lifeTrajectory.push(trajectory);
|
||||||
const { age, content } = trajectory;
|
const { age, content } = trajectory;
|
||||||
console.debug(
|
console.debug(
|
||||||
`---------------------------------`,
|
`---------------------------------`,
|
||||||
@@ -42,6 +66,7 @@ async function debug() {
|
|||||||
}
|
}
|
||||||
).join('\n ')
|
).join('\n ')
|
||||||
);
|
);
|
||||||
|
if(age == 60) debugger
|
||||||
} while(!trajectory.isEnd)
|
} while(!trajectory.isEnd)
|
||||||
// debugger;
|
// debugger;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,58 +6,154 @@ import { join, extname, dirname } from 'path';
|
|||||||
// const XLSX = require('xlsx');
|
// const XLSX = require('xlsx');
|
||||||
// const { join, extname, dirname } = require('path');
|
// const { join, extname, dirname } = require('path');
|
||||||
|
|
||||||
async function transform(filePath) {
|
async function read(xlsxPath) {
|
||||||
const xlsxFileBuffer = await readFile(filePath);
|
const xlsxFileBuffer = await readFile(xlsxPath);
|
||||||
const xlsx = XLSX.read(xlsxFileBuffer, {type: 'buffer'});
|
const xlsx = XLSX.read(xlsxFileBuffer, {type: 'buffer'});
|
||||||
const sheets = xlsx.Sheets;
|
const sheets = xlsx.Sheets;
|
||||||
|
|
||||||
const data = {};
|
const data = {};
|
||||||
for(const sheetName in sheets) {
|
for(const sheetName in sheets) {
|
||||||
const sheetRawData = sheets[sheetName];
|
const sheetRawData = sheets[sheetName];
|
||||||
if(!sheetRawData['!ref']) break;
|
if(!sheetRawData['!ref']) break;
|
||||||
const rawData = XLSX.utils.sheet_to_json(sheetRawData);
|
data[sheetName] = XLSX.utils.sheet_to_json(sheetRawData);
|
||||||
const newData = {};
|
|
||||||
data[sheetName] = newData;
|
|
||||||
rawData.shift();
|
|
||||||
for(const row of rawData) {
|
|
||||||
const rowData = {};
|
|
||||||
let mainKey;
|
|
||||||
for(let key in row) {
|
|
||||||
const cell = row[key];
|
|
||||||
if(key[0] == "$") {
|
|
||||||
key = key.substr(1);
|
|
||||||
mainKey = cell;
|
|
||||||
}
|
|
||||||
if(key.includes(':')) {
|
|
||||||
const keys = key.split(':');
|
|
||||||
const lastKey = keys.pop();
|
|
||||||
let temp = rowData;
|
|
||||||
for(const subKey of keys) {
|
|
||||||
if(!temp[subKey]) temp[subKey] = {};
|
|
||||||
temp = temp[subKey];
|
|
||||||
}
|
|
||||||
if(lastKey.includes('[]')) {
|
|
||||||
const aKey = lastKey.split('[]')[0];
|
|
||||||
if(!temp[aKey]) temp[aKey] = [cell];
|
|
||||||
else temp[aKey].push(cell);
|
|
||||||
} else {
|
|
||||||
temp[lastKey] = cell;
|
|
||||||
}
|
|
||||||
} else if(key.includes('[]')) {
|
|
||||||
const aKey = key.split('[]')[0];
|
|
||||||
if(!rowData[aKey]) rowData[aKey] = [cell];
|
|
||||||
else rowData[aKey].push(cell);
|
|
||||||
} else {
|
|
||||||
rowData[key] = cell;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(mainKey===undefined) return console.error('No Main Key', rowData);
|
|
||||||
newData[mainKey] = rowData;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function write(sheets) {
|
||||||
|
for(const sheetName in sheets) {
|
||||||
|
const { dirname, data, source } = sheets[sheetName];
|
||||||
|
const savePath = join(dirname, `${sheetName}.json`);
|
||||||
|
console.info('[Transform] XLSX(', source.map(([p, s])=>`${p}:${s}`).join('\n\t\t '), `) \n\t -> JSON( ${savePath} )`);
|
||||||
|
await writeFile(
|
||||||
|
savePath,
|
||||||
|
JSON.stringify(data, null, 4),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function format(rawSheet, isArray, xlsxPath, rawSheetName) {
|
||||||
|
const newSheet = isArray?[]:{};
|
||||||
|
rawSheet.shift();
|
||||||
|
for(const index in rawSheet) {
|
||||||
|
const row = rawSheet[index];
|
||||||
|
const rowData = {};
|
||||||
|
let mainKey;
|
||||||
|
for(let key in row) {
|
||||||
|
const cell = row[key];
|
||||||
|
if(key[0] == "$") {
|
||||||
|
key = key.substr(1);
|
||||||
|
mainKey = cell;
|
||||||
|
}
|
||||||
|
if(key.includes(':')) {
|
||||||
|
const keys = key.split(':');
|
||||||
|
const lastKey = keys.pop();
|
||||||
|
let temp = rowData;
|
||||||
|
for(const subKey of keys) {
|
||||||
|
if(!temp[subKey]) temp[subKey] = {};
|
||||||
|
temp = temp[subKey];
|
||||||
|
}
|
||||||
|
if(lastKey.includes('[]')) {
|
||||||
|
const aKey = lastKey.split('[]')[0];
|
||||||
|
if(!temp[aKey]) temp[aKey] = [cell];
|
||||||
|
else temp[aKey].push(cell);
|
||||||
|
} else {
|
||||||
|
temp[lastKey] = cell;
|
||||||
|
}
|
||||||
|
} else if(key.includes('[]')) {
|
||||||
|
const aKey = key.split('[]')[0];
|
||||||
|
if(!rowData[aKey]) rowData[aKey] = [cell];
|
||||||
|
else rowData[aKey].push(cell);
|
||||||
|
} else {
|
||||||
|
rowData[key] = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(isArray) {
|
||||||
|
newSheet.push(rowData);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(mainKey===undefined) {
|
||||||
|
console.warn(`[WARN][No Main Key] ${xlsxPath}:${rawSheetName}`, parseInt(index)+3, rowData);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(newSheet[mainKey]) console.warn(`[WARN][Duplicate Key] ${mainKey} ${xlsxPath}:${rawSheetName}`, parseInt(index), '\n\t', JSON.stringify(newSheet[mainKey]), '\n\t', JSON.stringify(rowData));
|
||||||
|
newSheet[mainKey] = rowData;
|
||||||
|
}
|
||||||
|
return newSheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge(original, rawData, isMerge, isArray, xlsxPath, rawSheetName) {
|
||||||
|
if(!original)
|
||||||
|
return {
|
||||||
|
isMerge,
|
||||||
|
isArray,
|
||||||
|
source: [[xlsxPath, rawSheetName]],
|
||||||
|
data: format(rawData, isArray, xlsxPath, rawSheetName)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if(!isMerge) {
|
||||||
|
if(original) {
|
||||||
|
console.warn(`[WARN][Sheet Duplicate] ${xlsxPath}:${rawSheetName}\n\t\t${original.source[0][0]}:${original.source[0][1]}`)
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!original.isMerge) {
|
||||||
|
console.warn(`[WARN][Sheet Duplicate] ${xlsxPath}:${rawSheetName}\n\t\t${original.source[0][0]}:${original.source[0][1]}`)
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(original.isArray != isArray) {
|
||||||
|
console.warn(`[WARN][Sheet Format not pair] ${xlsxPath}:${rawSheetName}\n\t\t${original.source[0][0]}:${original.source[0][1]}`)
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatData = format(rawData, isArray, xlsxPath, rawSheetName);
|
||||||
|
|
||||||
|
original.source.push([xlsxPath, rawSheetName]);
|
||||||
|
|
||||||
|
if(isArray) {
|
||||||
|
original.data = original.data.concat(formatData)
|
||||||
|
} else {
|
||||||
|
for(const key in formatData) {
|
||||||
|
if(original.data[key]) {
|
||||||
|
console.warn(`[WARN][Duplicate key] ${key} ${xlsxPath}:${rawSheetName} ${JSON.stringify(formatData[key])}\n\t\t${original.source[0][0]}:${original.source[0][1]} ${JSON.stringify(original.data[key])}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
original.data[key] = formatData[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transform(rawSheets) {
|
||||||
|
const sheets = {};
|
||||||
|
for(const xlsxPath in rawSheets) {
|
||||||
|
const {dirname: d, data: rawSheetsData} = rawSheets[xlsxPath];
|
||||||
|
for(const rawSheetName in rawSheetsData) {
|
||||||
|
const rawData = rawSheetsData[rawSheetName];
|
||||||
|
if(rawSheetName[0] === "#") continue;
|
||||||
|
let sheetName = rawSheetName;
|
||||||
|
const isArray = rawSheetName.substr(-5) === "<arr>";
|
||||||
|
if(isArray) sheetName = sheetName.substring(0, sheetName.length - 5);
|
||||||
|
const isMerge = rawSheetName[0] === ">";
|
||||||
|
if(isMerge) sheetName = sheetName.substr(1);
|
||||||
|
sheets[sheetName] = merge(
|
||||||
|
sheets[sheetName],
|
||||||
|
rawData,
|
||||||
|
isMerge,
|
||||||
|
isArray,
|
||||||
|
xlsxPath,
|
||||||
|
rawSheetName
|
||||||
|
);
|
||||||
|
sheets[sheetName].dirname = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sheets;
|
||||||
|
}
|
||||||
|
|
||||||
async function walk(filePath) {
|
async function walk(filePath) {
|
||||||
const xlsxPaths = [];
|
const xlsxPaths = [];
|
||||||
if(Array.isArray(filePath)) {
|
if(Array.isArray(filePath)) {
|
||||||
@@ -82,18 +178,18 @@ async function main() {
|
|||||||
const filePaths = process.argv.slice(2);
|
const filePaths = process.argv.slice(2);
|
||||||
if(filePaths.length<0) process.exit(0);
|
if(filePaths.length<0) process.exit(0);
|
||||||
const xlsxs = await walk(filePaths);
|
const xlsxs = await walk(filePaths);
|
||||||
|
const sheets = {};
|
||||||
for(const p of xlsxs) {
|
for(const p of xlsxs) {
|
||||||
const data = await transform(p);
|
const data = await read(p);
|
||||||
const d = dirname(p);
|
const d = dirname(p);
|
||||||
for(const sheetName in data) {
|
sheets[p] = {
|
||||||
const savePath = join(d, `${sheetName}.json`);
|
dirname: d,
|
||||||
console.info(`[Transform] XLSX(${p}:${sheetName}) -> JSON(${savePath})`);
|
data
|
||||||
await writeFile(
|
};
|
||||||
savePath,
|
|
||||||
JSON.stringify(data[sheetName], null, 4),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
await write(
|
||||||
|
transform(sheets)
|
||||||
|
);
|
||||||
console.info(`
|
console.info(`
|
||||||
------------------------
|
------------------------
|
||||||
| Transform Complete |
|
| Transform Complete |
|
||||||
|
|||||||
903
view/dark.css
Normal file
@@ -0,0 +1,903 @@
|
|||||||
|
@media (min-width:640px){html{font-size:24px;}}
|
||||||
|
@media (min-width:631px) and (max-width:639px){html{font-size:23.66px;}}
|
||||||
|
@media (min-width:622px) and (max-width:630px){html{font-size:23.33px;}}
|
||||||
|
@media (min-width:613px) and (max-width:621px){html{font-size:23px;}}
|
||||||
|
@media (min-width:604px) and (max-width:612px){html{font-size:22.66px;}}
|
||||||
|
@media (min-width:595px) and (max-width:603px){html{font-size:22.33px;}}
|
||||||
|
@media (min-width:586px) and (max-width:594px){html{font-size:22px;}}
|
||||||
|
@media (min-width:577px) and (max-width:585px){html{font-size:21.66px;}}
|
||||||
|
@media (min-width:568px) and (max-width:576px){html{font-size:21.33px;}}
|
||||||
|
@media (min-width:559px) and (max-width:567px){html{font-size:21px;}}
|
||||||
|
@media (min-width:550px) and (max-width:558px){html{font-size:20.66px;}}
|
||||||
|
@media (min-width:541px) and (max-width:549px){html{font-size:20.33px;}}
|
||||||
|
@media (min-width:533px) and (max-width:540px){html{font-size:20px;}}
|
||||||
|
@media (min-width:524px) and (max-width:532px){html{font-size:19.66px;}}
|
||||||
|
@media (min-width:515px) and (max-width:523px){html{font-size:19.33px;}}
|
||||||
|
@media (min-width:506px) and (max-width:514px){html{font-size:19px;}}
|
||||||
|
@media (min-width:497px) and (max-width:505px){html{font-size:18.66px;}}
|
||||||
|
@media (min-width:488px) and (max-width:496px){html{font-size:18.33px;}}
|
||||||
|
@media (min-width:480px) and (max-width:487px){html{font-size:18px;}}
|
||||||
|
@media (min-width:471px) and (max-width:479px){html{font-size:17.66px;}}
|
||||||
|
@media (min-width:462px) and (max-width:470px){html{font-size:17.33px;}}
|
||||||
|
@media (min-width:453px) and (max-width:461px){html{font-size:17px;}}
|
||||||
|
@media (min-width:444px) and (max-width:452px){html{font-size:17.12px;}}
|
||||||
|
@media (min-width:435px) and (max-width:443px){html{font-size:16.33px;}}
|
||||||
|
@media (min-width:426px) and (max-width:434px){html{font-size:16px;}}
|
||||||
|
@media (min-width:417px) and (max-width:425px){html{font-size:15.66px;}}
|
||||||
|
@media (min-width:408px) and (max-width:416px){html{font-size:15.33px;}}
|
||||||
|
@media (min-width:400px) and (max-width:407px){html{font-size:15px;}}
|
||||||
|
@media (min-width:391px) and (max-width:399px){html{font-size:14.66px;}}
|
||||||
|
@media (min-width:382px) and (max-width:390px){html{font-size:14.33px;}}
|
||||||
|
@media (min-width:374px) and (max-width:381px){html{font-size:14px;}}
|
||||||
|
@media (min-width:365px) and (max-width:373px){html{font-size:13.66px;}}
|
||||||
|
@media (min-width:356px) and (max-width:364px){html{font-size:13.33px;}}
|
||||||
|
@media (min-width:347px) and (max-width:355px){html{font-size:13px;}}
|
||||||
|
@media (min-width:338px) and (max-width:346px){html{font-size:12.66px;}}
|
||||||
|
@media (min-width:329px) and (max-width:337px){html{font-size:12.44px;}}
|
||||||
|
@media (max-width:328px){html{font-size:12px;}}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'iconfont';
|
||||||
|
src: url('iconfont.woff2?t=1628944689555') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1628944689555') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1628944689555') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
input[type="number"]{
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
background-color: #222831;
|
||||||
|
font-family: PingFangSC, 'Noto Sans CJK SC', 'MS Yahei';
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 30rem;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title {
|
||||||
|
position: fixed;
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
top: 35%;
|
||||||
|
left: 50%;
|
||||||
|
white-space: nowrap;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restart {
|
||||||
|
position: fixed;
|
||||||
|
top: 65%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#restart .iconfont {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#next {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#talentSelectedView {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainbtn {
|
||||||
|
margin: 0.5rem 1rem 1rem;
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
background-color: #393E46;
|
||||||
|
border: 1px #EEEEEE solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainbtn:hover {
|
||||||
|
background: #ff7878;
|
||||||
|
color: #fff;
|
||||||
|
transition: all .4s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-area>.mainbtn {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor,
|
||||||
|
#rank,
|
||||||
|
#specialthanks,
|
||||||
|
#achievement {
|
||||||
|
position: fixed;
|
||||||
|
top: 4rem;
|
||||||
|
right: 1rem;
|
||||||
|
padding: 0.1rem;
|
||||||
|
width: 6rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
background-color:lightsteelblue;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index:2;
|
||||||
|
word-wrap: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#specialthanks {
|
||||||
|
background-color: #5865F2;
|
||||||
|
top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor {
|
||||||
|
top: auto;
|
||||||
|
bottom: 0;
|
||||||
|
width: auto;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rank {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 1.5rem;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx {
|
||||||
|
position: fixed;
|
||||||
|
display: grid;
|
||||||
|
top: 4rem;
|
||||||
|
bottom: 5rem;
|
||||||
|
left: 50%;
|
||||||
|
width: 30rem;
|
||||||
|
max-width: calc(100% - 2rem);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 {
|
||||||
|
display: grid;
|
||||||
|
max-block-size: 9rem;
|
||||||
|
max-height: 9rem;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li {
|
||||||
|
display: inline-grid;
|
||||||
|
background-color: orange;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
padding: 0.2rem 0;
|
||||||
|
grid-template-columns: 7rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li .name {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li .comment {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g2 {
|
||||||
|
color: white;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 50% 50%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g2 li {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: white;
|
||||||
|
position: relative;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total,
|
||||||
|
#achievements {
|
||||||
|
list-style-type: none;
|
||||||
|
display: grid;
|
||||||
|
justify-items: center;
|
||||||
|
grid-template-columns: 50% 50%;
|
||||||
|
grid-auto-columns: max-content;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total li,
|
||||||
|
#achievements li {
|
||||||
|
position: relative;
|
||||||
|
color: white;
|
||||||
|
display: inline-grid;
|
||||||
|
margin: 0.5rem;
|
||||||
|
width: 12rem;
|
||||||
|
height: 6rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total li .achievementtitle,
|
||||||
|
#achievements li .achievementtitle{
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#achievements {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save,
|
||||||
|
#load,
|
||||||
|
#themeToggleBtn {
|
||||||
|
padding: 0 0.7rem;
|
||||||
|
width: 6.5rem;
|
||||||
|
background-color:#EEEEEE;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: #222831;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
position: fixed;
|
||||||
|
z-index:2;
|
||||||
|
right: 0.5rem;
|
||||||
|
bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save {
|
||||||
|
background-color:#007046;
|
||||||
|
color: white;
|
||||||
|
bottom: 6.5rem;
|
||||||
|
}
|
||||||
|
#load {
|
||||||
|
background-color: #fc5531;
|
||||||
|
color: white;
|
||||||
|
bottom: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.head {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
height: 5.2rem;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial,
|
||||||
|
.selectlist {
|
||||||
|
list-style: none;
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty {
|
||||||
|
list-style: none;
|
||||||
|
padding: 2rem 1rem 0.5rem 1rem;
|
||||||
|
display: flex;
|
||||||
|
color: #FFFFFF;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty>li {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0.1rem 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px #ccc solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty>li>span:last-child {
|
||||||
|
background: #eee;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectlist>li {
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
display: block;
|
||||||
|
border: 1px #EEEEEE solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
user-select: none;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectlist>li:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg0,
|
||||||
|
.grade0b {
|
||||||
|
background-color: #464646;
|
||||||
|
border: #f8f8f8 2px solid !important;
|
||||||
|
}
|
||||||
|
.achvg1,
|
||||||
|
.grade1b {
|
||||||
|
background-color: #6495ed;
|
||||||
|
border: #f8f8f8 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg2,
|
||||||
|
.grade2b {
|
||||||
|
background-color: #e2a7ff;
|
||||||
|
border: #f8f8f8 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg3,
|
||||||
|
.grade3b {
|
||||||
|
background-color: #ffa07a;
|
||||||
|
border: #f8f8f8 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask::before {
|
||||||
|
display: block;
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #000;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1080px) {
|
||||||
|
.grade0b:hover {
|
||||||
|
background-color: #c0c0c0;
|
||||||
|
color: #3b3b3b;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade1b:hover {
|
||||||
|
background-color: #87cefa;
|
||||||
|
color: #3b3b3b;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade2b:hover {
|
||||||
|
background-color: #e7beff;
|
||||||
|
color: #3b3b3b;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade3b:hover {
|
||||||
|
background-color: #f7a989;
|
||||||
|
color: #3b3b3b;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade0b.selected,
|
||||||
|
.grade1b.selected,
|
||||||
|
.grade2b.selected,
|
||||||
|
.grade3b.selected {
|
||||||
|
box-shadow: #ccc 0px 0px 10px;
|
||||||
|
color: #3b3b3b;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.grade0b.selected::after,
|
||||||
|
.grade1b.selected::after,
|
||||||
|
.grade2b.selected::after,
|
||||||
|
.grade3b.selected::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
background-color:#000;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
box-shadow: 0 0 10px #000;
|
||||||
|
opacity: 0;
|
||||||
|
animation: blink 3s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-150%);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: .2;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(150%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade0b.selected {
|
||||||
|
background-color: #c0c0c0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade1b.selected {
|
||||||
|
background-color: #87cefa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade2b.selected {
|
||||||
|
background-color: #e7beff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade3b.selected {
|
||||||
|
background-color: #f1bfac !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propbtn:hover {
|
||||||
|
color: #5c5c5c;
|
||||||
|
transition: all .2s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial>li {
|
||||||
|
position: relative;
|
||||||
|
margin: 0.1rem auto;
|
||||||
|
padding: 0.2rem;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial>li>input {
|
||||||
|
height: 2.2rem;
|
||||||
|
width: 2.2rem;
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 2rem;
|
||||||
|
border: 0.1rem #EEEEEE solid;
|
||||||
|
background-color: #393E46;
|
||||||
|
color: #EEEEEE;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propbtn {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 2rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li>span:nth-child(1),
|
||||||
|
.lifeTrajectory>li>span:nth-child(1) {
|
||||||
|
width: 5rem;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.judge>li>span:nth-child(2),
|
||||||
|
.lifeTrajectory>li>span:nth-child(2) {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeTrajectory {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0.5rem 1rem;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px #9b9b9b solid;
|
||||||
|
background-color: #393E46;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeTrajectory>li {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
display: flex;
|
||||||
|
background-color: #4a5361;
|
||||||
|
box-shadow: #EEEEEE 0 0 0.4rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.judge {
|
||||||
|
list-style: none;
|
||||||
|
flex: 1;
|
||||||
|
margin: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid #EEEEEE;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #4a5361;
|
||||||
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
box-shadow: none;
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li:last-child {
|
||||||
|
border-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade1 span,
|
||||||
|
.judge>li.grade1 {
|
||||||
|
background-color: #87cefa;
|
||||||
|
color: #4a5361;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade2 span,
|
||||||
|
.judge>li.grade2 {
|
||||||
|
background-color: #e7beff;
|
||||||
|
color: #4a5361;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade3 span,
|
||||||
|
.judge>li.grade3 {
|
||||||
|
background-color: #f7a989;
|
||||||
|
color: #4a5361;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,400i,700");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: "Montserrat";
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banners-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
color: white;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-message {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 2rem;
|
||||||
|
word-break: break-word;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-close {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.1rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .iconfont {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-close:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.success {
|
||||||
|
background: lightgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.success::after {
|
||||||
|
background: lightgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.error {
|
||||||
|
background: #ed1c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.error::after {
|
||||||
|
background: #ed1c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.info {
|
||||||
|
background: skyblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.info::after {
|
||||||
|
background: skyblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
height: 10%;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner:not(.visible) {
|
||||||
|
display: none;
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.visible {
|
||||||
|
box-shadow: 0 2px 2px 2px rgba(0, 0, 0, 0.12);
|
||||||
|
animation-name: banner-in;
|
||||||
|
animation-direction: forwards;
|
||||||
|
animation-duration: 0.6s;
|
||||||
|
animation-timing-function: ease-in-out;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes banner-in {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translateY(10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-banner {
|
||||||
|
appearance: none;
|
||||||
|
background: #ededed;
|
||||||
|
border: 0;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
.eva-animation {
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-infinite {
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-shake {
|
||||||
|
animation-name: eva-shake;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-zoom {
|
||||||
|
animation-name: eva-zoomIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-pulse {
|
||||||
|
animation-name: eva-pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-flip {
|
||||||
|
animation-name: eva-flipInY;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-shake,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-shake {
|
||||||
|
animation-name: eva-shake;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-zoom,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-zoom {
|
||||||
|
animation-name: eva-zoomIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-pulse,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-pulse {
|
||||||
|
animation-name: eva-pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-flip,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-flip {
|
||||||
|
animation-name: eva-flipInY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-flipInY {
|
||||||
|
from {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
60% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: perspective(400px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-shake {
|
||||||
|
|
||||||
|
from,
|
||||||
|
to {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
10%,
|
||||||
|
30%,
|
||||||
|
50%,
|
||||||
|
70%,
|
||||||
|
90% {
|
||||||
|
transform: translate3d(-3px, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
20%,
|
||||||
|
40%,
|
||||||
|
60%,
|
||||||
|
80% {
|
||||||
|
transform: translate3d(3px, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-pulse {
|
||||||
|
from {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: scale3d(1.2, 1.2, 1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-zoomIn {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale3d(0.5, 0.5, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteFixed {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operateBtn {
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
border: 1px #EEEEEE solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
background-color:#393E46;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
cursor: pointer;
|
||||||
|
z-index:2;
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operateBtn:hover {
|
||||||
|
background: #ff7878;
|
||||||
|
color: #fff;
|
||||||
|
transition: all .4s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domToImage2wx {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1111;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domToImage2wx img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
906
view/halloween.css
Normal file
@@ -0,0 +1,906 @@
|
|||||||
|
@media (min-width:640px){html{font-size:24px;}}
|
||||||
|
@media (min-width:631px) and (max-width:639px){html{font-size:23.66px;}}
|
||||||
|
@media (min-width:622px) and (max-width:630px){html{font-size:23.33px;}}
|
||||||
|
@media (min-width:613px) and (max-width:621px){html{font-size:23px;}}
|
||||||
|
@media (min-width:604px) and (max-width:612px){html{font-size:22.66px;}}
|
||||||
|
@media (min-width:595px) and (max-width:603px){html{font-size:22.33px;}}
|
||||||
|
@media (min-width:586px) and (max-width:594px){html{font-size:22px;}}
|
||||||
|
@media (min-width:577px) and (max-width:585px){html{font-size:21.66px;}}
|
||||||
|
@media (min-width:568px) and (max-width:576px){html{font-size:21.33px;}}
|
||||||
|
@media (min-width:559px) and (max-width:567px){html{font-size:21px;}}
|
||||||
|
@media (min-width:550px) and (max-width:558px){html{font-size:20.66px;}}
|
||||||
|
@media (min-width:541px) and (max-width:549px){html{font-size:20.33px;}}
|
||||||
|
@media (min-width:533px) and (max-width:540px){html{font-size:20px;}}
|
||||||
|
@media (min-width:524px) and (max-width:532px){html{font-size:19.66px;}}
|
||||||
|
@media (min-width:515px) and (max-width:523px){html{font-size:19.33px;}}
|
||||||
|
@media (min-width:506px) and (max-width:514px){html{font-size:19px;}}
|
||||||
|
@media (min-width:497px) and (max-width:505px){html{font-size:18.66px;}}
|
||||||
|
@media (min-width:488px) and (max-width:496px){html{font-size:18.33px;}}
|
||||||
|
@media (min-width:480px) and (max-width:487px){html{font-size:18px;}}
|
||||||
|
@media (min-width:471px) and (max-width:479px){html{font-size:17.66px;}}
|
||||||
|
@media (min-width:462px) and (max-width:470px){html{font-size:17.33px;}}
|
||||||
|
@media (min-width:453px) and (max-width:461px){html{font-size:17px;}}
|
||||||
|
@media (min-width:444px) and (max-width:452px){html{font-size:17.12px;}}
|
||||||
|
@media (min-width:435px) and (max-width:443px){html{font-size:16.33px;}}
|
||||||
|
@media (min-width:426px) and (max-width:434px){html{font-size:16px;}}
|
||||||
|
@media (min-width:417px) and (max-width:425px){html{font-size:15.66px;}}
|
||||||
|
@media (min-width:408px) and (max-width:416px){html{font-size:15.33px;}}
|
||||||
|
@media (min-width:400px) and (max-width:407px){html{font-size:15px;}}
|
||||||
|
@media (min-width:391px) and (max-width:399px){html{font-size:14.66px;}}
|
||||||
|
@media (min-width:382px) and (max-width:390px){html{font-size:14.33px;}}
|
||||||
|
@media (min-width:374px) and (max-width:381px){html{font-size:14px;}}
|
||||||
|
@media (min-width:365px) and (max-width:373px){html{font-size:13.66px;}}
|
||||||
|
@media (min-width:356px) and (max-width:364px){html{font-size:13.33px;}}
|
||||||
|
@media (min-width:347px) and (max-width:355px){html{font-size:13px;}}
|
||||||
|
@media (min-width:338px) and (max-width:346px){html{font-size:12.66px;}}
|
||||||
|
@media (min-width:329px) and (max-width:337px){html{font-size:12.44px;}}
|
||||||
|
@media (max-width:328px){html{font-size:12px;}}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'iconfont';
|
||||||
|
src: url('iconfont.woff2?t=1628944689555') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1628944689555') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1628944689555') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
input[type="number"]{
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
background-color: #241619;
|
||||||
|
font-family: PingFangSC, 'Noto Sans CJK SC', 'MS Yahei';
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 30rem;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title {
|
||||||
|
position: fixed;
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
top: 35%;
|
||||||
|
left: 50%;
|
||||||
|
white-space: nowrap;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: #ff9f27;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restart {
|
||||||
|
position: fixed;
|
||||||
|
top: 65%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#restart .iconfont {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#next {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#talentSelectedView {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainbtn {
|
||||||
|
margin: 0.5rem 1rem 1rem;
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
background-color: #4a0388;
|
||||||
|
border: 1px #4a0388 solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #ff197b;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainbtn:hover {
|
||||||
|
background: #fd373c;
|
||||||
|
color: #4a0388;
|
||||||
|
transition: all .4s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-area>.mainbtn {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor,
|
||||||
|
#rank,
|
||||||
|
#specialthanks,
|
||||||
|
#achievement {
|
||||||
|
position: fixed;
|
||||||
|
top: 4rem;
|
||||||
|
right: 1rem;
|
||||||
|
padding: 0.1rem;
|
||||||
|
width: 6rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
background-color: #1a0c18;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: #ff9f27;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index:2;
|
||||||
|
word-wrap: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#specialthanks {
|
||||||
|
background-color: #1a0c18;
|
||||||
|
top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor {
|
||||||
|
top: auto;
|
||||||
|
bottom: 0;
|
||||||
|
width: auto;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rank {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 1.5rem;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx {
|
||||||
|
position: fixed;
|
||||||
|
display: grid;
|
||||||
|
top: 4rem;
|
||||||
|
bottom: 5rem;
|
||||||
|
left: 50%;
|
||||||
|
width: 30rem;
|
||||||
|
max-width: calc(100% - 2rem);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 {
|
||||||
|
display: grid;
|
||||||
|
max-block-size: 9rem;
|
||||||
|
max-height: 9rem;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li {
|
||||||
|
display: inline-grid;
|
||||||
|
background-color: orange;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
padding: 0.2rem 0;
|
||||||
|
grid-template-columns: 7rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li .name {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li .comment {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g2 {
|
||||||
|
color: white;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 50% 50%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g2 li {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #ff9f27;
|
||||||
|
position: relative;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total,
|
||||||
|
#achievements {
|
||||||
|
list-style-type: none;
|
||||||
|
display: grid;
|
||||||
|
justify-items: center;
|
||||||
|
grid-template-columns: 50% 50%;
|
||||||
|
grid-auto-columns: max-content;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total li,
|
||||||
|
#achievements li {
|
||||||
|
position: relative;
|
||||||
|
color: #ff9f27;
|
||||||
|
display: inline-grid;
|
||||||
|
margin: 0.5rem;
|
||||||
|
width: 12rem;
|
||||||
|
height: 6rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total li .achievementtitle,
|
||||||
|
#achievements li .achievementtitle{
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#achievements {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save,
|
||||||
|
#load,
|
||||||
|
#themeToggleBtn {
|
||||||
|
padding: 0 0.7rem;
|
||||||
|
width: 6.5rem;
|
||||||
|
background-color: #1a0c18;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: #ff9f27;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
position: fixed;
|
||||||
|
z-index:2;
|
||||||
|
right: 0.5rem;
|
||||||
|
bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#themeToggleBtn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save {
|
||||||
|
bottom: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.head {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
height: 5.2rem;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #ff9f27;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial,
|
||||||
|
.selectlist {
|
||||||
|
list-style: none;
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty {
|
||||||
|
list-style: none;
|
||||||
|
padding: 2rem 1rem 0.5rem 1rem;
|
||||||
|
display: flex;
|
||||||
|
color: #fd373c;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty>li {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0.1rem 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px #fd373c solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty>li>span:last-child {
|
||||||
|
background: #fd373c;
|
||||||
|
color: #4a0388;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectlist>li {
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
display: block;
|
||||||
|
border: 1px #ff9f27 solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #ff9f27;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
user-select: none;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectlist>li:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg0,
|
||||||
|
.grade0b {
|
||||||
|
background-color: #231815;
|
||||||
|
border: #ff9f27 2px solid !important;
|
||||||
|
color: #ff9f27 !important;
|
||||||
|
}
|
||||||
|
.achvg1,
|
||||||
|
.grade1b {
|
||||||
|
background-color: #3b3894;
|
||||||
|
border: #ff9f27 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg2,
|
||||||
|
.grade2b {
|
||||||
|
background-color: #470063;
|
||||||
|
border: #ff9f27 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg3,
|
||||||
|
.grade3b {
|
||||||
|
background-color: #f73c47;
|
||||||
|
border: #ff9f27 2px solid !important;
|
||||||
|
color: #f8ea8b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask::before {
|
||||||
|
display: block;
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #241619;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1080px) {
|
||||||
|
.grade0b:hover {
|
||||||
|
background-color: #452915;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade1b:hover {
|
||||||
|
background-color: #5553b3;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade2b:hover {
|
||||||
|
background-color: #672183;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade3b:hover {
|
||||||
|
background-color: #ff8561;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade0b.selected,
|
||||||
|
.grade1b.selected,
|
||||||
|
.grade2b.selected,
|
||||||
|
.grade3b.selected {
|
||||||
|
box-shadow: #f74745 8px 4px 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.grade0b.selected::after,
|
||||||
|
.grade1b.selected::after,
|
||||||
|
.grade2b.selected::after,
|
||||||
|
.grade3b.selected::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
background-color: #fe028b;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
box-shadow: 0 0 10px #fe028b;
|
||||||
|
opacity: 0;
|
||||||
|
animation: blink 3s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-150%);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: .2;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(150%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade0b.selected {
|
||||||
|
background-color: #452915 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade1b.selected {
|
||||||
|
background-color: #5553b3!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade2b.selected {
|
||||||
|
background-color: #672183 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade3b.selected {
|
||||||
|
background-color: #ff8561 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propbtn:hover {
|
||||||
|
color: #5c5c5c;
|
||||||
|
transition: all .2s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial>li {
|
||||||
|
position: relative;
|
||||||
|
margin: 0.1rem auto;
|
||||||
|
padding: 0.2rem;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #ff9f27;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial>li>input {
|
||||||
|
height: 2.2rem;
|
||||||
|
width: 2.2rem;
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 2rem;
|
||||||
|
border: 0.1rem #ff9f27 solid;
|
||||||
|
background-color: #393E46;
|
||||||
|
color: #ff9f27;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propbtn {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 2rem;
|
||||||
|
color: #ff9f27;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li>span:nth-child(1),
|
||||||
|
.lifeTrajectory>li>span:nth-child(1) {
|
||||||
|
width: 5rem;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.judge>li>span:nth-child(2),
|
||||||
|
.lifeTrajectory>li>span:nth-child(2) {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeTrajectory {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0.5rem 1rem;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px #ff9f27 solid;
|
||||||
|
background-color: #241619;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeTrajectory>li {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
display: flex;
|
||||||
|
background-color: #231815;
|
||||||
|
box-shadow: #ff9f27 0 0 0.4rem;
|
||||||
|
color: #ff9f27;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.judge {
|
||||||
|
list-style: none;
|
||||||
|
flex: 1;
|
||||||
|
margin: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid #ff9f27;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #231815;
|
||||||
|
border-bottom: 1px solid #ff9f27;
|
||||||
|
box-shadow: none;
|
||||||
|
color: #ff9f27;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li:last-child {
|
||||||
|
border-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade1 span,
|
||||||
|
.judge>li.grade1 {
|
||||||
|
background-color: #3b3894;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade2 span,
|
||||||
|
.judge>li.grade2 {
|
||||||
|
background-color: #470063;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade3 span,
|
||||||
|
.judge>li.grade3 {
|
||||||
|
background-color: #f73c47;
|
||||||
|
color: #f8ea8b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,400i,700");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: "Montserrat";
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banners-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
color: white;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-message {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 2rem;
|
||||||
|
word-break: break-word;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-close {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.1rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .iconfont {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-close:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.success {
|
||||||
|
background: #c101f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.success::after {
|
||||||
|
background: #c101f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.error {
|
||||||
|
background: #ff3a3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.error::after {
|
||||||
|
background: #ff3a3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.info {
|
||||||
|
background: #282366;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.info::after {
|
||||||
|
background: #282366;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
height: 10%;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner:not(.visible) {
|
||||||
|
display: none;
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.visible {
|
||||||
|
box-shadow: 0 2px 2px 2px rgba(0, 0, 0, 0.12);
|
||||||
|
animation-name: banner-in;
|
||||||
|
animation-direction: forwards;
|
||||||
|
animation-duration: 0.6s;
|
||||||
|
animation-timing-function: ease-in-out;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes banner-in {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translateY(10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-banner {
|
||||||
|
appearance: none;
|
||||||
|
background: #ededed;
|
||||||
|
border: 0;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
.eva-animation {
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-infinite {
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-shake {
|
||||||
|
animation-name: eva-shake;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-zoom {
|
||||||
|
animation-name: eva-zoomIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-pulse {
|
||||||
|
animation-name: eva-pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-flip {
|
||||||
|
animation-name: eva-flipInY;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-shake,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-shake {
|
||||||
|
animation-name: eva-shake;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-zoom,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-zoom {
|
||||||
|
animation-name: eva-zoomIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-pulse,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-pulse {
|
||||||
|
animation-name: eva-pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-flip,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-flip {
|
||||||
|
animation-name: eva-flipInY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-flipInY {
|
||||||
|
from {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
60% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: perspective(400px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-shake {
|
||||||
|
|
||||||
|
from,
|
||||||
|
to {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
10%,
|
||||||
|
30%,
|
||||||
|
50%,
|
||||||
|
70%,
|
||||||
|
90% {
|
||||||
|
transform: translate3d(-3px, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
20%,
|
||||||
|
40%,
|
||||||
|
60%,
|
||||||
|
80% {
|
||||||
|
transform: translate3d(3px, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-pulse {
|
||||||
|
from {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: scale3d(1.2, 1.2, 1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-zoomIn {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale3d(0.5, 0.5, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteFixed {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operateBtn {
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
border: 1px #EEEEEE solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
background-color:#393E46;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
cursor: pointer;
|
||||||
|
z-index:2;
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operateBtn:hover {
|
||||||
|
background: #ff7878;
|
||||||
|
color: #fff;
|
||||||
|
transition: all .4s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domToImage2wx {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1111;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domToImage2wx img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github-corner,
|
||||||
|
.discord-btn {
|
||||||
|
background-color: #1a0c18 !important;
|
||||||
|
color: #ff9f27 !important;
|
||||||
|
}
|
||||||
|
.github-corner > svg path.octo-arm,
|
||||||
|
.github-corner > svg path.octo-body,
|
||||||
|
.discord-btn > svg > g > path {
|
||||||
|
fill: #ff9f27 !important;
|
||||||
|
}
|
||||||
BIN
view/images/icons/icon-128x128.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
view/images/icons/icon-144x144.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
view/images/icons/icon-152x152.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
view/images/icons/icon-192x192.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
view/images/icons/icon-384x384.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
view/images/icons/icon-512x512.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
view/images/icons/icon-72x72.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
view/images/icons/icon-96x96.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
@@ -4,13 +4,13 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="style.css">
|
<meta name="description" content="やり直すんだ。そして、次はうまくやる。"/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
|
<meta name="keywords" content="人生重开模拟器 liferestart life restart remake 人生重来"/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
<link id="themeLink" rel="stylesheet" href="light.css">
|
||||||
<script>window.json = async fileName=>(await axios(`../data/${fileName}.json`)).data;</script>
|
<link rel="manifest" href="./manifest.json">
|
||||||
<title>Document</title>
|
<title>Life Restart</title>
|
||||||
</head>
|
</head>
|
||||||
<body style="margin: 0; height: 100%">
|
<body>
|
||||||
<div class="banners-container">
|
<div class="banners-container">
|
||||||
<div class="banners">
|
<div class="banners">
|
||||||
<div class="banner error">
|
<div class="banner error">
|
||||||
@@ -30,18 +30,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a href="https://github.com/VickScarlet/lifeRestart" class="github-corner" style="z-index: 9999;" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; left: 0; transform: scale(-1, 1);" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style></a>
|
||||||
|
|
||||||
|
<script src="../lib/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="../lib/dom-to-image.min.js"></script>
|
||||||
|
<script src="../public/bundle.js"></script>
|
||||||
|
<script>
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
window.addEventListener('load', function () {
|
||||||
|
navigator.serviceWorker.register('./sw.js', {scope: '.'})
|
||||||
|
.then(function (registration) {
|
||||||
|
console.log('ServiceWorker registration successful');
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log('ServiceWorker registration failed');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
<script>
|
|
||||||
// Pssst, I've created a github package - https://github.com/brookesb91/dismissible
|
|
||||||
const hideBanners = (e) => {
|
|
||||||
document
|
|
||||||
.querySelectorAll(".banner.visible")
|
|
||||||
.forEach((b) => b.classList.remove("visible"));
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="module">
|
|
||||||
import App from '../src/app.js';
|
|
||||||
const app = new App();
|
|
||||||
app.initial();
|
|
||||||
</script>
|
|
||||||
</html>
|
</html>
|
||||||
900
view/light.css
Normal file
@@ -0,0 +1,900 @@
|
|||||||
|
@media (min-width:640px){html{font-size:24px;}}
|
||||||
|
@media (min-width:631px) and (max-width:639px){html{font-size:23.66px;}}
|
||||||
|
@media (min-width:622px) and (max-width:630px){html{font-size:23.33px;}}
|
||||||
|
@media (min-width:613px) and (max-width:621px){html{font-size:23px;}}
|
||||||
|
@media (min-width:604px) and (max-width:612px){html{font-size:22.66px;}}
|
||||||
|
@media (min-width:595px) and (max-width:603px){html{font-size:22.33px;}}
|
||||||
|
@media (min-width:586px) and (max-width:594px){html{font-size:22px;}}
|
||||||
|
@media (min-width:577px) and (max-width:585px){html{font-size:21.66px;}}
|
||||||
|
@media (min-width:568px) and (max-width:576px){html{font-size:21.33px;}}
|
||||||
|
@media (min-width:559px) and (max-width:567px){html{font-size:21px;}}
|
||||||
|
@media (min-width:550px) and (max-width:558px){html{font-size:20.66px;}}
|
||||||
|
@media (min-width:541px) and (max-width:549px){html{font-size:20.33px;}}
|
||||||
|
@media (min-width:533px) and (max-width:540px){html{font-size:20px;}}
|
||||||
|
@media (min-width:524px) and (max-width:532px){html{font-size:19.66px;}}
|
||||||
|
@media (min-width:515px) and (max-width:523px){html{font-size:19.33px;}}
|
||||||
|
@media (min-width:506px) and (max-width:514px){html{font-size:19px;}}
|
||||||
|
@media (min-width:497px) and (max-width:505px){html{font-size:18.66px;}}
|
||||||
|
@media (min-width:488px) and (max-width:496px){html{font-size:18.33px;}}
|
||||||
|
@media (min-width:480px) and (max-width:487px){html{font-size:18px;}}
|
||||||
|
@media (min-width:471px) and (max-width:479px){html{font-size:17.66px;}}
|
||||||
|
@media (min-width:462px) and (max-width:470px){html{font-size:17.33px;}}
|
||||||
|
@media (min-width:453px) and (max-width:461px){html{font-size:17px;}}
|
||||||
|
@media (min-width:444px) and (max-width:452px){html{font-size:17.12px;}}
|
||||||
|
@media (min-width:435px) and (max-width:443px){html{font-size:16.33px;}}
|
||||||
|
@media (min-width:426px) and (max-width:434px){html{font-size:16px;}}
|
||||||
|
@media (min-width:417px) and (max-width:425px){html{font-size:15.66px;}}
|
||||||
|
@media (min-width:408px) and (max-width:416px){html{font-size:15.33px;}}
|
||||||
|
@media (min-width:400px) and (max-width:407px){html{font-size:15px;}}
|
||||||
|
@media (min-width:391px) and (max-width:399px){html{font-size:14.66px;}}
|
||||||
|
@media (min-width:382px) and (max-width:390px){html{font-size:14.33px;}}
|
||||||
|
@media (min-width:374px) and (max-width:381px){html{font-size:14px;}}
|
||||||
|
@media (min-width:365px) and (max-width:373px){html{font-size:13.66px;}}
|
||||||
|
@media (min-width:356px) and (max-width:364px){html{font-size:13.33px;}}
|
||||||
|
@media (min-width:347px) and (max-width:355px){html{font-size:13px;}}
|
||||||
|
@media (min-width:338px) and (max-width:346px){html{font-size:12.66px;}}
|
||||||
|
@media (min-width:329px) and (max-width:337px){html{font-size:12.44px;}}
|
||||||
|
@media (max-width:328px){html{font-size:12px;}}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'iconfont';
|
||||||
|
src: url('iconfont.woff2?t=1628944689555') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1628944689555') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1628944689555') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
input[type="number"]{
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: PingFangSC, 'Noto Sans CJK SC', 'MS Yahei';
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 30rem;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title {
|
||||||
|
position: fixed;
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
top: 35%;
|
||||||
|
left: 50%;
|
||||||
|
white-space: nowrap;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restart {
|
||||||
|
position: fixed;
|
||||||
|
top: 65%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#restart .iconfont {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#next {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#talentSelectedView {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainbtn {
|
||||||
|
margin: 0.5rem 1rem 1rem;
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border: 1px #CCCCCC solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainbtn:hover {
|
||||||
|
background: #ff7878;
|
||||||
|
color: #FFFFFF;
|
||||||
|
transition: all .4s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-area>.mainbtn {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor,
|
||||||
|
#rank,
|
||||||
|
#specialthanks,
|
||||||
|
#achievement {
|
||||||
|
position: fixed;
|
||||||
|
top: 4rem;
|
||||||
|
right: 1rem;
|
||||||
|
padding: 0.1rem;
|
||||||
|
width: 6rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
background-color:lightsteelblue;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index:2;
|
||||||
|
word-wrap: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#specialthanks {
|
||||||
|
background-color: #5865F2;
|
||||||
|
top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor {
|
||||||
|
top: auto;
|
||||||
|
bottom: 0;
|
||||||
|
width: auto;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rank {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 1.5rem;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx {
|
||||||
|
position: fixed;
|
||||||
|
display: grid;
|
||||||
|
top: 4rem;
|
||||||
|
bottom: 5rem;
|
||||||
|
left: 50%;
|
||||||
|
width: 30rem;
|
||||||
|
max-width: calc(100% - 2rem);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 {
|
||||||
|
display: grid;
|
||||||
|
max-block-size: 9rem;
|
||||||
|
max-height: 9rem;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li {
|
||||||
|
display: inline-grid;
|
||||||
|
background-color: orange;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
padding: 0.2rem 0;
|
||||||
|
grid-template-columns: 7rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li .name {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g1 li .comment {
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g2 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 50% 50%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#spthx ul.g2 li {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
position: relative;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total,
|
||||||
|
#achievements {
|
||||||
|
list-style-type: none;
|
||||||
|
display: grid;
|
||||||
|
justify-items: center;
|
||||||
|
grid-template-columns: 50% 50%;
|
||||||
|
grid-auto-columns: max-content;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total li,
|
||||||
|
#achievements li {
|
||||||
|
position: relative;
|
||||||
|
display: inline-grid;
|
||||||
|
margin: 0.5rem;
|
||||||
|
width: 12rem;
|
||||||
|
height: 6rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#total li .achievementtitle,
|
||||||
|
#achievements li .achievementtitle{
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#achievements {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save,
|
||||||
|
#load,
|
||||||
|
#themeToggleBtn {
|
||||||
|
padding: 0 0.7rem;
|
||||||
|
width: 6.5rem;
|
||||||
|
background-color:#222831;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: #EEEEEE;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
position: fixed;
|
||||||
|
z-index:2;
|
||||||
|
right: 0.5rem;
|
||||||
|
bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save {
|
||||||
|
background-color:#007046;
|
||||||
|
color: white;
|
||||||
|
bottom: 6.5rem;
|
||||||
|
}
|
||||||
|
#load {
|
||||||
|
background-color: #fc5531;
|
||||||
|
color: white;
|
||||||
|
bottom: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.head {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
height: 5.2rem;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial,
|
||||||
|
.selectlist {
|
||||||
|
list-style: none;
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty {
|
||||||
|
list-style: none;
|
||||||
|
padding: 2rem 1rem 0.5rem 1rem;
|
||||||
|
display: flex;
|
||||||
|
color: #FFFFFF;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty>li {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0.1rem 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #8d8d8d;
|
||||||
|
border: 1px #ccc solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeProperty>li>span:last-child {
|
||||||
|
background: #fff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectlist>li {
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
display: block;
|
||||||
|
border: 1px #EEEEEE solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #666;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
user-select: none;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectlist>li:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propbtn:hover {
|
||||||
|
color: #5c5c5c;
|
||||||
|
transition: all .2s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial>li {
|
||||||
|
position: relative;
|
||||||
|
margin: 0.1rem auto;
|
||||||
|
padding: 0.2rem;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
color: #000;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propinitial>li>input {
|
||||||
|
height: 2.2rem;
|
||||||
|
width: 2.2rem;
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 2rem;
|
||||||
|
border: 0.1rem #000 solid;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #000;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.propbtn {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 2rem;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li>span:nth-child(1),
|
||||||
|
.lifeTrajectory>li>span:nth-child(1) {
|
||||||
|
width: 5rem;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.judge>li>span:nth-child(2),
|
||||||
|
.lifeTrajectory>li>span:nth-child(2) {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeTrajectory {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0.5rem 1rem;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px #9b9b9b solid;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lifeTrajectory>li {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
display: flex;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: #b1b1b1 0 0 0.4rem;
|
||||||
|
color: #1a1a1a;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.judge {
|
||||||
|
list-style: none;
|
||||||
|
flex: 1;
|
||||||
|
margin: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid #EEEEEE;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #6f6f6f;
|
||||||
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
box-shadow: none;
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li:last-child {
|
||||||
|
border-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade1 span,
|
||||||
|
.judge>li.grade1 {
|
||||||
|
background-color: #87cefa;
|
||||||
|
color: #4a5361;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade2 span,
|
||||||
|
.judge>li.grade2 {
|
||||||
|
background-color: #e7beff;
|
||||||
|
color: #4a5361;
|
||||||
|
}
|
||||||
|
|
||||||
|
.judge>li.grade3 span,
|
||||||
|
.judge>li.grade3 {
|
||||||
|
background-color: #f7a989;
|
||||||
|
color: #4a5361;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,400i,700");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: "Montserrat";
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banners-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
color: white;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-message {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 2rem;
|
||||||
|
word-break: break-word;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-close {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.1rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .iconfont {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner .banner-close:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.success {
|
||||||
|
background: lightgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.success::after {
|
||||||
|
background: lightgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.error {
|
||||||
|
background: #ed1c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.error::after {
|
||||||
|
background: #ed1c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.info {
|
||||||
|
background: skyblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.info::after {
|
||||||
|
background: skyblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
height: 10%;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner:not(.visible) {
|
||||||
|
display: none;
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.visible {
|
||||||
|
box-shadow: 0 2px 2px 2px rgba(0, 0, 0, 0.12);
|
||||||
|
animation-name: banner-in;
|
||||||
|
animation-direction: forwards;
|
||||||
|
animation-duration: 0.6s;
|
||||||
|
animation-timing-function: ease-in-out;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg0,
|
||||||
|
.grade0b {
|
||||||
|
background-color: #ededed;
|
||||||
|
border: #c5c5c5 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg1,
|
||||||
|
.grade1b {
|
||||||
|
background-color: #7ea5ec;
|
||||||
|
border: #c5c5c5 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg2,
|
||||||
|
.grade2b {
|
||||||
|
background-color: #e2a7ff;
|
||||||
|
border: #c5c5c5 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.achvg3,
|
||||||
|
.grade3b {
|
||||||
|
background-color: #ffa07a;
|
||||||
|
border: #c5c5c5 2px solid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask::before {
|
||||||
|
display: block;
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #000;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1080px) {
|
||||||
|
.grade0b:hover {
|
||||||
|
background-color: #868686;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade1b:hover {
|
||||||
|
background-color: #5d90ff;
|
||||||
|
color: #3b3b3b;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade2b:hover {
|
||||||
|
background-color: #bc72ec;
|
||||||
|
color: #3b3b3b;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade3b:hover {
|
||||||
|
background-color: #e09074;
|
||||||
|
color: #3b3b3b;
|
||||||
|
transition: all .3s ease 0s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade0b.selected,
|
||||||
|
.grade1b.selected,
|
||||||
|
.grade2b.selected,
|
||||||
|
.grade3b.selected {
|
||||||
|
box-shadow: #bbb 0px 0px 10px;
|
||||||
|
color: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.grade0b.selected::after,
|
||||||
|
.grade1b.selected::after,
|
||||||
|
.grade2b.selected::after,
|
||||||
|
.grade3b.selected::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
background-color:#000;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
box-shadow: 0 0 10px #000;
|
||||||
|
opacity: 0;
|
||||||
|
animation: blink 3s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-150%);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: .2;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(150%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade0b.selected {
|
||||||
|
background-color: #444 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade1b.selected {
|
||||||
|
background-color: #407dec !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade2b.selected {
|
||||||
|
background-color: #b362e7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade3b.selected {
|
||||||
|
background-color: #ff7f4d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes banner-in {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translateY(10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-banner {
|
||||||
|
appearance: none;
|
||||||
|
background: #ededed;
|
||||||
|
border: 0;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
.eva-animation {
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-infinite {
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-shake {
|
||||||
|
animation-name: eva-shake;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-zoom {
|
||||||
|
animation-name: eva-zoomIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-pulse {
|
||||||
|
animation-name: eva-pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-icon-flip {
|
||||||
|
animation-name: eva-flipInY;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-shake,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-shake {
|
||||||
|
animation-name: eva-shake;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-zoom,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-zoom {
|
||||||
|
animation-name: eva-zoomIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-pulse,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-pulse {
|
||||||
|
animation-name: eva-pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eva-hover:hover .eva-icon-hover-flip,
|
||||||
|
.eva-parent-hover:hover .eva-icon-hover-flip {
|
||||||
|
animation-name: eva-flipInY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-flipInY {
|
||||||
|
from {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
60% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: perspective(400px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-shake {
|
||||||
|
|
||||||
|
from,
|
||||||
|
to {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
10%,
|
||||||
|
30%,
|
||||||
|
50%,
|
||||||
|
70%,
|
||||||
|
90% {
|
||||||
|
transform: translate3d(-3px, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
20%,
|
||||||
|
40%,
|
||||||
|
60%,
|
||||||
|
80% {
|
||||||
|
transform: translate3d(3px, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-pulse {
|
||||||
|
from {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: scale3d(1.2, 1.2, 1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eva-zoomIn {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale3d(0.5, 0.5, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteFixed {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operateBtn {
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
border: 1px #EEEEEE solid;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
background-color:#393E46;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
cursor: pointer;
|
||||||
|
z-index:2;
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operateBtn:hover {
|
||||||
|
background: #ff7878;
|
||||||
|
color: #fff;
|
||||||
|
transition: all .4s ease 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domToImage2wx {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1111;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domToImage2wx img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
51
view/manifest.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-72x72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-96x96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-128x128.png",
|
||||||
|
"sizes": "128x128",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-144x144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-152x152.png",
|
||||||
|
"sizes": "152x152",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-384x384.png",
|
||||||
|
"sizes": "384x384",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./images/icons/icon-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "人生重开模拟器",
|
||||||
|
"short_name": "LifeRestart",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"display": "standalone",
|
||||||
|
"start_url": "/view/index.html",
|
||||||
|
"description": "人生重开模拟器",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
457
view/style.css
@@ -1,457 +0,0 @@
|
|||||||
@media (min-width:640px){html{font-size:24px;}}
|
|
||||||
@media (min-width:631px) and (max-width:639px){html{font-size:23.66px;}}
|
|
||||||
@media (min-width:622px) and (max-width:630px){html{font-size:23.33px;}}
|
|
||||||
@media (min-width:613px) and (max-width:621px){html{font-size:23px;}}
|
|
||||||
@media (min-width:604px) and (max-width:612px){html{font-size:22.66px;}}
|
|
||||||
@media (min-width:595px) and (max-width:603px){html{font-size:22.33px;}}
|
|
||||||
@media (min-width:586px) and (max-width:594px){html{font-size:22px;}}
|
|
||||||
@media (min-width:577px) and (max-width:585px){html{font-size:21.66px;}}
|
|
||||||
@media (min-width:568px) and (max-width:576px){html{font-size:21.33px;}}
|
|
||||||
@media (min-width:559px) and (max-width:567px){html{font-size:21px;}}
|
|
||||||
@media (min-width:550px) and (max-width:558px){html{font-size:20.66px;}}
|
|
||||||
@media (min-width:541px) and (max-width:549px){html{font-size:20.33px;}}
|
|
||||||
@media (min-width:533px) and (max-width:540px){html{font-size:20px;}}
|
|
||||||
@media (min-width:524px) and (max-width:532px){html{font-size:19.66px;}}
|
|
||||||
@media (min-width:515px) and (max-width:523px){html{font-size:19.33px;}}
|
|
||||||
@media (min-width:506px) and (max-width:514px){html{font-size:19px;}}
|
|
||||||
@media (min-width:497px) and (max-width:505px){html{font-size:18.66px;}}
|
|
||||||
@media (min-width:488px) and (max-width:496px){html{font-size:18.33px;}}
|
|
||||||
@media (min-width:480px) and (max-width:487px){html{font-size:18px;}}
|
|
||||||
@media (min-width:471px) and (max-width:479px){html{font-size:17.66px;}}
|
|
||||||
@media (min-width:462px) and (max-width:470px){html{font-size:17.33px;}}
|
|
||||||
@media (min-width:453px) and (max-width:461px){html{font-size:17px;}}
|
|
||||||
@media (min-width:444px) and (max-width:452px){html{font-size:17.12px;}}
|
|
||||||
@media (min-width:435px) and (max-width:443px){html{font-size:16.33px;}}
|
|
||||||
@media (min-width:426px) and (max-width:434px){html{font-size:16px;}}
|
|
||||||
@media (min-width:417px) and (max-width:425px){html{font-size:15.66px;}}
|
|
||||||
@media (min-width:408px) and (max-width:416px){html{font-size:15.33px;}}
|
|
||||||
@media (min-width:400px) and (max-width:407px){html{font-size:15px;}}
|
|
||||||
@media (min-width:391px) and (max-width:399px){html{font-size:14.66px;}}
|
|
||||||
@media (min-width:382px) and (max-width:390px){html{font-size:14.33px;}}
|
|
||||||
@media (min-width:374px) and (max-width:381px){html{font-size:14px;}}
|
|
||||||
@media (min-width:365px) and (max-width:373px){html{font-size:13.66px;}}
|
|
||||||
@media (min-width:356px) and (max-width:364px){html{font-size:13.33px;}}
|
|
||||||
@media (min-width:347px) and (max-width:355px){html{font-size:13px;}}
|
|
||||||
@media (min-width:338px) and (max-width:346px){html{font-size:12.66px;}}
|
|
||||||
@media (min-width:329px) and (max-width:337px){html{font-size:12.44px;}}
|
|
||||||
@media (max-width:328px){html{font-size:12px;}}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'iconfont';
|
|
||||||
src: url('iconfont.woff2?t=1628944689555') format('woff2'),
|
|
||||||
url('iconfont.woff?t=1628944689555') format('woff'),
|
|
||||||
url('iconfont.ttf?t=1628944689555') format('truetype');
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
font-family: PingFangSC, 'Noto Sans CJK SC', 'MS Yahei';
|
|
||||||
}
|
|
||||||
|
|
||||||
#main {
|
|
||||||
align-content: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#title {
|
|
||||||
position: fixed;
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: 700;
|
|
||||||
top: 35%;
|
|
||||||
left: 50%;
|
|
||||||
white-space: nowrap;
|
|
||||||
transform: translate(-50%,-50%);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mainbtn {
|
|
||||||
position: fixed;
|
|
||||||
top: 65%;
|
|
||||||
left: 50%;
|
|
||||||
padding: 0.8rem 1rem;
|
|
||||||
border: 1px #ccc solid;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
background-color:white;
|
|
||||||
font-size: 1.6rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
transform: translate(-50%,-50%);
|
|
||||||
cursor: pointer;
|
|
||||||
z-index:2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconfont {
|
|
||||||
font-family: "iconfont" !important;
|
|
||||||
font-style: normal;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
#rank {
|
|
||||||
position: fixed;
|
|
||||||
top: 1rem;
|
|
||||||
right: 1rem;
|
|
||||||
padding: 0.1rem 1rem;
|
|
||||||
border: none;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
background-color:lightsteelblue;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
z-index:2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.head {
|
|
||||||
position: fixed;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
top: 1.1rem;
|
|
||||||
left: 50%;
|
|
||||||
white-space: nowrap;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.judge,
|
|
||||||
.lifeTrajectory,
|
|
||||||
.propinitial,
|
|
||||||
.selectlist {
|
|
||||||
position: fixed;
|
|
||||||
list-style-type: none;
|
|
||||||
left: 50%;
|
|
||||||
top: 5rem;
|
|
||||||
bottom: 8.5rem;
|
|
||||||
width: 30rem;
|
|
||||||
max-width: calc(100% - 2rem);
|
|
||||||
margin: auto;
|
|
||||||
padding: 0;
|
|
||||||
overflow: auto;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.selectlist > li {
|
|
||||||
position: relative;
|
|
||||||
border: 1px #ccc solid;
|
|
||||||
display: inline-block;
|
|
||||||
width: 95%;
|
|
||||||
margin: 0.1rem auto;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selectlist > li::before {
|
|
||||||
position: absolute;
|
|
||||||
display: inline-block;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
border-radius: 0.2rem 0 0 0.2rem;
|
|
||||||
margin: -1px;
|
|
||||||
padding: 1px;
|
|
||||||
height: 100%;
|
|
||||||
width: 1.5rem;
|
|
||||||
content: " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
.grade1,
|
|
||||||
.grade1b::before {
|
|
||||||
background-color: rgb(116, 191, 255) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grade2,
|
|
||||||
.grade2b::before {
|
|
||||||
background-color: rgb(226, 167, 255) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grade3,
|
|
||||||
.grade3b::before {
|
|
||||||
background-color: lightsalmon !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected {
|
|
||||||
background-color: gray;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.propinitial {
|
|
||||||
top: 6rem;
|
|
||||||
bottom: 14rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.propinitial > li {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
width: 95%;
|
|
||||||
margin: 0.1rem auto;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
padding: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.propinitial > li > input {
|
|
||||||
height: 2.2rem;
|
|
||||||
width: 2.2rem;
|
|
||||||
margin: 0 0.5rem;
|
|
||||||
padding: 0;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 2rem;
|
|
||||||
border: 0.1rem #ccc solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.propbtn {
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lifeTrajectory {
|
|
||||||
border: 1px lightblue solid;
|
|
||||||
background-color: aliceblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.judge > li,
|
|
||||||
.lifeTrajectory > li {
|
|
||||||
position: relative;
|
|
||||||
width: calc(100% - 7rem);
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
padding: 0.5rem 1rem 0.5rem 6rem;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: lightblue 0 0 0.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.judge > li > span,
|
|
||||||
.lifeTrajectory > li > span {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
width: 6rem;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.judge > li {
|
|
||||||
box-shadow: lightgray 0 0 0.4rem;
|
|
||||||
width: calc(100% - 9rem);
|
|
||||||
margin: 0.5rem;
|
|
||||||
padding: 0.5rem 1rem 0.5rem 7rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.judge > li > span {
|
|
||||||
background-color: white;
|
|
||||||
height: calc(100% - 1rem);
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,400i,700");
|
|
||||||
:root {
|
|
||||||
font-family: "Montserrat";
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banners-container {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner {
|
|
||||||
color: white;
|
|
||||||
font-weight: 700;
|
|
||||||
padding: 2rem;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.banner .banner-message {
|
|
||||||
flex: 1;
|
|
||||||
padding: 0 2rem;
|
|
||||||
word-break: break-word;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
.banner .banner-close {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0.1rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner .iconfont {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner .banner-close:hover {
|
|
||||||
background: rgba(0, 0, 0, 0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner.success {
|
|
||||||
background: lightgreen;
|
|
||||||
}
|
|
||||||
.banner.success::after {
|
|
||||||
background: lightgreen;
|
|
||||||
}
|
|
||||||
.banner.error {
|
|
||||||
background: #ed1c24;
|
|
||||||
}
|
|
||||||
.banner.error::after {
|
|
||||||
background: #ed1c24;
|
|
||||||
}
|
|
||||||
.banner.info {
|
|
||||||
background: skyblue;
|
|
||||||
}
|
|
||||||
.banner.info::after {
|
|
||||||
background: skyblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
height: 10%;
|
|
||||||
width: 100%;
|
|
||||||
bottom: 100%;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner:not(.visible) {
|
|
||||||
display: none;
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner.visible {
|
|
||||||
box-shadow: 0 2px 2px 2px rgba(0, 0, 0, 0.12);
|
|
||||||
animation-name: banner-in;
|
|
||||||
animation-direction: forwards;
|
|
||||||
animation-duration: 0.6s;
|
|
||||||
animation-timing-function: ease-in-out;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
animation-iteration-count: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes banner-in {
|
|
||||||
0% {
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
transform: translateY(10%);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.show-banner {
|
|
||||||
appearance: none;
|
|
||||||
background: #ededed;
|
|
||||||
border: 0;
|
|
||||||
padding: 1rem 2rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Akveo. All Rights Reserved.
|
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
*/
|
|
||||||
.eva-animation {
|
|
||||||
animation-duration: 1s;
|
|
||||||
animation-fill-mode: both; }
|
|
||||||
|
|
||||||
.eva-infinite {
|
|
||||||
animation-iteration-count: infinite; }
|
|
||||||
|
|
||||||
.eva-icon-shake {
|
|
||||||
animation-name: eva-shake; }
|
|
||||||
|
|
||||||
.eva-icon-zoom {
|
|
||||||
animation-name: eva-zoomIn; }
|
|
||||||
|
|
||||||
.eva-icon-pulse {
|
|
||||||
animation-name: eva-pulse; }
|
|
||||||
|
|
||||||
.eva-icon-flip {
|
|
||||||
animation-name: eva-flipInY; }
|
|
||||||
|
|
||||||
.eva-hover {
|
|
||||||
display: inline-block; }
|
|
||||||
|
|
||||||
.eva-hover:hover .eva-icon-hover-shake, .eva-parent-hover:hover .eva-icon-hover-shake {
|
|
||||||
animation-name: eva-shake; }
|
|
||||||
|
|
||||||
.eva-hover:hover .eva-icon-hover-zoom, .eva-parent-hover:hover .eva-icon-hover-zoom {
|
|
||||||
animation-name: eva-zoomIn; }
|
|
||||||
|
|
||||||
.eva-hover:hover .eva-icon-hover-pulse, .eva-parent-hover:hover .eva-icon-hover-pulse {
|
|
||||||
animation-name: eva-pulse; }
|
|
||||||
|
|
||||||
.eva-hover:hover .eva-icon-hover-flip, .eva-parent-hover:hover .eva-icon-hover-flip {
|
|
||||||
animation-name: eva-flipInY; }
|
|
||||||
|
|
||||||
@keyframes eva-flipInY {
|
|
||||||
from {
|
|
||||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
|
||||||
animation-timing-function: ease-in;
|
|
||||||
opacity: 0; }
|
|
||||||
40% {
|
|
||||||
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
|
||||||
animation-timing-function: ease-in; }
|
|
||||||
60% {
|
|
||||||
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
|
||||||
opacity: 1; }
|
|
||||||
80% {
|
|
||||||
transform: perspective(400px) rotate3d(0, 1, 0, -5deg); }
|
|
||||||
to {
|
|
||||||
transform: perspective(400px); } }
|
|
||||||
|
|
||||||
@keyframes eva-shake {
|
|
||||||
from,
|
|
||||||
to {
|
|
||||||
transform: translate3d(0, 0, 0); }
|
|
||||||
10%,
|
|
||||||
30%,
|
|
||||||
50%,
|
|
||||||
70%,
|
|
||||||
90% {
|
|
||||||
transform: translate3d(-3px, 0, 0); }
|
|
||||||
20%,
|
|
||||||
40%,
|
|
||||||
60%,
|
|
||||||
80% {
|
|
||||||
transform: translate3d(3px, 0, 0); } }
|
|
||||||
|
|
||||||
@keyframes eva-pulse {
|
|
||||||
from {
|
|
||||||
transform: scale3d(1, 1, 1); }
|
|
||||||
50% {
|
|
||||||
transform: scale3d(1.2, 1.2, 1.2); }
|
|
||||||
to {
|
|
||||||
transform: scale3d(1, 1, 1); } }
|
|
||||||
|
|
||||||
@keyframes eva-zoomIn {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale3d(0.5, 0.5, 0.5); }
|
|
||||||
50% {
|
|
||||||
opacity: 1; } }
|
|
||||||
27
view/sw.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
var CACHE_VERSION = 'sw_v1';
|
||||||
|
|
||||||
|
var CACHE_FILES = [
|
||||||
|
'/',
|
||||||
|
];
|
||||||
|
|
||||||
|
self.addEventListener('install', function (event) {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.open(CACHE_VERSION)
|
||||||
|
.then(cache => cache.addAll(CACHE_FILES)
|
||||||
|
.then(() => self.skipWaiting())
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', function (event) {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.keys().then(function (keys) {
|
||||||
|
return Promise.all(keys.map(function (key, i) {
|
||||||
|
if (key !== CACHE_VERSION) {
|
||||||
|
return caches.delete(keys[i]);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('fetch', function(event) {});
|
||||||
@@ -4,36 +4,34 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="style.css">
|
<meta name="description" content="やり直すんだ。そして、次はうまくやる。"/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
|
<meta name="keywords" content="人生重开模拟器 liferestart life restart remake 人生重来"/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
<link id="themeLink" rel="stylesheet" href="light.css">
|
||||||
<script>window.json = async fileName=>(await axios(`../data/${fileName}.json`)).data;</script>
|
<script src="../lib/jquery-3.6.0.min.js"></script>
|
||||||
<title>Document</title>
|
<script src="../lib/dom-to-image.min.js"></script>
|
||||||
|
<script type="module" src="../src/index.js"></script>
|
||||||
|
<title>Life Restart</title>
|
||||||
</head>
|
</head>
|
||||||
<body style="margin: 0; height: 100%">
|
<body style="margin: 0; height: 100%">
|
||||||
<div id="main">
|
<div class="banners-container">
|
||||||
<div class="head">人生总结</div>
|
<div class="banners">
|
||||||
<ul id="judge" class="judge" style="bottom: calc(35% + 2.5rem)">
|
<div class="banner error">
|
||||||
<li class="grade2"><span>颜值:</span>9级 美若天仙</li>
|
<div class="banner-icon"><span class="iconfont"></span></div>
|
||||||
<li><span>智力:</span>4级 智力一般</li>
|
<pre class="banner-message">Oops! Something went wrong!</pre>
|
||||||
<li><span>体质:</span>1级 极度虚弱</li>
|
<div class="banner-close" onclick="hideBanners()"><span class="iconfont"></span></div>
|
||||||
<li><span>家境:</span>6级 小康之家</li>
|
</div>
|
||||||
<li><span>享年:</span>3岁 早夭</li>
|
<div class="banner success">
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<div class="banner-icon"><span class="iconfont"></span></div>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<pre class="banner-message">Everything was fine!</pre>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<div class="banner-close" onclick="hideBanners()"><span class="iconfont"></span></div>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
</div>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<div class="banner info">
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<div class="banner-icon"><span class="iconfont"></span></div>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<pre class="banner-message">Here is some useful information</pre>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
<div class="banner-close" onclick="hideBanners()"><span class="iconfont"></span></div>
|
||||||
<li><span>快乐:</span>3级 不太幸福的人生</li>
|
</div>
|
||||||
</ul>
|
|
||||||
<div class="head" style="top:auto; bottom:35%">天赋,你可以选一个,下辈子还能抽到</div>
|
|
||||||
<ul id="talents" class="selectlist" style="top:calc(65% + 0.5rem); bottom:8rem">
|
|
||||||
<li class="grade2b">黑幕(面试一定成功)</li>
|
|
||||||
</ul>
|
|
||||||
<button id="again" class="mainbtn" style="top:auto; bottom:0.1em"><span class="iconfont"></span>再次重开</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="https://github.com/VickScarlet/lifeRestart" class="github-corner" style="z-index: 9999;" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; left: 0; transform: scale(-1, 1);" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style></a>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
60
webpack.config.cjs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'production',
|
||||||
|
entry: './src/index.js',
|
||||||
|
devtool: 'eval-cheap-module-source-map',
|
||||||
|
devServer: {
|
||||||
|
static: [
|
||||||
|
{
|
||||||
|
directory: path.join(__dirname, 'data'),
|
||||||
|
publicPath: '/data',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directory: path.join(__dirname, 'public'),
|
||||||
|
publicPath: '/public',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directory: path.join(__dirname, 'view'),
|
||||||
|
publicPath: '/view',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directory: path.join(__dirname, 'src'),
|
||||||
|
publicPath: '/src',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directory: path.join(__dirname, 'lib'),
|
||||||
|
publicPath: '/lib',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, 'public'),
|
||||||
|
filename: 'bundle.js',
|
||||||
|
clean: true,
|
||||||
|
},
|
||||||
|
// resolve: {
|
||||||
|
// extensions: ['.js'],
|
||||||
|
// },
|
||||||
|
module: {
|
||||||
|
rules: [{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
"targets": "> 0.25%, not dead",
|
||||||
|
"useBuiltIns": "usage",
|
||||||
|
"corejs": "3.8.3",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||