Puzzles / app.py
PacifistH's picture
Upload 20 files
8de4bc3 verified
Raw
History Blame Contribute Delete
6.29 kB
from flask import Flask, render_template_string
import json
import os
import re
app = Flask(__name__)
# Получаем абсолютный путь к папке, где лежит app.py
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def read_json(filename):
# Строим путь через BASE_DIR
path = os.path.join(BASE_DIR, 'static', 'json', filename)
if os.path.exists(path):
try:
with open(path, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
print(f"Ошибка чтения JSON {filename}: {e}")
return []
return []
def read_txt(filename):
path = os.path.join(BASE_DIR, 'static', 'txt', filename)
if os.path.exists(path):
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
return process_custom_tags(content)
return f"Файл {filename} не найден"
def process_custom_tags(text):
# УБРАЛИ ведущий слэш перед static: 'static/images/...' вместо '/static/images/...'
img_pattern = r'\[IMG:(.*?)\]'
text = re.sub(img_pattern, r'<img src="static/images/\1" class="thumbnail" onclick="window.open(this.src)">', text)
table_pattern = r'\[TABLE:(.*?):(.*?)\]'
def build_table(match):
filename = match.group(1)
columns = match.group(2).split(',')
data = read_json(filename)
if not data: return ""
html = '<table class="data-table"><tbody>'
for row in data:
html += '<tr>'
for col in columns:
val = row.get(col, '')
if col == 'Icon':
# Тоже убрали слэш здесь
content = f'<img src="static/images/{val}" class="unit-icon">'
elif col == 'Order':
content = f'<b style="color:#e67e22">{val}</b>'
else: content = val
html += f'<td>{content}</td>'
html += '</tr>'
html += '</tbody></table>'
return html
return re.sub(table_pattern, build_table, text)
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Game Academy</title>
<style>
body { font-family: -apple-system, sans-serif; background: #f0f2f5; padding: 10px; margin: 0; color: #333; }
.container { max-width: 650px; margin: 0 auto; }
h1 { text-align: center; color: #2c3e50; font-size: 1.5em; margin: 20px 0; }
.section-card { background: white; padding: 15px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); margin-bottom: 12px; }
summary { cursor: pointer; font-weight: bold; color: #1a73e8; font-size: 1.05em; padding: 5px; outline: none; }
details[open] summary { border-bottom: 1px solid #eee; margin-bottom: 12px; padding-bottom: 8px; }
.description { line-height: 1.6; font-size: 0.92em; }
ul { padding-left: 20px; margin: 10px 0; }
li { margin-bottom: 6px; }
.thumbnail { width: 25%; min-width: 120px; cursor: pointer; border: 2px solid #eee; border-radius: 6px; margin: 8px 0; display: block; }
.unit-icon { width: 42px; height: 42px; background: #2c3e50; border-radius: 4px; display: block; margin: 0 auto; }
.data-table { width: 100%; border-collapse: collapse; margin: 12px 0; background: #fff; }
.data-table td { border: 1px solid #eee; padding: 8px; text-align: center; vertical-align: middle; }
.ladder-table { width: 100%; border-collapse: collapse; }
.ladder-table td { padding: 8px; border-bottom: 1px solid #eee; }
</style>
</head>
<body>
<div class="container">
<h1>🛡️ Game Academy</h1>
<div class="section-card"><details open><summary>1.1 Стандартная лестница</summary>
<div class="description">{{ t1_1 | safe }}
<table class="ladder-table">
{% for row in l_json %}
<tr>
<td style="width: 45px;"><img src="static/images/{{ row.Icon }}" class="unit-icon"></td>
<td style="font-weight: bold; padding-left: 12px;">{{ row.TXT }}</td>
</tr>
{% endfor %}
</table></div>
</details></div>
<div class="section-card"><details><summary>1.2 Боевые порядки</summary><div class="description">{{ t1_2 | safe }}</div></details></div>
<div class="section-card"><details><summary>1.3 Формации</summary><div class="description">{{ t1_3 | safe }}</div></details></div>
<div class="section-card"><details><summary>1.4 Механика боя</summary><div class="description">{{ t1_4 | safe }}</div></details></div>
<div class="section-card"><details><summary>1.4.1 Сплоченная атака (СА)</summary><div class="description">{{ t1_4_1 | safe }}</div></details></div>
<div class="section-card"><details><summary>1.4.2 Замок на замок</summary><div class="description">{{ t1_4_2 | safe }}</div></details></div>
<div class="section-card"><details><summary>1.4.3 Саура</summary><div class="description">{{ t1_4_3 | safe }}</div></details></div>
<div class="section-card"><details><summary>1.4.4 Арена, тропы</summary><div class="description">{{ t1_4_4 | safe }}</div></details></div>
</div>
</body>
</html>
"""
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE,
t1_1=read_txt('chapter1_1.txt'), l_json=read_json('ladder.json'),
t1_2=read_txt('chapter1_2.txt'), t1_3=read_txt('chapter1_3.txt'),
t1_4=read_txt('chapter1_4.txt'), t1_4_1=read_txt('chapter1_4_1.txt'),
t1_4_2=read_txt('chapter1_4_2.txt'), t1_4_3=read_txt('chapter1_4_3.txt'),
t1_4_4=read_txt('chapter1_4_4.txt'))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860)