🧐 Render melee cards

This commit is contained in:
zhbaor 2022-09-29 11:28:58 +08:00
parent c0fc97a578
commit 8c7e842d2e
78 changed files with 243 additions and 1 deletions

Binary file not shown.

View file

@ -8,3 +8,4 @@ class Melee(db.Entity):
description = Optional(str)
mechanism = Optional(str)
icon = Required(bytes)
stats = Required(int)

View file

@ -51,9 +51,16 @@ with db_session:
region_arr = io.BytesIO()
region.save(region_arr, format="PNG")
stats_map = {"Brutality": 1, "Survival": 2, "Tactic": 4}
stats = 0
for t in ["tier1", "tier2"]:
if t in i:
stats += stats_map[i[t]]
Melee(
name=i["name"],
description=i["ambiantDesc"],
mechanism=i["gameplayDesc"],
icon=region_arr.getbuffer().tobytes()
icon=region_arr.getbuffer().tobytes(),
stats=stats,
)

9
data/render/README.md Normal file
View file

@ -0,0 +1,9 @@
# 数据渲染
将数据导出为图片
`server.py` 是用 Bottle 写的后端,运行 `./server.py` 然后打开 <http://localhost:8080/怨恨之刃> 就能看到怨恨之刃的网页。
之所以不直接用模板渲染,而要用 Web 服务器,是为了方便开发。
运行 `render_all.py` 会渲染所有近战武器,输出到 `output` 文件夹中。

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

21
data/render/render_all.py Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# # -*- coding: utf-8 -*-
import sys
from playwright.sync_api import sync_playwright
sys.path.append("../convert/31-0")
from db import *
db.bind(provider="sqlite", filename="../clean/31-0/data.sqlite3")
db.generate_mapping(create_tables=True)
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
with db_session:
for m in Melee.select():
print(f"rendering {m.name}...")
page.goto(f"http://localhost:8080/{m.name}")
page.locator(".container").screenshot(path=f"./output/{m.name}.png")
browser.close()

47
data/render/server.py Executable file
View file

@ -0,0 +1,47 @@
#!/usr/bin/env python3
# # -*- coding: utf-8 -*-
import sys
import base64
import re
from bottle import route, run, static_file, view
sys.path.append("../convert/31-0")
from db import *
db.bind(provider="sqlite", filename="../clean/31-0/data.sqlite3")
db.generate_mapping(create_tables=True)
@route("/<name>")
@view("weapon")
def melee(name):
with db_session:
query = select(w for w in Melee if w.name == name)
weapon = query.first()
mechanism, _ = re.subn(
r"{(.*?)@(.*?)}", r"<span class='\2'>\1</span>", weapon.mechanism
)
stats_map = {
1: "brutality",
2: "survival",
3: "minotaur",
4: "tactics",
5: "assassin",
6: "guardian",
}
return {
"title": name,
"icon": base64.b64encode(weapon.icon),
"mechanism": mechanism,
"description": weapon.description,
"stats": stats_map[weapon.stats]
}
@route("/static/<filepath:path>")
def server_static(filepath):
return static_file(filepath, root="./static")
run(host="localhost", port=8080)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -0,0 +1,131 @@
body {
background: rgba(7, 12, 25, 0.85);
margin: 0;
}
.container {
box-sizing: border-box;
width: 350px;
border: 1px solid transparent;
border-image: url("/static/Table-border.webp");
border-image-width: 15px;
border-image-slice: 15 16;
border-radius: 5px;
padding: 6px;
background: rgba(21, 30, 61, 0.7);
background-image: url("/static/Infobox-background.webp");
background-position: bottom right;
background-repeat: no-repeat;
}
.title {
background: rgba(6, 9, 19, 0.5);
font-family: "Noto Sans CJK SC";
font-weight: bold;
color: #f7eb62;
font-size: 18px;
line-height: 1.6;
text-align: center;
letter-spacing: 4px;
}
.weapon-icon-bg {
margin: 5px;
padding: 10px;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
image-rendering: pixelated;
display: flex;
justify-content: center;
}
.weapon-icon {
width: 72px;
height: 72px;
}
.mechanism {
padding: 2px 16px;
color: #e0e0e0;
text-align: center;
font-size: 14px;
font-family: "Noto Sans CJK SC";
line-height: 1.7;
}
.CC {
color: #f0d60d;
}
.BL {
color: #e03e35;
}
.RO {
color: #82a082;
}
.TO {
color: #75dc2c;
}
.FI {
color: #e5822b;
}
.EL {
color: #37a3d7;
}
.IC {
color: #91d5fb;
}
.description {
padding: 2px 16px;
color: #90abe6;
text-align: center;
font-size: 14px;
font-family: "Noto Sans CJK SC";
line-height: 1.7;
}
.subtitle {
color: #e0e0e0;
background: rgba(6, 9, 19, 0.5);
text-align: center;
font-family: "Noto Sans CJK SC";
font-weight: bold;
line-height: 1.8;
font-size: 18px;
}
.dps {
padding: 10px 40px;
display: flex;
justify-content: center;
gap: 20px;
}
.table {
color: #e0e0e0;
margin: 2px auto;
text-align: center;
border-collapse: collapse;
}
.table > tbody > tr:nth-child(odd) {
background: rgba(6, 9, 19, 0.1);
}
.table > tbody > tr > td {
font-size: 16px;
font-family: "Noto Sans CJK SC";
line-height: 28px;
padding: 2px 10px;
}
.summary > td:first-child {
font-weight: bold;
}

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Template</title>
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<div class="container">
<div class="title">{{ title }}</div>
<figure
class="weapon-icon-bg"
style="background-image: url('/static/bg/{{ stats }}.png');"
>
<img class="weapon-icon" src="data:image/png;base64,{{ icon }}" />
</figure>
% if mechanism:
<div class="mechanism">{{ !mechanism }}</div>
% end
% if description:
<div class="description">{{ description }}</div>
%end
</div>
</body>
</html>