This commit is contained in:
2025-12-15 09:08:49 +05:00
parent dab7ef852b
commit 86a9d2bad9
5 changed files with 1159 additions and 42 deletions

View File

@@ -1,6 +1,6 @@
import flet as ft
import designer as ds
from pages.tabs import start1,calculater2, binary_data3, binary_calculeator4, octogon_data5, octogon_calculeator6, sedecim_data7,sedecim_calculeator8, pentecostal_system9, pentecostal_calculeator10, arbitrary_calculator11
from pages.tabs import roman_converter13, roman_calculator12, start1,calculater2, binary_data3, binary_calculeator4, octogon_data5, octogon_calculeator6, sedecim_data7,sedecim_calculeator8, pentecostal_system9, pentecostal_calculeator10, arbitrary_calculator11
class Main_page(ft.View):
def __init__(self, page):
@@ -15,6 +15,7 @@ class Main_page(ft.View):
horizontal_alignment=ft.CrossAxisAlignment.START,
width=300,
alignment=ft.MainAxisAlignment.START,
scroll="auto",
controls=[
start1.Button_text_data(),
calculater2.Button_calculeator(),
@@ -27,8 +28,10 @@ class Main_page(ft.View):
pentecostal_system9.Button_binary_data(),
pentecostal_calculeator10.Button_quinquagesimal_calculator(),
arbitrary_calculator11.Button_arbitrary_calculator(),
roman_calculator12.Button_roman_calculator(),
roman_converter13.RomanConverter(),
ft.Container(
bgcolor="#280A3F",
bgcolor="#221929",
expand=True,
)
]

View File

