121 lines
5.2 KiB
Python
121 lines
5.2 KiB
Python
# Создано: 2026-04-10
|
||
# Простой калькулятор — возвращает HTML страницу с кнопками.
|
||
# Роутинг: GET → HTML страница; POST с {a, op, b} → вычисление и редирект с результатом.
|
||
# _method приходит от python3.11 рантайма в event.
|
||
|
||
_HTML = """<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Калькулятор (Python)</title>
|
||
<style>
|
||
body { font-family: sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background: #1a1a2e; }
|
||
.calc { background: #16213e; border-radius: 16px; padding: 24px; box-shadow: 0 8px 32px rgba(0,0,0,0.5); width: 280px; }
|
||
h2 { color: #e2e8f0; text-align: center; margin: 0 0 16px; font-size: 18px; }
|
||
.badge { text-align: center; font-size: 11px; color: #64748b; margin-bottom: 16px; }
|
||
.display { background: #0f172a; color: #f1f5f9; font-size: 28px; text-align: right; padding: 12px 16px; border-radius: 8px; margin-bottom: 16px; min-height: 52px; word-break: break-all; }
|
||
.result { color: #22d3ee; font-size: 20px; text-align: right; padding: 4px 16px; margin-bottom: 8px; min-height: 28px; }
|
||
.btns { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
|
||
button { border: none; border-radius: 8px; padding: 16px 0; font-size: 18px; cursor: pointer; transition: filter 0.1s; }
|
||
button:active { filter: brightness(1.3); }
|
||
.btn-num { background: #334155; color: #f1f5f9; }
|
||
.btn-op { background: #0891b2; color: #fff; }
|
||
.btn-eq { background: #0d9488; color: #fff; grid-column: span 2; }
|
||
.btn-clr { background: #7f1d1d; color: #fca5a5; grid-column: span 2; }
|
||
.btn-zero { grid-column: span 2; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="calc">
|
||
<h2>Калькулятор</h2>
|
||
<div class="badge">Python 3.11</div>
|
||
<div id="display" class="display">0</div>
|
||
<div id="result" class="result">{result_line}</div>
|
||
<div class="btns">
|
||
<button class="btn-clr btn-zero" onclick="clr()">C</button>
|
||
<button class="btn-op" onclick="setOp('%2F')">÷</button>
|
||
<button class="btn-op" onclick="setOp('*')">×</button>
|
||
<button class="btn-num" onclick="inp('7')">7</button>
|
||
<button class="btn-num" onclick="inp('8')">8</button>
|
||
<button class="btn-num" onclick="inp('9')">9</button>
|
||
<button class="btn-op" onclick="setOp('-')">−</button>
|
||
<button class="btn-num" onclick="inp('4')">4</button>
|
||
<button class="btn-num" onclick="inp('5')">5</button>
|
||
<button class="btn-num" onclick="inp('6')">6</button>
|
||
<button class="btn-op" onclick="setOp('+')">+</button>
|
||
<button class="btn-num" onclick="inp('1')">1</button>
|
||
<button class="btn-num" onclick="inp('2')">2</button>
|
||
<button class="btn-num" onclick="inp('3')">3</button>
|
||
<button class="btn-num btn-zero" onclick="inp('0')">0</button>
|
||
<button class="btn-num" onclick="inp('.')">.</button>
|
||
<button class="btn-eq" onclick="calc()">=</button>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
let a = '', op = '', b = '', fresh = {fresh_js};
|
||
const disp = document.getElementById('display');
|
||
function inp(v) {{
|
||
if (op === '') {{ a += v; disp.textContent = a || '0'; }}
|
||
else {{ b += v; disp.textContent = b || '0'; }}
|
||
fresh = false;
|
||
}}
|
||
function setOp(o) {{
|
||
if (a === '') return;
|
||
if (b !== '') calc();
|
||
else {{ op = o; disp.textContent = a + ' ' + decodeURIComponent(o) + ' …'; }}
|
||
fresh = false;
|
||
}}
|
||
function clr() {{ a = ''; op = ''; b = ''; disp.textContent = '0'; }}
|
||
function calc() {{
|
||
if (a === '' || op === '' || b === '') return;
|
||
const form = document.createElement('form');
|
||
form.method = 'POST'; form.action = '';
|
||
const fields = {{a, op, b}};
|
||
for (const [k, v] of Object.entries(fields)) {{
|
||
const i = document.createElement('input');
|
||
i.type = 'hidden'; i.name = k; i.value = decodeURIComponent(v);
|
||
form.appendChild(i);
|
||
}}
|
||
document.body.appendChild(form);
|
||
form.submit();
|
||
}}
|
||
</script>
|
||
</body>
|
||
</html>"""
|
||
|
||
def handler(event):
|
||
# POST: тело приходит как JSON от рантайма
|
||
if event.get('_method') == 'POST':
|
||
return _compute(event)
|
||
# GET: показываем чистую страницу
|
||
return _html()
|
||
|
||
|
||
def _html(result_line='', fresh_js='true'):
|
||
return _HTML.replace('{result_line}', result_line).replace('{fresh_js}', fresh_js)
|
||
|
||
|
||
def _compute(event):
|
||
try:
|
||
a = float(event.get('a', 0))
|
||
b = float(event.get('b', 0))
|
||
op = event.get('op', '')
|
||
if op == '+':
|
||
res = a + b
|
||
elif op == '-':
|
||
res = a - b
|
||
elif op == '*':
|
||
res = a * b
|
||
elif op == '/':
|
||
if b == 0:
|
||
return _html('Деление на ноль', 'false')
|
||
res = a / b
|
||
else:
|
||
return _html('Неизвестный оператор', 'false')
|
||
# Убираем лишний .0 для целых результатов
|
||
res_str = str(int(res)) if res == int(res) else str(res)
|
||
return _html(f'{int(a) if a == int(a) else a} {op} {int(b) if b == int(b) else b} = {res_str}', 'false')
|
||
except (ValueError, TypeError) as exc:
|
||
return _html(f'Ошибка: {exc}', 'false')
|