♻️ Abyss overview show all data

This commit is contained in:
omg-xtao 2024-12-15 15:25:38 +08:00 committed by GitHub
parent e4b10e8dd6
commit 0bbaf5a65e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 90 additions and 233 deletions

View File

@ -1,12 +1,10 @@
"""深渊数据查询""" """深渊数据查询"""
import asyncio
import math import math
import re import re
from functools import lru_cache, partial from functools import lru_cache, partial
from typing import Any, Coroutine, List, Optional, Tuple, Union, Dict from typing import List, Optional, Tuple, Dict
from arkowrapper import ArkoWrapper
from simnet import GenshinClient from simnet import GenshinClient
from simnet.models.genshin.chronicle.abyss import SpiralAbyss from simnet.models.genshin.chronicle.abyss import SpiralAbyss
from telegram import Message, Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram import Message, Update, InlineKeyboardButton, InlineKeyboardMarkup
@ -18,7 +16,7 @@ from core.plugin import Plugin, handler
from core.services.cookies.error import TooManyRequestPublicCookies from core.services.cookies.error import TooManyRequestPublicCookies
from core.services.history_data.models import HistoryDataAbyss from core.services.history_data.models import HistoryDataAbyss
from core.services.history_data.services import HistoryDataAbyssServices from core.services.history_data.services import HistoryDataAbyssServices
from core.services.template.models import RenderGroupResult, RenderResult from core.services.template.models import RenderResult
from core.services.template.services import TemplateService from core.services.template.services import TemplateService
from gram_core.config import config from gram_core.config import config
from gram_core.dependence.redisdb import RedisDB from gram_core.dependence.redisdb import RedisDB
@ -38,17 +36,9 @@ get_args_pattern = re.compile(r"\d+")
@lru_cache @lru_cache
def get_args(text: str) -> Tuple[int, bool, bool]: def get_args(text: str) -> bool:
total = "all" in text or "总览" in text
prev = "pre" in text or "上期" in text prev = "pre" in text or "上期" in text
floor = 0 return prev
if not total:
m = get_args_pattern.search(text)
if m is not None:
floor = int(m.group(0))
return floor, total, prev
class AbyssUnlocked(Exception): class AbyssUnlocked(Exception):
@ -107,23 +97,12 @@ class AbyssPlugin(Plugin):
return return
# 解析参数 # 解析参数
floor, total, previous = get_args(" ".join([i for i in args if not i.startswith("@")])) previous = get_args(" ".join([i for i in args if not i.startswith("@")]))
if floor > 12 or floor < 0:
reply_msg = await message.reply_text("深渊层数输入错误,请重新输入。支持的参数为: 1-12 或 all")
if filters.ChatType.GROUPS.filter(message):
self.add_delete_message_job(reply_msg)
self.add_delete_message_job(message)
return
if 0 < floor < 9:
previous = False
self.log_user( self.log_user(
update, update,
logger.info, logger.info,
"[bold]深渊挑战数据[/bold]请求: floor=%s total=%s previous=%s", "[bold]深渊挑战数据[/bold]请求: previous=%s",
floor,
total,
previous, previous,
extra={"markup": True}, extra={"markup": True},
) )
@ -132,14 +111,12 @@ class AbyssPlugin(Plugin):
reply_text: Optional[Message] = None reply_text: Optional[Message] = None
if total:
reply_text = await message.reply_text(f"{config.notice.bot_name}需要时间整理深渊数据,还请耐心等待哦~")
try: try:
async with self.helper.genshin_or_public(user_id, uid=uid, offset=offset) as client: async with self.helper.genshin_or_public(user_id, uid=uid, offset=offset) as client:
if not client.public: if not client.public:
await client.get_record_cards() await client.get_record_cards()
abyss_data, avatar_data = await self.get_rendered_pic_data(client, client.player_id, previous) abyss_data, avatar_data = await self.get_rendered_pic_data(client, client.player_id, previous)
images = await self.get_rendered_pic(abyss_data, avatar_data, client.player_id, floor, total) images = await self.get_rendered_pic(abyss_data, avatar_data, client.player_id)
except AbyssUnlocked: # 若深渊未解锁 except AbyssUnlocked: # 若深渊未解锁
await message.reply_text("还未解锁深渊哦~") await message.reply_text("还未解锁深渊哦~")
return return
@ -162,14 +139,8 @@ class AbyssPlugin(Plugin):
if reply_text is not None: if reply_text is not None:
await reply_text.delete() await reply_text.delete()
if images is None:
await message.reply_text(f"还没有第 {floor} 层的挑战数据")
return
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO) await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
await images.reply_photo(message)
for group in ArkoWrapper(images).group(10): # 每 10 张图片分一个组
await RenderGroupResult(results=group).reply_media_group(message, write_timeout=60)
self.log_user(update, logger.info, "[bold]深渊挑战数据[/bold]: 成功发送图片", extra={"markup": True}) self.log_user(update, logger.info, "[bold]深渊挑战数据[/bold]: 成功发送图片", extra={"markup": True})
@ -186,8 +157,11 @@ class AbyssPlugin(Plugin):
return abyss_data, avatar_data return abyss_data, avatar_data
async def get_rendered_pic( # skipcq: PY-R1000 # async def get_rendered_pic( # skipcq: PY-R1000 #
self, abyss_data: "SpiralAbyss", avatar_data: Dict[int, int], uid: int, floor: int, total: bool self,
) -> Union[Tuple[Any], List[RenderResult], None]: abyss_data: "SpiralAbyss",
avatar_data: Dict[int, int],
uid: int,
) -> RenderResult:
""" """
获取渲染后的图片 获取渲染后的图片
@ -195,8 +169,6 @@ class AbyssPlugin(Plugin):
abyss_data (SpiralAbyss): 深渊数据 abyss_data (SpiralAbyss): 深渊数据
avatar_data (Dict[int, int]): 角色数据 avatar_data (Dict[int, int]): 角色数据
uid (int): 需要查询的 uid uid (int): 需要查询的 uid
floor (int): 层数
total (bool): 是否为总览
Returns: Returns:
bytes格式的图片 bytes格式的图片
@ -206,9 +178,9 @@ class AbyssPlugin(Plugin):
raise AbyssUnlocked raise AbyssUnlocked
if not abyss_data.ranks.most_kills: if not abyss_data.ranks.most_kills:
raise NoMostKills raise NoMostKills
if (total or (floor > 0)) and len(abyss_data.floors) == 0: if len(abyss_data.floors) == 0:
raise FloorNotFoundError raise FloorNotFoundError
if (total or (floor > 0)) and len(abyss_data.floors[0].chambers[0].battles) == 0: if len(abyss_data.floors[0].chambers[0].battles) == 0:
raise AbyssNotFoundError raise AbyssNotFoundError
start_time = abyss_data.start_time start_time = abyss_data.start_time
@ -236,53 +208,8 @@ class AbyssPlugin(Plugin):
11: "#252550", 11: "#252550",
12: "#1D2A4A", 12: "#1D2A4A",
} }
data = jsonlib.loads(result)
if total:
render_data["avatar_data"] = avatar_data
data = jsonlib.loads(result)
render_data["data"] = data
render_inputs: List[Tuple[int, Coroutine[Any, Any, RenderResult]]] = []
def overview_task():
return -1, self.template_service.render(
"genshin/abyss/overview.jinja2", render_data, viewport={"width": 750, "height": 580}
)
def floor_task(floor_index: int):
floor_d = data["floors"][floor_index]
return (
floor_d["floor"],
self.template_service.render(
"genshin/abyss/floor.jinja2",
{
**render_data,
"floor": floor_d,
"total_stars": f"{floor_d['stars']}/{floor_d['max_stars']}",
},
viewport={"width": 690, "height": 500},
full_page=True,
ttl=15 * 24 * 60 * 60,
),
)
render_inputs.append(overview_task())
for i, f in enumerate(data["floors"]):
if f["floor"] >= 9:
render_inputs.append(floor_task(i))
render_group_inputs = list(map(lambda x: x[1], sorted(render_inputs, key=lambda x: x[0])))
return await asyncio.gather(*render_group_inputs)
if floor < 1:
render_data["data"] = jsonlib.loads(result)
return [
await self.template_service.render(
"genshin/abyss/overview.jinja2", render_data, viewport={"width": 750, "height": 580}
)
]
num_dic = { num_dic = {
"0": "", "0": "",
"1": "", "1": "",
@ -295,21 +222,21 @@ class AbyssPlugin(Plugin):
"8": "", "8": "",
"9": "", "9": "",
} }
if num := num_dic.get(str(floor)): for _i in data.get("floors", []):
render_data["floor-num"] = num floor = int(_i["floor"])
else: if num := num_dic.get(str(floor)):
render_data["floor-num"] = f"{num_dic.get(str(floor % 10))}" _i["floor_num"] = num
floors = jsonlib.loads(result)["floors"] else:
if not (floor_data := list(filter(lambda x: x["floor"] == floor, floors))): _i["floor_num"] = f"{num_dic.get(str(floor % 10))}"
return None _i["total_stars"] = f"{_i['stars']}/{_i['max_stars']}"
render_data["avatar_data"] = avatar_data render_data["avatar_data"] = avatar_data
render_data["floor"] = floor_data[0] render_data["data"] = data
render_data["total_stars"] = f"{floor_data[0]['stars']}/{floor_data[0]['max_stars']}" return await self.template_service.render(
return [ "genshin/abyss/overview.jinja2",
await self.template_service.render( render_data,
"genshin/abyss/floor.jinja2", render_data, viewport={"width": 690, "height": 500} viewport={"width": 2745, "height": 4000},
) query_selector=".container",
] )
@staticmethod @staticmethod
async def save_abyss_data( async def save_abyss_data(
@ -414,40 +341,6 @@ class AbyssPlugin(Plugin):
send_buttons.append(last_button) send_buttons.append(last_button)
return send_buttons return send_buttons
@staticmethod
async def gen_floor_button(
data_id: int,
abyss_data: "HistoryDataAbyss",
user_id: int,
uid: int,
) -> List[List[InlineKeyboardButton]]:
floors = [i.floor for i in abyss_data.abyss_data.floors if i.floor]
floors.sort()
buttons = [
InlineKeyboardButton(
f"{i}",
callback_data=f"get_abyss_history|{user_id}|{uid}|{data_id}|{i}",
)
for i in floors
]
send_buttons = [buttons[i : i + 4] for i in range(0, len(buttons), 4)]
all_buttons = [
InlineKeyboardButton(
"<< 返回",
callback_data=f"get_abyss_history|{user_id}|{uid}|p_1",
),
InlineKeyboardButton(
"总览",
callback_data=f"get_abyss_history|{user_id}|{uid}|{data_id}|total",
),
InlineKeyboardButton(
"所有",
callback_data=f"get_abyss_history|{user_id}|{uid}|{data_id}|all",
),
]
send_buttons.append(all_buttons)
return send_buttons
@handler.command("abyss_history", block=False) @handler.command("abyss_history", block=False)
@handler.message(filters.Regex(r"^深渊历史数据"), block=False) @handler.message(filters.Regex(r"^深渊历史数据"), block=False)
async def abyss_history_command_start(self, update: Update, _: CallbackContext) -> None: async def abyss_history_command_start(self, update: Update, _: CallbackContext) -> None:
@ -479,23 +372,7 @@ class AbyssPlugin(Plugin):
await callback_query.edit_message_reply_markup(reply_markup=InlineKeyboardMarkup(buttons)) await callback_query.edit_message_reply_markup(reply_markup=InlineKeyboardMarkup(buttons))
await callback_query.answer(f"已切换到第 {page}", show_alert=False) await callback_query.answer(f"已切换到第 {page}", show_alert=False)
async def get_abyss_history_season(self, update: "Update", data_id: int): async def get_abyss_history_floor(self, update: "Update", data_id: int):
"""进入选择层数"""
callback_query = update.callback_query
user = callback_query.from_user
self.log_user(update, logger.info, "切换深渊历史数据到层数页 data_id[%s]", data_id)
data = await self.history_data_abyss.get_by_id(data_id)
if not data:
await callback_query.answer("数据不存在,请尝试重新发送命令~", show_alert=True)
await callback_query.edit_message_text("数据不存在,请尝试重新发送命令~")
return
abyss_data = HistoryDataAbyss.from_data(data)
buttons = await self.gen_floor_button(data_id, abyss_data, user.id, data.user_id)
await callback_query.edit_message_reply_markup(reply_markup=InlineKeyboardMarkup(buttons))
await callback_query.answer("已切换到层数页", show_alert=False)
async def get_abyss_history_floor(self, update: "Update", data_id: int, detail: str):
"""渲染层数数据""" """渲染层数数据"""
callback_query = update.callback_query callback_query = update.callback_query
message = callback_query.message message = callback_query.message
@ -503,14 +380,6 @@ class AbyssPlugin(Plugin):
if message.reply_to_message: if message.reply_to_message:
reply = message.reply_to_message reply = message.reply_to_message
floor = 0
total = False
if detail == "total":
floor = 0
elif detail == "all":
total = True
else:
floor = int(detail)
data = await self.history_data_abyss.get_by_id(data_id) data = await self.history_data_abyss.get_by_id(data_id)
if not data: if not data:
await callback_query.answer("数据不存在,请尝试重新发送命令", show_alert=True) await callback_query.answer("数据不存在,请尝试重新发送命令", show_alert=True)
@ -518,18 +387,16 @@ class AbyssPlugin(Plugin):
return return
abyss_data = HistoryDataAbyss.from_data(data) abyss_data = HistoryDataAbyss.from_data(data)
images = await self.get_rendered_pic(
abyss_data.abyss_data, abyss_data.character_data, data.user_id, floor, total
)
if images is None:
await callback_query.answer(f"还没有第 {floor} 层的挑战数据", show_alert=True)
return
await callback_query.answer("正在渲染图片中 请稍等 请不要重复点击按钮", show_alert=False) await callback_query.answer("正在渲染图片中 请稍等 请不要重复点击按钮", show_alert=False)
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO) images = await self.get_rendered_pic(
abyss_data.abyss_data,
abyss_data.character_data,
data.user_id,
)
for group in ArkoWrapper(images).group(10): # 每 10 张图片分一个组 await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
await RenderGroupResult(results=group).reply_media_group(reply or message, write_timeout=60) await images.reply_photo(reply or message)
self.log_user(update, logger.info, "[bold]深渊挑战数据[/bold]: 成功发送图片", extra={"markup": True}) self.log_user(update, logger.info, "[bold]深渊挑战数据[/bold]: 成功发送图片", extra={"markup": True})
self.add_delete_message_job(message, delay=1) self.add_delete_message_job(message, delay=1)
@ -540,22 +407,20 @@ class AbyssPlugin(Plugin):
async def get_abyss_history_callback( async def get_abyss_history_callback(
callback_query_data: str, callback_query_data: str,
) -> Tuple[str, str, int, int]: ) -> Tuple[str, int, int]:
_data = callback_query_data.split("|") _data = callback_query_data.split("|")
_user_id = int(_data[1]) _user_id = int(_data[1])
_uid = int(_data[2]) _uid = int(_data[2])
_result = _data[3] _result = _data[3]
_detail = _data[4] if len(_data) > 4 else None
logger.debug( logger.debug(
"callback_query_data函数返回 detail[%s] result[%s] user_id[%s] uid[%s]", "callback_query_data函数返回 result[%s] user_id[%s] uid[%s]",
_detail,
_result, _result,
_user_id, _user_id,
_uid, _uid,
) )
return _detail, _result, _user_id, _uid return _result, _user_id, _uid
detail, result, user_id, uid = await get_abyss_history_callback(callback_query.data) result, user_id, uid = await get_abyss_history_callback(callback_query.data)
if user.id != user_id: if user.id != user_id:
await callback_query.answer(text="这不是你的按钮!\n" + config.notice.user_mismatch, show_alert=True) await callback_query.answer(text="这不是你的按钮!\n" + config.notice.user_mismatch, show_alert=True)
return return
@ -566,10 +431,7 @@ class AbyssPlugin(Plugin):
await self.get_abyss_history_page(update, user_id, uid, result) await self.get_abyss_history_page(update, user_id, uid, result)
return return
data_id = int(result) data_id = int(result)
if detail: await self.get_abyss_history_floor(update, data_id)
await self.get_abyss_history_floor(update, data_id, detail)
return
await self.get_abyss_history_season(update, data_id)
async def abyss_use_by_inline(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE", previous: bool): async def abyss_use_by_inline(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE", previous: bool):
callback_query = update.callback_query callback_query = update.callback_query
@ -584,8 +446,7 @@ class AbyssPlugin(Plugin):
if not client.public: if not client.public:
await client.get_record_cards() await client.get_record_cards()
abyss_data, avatar_data = await self.get_rendered_pic_data(client, client.player_id, previous) abyss_data, avatar_data = await self.get_rendered_pic_data(client, client.player_id, previous)
images = await self.get_rendered_pic(abyss_data, avatar_data, client.player_id, 0, False) image = await self.get_rendered_pic(abyss_data, avatar_data, client.player_id)
image = images[0]
except AbyssUnlocked: # 若深渊未解锁 except AbyssUnlocked: # 若深渊未解锁
notice = "还未解锁深渊哦~" notice = "还未解锁深渊哦~"
except NoMostKills: # 若深渊还未挑战 except NoMostKills: # 若深渊还未挑战

View File

@ -92,7 +92,7 @@
<div class="floor" style="background-image: url('./background/floor1.png');background-color: #374952;"> <div class="floor" style="background-image: url('./background/floor1.png');background-color: #374952;">
<div class="head"> <div class="head">
<div class="floor-name"> <div class="floor-name">
<div class="floor-num"></div> <div class="floor_num"></div>
<div>深境螺旋第一层</div> <div>深境螺旋第一层</div>
</div> </div>
<div class="star"> <div class="star">
@ -306,7 +306,7 @@
<div class="floor" style="background-image: url('./background/floor1.png');background-color: #374952;"> <div class="floor" style="background-image: url('./background/floor1.png');background-color: #374952;">
<div class="head"> <div class="head">
<div class="floor-name"> <div class="floor-name">
<div class="floor-num"> <div class="floor_num">
<div>1</div> <div>1</div>
</div> </div>
<span>深境螺旋第一层</span> <span>深境螺旋第一层</span>

View File

@ -1,33 +1,4 @@
<!DOCTYPE html> <div class="floors">
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>floor</title>
<link type="text/css" href="./style.css" rel="stylesheet"/>
<link type="text/css" href="../../styles/public.css" rel="stylesheet"/>
<style>
body {
margin: 0;
padding: 0;
}
.floors, .floor {
border-radius: unset;
margin: 0;
}
.floor-num > div:last-child {
display: flex;
flex-flow: column;
justify-content: center;
align-content: center;
}
</style>
</head>
<body>
<div class="container">
<div class="floors">
<div <div
class="floor" class="floor"
style=" style="
@ -36,7 +7,7 @@
> >
<div class="head"> <div class="head">
<div class="floor-name"> <div class="floor-name">
<div class="floor-num"></div> <div class="floor_num"></div>
<div> <div>
<div>UID: {{ uid }}</div> <div>UID: {{ uid }}</div>
<div>深境螺旋第 {{ floor.floor }} 层</div> <div>深境螺旋第 {{ floor.floor }} 层</div>
@ -93,7 +64,4 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div>
</body>
</html>

View File

@ -26,8 +26,6 @@
<div class="star"> <div class="star">
<span>{{ stars }}</span> <span>{{ stars }}</span>
</div> </div>
</div>
<div>
<div>时间: {{ time }}</div> <div>时间: {{ time }}</div>
<div>最深抵达: {{ data.max_floor }}</div> <div>最深抵达: {{ data.max_floor }}</div>
</div> </div>
@ -56,18 +54,19 @@
<div> <div>
<div class="caption">战斗数据</div> <div class="caption">战斗数据</div>
<div class="ranks"> <div class="ranks">
<div style="background-color: rgb(61 76 86 / 60%);"></div>
<div style="background-color: rgb(61 76 86 / 60%);"> <div style="background-color: rgb(61 76 86 / 60%);">
<div class="rank">战斗次数: {{ data.total_battles }}</div> <div class="rank">战斗次数: {{ data.total_battles }}</div>
<div class="rank"> <div class="rank">
<span>最多击破:{{ data.ranks.most_kills[0].value }}</span> <span>最多击破:{{ data.ranks.most_kills[0].value }}</span>
<img src="{{ data.ranks.most_kills[0].icon }}" alt=""/> <img src="{{ data.ranks.most_kills[0].icon }}" alt=""/>
</div> </div>
</div>
<div>
<div class="rank"> <div class="rank">
<span>最强一击: {{ data.ranks.strongest_strike[0].value }}</span> <span>最强一击: {{ data.ranks.strongest_strike[0].value }}</span>
<img src="{{ data.ranks.strongest_strike[0].icon }}" alt=""/> <img src="{{ data.ranks.strongest_strike[0].icon }}" alt=""/>
</div> </div>
</div>
<div style="background-color: rgb(61 76 86 / 60%);">
<div class="rank"> <div class="rank">
{% if data.ranks.most_damage_taken is defined and data.ranks.most_damage_taken|length > 0 %} {% if data.ranks.most_damage_taken is defined and data.ranks.most_damage_taken|length > 0 %}
<span>最多承伤: {{ data.ranks.most_damage_taken[0].value }}</span> <span>最多承伤: {{ data.ranks.most_damage_taken[0].value }}</span>
@ -76,8 +75,6 @@
<span>最多承伤: </span> <span>最多承伤: </span>
{% endif %} {% endif %}
</div> </div>
</div>
<div style="background-color: rgb(61 76 86 / 60%);">
<div class="rank"> <div class="rank">
{% if data.ranks.most_bursts_used is defined and data.ranks.most_bursts_used|length > 0 %} {% if data.ranks.most_bursts_used is defined and data.ranks.most_bursts_used|length > 0 %}
<span>元素爆发: {{ data.ranks.most_bursts_used[0].value }}</span> <span>元素爆发: {{ data.ranks.most_bursts_used[0].value }}</span>
@ -95,9 +92,21 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div style="background-color: rgb(61 76 86 / 60%);"></div>
</div> </div>
</div> </div>
</div> </div>
{% for floor in data.floors %}
{% if loop.index % 4 == 1 %}
<div class="floors_row">
{% endif %}
{% set floor_num = floor.floor_num %}
{% set total_stars = floor.total_stars %}
{% include "genshin/abyss/floor.jinja2" %}
{% if loop.index % 4 == 0 or loop.index == loop.length %}
</div>
{% endif %}
{% endfor %}
</div> </div>
</body> </body>
</html> </html>

View File

@ -19,14 +19,13 @@ body {
} }
.container { .container {
width: 750px;
position: relative; position: relative;
filter: drop-shadow(2px 2px 5px rgb(0 0 0 /70%)); filter: drop-shadow(2px 2px 5px rgb(0 0 0 /70%));
} }
.title { .title {
text-align: center; text-align: center;
font-size: 27px; font-size: 30px;
font-weight: bold; font-weight: bold;
color: var(--h-color); color: var(--h-color);
} }
@ -41,7 +40,7 @@ body {
.overview { .overview {
height: 540px; height: 540px;
padding: 20px 40px; padding: 20px 540px;
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
@ -52,9 +51,8 @@ body {
} }
.summarize { .summarize {
font-size: 20px; font-size: 30px;
width: calc(100% - 90px); width: calc(100% - 90px);
height: calc(100px - 20px);
margin: 20px 0; margin: 20px 0;
padding: 10px 0 10px 80px; padding: 10px 0 10px 80px;
border-radius: 5px; border-radius: 5px;
@ -200,6 +198,7 @@ body {
} }
.rank { .rank {
font-size: 30px;
flex: 1; flex: 1;
position: relative; position: relative;
display: flex; display: flex;
@ -251,12 +250,12 @@ body {
color: var(--white); color: var(--white);
} }
.floor-name > div:not(.floor-num) { .floor-name > div:not(.floor_num) {
margin-left: 20px; margin-left: 20px;
text-shadow: 1px 1px 5px rgb(0 0 0/50%); text-shadow: 1px 1px 5px rgb(0 0 0/50%);
} }
.floor-num { .floor_num {
color: black; color: black;
width: 100px; width: 100px;
height: 100px; height: 100px;
@ -355,3 +354,23 @@ body {
font-size: 20px; font-size: 20px;
margin-top: 2px; margin-top: 2px;
} }
.floors_row {
display: flex;
}
.floors {
flex: 1;
}
.floors, .floor {
border-radius: unset;
margin: 0;
}
.floor_num > div:last-child {
display: flex;
flex-flow: column;
justify-content: center;
align-content: center;
}