@@ -47,11 +47,12 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
self.steps_mult = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5)
self.steps_div = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5)
# Стандартный набор цифр для систем до 36
self.digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# Стандартный набор цифр для систем до 50
# 0-9 (10 цифр) + A-Z (26 букв) + a-n (14 букв) = 50 символов
self.digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"
super().__init__(
bgcolor="#00000000",
bgcolor="#211D1D00",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
@@ -112,7 +113,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
ft.Container(ft.Text("Вес (база^поз)", weight=ft.FontWeight.BOLD, size=12), width=120, alignment=ft.alignment.center),
ft.Container(ft.Text("Вклад", weight=ft.FontWeight.BOLD, size=12), width=150, alignment=ft.alignment.center),
])
rows.append(ft.Container(content=header, bgcolor="#E3F2FD", padding=5, border_radius=5))
rows.append(ft.Container(content=header, bgcolor="#71838C", padding=5, border_radius=5))
total_sum = 0
calculation_parts = []
@@ -125,20 +126,20 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
total_sum += contribution
row = ft.Row([
ft.Container(ft.Text(str(i), size=12), width=80, alignment=ft.alignment.center),
ft.Container(ft.Text(str(i),color="#FF0000", size=12), width=80, alignment=ft.alignment.center),
ft.Container(ft.Text(digit, size=14, weight=ft.FontWeight.BOLD, color="#1565C0"), width=70, alignment=ft.alignment.center),
ft.Container(ft.Text(str(digit_value), size=12), width=80, alignment=ft.alignment.center),
ft.Container(ft.Text(f"{base}^{i} = {power}", size=11), width=120, alignment=ft.alignment.center),
ft.Container(ft.Text(str(digit_value),color="#FF0000", size=12), width=80, alignment=ft.alignment.center),
ft.Container(ft.Text(f"{base}^{i} = {power}",color="#FF0000", size=11), width=120, alignment=ft.alignment.center),
ft.Container(ft.Text(f"{digit_value} × {power} = {contribution}", size=11, color="#2E7D32"), width=150, alignment=ft.alignment.center),
])
rows.append(ft.Container(content=row, bgcolor="#F5F5F5" if i % 2 == 0 else "white", padding=5))
rows.append(ft.Container(content=row, bgcolor="#2E2727" if i % 2 == 0 else "white", padding=5))
calculation_parts.append(str(contribution))
# Итоговая сумма
sum_text = " + ".join(calculation_parts) + f" = {total_sum}"
rows.append(ft.Container(
content=ft.Text(f"СУММА: {sum_text}", size=13, weight=ft.FontWeight.BOLD, color="#1976D2"),
bgcolor="#E8F5E9",
bgcolor="#2B2F2B",
padding=10,
border_radius=5
))
@@ -148,7 +149,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
def create_division_steps(self, decimal_num: int, target_base: int) -> ft.Column:
"""Создаёт подробную визуализацию деления с остатком"""
if decimal_num == 0:
return ft.Column([ft.Text("0 уже в любой системе = 0", size=14, color="#757575")])
return ft.Column([ft.Text("0 уже в любой системе = 0", size=14, color="#1A1717")])
is_negative = decimal_num < 0
decimal_num = abs(decimal_num)
@@ -166,11 +167,11 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
step_row = ft.Row([
ft.Container(
ft.Text(f"Шаг {step_num}", size=11, weight=ft.FontWeight.BOLD),
ft.Text(f"Шаг {step_num}", size=11,color="#FF6F00", weight=ft.FontWeight.BOLD),
width=70
),
ft.Container(
ft.Text(f"{temp} ÷ {target_base} = {quotient}", size=12),
ft.Text(f"{temp} ÷ {target_base} = {quotient}",color="#FF6F00", size=12),
width=150
),
ft.Container(
@@ -182,7 +183,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
width=120
),
])
steps.append(ft.Container(content=step_row, bgcolor="#F5F5F5" if step_num % 2 == 0 else "white", padding=5))
steps.append(ft.Container(content=step_row, bgcolor="#2E2B2B" if step_num % 2 == 0 else "white", padding=5))
temp = quotient
step_num += 1
@@ -190,13 +191,13 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
# Визуализация сборки числа
result = ''.join(remainders)
assembly = ft.Column([
ft.Divider(height=1, color="#E0E0E0"),
ft.Divider(height=1, color="#0B0909"),
ft.Text("📌 Собираем остатки СНИЗУ ВВЕРХ:", size=13, weight=ft.FontWeight.BOLD, color="#1976D2"),
ft.Row([
ft.Text("", size=20, color="#4CAF50"),
*[ft.Container(
ft.Text(digit, size=16, weight=ft.FontWeight.BOLD),
bgcolor="#E3F2FD",
bgcolor="#94BBCF",
padding=8,
border_radius=5
) for digit in remainders]
@@ -204,7 +205,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
ft.Container(
ft.Text(f"Результат: {('-' if is_negative else '')}{result}{target_base}",
size=15, weight=ft.FontWeight.BOLD, color="#2E7D32"),
bgcolor="#E8F5E9",
bgcolor="#0F110F",
padding=10,
border_radius=5
)
@@ -322,7 +323,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
f"мы используем метод 'переводчика' - переведём всё в десятичную,\n"
f"выполним операцию и переведём результат обратно.",
size=13,
color="#E0E0E0"
color="#B27171"
),
], spacing=10)
steps_container.controls.append(self.create_step_card("ШАГ 1", "Условие задачи", step1_content))
@@ -333,14 +334,14 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
step2_content = ft.Column([
ft.Text(f"🔄 ПЕРЕВОД ПЕРВОГО ЧИСЛА: {num1}{base1}₎ → десятичная",
size=18, weight=ft.FontWeight.BOLD, color="#00FFFF"),
ft.Divider(height=1, color="#E0E0E0"),
ft.Divider(height=1, color="#000000"),
ft.Text(
f"Каждая позиция в {base1}-ричной системе имеет свой 'вес' - степень числа {base1}.\n"
f"Самая правая позиция (позиция 0) весит {base1}^0 = 1\n"
f"Следующая (позиция 1) весит {base1}^1 = {base1}\n"
f"Потом (позиция 2) весит {base1}^2 = {base1*base1}, и так далее.",
size=12,
color="#616161"
color="#9E7979"
),
ft.Container(height=10),
self.create_detailed_conversion_table(num1, base1, dec1),
@@ -365,12 +366,12 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
step3_content = ft.Column([
ft.Text(f"🔄 ПЕРЕВОД ВТОРОГО ЧИСЛА: {num2}{base2}₎ → десятичная",
size=18, weight=ft.FontWeight.BOLD, color="#00FFFF"),
ft.Divider(height=1, color="#E0E0E0"),
ft.Divider(height=1, color="#000000"),
ft.Text(
f"Аналогично переводим второе число из {base2}-ричной системы.\n"
f"В {base2}-ричной системе веса позиций: 1, {base2}, {base2*base2}, {base2*base2*base2}...",
size=12,
color="#616161"
color="#CB8686"
),
ft.Container(height=10),
self.create_detailed_conversion_table(num2, base2, dec2),
@@ -414,14 +415,14 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
step4_content = ft.Column([
ft.Text(f"🧮 ВЫПОЛНЕНИЕ ОПЕРАЦИИ: {op_name.upper()}",
size=18, weight=ft.FontWeight.BOLD, color="#FFD700"),
ft.Divider(height=1, color="#E0E0E0"),
ft.Divider(height=1, color="#1D1919"),
ft.Text(
f"Теперь у нас есть оба числа в десятичной системе:\n"
f"• Первое число: {dec1}\n"
f"• Второе число: {dec2}\n\n"
f"Можем выполнить {op_name} обычным способом!",
size=13,
color="#616161"
color="#C9A5A5"
),
ft.Container(
content=ft.Text(calc_text, size=22, weight=ft.FontWeight.BOLD, color="white"),
@@ -432,7 +433,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
),
ft.Container(
content=ft.Text(explanation, size=12, italic=True),
bgcolor="#FFF3E0",
bgcolor="#282724",
padding=15,
border_radius=8
)
@@ -448,7 +449,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
step5_content = ft.Column([
ft.Text(f"🔢 ПЕРЕВОД РЕЗУЛЬТАТА: {result_dec}₍₁₀₎ → {result_base}-ричная",
size=18, weight=ft.FontWeight.BOLD, color="#00FFFF"),
ft.Divider(height=1, color="#E0E0E0"),
ft.Divider(height=1, color="#7A5555"),
ft.Text(
f"Последний шаг - переводим результат {result_dec} в {result_base}-ричную систему.\n"
f"Используем алгоритм деления с остатком:\n"
@@ -457,7 +458,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
f"• Продолжаем с частным, пока оно не станет равно 0\n"
f"• Читаем остатки СНИЗУ ВВЕРХ",
size=12,
color="#616161"
color="#FAE1E1"
),
ft.Container(height=10),
self.create_division_steps(result_dec, result_base),
@@ -502,7 +503,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
border_radius=15,
alignment=ft.alignment.center
),
ft.Divider(height=1, color="#E0E0E0"),
ft.Divider(height=1, color="#231D1D"),
ft.Text("📊 ПРОВЕРКА РЕШЕНИЯ:", size=16, weight=ft.FontWeight.BOLD, color="#E0E0E0"),
ft.Container(
content=ft.Column([
@@ -511,7 +512,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
ft.Text(f"3. Операция: {dec1} {op_symbol} {dec2} = {result_dec}₍₁₀₎ ✓", size=13),
ft.Text(f"4. Результат: {result_dec}₍₁₀₎ = {result_str}{result_base}₎ ✓", size=13),
]),
bgcolor="#F5F5F5",
bgcolor="#1F1919",
padding=15,
border_radius=8
),
@@ -597,7 +598,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
def create_base_selector(self, label: str, default_value: str = "10") -> ft.Dropdown:
"""Создаёт выпадающий список для выбора системы счисления с подсказкой"""
bases = [str(i) for i in range(2, 37)] # От 2 до 36
bases = [str(i) for i in range(2, 51)] # От 2 до 50
return ft.Dropdown(
label=label,
value=default_value,
@@ -702,9 +703,10 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
ft.Text(
"В 5-ричной системе используются цифры: 0, 1, 2, 3, 4\n"
"В 18-ричной системе: 0-9, A-H (где A=10, B=11, ..., H=17)\n"
"Результат можно получить в любой системе от 2 до 36",
"В 50-ричной: 0-9, A-Z, a-n (всего 50 символов!)\n"
"• Результат можно получить в любой системе от 2 до 50",
size=12,
color="#424242"
color="#281B1B"
)
]),
bgcolor="#E3F2FD",
@@ -721,7 +723,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
"• Числа могут быть в разных системах счисления\n"
"• Если результат отрицательный, появится знак минус",
size=12,
color="#424242"
color="#1F1C1C"
)
]),
bgcolor="#FFF3E0",
@@ -738,7 +740,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
"В шестнадцатеричной: 0-9, A-F (где F=15)\n"
"• Попробуйте A₍₁₆₎ × 12₍₈₎ (это 10 × 10 в десятичной)",
size=12,
color="#424242"
color="#292424"
)
]),
bgcolor="#E3F2FD",
@@ -792,7 +794,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
ft.Divider(),
ft.Container(
content=ft.Row([
ft.Text("📊 Результат:", size=18, weight=ft.FontWeight.BOLD),
ft.Text("📊 Результат:",color="#3C2525", size=18, weight=ft.FontWeight.BOLD),
self.result_add
]),
bgcolor="#F5F5F5",
@@ -833,7 +835,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
ft.Divider(),
ft.Container(
content=ft.Row([
ft.Text("📊 Результат:", size=18, weight=ft.FontWeight.BOLD),
ft.Text("📊 Результат:",color="#452020", size=18, weight=ft.FontWeight.BOLD),
self.result_sub
]),
bgcolor="#F5F5F5",
@@ -874,7 +876,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
ft.Divider(),
ft.Container(
content=ft.Row([
ft.Text("📊 Результат:", size=18, weight=ft.FontWeight.BOLD),
ft.Text("📊 Результат:",color="#422525", size=18, weight=ft.FontWeight.BOLD),
self.result_mult
]),
bgcolor="#F5F5F5",
@@ -964,7 +966,7 @@ class Button_arbitrary_calculator(ft.CupertinoButton):
text_align=ft.TextAlign.CENTER
),
ft.Text(
"Выполняйте операции с числами в системах от 2 до 36 с подробными объяснениями!",
"Выполняйте операции с числами в системах от 2 до 50 с подробными объяснениями!",
size=14,
color="white",
text_align=ft.TextAlign.CENTER,

View File

@@ -0,0 +1,754 @@
from designer import right_column, StepByStepDisplay
import flet as ft
import sys
import os
# Добавляем путь к модулю step_by_step_solver
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from step_by_step_solver import StepByStepSolver, Operation
class Button_roman_calculator(ft.CupertinoButton):
def __init__(self, text: str = "Римский калькулятор"):
self.result_left = ft.Text(value="", size=30, width=300)
self.result_right = ft.Text(value="", size=30, width=300)
self.result_mult = ft.Text(value="", size=30, width=300)
self.result_div = ft.Text(value="", size=30, width=300)
self.decimal_left = ft.Text(value="", size=14, color="#B0B0B0", width=300)
self.decimal_right = ft.Text(value="", size=14, color="#B0B0B0", width=300)
self.decimal_mult = ft.Text(value="", size=14, color="#B0B0B0", width=300)
self.decimal_div = ft.Text(value="", size=14, color="#B0B0B0", width=300)
# Поля ввода для вычитания
self.input_left_1 = None
self.input_left_2 = None
# Поля ввода для сложения
self.input_right_1 = None
self.input_right_2 = None
# Поля ввода для умножения
self.input_mult_1 = None
self.input_mult_2 = None
# Поля ввода для деления
self.input_div_1 = None
self.input_div_2 = None
# Контейнеры для пошагового решения
self.steps_left = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5)
self.steps_right = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5)
self.steps_mult = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5)
self.steps_div = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5)
# Римские числа от 1 до 3999
self.roman_map = [
(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
(100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
(10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')
]
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def validate_roman(self, value: str) -> bool:
"""Проверяет, является ли строка корректным римским числом."""
if value is None:
return True
v = value.strip().upper()
if v == "":
return True
# Проверяем, что строка содержит только римские цифры
return all(c in 'IVXLCDM' for c in v)
def roman_to_int(self, roman: str) -> int:
"""Преобразует римское число в десятичное."""
roman = roman.strip().upper()
if not roman:
return 0
roman_values = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
result = 0
prev_value = 0
for char in reversed(roman):
if char not in roman_values:
raise ValueError(f"Неверный символ '{char}' в римском числе")
value = roman_values[char]
if value < prev_value:
result -= value
else:
result += value
prev_value = value
return result
def int_to_roman(self, num: int) -> str:
"""Преобразует десятичное число в римское."""
if num <= 0:
return "Нет" # Римские числа не поддерживают 0 и отрицательные числа
if num >= 4000:
return "Превышает 3999"
result = []
for value, numeral in self.roman_map:
count = num // value
if count:
result.append(numeral * count)
num -= value * count
return ''.join(result)
def get_steps_text(self, roman: str) -> str:
"""Создает текстовое описание разбора римского числа."""
roman = roman.strip().upper()
if not roman:
return ""
roman_values = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
steps = []
result = 0
prev_value = 0
for i, char in enumerate(reversed(roman)):
value = roman_values[char]
if value < prev_value:
steps.append(f"{char} = {value} (вычитаем, т.к. меньше следующего)")
result -= value
else:
steps.append(f"{char} = {value} (добавляем)")
result += value
prev_value = value
return "\n".join(reversed(steps)) + f"\n\nИтого: {result}"
def calculate_subtraction(self, e):
try:
val1 = (self.input_left_1.value or "").strip().upper()
val2 = (self.input_left_2.value or "").strip().upper()
# Проверка корректности римских чисел
if not self.validate_roman(val1) or not self.validate_roman(val2):
self.result_left.value = "Ошибка: неверный формат"
self.decimal_left.value = ""
self.result_left.update()
self.decimal_left.update()
return
# Преобразуем в десятичные числа
num1 = self.roman_to_int(val1) if val1 else 0
num2 = self.roman_to_int(val2) if val2 else 0
# Вычисляем результат
result = num1 - num2
# Преобразуем обратно в римское число
roman_result = self.int_to_roman(result)
self.result_left.value = roman_result
self.decimal_left.value = f"({result}₁₀)" if result > 0 else f"({result}₁₀, не представимо)"
self.result_left.update()
self.decimal_left.update()
# Показываем пошаговое решение
self.show_steps_left_custom(val1, val2, num1, num2, result, "Вычитание")
except ValueError as ex:
self.result_left.value = "Ошибка"
self.decimal_left.value = str(ex)
self.result_left.update()
self.decimal_left.update()
def calculate_addition(self, e):
try:
val1 = (self.input_right_1.value or "").strip().upper()
val2 = (self.input_right_2.value or "").strip().upper()
# Проверка корректности римских чисел
if not self.validate_roman(val1) or not self.validate_roman(val2):
self.result_right.value = "Ошибка: неверный формат"
self.decimal_right.value = ""
self.result_right.update()
self.decimal_right.update()
return
num1 = self.roman_to_int(val1) if val1 else 0
num2 = self.roman_to_int(val2) if val2 else 0
# Вычисляем результат
result = num1 + num2
# Преобразуем обратно в римское число
roman_result = self.int_to_roman(result)
self.result_right.value = roman_result
self.decimal_right.value = f"({result}₁₀)" if result <= 3999 else f"({result}₁₀, превышает 3999)"
self.result_right.update()
self.decimal_right.update()
# Показываем пошаговое решение
self.show_steps_right_custom(val1, val2, num1, num2, result, "Сложение")
except ValueError as ex:
self.result_right.value = "Ошибка"
self.decimal_right.value = str(ex)
self.result_right.update()
self.decimal_right.update()
def calculate_multiplication(self, e):
try:
val1 = (self.input_mult_1.value or "").strip().upper()
val2 = (self.input_mult_2.value or "").strip().upper()
if not self.validate_roman(val1) or not self.validate_roman(val2):
self.result_mult.value = "Ошибка: неверный формат"
self.decimal_mult.value = ""
self.result_mult.update()
self.decimal_mult.update()
return
num1 = self.roman_to_int(val1) if val1 else 0
num2 = self.roman_to_int(val2) if val2 else 0
result = num1 * num2
roman_result = self.int_to_roman(result)
self.result_mult.value = roman_result
self.decimal_mult.value = f"({result}₁₀)" if result <= 3999 else f"({result}₁₀, превышает 3999)"
self.result_mult.update()
self.decimal_mult.update()
self.show_steps_mult_custom(val1, val2, num1, num2, result, "Умножение")
except ValueError as ex:
self.result_mult.value = "Ошибка"
self.decimal_mult.value = str(ex)
self.result_mult.update()
self.decimal_mult.update()
def calculate_division(self, e):
try:
val1 = (self.input_div_1.value or "").strip().upper()
val2 = (self.input_div_2.value or "").strip().upper()
if not self.validate_roman(val1) or not self.validate_roman(val2):
self.result_div.value = "Ошибка: неверный формат"
self.decimal_div.value = ""
self.result_div.update()
self.decimal_div.update()
return
num1 = self.roman_to_int(val1) if val1 else 0
num2 = self.roman_to_int(val2) if val2 else 0
if num2 == 0:
self.result_div.value = "Деление на 0!"
self.decimal_div.value = ""
self.result_div.update()
self.decimal_div.update()
return
quotient = num1 // num2
remainder = num1 % num2
roman_quotient = self.int_to_roman(quotient)
if remainder == 0:
self.result_div.value = roman_quotient
self.decimal_div.value = f"({quotient}₁₀)"
else:
roman_remainder = self.int_to_roman(remainder) if remainder <= 3999 else str(remainder)
self.result_div.value = roman_quotient
self.decimal_div.value = f"({quotient}₁₀, ост. {remainder}₁₀ = {roman_remainder})"
self.result_div.update()
self.decimal_div.update()
self.show_steps_div_custom(val1, val2, num1, num2, quotient, remainder, "Деление")
except ValueError as ex:
self.result_div.value = "Ошибка"
self.decimal_div.value = str(ex)
self.result_div.update()
self.decimal_div.update()
def show_steps_left_custom(self, val1: str, val2: str, num1: int, num2: int, result: int, operation: str):
"""Отображает пошаговое решение для вычитания"""
self.steps_left.controls.clear()
self.steps_left.controls.append(
ft.Text("📝 Ход решения:", size=14, weight=ft.FontWeight.BOLD, color="#FFD700")
)
# Шаг 1: Преобразование первого числа
step1_content = []
step1_content.append(ft.Text(f"Шаг 1: Преобразование {val1} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step1_content.append(ft.Text(self.get_steps_text(val1), size=10, font_family="Courier New", color="#90EE90"))
self.steps_left.controls.append(
ft.Container(
content=ft.Column(step1_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 2: Преобразование второго числа
step2_content = []
step2_content.append(ft.Text(f"Шаг 2: Преобразование {val2} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step2_content.append(ft.Text(self.get_steps_text(val2), size=10, font_family="Courier New", color="#90EE90"))
self.steps_left.controls.append(
ft.Container(
content=ft.Column(step2_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 3: Вычитание в десятичной системе
step3_content = []
step3_content.append(ft.Text(f"Шаг 3: {operation} в десятичной системе", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step3_content.append(ft.Text(f"{num1} - {num2} = {result}", size=10, color="#E0E0E0"))
self.steps_left.controls.append(
ft.Container(
content=ft.Column(step3_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 4: Преобразование результата обратно в римское
step4_content = []
step4_content.append(ft.Text(f"Шаг 4: Преобразование {result} в римское число", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
roman_result = self.int_to_roman(result)
step4_content.append(ft.Text(f"Результат: {roman_result}", size=11, weight=ft.FontWeight.BOLD, color="#00FF00"))
self.steps_left.controls.append(
ft.Container(
content=ft.Column(step4_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
self.steps_left.update()
def show_steps_right_custom(self, val1: str, val2: str, num1: int, num2: int, result: int, operation: str):
"""Отображает пошаговое решение для сложения"""
self.steps_right.controls.clear()
self.steps_right.controls.append(
ft.Text("📝 Ход решения:", size=14, weight=ft.FontWeight.BOLD, color="#FFD700")
)
# Шаг 1: Преобразование первого числа
step1_content = []
step1_content.append(ft.Text(f"Шаг 1: Преобразование {val1} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step1_content.append(ft.Text(self.get_steps_text(val1), size=10, font_family="Courier New", color="#90EE90"))
self.steps_right.controls.append(
ft.Container(
content=ft.Column(step1_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 2: Преобразование второго числа
step2_content = []
step2_content.append(ft.Text(f"Шаг 2: Преобразование {val2} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step2_content.append(ft.Text(self.get_steps_text(val2), size=10, font_family="Courier New", color="#90EE90"))
self.steps_right.controls.append(
ft.Container(
content=ft.Column(step2_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 3: Сложение в десятичной системе
step3_content = []
step3_content.append(ft.Text(f"Шаг 3: {operation} в десятичной системе", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step3_content.append(ft.Text(f"{num1} + {num2} = {result}", size=10, color="#E0E0E0"))
self.steps_right.controls.append(
ft.Container(
content=ft.Column(step3_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 4: Преобразование результата обратно в римское
step4_content = []
step4_content.append(ft.Text(f"Шаг 4: Преобразование {result} в римское число", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
roman_result = self.int_to_roman(result)
step4_content.append(ft.Text(f"Результат: {roman_result}", size=11, weight=ft.FontWeight.BOLD, color="#00FF00"))
self.steps_right.controls.append(
ft.Container(
content=ft.Column(step4_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
self.steps_right.update()
def show_steps_mult_custom(self, val1: str, val2: str, num1: int, num2: int, result: int, operation: str):
"""Отображает пошаговое решение для умножения"""
self.steps_mult.controls.clear()
self.steps_mult.controls.append(
ft.Text("📝 Ход решения:", size=14, weight=ft.FontWeight.BOLD, color="#FFD700")
)
# Шаг 1: Преобразование первого числа
step1_content = []
step1_content.append(ft.Text(f"Шаг 1: Преобразование {val1} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step1_content.append(ft.Text(self.get_steps_text(val1), size=10, font_family="Courier New", color="#90EE90"))
self.steps_mult.controls.append(
ft.Container(
content=ft.Column(step1_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 2: Преобразование второго числа
step2_content = []
step2_content.append(ft.Text(f"Шаг 2: Преобразование {val2} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step2_content.append(ft.Text(self.get_steps_text(val2), size=10, font_family="Courier New", color="#90EE90"))
self.steps_mult.controls.append(
ft.Container(
content=ft.Column(step2_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 3: Умножение в десятичной системе
step3_content = []
step3_content.append(ft.Text(f"Шаг 3: {operation} в десятичной системе", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step3_content.append(ft.Text(f"{num1} × {num2} = {result}", size=10, color="#E0E0E0"))
self.steps_mult.controls.append(
ft.Container(
content=ft.Column(step3_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 4: Преобразование результата обратно в римское
step4_content = []
step4_content.append(ft.Text(f"Шаг 4: Преобразование {result} в римское число", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
roman_result = self.int_to_roman(result)
step4_content.append(ft.Text(f"Результат: {roman_result}", size=11, weight=ft.FontWeight.BOLD, color="#00FF00"))
self.steps_mult.controls.append(
ft.Container(
content=ft.Column(step4_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
self.steps_mult.update()
def show_steps_div_custom(self, val1: str, val2: str, num1: int, num2: int, quotient: int, remainder: int, operation: str):
"""Отображает пошаговое решение для деления"""
self.steps_div.controls.clear()
self.steps_div.controls.append(
ft.Text("📝 Ход решения:", size=14, weight=ft.FontWeight.BOLD, color="#FFD700")
)
# Шаг 1: Преобразование первого числа
step1_content = []
step1_content.append(ft.Text(f"Шаг 1: Преобразование {val1} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step1_content.append(ft.Text(self.get_steps_text(val1), size=10, font_family="Courier New", color="#90EE90"))
self.steps_div.controls.append(
ft.Container(
content=ft.Column(step1_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 2: Преобразование второго числа
step2_content = []
step2_content.append(ft.Text(f"Шаг 2: Преобразование {val2} в десятичное", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
step2_content.append(ft.Text(self.get_steps_text(val2), size=10, font_family="Courier New", color="#90EE90"))
self.steps_div.controls.append(
ft.Container(
content=ft.Column(step2_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 3: Деление в десятичной системе
step3_content = []
step3_content.append(ft.Text(f"Шаг 3: {operation} в десятичной системе", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
if remainder == 0:
step3_content.append(ft.Text(f"{num1} ÷ {num2} = {quotient}", size=10, color="#E0E0E0"))
else:
step3_content.append(ft.Text(f"{num1} ÷ {num2} = {quotient} (остаток {remainder})", size=10, color="#E0E0E0"))
self.steps_div.controls.append(
ft.Container(
content=ft.Column(step3_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
# Шаг 4: Преобразование результата обратно в римское
step4_content = []
step4_content.append(ft.Text(f"Шаг 4: Преобразование {quotient} в римское число", size=12, weight=ft.FontWeight.BOLD, color="#00FFFF"))
roman_quotient = self.int_to_roman(quotient)
if remainder == 0:
step4_content.append(ft.Text(f"Результат: {roman_quotient}", size=11, weight=ft.FontWeight.BOLD, color="#00FF00"))
else:
roman_remainder = self.int_to_roman(remainder) if remainder <= 3999 else str(remainder)
step4_content.append(ft.Text(f"Результат: {roman_quotient} (остаток {remainder}₁₀ = {roman_remainder})", size=11, weight=ft.FontWeight.BOLD, color="#00FF00"))
self.steps_div.controls.append(
ft.Container(
content=ft.Column(step4_content, spacing=3),
bgcolor="#2A1A3A",
padding=8,
border_radius=5,
border=ft.border.all(1, "#4A3A5A")
)
)
self.steps_div.update()
def test_data(self, e):
# Создаем поля ввода с валидацией для римских чисел
self.input_left_1 = ft.TextField(
label="Римское число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: X (10) или MCMXC (1990)"
)
self.input_left_2 = ft.TextField(
label="Римское число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: V (5)"
)
self.input_right_1 = ft.TextField(
label="Римское число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: XII (12)"
)
self.input_right_2 = ft.TextField(
label="Римское число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: VIII (8)"
)
self.input_mult_1 = ft.TextField(
label="Римское число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: X (10)"
)
self.input_mult_2 = ft.TextField(
label="Римское число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: III (3)"
)
self.input_div_1 = ft.TextField(
label="Римское число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: C (100)"
)
self.input_div_2 = ft.TextField(
label="Римское число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$"),
hint_text="Например: X (10)"
)
right_column.controls = [ft.Container(
bgcolor="#55257D",
padding=ft.padding.all(10),
border_radius=10,
expand=True,
content=ft.Column(
scroll=ft.ScrollMode.AUTO,
expand=True,
controls=[
ft.Text("Римский калькулятор", size=20, color="white", weight=ft.FontWeight.BOLD),
ft.Text("Вводите числа римскими цифрами (I, V, X, L, C, D, M). Диапазон: 1-3999.", size=11, color="#B0B0B0", italic=True),
ft.Text(f"Пример: XII = 12₁₀, MCMXC = 1990₁₀. Регистр не важен.", size=11, color="#B0B0B0"),
ft.Row(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
vertical_alignment=ft.CrossAxisAlignment.START,
controls=[
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.START,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.input_left_1,
ft.Text("——— Вычитание", size=12, color="white"),
self.input_left_2,
ft.Container(
content=ft.Column([
self.result_left,
self.decimal_left
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_subtraction),
ft.Container(
expand=True,
content=self.steps_left,
bgcolor="#1A0A2A",
padding=10,
border_radius=5,
)
]
),
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.START,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.input_right_1,
ft.Text("—|— Сложение", size=12, color="white"),
self.input_right_2,
ft.Container(
content=ft.Column([
self.result_right,
self.decimal_right
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_addition),
ft.Container(
expand=True,
content=self.steps_right,
bgcolor="#1A0A2A",
padding=10,
border_radius=5,
)
]
),
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.START,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.input_mult_1,
ft.Text("× Умножение", size=12, color="white"),
self.input_mult_2,
ft.Container(
content=ft.Column([
self.result_mult,
self.decimal_mult
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_multiplication),
ft.Container(
expand=True,
content=self.steps_mult,
bgcolor="#1A0A2A",
padding=10,
border_radius=5,
)
]
),
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.START,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.input_div_1,
ft.Text("÷ Деление", size=12, color="white"),
self.input_div_2,
ft.Container(
content=ft.Column([
self.result_div,
self.decimal_div
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_division),
ft.Container(
expand=True,
content=self.steps_div,
bgcolor="#1A0A2A",
padding=10,
border_radius=5,
)
]
)
]
)
],
)
)]
e.page.update()

View File

@@ -0,0 +1,358 @@
from designer import right_column, StepByStepDisplay
import flet as ft
import sys
import os
# Добавляем путь к модулю step_by_step_solver
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class RomanConverter(ft.CupertinoButton):
def __init__(self, text: str = "Римские числа - конвертер"):
self.result_to_roman = ft.Text(value="I", size=30, width=300)
self.result_from_roman = ft.Text(value="1", size=30, width=300)
# Поля ввода
self.input_decimal = None
self.input_roman = None
# Контейнеры для пошагового решения
self.steps_to_roman = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5, expand=True)
self.steps_from_roman = ft.Column(scroll=ft.ScrollMode.AUTO, spacing=5, expand=True)
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def decimal_to_roman(self, num):
"""Преобразует десятичное число в римское (1-3999)"""
if num <= 0 or num > 3999:
return None
val = [
1000, 900, 500, 400,
100, 90, 50, 40,
10, 9, 5, 4,
1
]
syms = [
"M", "CM", "D", "CD",
"C", "XC", "L", "XL",
"X", "IX", "V", "IV",
"I"
]
roman_num = ''
i = 0
while num > 0:
for _ in range(num // val[i]):
roman_num += syms[i]
num -= val[i]
i += 1
return roman_num
def decimal_to_roman_with_steps(self, num):
"""Преобразует десятичное число в римское с пошаговым объяснением"""
if num <= 0 or num > 3999:
return None, []
val = [
1000, 900, 500, 400,
100, 90, 50, 40,
10, 9, 5, 4,
1
]
syms = [
"M", "CM", "D", "CD",
"C", "XC", "L", "XL",
"X", "IX", "V", "IV",
"I"
]
steps = []
roman_num = ''
remaining = num
i = 0
steps.append(f"Начальное число: {num}")
steps.append("")
while remaining > 0:
count = remaining // val[i]
if count > 0:
added = syms[i] * count
roman_num += added
steps.append(f"{remaining} ÷ {val[i]} = {count}")
steps.append(f"Добавляем: {added} (римское обозначение {val[i]})")
remaining -= val[i] * count
steps.append(f"Результат: {roman_num}")
steps.append(f"Осталось: {remaining}")
steps.append("")
i += 1
steps.append(f"Итоговое римское число: {roman_num}")
return roman_num, steps
def roman_to_decimal(self, s):
"""Преобразует римское число в десятичное"""
roman = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
total = 0
prev_value = 0
for char in reversed(s.upper()):
if char not in roman:
return None
value = roman[char]
if value < prev_value:
total -= value
else:
total += value
prev_value = value
return total
def roman_to_decimal_with_steps(self, s):
"""Преобразует римское число в десятичное с пошаговым объяснением"""
roman = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
s = s.upper()
# Проверка валидности
for char in s:
if char not in roman:
return None, [f"Ошибка: '{char}' не является римской цифрой"]
steps = []
total = 0
prev_value = 0
steps.append(f"Римское число: {s}")
steps.append("Читаем справа налево:")
steps.append("")
operations = []
for char in reversed(s):
value = roman[char]
if value < prev_value:
operations.append(f"- {char} ({value})")
total -= value
else:
operations.append(f"+ {char} ({value})")
total += value
prev_value = value
# Показываем в обратном порядке (как читается)
for op in reversed(operations):
steps.append(op)
steps.append("")
steps.append(f"Итоговое десятичное число: {total}")
return total, steps
def convert_to_roman(self, e):
"""Конвертирует из десятичной в римскую"""
try:
num = int(self.input_decimal.value or 0)
if num <= 0 or num > 3999:
self.result_to_roman.value = "Ошибка: 1-3999"
self.result_to_roman.update()
self.steps_to_roman.controls.clear()
self.steps_to_roman.controls.append(
ft.Text("Римские числа поддерживают только диапазон от 1 до 3999",
size=14, color="#FF6B6B")
)
self.steps_to_roman.update()
return
roman, steps = self.decimal_to_roman_with_steps(num)
self.result_to_roman.value = roman
self.result_to_roman.update()
# Показываем шаги
self.steps_to_roman.controls.clear()
for step in steps:
if step:
self.steps_to_roman.controls.append(
ft.Text(step, size=14, color="white")
)
else:
self.steps_to_roman.controls.append(ft.Divider(color="#3A1E51"))
self.steps_to_roman.update()
except ValueError:
self.result_to_roman.value = "Ошибка"
self.result_to_roman.update()
def convert_from_roman(self, e):
"""Конвертирует из римской в десятичную"""
try:
roman_num = (self.input_roman.value or "I").strip().upper()
if not roman_num:
roman_num = "I"
result, steps = self.roman_to_decimal_with_steps(roman_num)
if result is None:
self.result_from_roman.value = "Ошибка"
self.result_from_roman.update()
self.steps_from_roman.controls.clear()
for step in steps:
self.steps_from_roman.controls.append(
ft.Text(step, size=14, color="#FF6B6B")
)
self.steps_from_roman.update()
return
self.result_from_roman.value = str(result)
self.result_from_roman.update()
# Показываем шаги
self.steps_from_roman.controls.clear()
for step in steps:
if step:
self.steps_from_roman.controls.append(
ft.Text(step, size=14, color="white")
)
else:
self.steps_from_roman.controls.append(ft.Divider(color="#3A1E51"))
self.steps_from_roman.update()
except Exception as ex:
self.result_from_roman.value = "Ошибка"
self.result_from_roman.update()
def test_data(self, e):
# Создаем поля ввода
self.input_decimal = ft.TextField(
label="Десятичное число",
width=300,
text_align=ft.TextAlign.RIGHT,
value="1",
input_filter=ft.InputFilter(regex_string=r"^[0-9]*$"),
keyboard_type=ft.KeyboardType.NUMBER,
hint_text="Например: 1984"
)
self.input_roman = ft.TextField(
label="Римское число",
width=300,
text_align=ft.TextAlign.CENTER,
value="I",
hint_text="Например: MCMLXXXIV",
input_filter=ft.InputFilter(regex_string=r"^[IVXLCDMivxlcdm]*$")
)
right_column.controls = [ft.Container(
bgcolor="#55257D",
padding=ft.padding.all(10),
border_radius=10,
expand=True,
content=ft.Column(
scroll=ft.ScrollMode.AUTO,
expand=True,
controls=[
ft.Text("Конвертер римских чисел", size=20, color="white", weight=ft.FontWeight.BOLD),
ft.Text("Поддерживаются числа от 1 до 3999", size=11, color="#B0B0B0", italic=True),
ft.Container(height=10),
ft.Row(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
vertical_alignment=ft.CrossAxisAlignment.START,
spacing=20,
controls=[
# Конвертация из десятичной в римскую
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.START,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text("Десятичная → Римская", size=16, color="white", weight=ft.FontWeight.BOLD),
ft.Container(height=10),
self.input_decimal,
ft.Container(height=10),
ft.Icon(ft.Icons.ARROW_DOWNWARD, color="white", size=30),
ft.Container(height=10),
ft.Container(
content=ft.Column([
self.result_to_roman,
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
width=300,
),
ft.Container(height=10),
ft.CupertinoButton("Конвертировать", on_click=self.convert_to_roman),
ft.Container(height=10),
ft.Text("Пошаговое объяснение:", size=14, color="#B0B0B0"),
ft.Container(
expand=True,
content=self.steps_to_roman,
bgcolor="#1A0A2A",
padding=10,
border_radius=5,
)
]
),
# Разделитель
ft.VerticalDivider(width=1, color="#3A1E51"),
# Конвертация из римской в десятичную
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.START,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text("Римская → Десятичная", size=16, color="white", weight=ft.FontWeight.BOLD),
ft.Container(height=10),
self.input_roman,
ft.Container(height=10),
ft.Icon(ft.Icons.ARROW_DOWNWARD, color="white", size=30),
ft.Container(height=10),
ft.Container(
content=ft.Column([
self.result_from_roman,
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
width=300,
),
ft.Container(height=10),
ft.CupertinoButton("Конвертировать", on_click=self.convert_from_roman),
ft.Container(height=10),
ft.Text("Пошаговое объяснение:", size=14, color="#B0B0B0"),
ft.Container(
expand=True,
content=self.steps_from_roman,
bgcolor="#1A0A2A",
padding=10,
border_radius=5,
)
]
)
]
),
ft.Container(height=20),
ft.Text("Справка по римским цифрам:", size=14, color="#B0B0B0", weight=ft.FontWeight.BOLD),
ft.Container(
content=ft.Column([
ft.Text("I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000",
size=12, color="white"),
ft.Text("Правило вычитания: если меньшая цифра стоит перед большей, она вычитается",
size=12, color="white"),
ft.Text("Примеры: IV = 4, IX = 9, XL = 40, XC = 90, CD = 400, CM = 900",
size=12, color="white"),
]),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
)
],
)
)]
e.page.update()

View File

@@ -330,12 +330,12 @@ class StepByStepSolver:
else:
explanation += f" = {digit_result}"
detailed_calc.insert(0, explanation)
detailed_calc.append(explanation)
carry = new_carry
if carry > 0:
result.insert(0, self.digits[carry])
detailed_calc.insert(0, f"Финальный перенос: {carry}")
detailed_calc.append(f"Финальный перенос: {carry}")
result_str = ''.join(result)
@@ -460,7 +460,7 @@ class StepByStepSolver:
digit_result = d1 - d2
result.insert(0, self.digits[digit_result])
detailed_calc.insert(0, explanation)
detailed_calc.append(explanation)
# Убираем ведущие нули
result_str = ''.join(result).lstrip('0') or '0'