dev: рабочие изменения

This commit is contained in:
2025-10-24 17:28:38 +05:00
commit 748a135156
27 changed files with 2301 additions and 0 deletions

163
app/.gitignore vendored Normal file
View File

@@ -0,0 +1,163 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
*.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Flet
storage/

81
app/README.md Normal file
View File

@@ -0,0 +1,81 @@
# App app
## Run the app
### uv
Run as a desktop app:
```
uv run flet run
```
Run as a web app:
```
uv run flet run --web
```
### Poetry
Install dependencies from `pyproject.toml`:
```
poetry install
```
Run as a desktop app:
```
poetry run flet run
```
Run as a web app:
```
poetry run flet run --web
```
For more details on running the app, refer to the [Getting Started Guide](https://flet.dev/docs/getting-started/).
## Build the app
### Android
```
flet build apk -v
```
For more details on building and signing `.apk` or `.aab`, refer to the [Android Packaging Guide](https://flet.dev/docs/publish/android/).
### iOS
```
flet build ipa -v
```
For more details on building and signing `.ipa`, refer to the [iOS Packaging Guide](https://flet.dev/docs/publish/ios/).
### macOS
```
flet build macos -v
```
For more details on building macOS package, refer to the [macOS Packaging Guide](https://flet.dev/docs/publish/macos/).
### Linux
```
flet build linux -v
```
For more details on building Linux package, refer to the [Linux Packaging Guide](https://flet.dev/docs/publish/linux/).
### Windows
```
flet build windows -v
```
For more details on building Windows package, refer to the [Windows Packaging Guide](https://flet.dev/docs/publish/windows/).

41
app/pyproject.toml Normal file
View File

@@ -0,0 +1,41 @@
[project]
name = "app"
version = "0.1.0"
description = ""
readme = "README.md"
requires-python = ">=3.9"
authors = [
{ name = "Flet developer", email = "you@example.com" }
]
dependencies = [
"flet==0.28.3"
]
[tool.flet]
# org name in reverse domain name notation, e.g. "com.mycompany".
# Combined with project.name to build bundle ID for iOS and Android apps
org = "com.mycompany"
# project display name that is used as an app title on Android and iOS home screens,
# shown in window titles and about app dialogs on desktop.
product = "app"
# company name to display in about app dialogs
company = "Flet"
# copyright text to display in about app dialogs
copyright = "Copyright (C) 2025 by Flet"
[tool.flet.app]
path = "src"
[tool.uv]
dev-dependencies = [
"flet[all]==0.28.3",
]
[tool.poetry]
package-mode = false
[tool.poetry.group.dev.dependencies]
flet = {extras = ["all"], version = "0.28.3"}

BIN
app/src/assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

10
app/src/designer.py Normal file
View File

@@ -0,0 +1,10 @@
import flet as ft
from flet.core.types import OptionalControlEventCallable
right_column = ft.Column(
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
expand=True,
)
alphabet="αβγδεζηθικλμνξοπρστυφχψω"

16
app/src/main.py Normal file
View File

@@ -0,0 +1,16 @@
import flet as ft
from views import ViewsHendler
import designer as ds
def main(page: ft.Page):
page.title = "Calculater CHELGU"
def PageLoading(route={}):
print(page.route)
page.views.clear()
page.views.append(ViewsHendler(page=page)[page.route])
page.update()
page.on_route_change = PageLoading
page.go("/")
ft.app(target=main, assets_dir="assets")

View File

@@ -0,0 +1,40 @@
import flet as ft
import designer as ds
from pages.tabs import start1,calculater2, binary_data3, binary_calculeator4, octogon_data5, octogon_calculeator6, sedecim_data7
class Main_page(ft.View):
def __init__(self, page):
self.page = page
super().__init__(
route="/",
controls=[
ft.Row(
expand=True,
controls=[
ft.Column(
horizontal_alignment=ft.CrossAxisAlignment.START,
width=300,
alignment=ft.MainAxisAlignment.START,
controls=[
start1.Button_text_data(),
calculater2.Button_calculeator(),
binary_data3.Button_binary_data(),
binary_calculeator4.Button_binary_calculator(),
octogon_data5.Button_text_data(),
octogon_calculeator6.Button_octogon_calculator(),
sedecim_data7.Button_sedecim_data(),
ft.Container(
bgcolor="#280A3F",
expand=True,
)
]
),
ds.right_column
]
)
]
)

View File

@@ -0,0 +1,237 @@
from designer import right_column
import flet as ft
class Button_binary_calculator(ft.CupertinoButton):
def __init__(self, text: str = "Двоичный калькулятор"):
self.result_left = ft.Text(value="0", size=30, width=300)
self.result_right = ft.Text(value="0", size=30, width=300)
self.decimal_left = ft.Text(value="(0₁₀)", size=14, color="#B0B0B0", width=300)
self.decimal_right = ft.Text(value="(0₁₀)", 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
# Количество бит для представления (по умолчанию 8)
self.bit_width = 16
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def to_twos_complement(self, num, bit_width):
"""Преобразует число в дополнительный код"""
if num >= 0:
return format(num, f'0{bit_width}b')
else:
# Для отрицательных чисел используем дополнительный код
return format((1 << bit_width) + num, f'0{bit_width}b')
def from_twos_complement(self, binary_str):
"""Преобразует из дополнительного кода в десятичное число"""
bit_width = len(binary_str)
value = int(binary_str, 2)
# Проверяем знаковый бит (старший бит)
if binary_str[0] == '1':
# Отрицательное число
value = value - (1 << bit_width)
return value
def validate_binary(self, value):
"""Проверяет, является ли строка корректным двоичным числом"""
if not value:
return True
# Только 0 и 1
return all(c in "01" for c in value)
def calculate_subtraction(self, e):
try:
bin1 = self.input_left_1.value or "0"
bin2 = self.input_left_2.value or "0"
# Проверка корректности двоичных чисел
if not self.validate_binary(bin1) or not self.validate_binary(bin2):
self.result_left.value = "Ошибка: неверный формат"
self.decimal_left.value = ""
self.result_left.update()
self.decimal_left.update()
return
# Преобразуем двоичные числа в десятичные
if len(bin1) > 0 and bin1[0] == '1' and len(bin1) >= 8:
num1 = self.from_twos_complement(bin1)
else:
num1 = int(bin1, 2) if bin1 else 0
if len(bin2) > 0 and bin2[0] == '1' and len(bin2) >= 8:
num2 = self.from_twos_complement(bin2)
else:
num2 = int(bin2, 2) if bin2 else 0
# Вычисляем результат
result = num1 - num2
# Преобразуем обратно в двоичный формат (дополнительный код)
binary_result = self.to_twos_complement(result, self.bit_width)
self.result_left.value = binary_result
self.decimal_left.value = f"({result}₁₀)"
self.result_left.update()
self.decimal_left.update()
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:
bin1 = self.input_right_1.value or "0"
bin2 = self.input_right_2.value or "0"
# Проверка корректности двоичных чисел
if not self.validate_binary(bin1) or not self.validate_binary(bin2):
self.result_right.value = "Ошибка: неверный формат"
self.decimal_right.value = ""
self.result_right.update()
self.decimal_right.update()
return
# Преобразуем двоичные числа в десятичные
# Если введено в дополнительном коде - интерпретируем как дополнительный код
if len(bin1) > 0 and bin1[0] == '1' and len(bin1) >= 8:
num1 = self.from_twos_complement(bin1)
else:
num1 = int(bin1, 2) if bin1 else 0
if len(bin2) > 0 and bin2[0] == '1' and len(bin2) >= 8:
num2 = self.from_twos_complement(bin2)
else:
num2 = int(bin2, 2) if bin2 else 0
# Вычисляем результат
result = num1 + num2
# Преобразуем обратно в двоичный формат (дополнительный код)
binary_result = self.to_twos_complement(result, self.bit_width)
self.result_right.value = binary_result
self.decimal_right.value = f"({result}₁₀)"
self.result_right.update()
self.decimal_right.update()
except ValueError as ex:
self.result_right.value = "Ошибка"
self.decimal_right.value = str(ex)
self.result_right.update()
self.decimal_right.update()
def test_data(self, e):
# Создаем поля ввода с валидацией для двоичных чисел
self.input_left_1 = ft.TextField(
label="Двоичное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"), # только 0 и 1
hint_text="Например: 00001010 (10) или 11110110 (-10)"
)
self.input_left_2 = ft.TextField(
label="Двоичное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"),
hint_text="Например: 00000101 (5)"
)
self.input_right_1 = ft.TextField(
label="Двоичное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"),
hint_text="Например: 00001010 (10)"
)
self.input_right_2 = ft.TextField(
label="Двоичное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"),
hint_text="Например: 00000101 (5)"
)
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)", size=11, color="#B0B0B0", italic=True),
ft.Text(f"Разрядность: {self.bit_width} бит. Диапазон: {-(1 << (self.bit_width-1))} .. {(1 << (self.bit_width-1))-1}", 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.CENTER,
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.Column(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
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)
]
)
]
)
],
)
)]
e.page.update()

View File

@@ -0,0 +1,120 @@
from designer import right_column
import flet as ft
class Button_binary_data(ft.CupertinoButton):
def __init__(self, text: str = "Двоичная система счисления"):
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def test_data(e, self):
md1="""
Двоичная система счисления — это система, в которой используются только две цифры: 0 и 1.
Двои́чная систе́ма счисле́ния — позиционная система счисления с основанием 2. Благодаря непосредственной реализации в цифровых электронных схемах на логических вентилях, двоичная система используется практически во всех современных компьютерах и прочих вычислительных электронных устройствах.
Компьютеры хранят отрицательные числа иначе, чем положительные, из-за особенностей двоичной системы и конструкции процессоров. Вот основные способы:
1. Прямой код (очень редко используется)
Старший бит (самый левый) делает число отрицательным:
Например, для 8 бит:
00010101 — это +21
10010101 — это -21
Недостатки: две разные записи нуля (положительный и отрицательный), сложнее реализовать арифметику.
2. Обратный код (редко используется)
Если число отрицательное, инвертируются все биты, кроме знакового:
+21: 00010101
-21: 11101010
Недостатки: две записи нуля, сложная арифметика.
3. Дополнительный код (почти всегда используется)
Для отрицательного числа инвертируются все биты и прибавляется единица:
+21: 00010101
-21: инвертируем: 11101010, прибавляем 1: 11101011
Преимущества: только одна запись нуля, простая арифметика (сложение и вычитание одинаковы для положительных и отрицательных чисел).
Почему люди пишут числа как "-10101"
Запись -10101 — это просто привычный способ обозначения отрицательных чисел в десятичной или любой другой системе счисления.
В памяти компьютера знак не хранится отдельно, а закодирован в битах (обычно старший бит — знаковый).
Для человека запись с минусом интуитивно понятна, для компьютера — это набор битов, интерпретируемый по правилам (обычно дополнительного кода).
Другие тонкости
Знаковый и беззнаковый типы:
Например, в языке C/C++ есть int (знаковый) и unsigned int (беззнаковый).
Переполнение:
Если сумма двух больших положительных чисел выходит за пределы диапазона типа, возникает переполнение.
Диапазон значений:
В 8 битах:
беззнаковый: 0..255
знаковый (доп. код): -128..127
Пример (8 бит, дополнительный код)
+5: 00000101
-5: инвертируем: 11111010, прибавляем 1: 11111011
Сложение: 00000101 + 11111011 = 00000000 (0), перенос игнорируется
Мантиса, запятая и хранение дробных чисел
Мантиса — это дробная часть числа в позиционной системе. В двоичной мантиса хранится как последовательность битов, где k-й бит дробной части соответствует весу 2^{-k}.
Запятая (разделитель) в человеческом вводе обозначает границу между целой частью и мантиссой. Пример: 101,101₂ = 1*2^2 + 0*2^1 + 1*2^0 + 1*2^{-1} + 0*2^{-2} + 1*2^{-3} = 5.625.
В реальной памяти компьютера точка (запятая) обычно не хранится как символ. Существует два распространённых способа хранения дробных чисел:
- Fixed-point (fixed Q-format): число хранится как целое, представляющее значение scaled = round(x * 2^{f}), где f — количество бит дробной части. Таким образом все числа интерпретируются как scaled/2^{f}.
- Floating-point (IEEE-754): хранится знак, экспонента и мантисса; формат сложнее, даёт большой диапазон и нормализацию.
В этом калькуляторе дроби вводятся через запятую и обрабатываются как обычные дробные значения (float) с фиксированной точностью при выводе (frac_precision бит).
Практические рекомендации
- Если хотите работать с отрицательными целыми в двоичной системе — вводите строку ровно N бит (например, 16). Старший бит будет определять знак.
- Для дробных значений используйте запятую и при необходимости ставьте знак '-' перед всем числом: -101,01.
- Помните про переполнение: при выводе целого результата в двоичной системе он должен помещаться в выбранную разрядность.
"""
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,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text(md1, size=16, color="white"),
ft.Text("Перевод из десятичной системы в двоичную:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 1.jpg", expand=True),
border_radius=10,
width=350,
height=300,
),
ft.Text("Перевод обратно в десятичную систему:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 2.png", expand=True),
border_radius=10,
width=580,
height=300,
),
ft.Text("Работа со знаком:", size=16, color="white"),
],
#width=600,
)
)]
e.page.update()

View File

@@ -0,0 +1,169 @@
from designer import right_column
import flet as ft
class Button_calculeator(ft.CupertinoButton):
def __init__(self, text: str = "Десятичный калькулятор"):
self.result_left = ft.Text(value="0", size=30, width=300)
self.result_right = ft.Text(value="0", size=30, width=300)
#self.binary_left = ft.Text(value="(0₂)", size=14, color="#B0B0B0", width=300)
#self.binary_right = ft.Text(value="(0₂)", 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
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def to_binary(self, num):
"""Преобразует десятичное число в двоичное"""
if num >= 0:
return bin(num)[2:] # Убираем '0b'
else:
return "-" + bin(num)[3:] # Убираем '-0b'
def calculate_subtraction(self, e):
try:
num1 = int(self.input_left_1.value or 0)
num2 = int(self.input_left_2.value or 0)
result = num1 - num2
self.result_left.value = str(result)
#self.binary_left.value = f"({self.to_binary(result)}₂)"
self.result_left.update()
#self.binary_left.update()
except ValueError:
self.result_left.value = "Ошибка"
#self.binary_left.value = "Неверный формат"
self.result_left.update()
#self.binary_left.update()
def calculate_addition(self, e):
try:
num1 = int(self.input_right_1.value or 0)
num2 = int(self.input_right_2.value or 0)
result = num1 + num2
self.result_right.value = str(result)
#self.binary_right.value = f"({self.to_binary(result)}₂)"
self.result_right.update()
#self.binary_right.update()
except ValueError:
self.result_right.value = "Ошибка"
#self.binary_right.value = "Неверный формат"
self.result_right.update()
#self.binary_right.update()
def test_data(self, e):
# Создаем поля ввода с валидацией
self.input_left_1 = ft.TextField(
label="Десятичное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?\d*$"), # только целые числа (с минусом)
keyboard_type=ft.KeyboardType.NUMBER,
hint_text="Например: 42"
)
self.input_left_2 = ft.TextField(
label="Десятичное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?\d*$"),
keyboard_type=ft.KeyboardType.NUMBER,
hint_text="Например: 17"
)
self.input_right_1 = ft.TextField(
label="Десятичное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?\d*$"),
keyboard_type=ft.KeyboardType.NUMBER,
hint_text="Например: 42"
)
self.input_right_2 = ft.TextField(
label="Десятичное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?\d*$"),
keyboard_type=ft.KeyboardType.NUMBER,
hint_text="Например: 17"
)
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("Введите целые числа (положительные или отрицательные)", size=11, color="#B0B0B0", italic=True),
ft.Row(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
vertical_alignment=ft.CrossAxisAlignment.START,
controls=[
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
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.binary_left
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_subtraction)
]
),
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
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.binary_right
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_addition)
]
)
]
)
],
)
)]
e.page.update()

View File

@@ -0,0 +1,223 @@
from designer import right_column
import flet as ft
class Button_octogon_calculator(ft.CupertinoButton):
def __init__(self, text: str = "Восьмеричный калькулятор"):
self.result_left = ft.Text(value="0", size=30, width=300)
self.result_right = ft.Text(value="0", size=30, width=300)
self.decimal_left = ft.Text(value="(0₁₀)", size=14, color="#B0B0B0", width=300)
self.decimal_right = ft.Text(value="(0₁₀)", 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
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def validate_octal(self, value: str) -> bool:
"""Проверяет, является ли строка корректным восьмеричным числом.
Допускается пустая строка, опциональный ведущий знак '-' и цифры 0..7.
"""
if value is None:
return True
v = value.strip()
if v == "":
return True
if v[0] == '-':
v = v[1:]
return all(c in '01234567' for c in v)
def calculate_subtraction(self, e):
try:
val1 = (self.input_left_1.value or "").strip()
val2 = (self.input_left_2.value or "").strip()
# Проверка корректности восьмеричных чисел
if not self.validate_octal(val1) or not self.validate_octal(val2):
self.result_left.value = "Ошибка: неверный формат"
self.decimal_left.value = ""
self.result_left.update()
self.decimal_left.update()
return
# Парсим восьмеричные числа (поддерживается знак '-')
def parse_octal(s: str) -> int:
s = s.strip()
if s == "":
return 0
sign = -1 if s.startswith('-') else 1
if s.startswith('-'):
s = s[1:]
return sign * int(s, 8) if s else 0
num1 = parse_octal(val1)
num2 = parse_octal(val2)
# Вычисляем результат
result = num1 - num2
# Преобразуем обратно в восьмеричный формат (без префикса 0o)
oct_result = ('-' if result < 0 else '') + format(abs(result), 'o')
self.result_left.value = oct_result
self.decimal_left.value = f"({result}₁₀)"
self.result_left.update()
self.decimal_left.update()
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()
val2 = (self.input_right_2.value or "").strip()
# Проверка корректности восьмеричных чисел
if not self.validate_octal(val1) or not self.validate_octal(val2):
self.result_right.value = "Ошибка: неверный формат"
self.decimal_right.value = ""
self.result_right.update()
self.decimal_right.update()
return
def parse_octal(s: str) -> int:
s = s.strip()
if s == "":
return 0
sign = -1 if s.startswith('-') else 1
if s.startswith('-'):
s = s[1:]
return sign * int(s, 8) if s else 0
num1 = parse_octal(val1)
num2 = parse_octal(val2)
# Вычисляем результат
result = num1 + num2
# Преобразуем обратно в восьмеричный формат
oct_result = ('-' if result < 0 else '') + format(abs(result), 'o')
self.result_right.value = oct_result
self.decimal_right.value = f"({result}₁₀)"
self.result_right.update()
self.decimal_right.update()
except ValueError as ex:
self.result_right.value = "Ошибка"
self.decimal_right.value = str(ex)
self.result_right.update()
self.decimal_right.update()
def test_data(self, e):
# Создаем поля ввода с валидацией для двоичных чисел
# Поля ввода для восьмеричной системы — допускаются цифры 0..7 и опциональный знак '-'
self.input_left_1 = ft.TextField(
label="Восьмеричное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?[0-7]*$"),
hint_text="Например: 123 (83₁₀) или -17 (-15₁₀)"
)
self.input_left_2 = ft.TextField(
label="Восьмеричное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?[0-7]*$"),
hint_text="Например: 45 (37₁₀)"
)
self.input_right_1 = ft.TextField(
label="Восьмеричное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?[0-7]*$"),
hint_text="Например: 12 (10₁₀)"
)
self.input_right_2 = ft.TextField(
label="Восьмеричное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^-?[0-7]*$"),
hint_text="Например: 7 (7₁₀)"
)
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("Вводите числа в системе с основанием 8 (цифры 0..7). Поддерживается знак '-' перед числом.", size=11, color="#B0B0B0", italic=True),
ft.Text(f"Пример: 123₈ = 83₁₀. Для ввода используйте цифры 0..7 и опциональный '-' перед числом.", 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.CENTER,
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.Column(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
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)
]
)
]
)
],
)
)]
e.page.update()

View File

@@ -0,0 +1,82 @@
from designer import right_column
import flet as ft
class Button_text_data(ft.CupertinoButton):
def __init__(self, text: str = "Восьмеричная система счисления"):
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def test_data(e, self):
md1 = """
Восьмерична́я (окта́льная) система счисления — позиционная система с основанием 8.
В ней используются цифры 0, 1, 2, 3, 4, 5, 6 и 7. Каждая позиция числа имеет вес, равный степени восьми: $8^0, 8^1, 8^2.
Коротко о сути и преимуществах:
- Простое представление целых чисел в альтернативах к двоичной системе (группировка по 3 бита).
- Удобна при отображении битовых полей и правах доступа (например, 0755 в UNIX).
Пример записи и перевода:
123₈ = 1*8^2 + 2*8^1 + 3*8^0 = 64 + 16 + 3 = 83₁₀.
Как переводить (алгоритмы):
- Из десятичной в восьмеричную (целая часть): делите число на 8, запоминайте остатки, читайте их в обратном порядке.
- Десятичная дробь → восьмеричная: умножайте дробную часть на 8, целая часть результата — следующая цифра; повторяйте для оставшейся дроби.
- Из двоичной в восьмеричную: группируйте биты по три (справа для целой части, слева для дробной) и заменяйте триплеты на соответствующую одну восьмеричную цифру, т.к. $8 = 2^3$.
Примеры:
- 83₁₀ → 123₈ (83:8=10 r3; 10:8=1 r2; 1:8=0 r1 → 123₈).
- 101110₂ → группируем: 101 110 → 5 6 → 56₈.
- 13.375₁₀ → 15.3₈ (13₁₀ = 15₈; 0.375·8 = 3.0 → .3).
Нотация в языках программирования и практическое применение:
- В Python/JS и многих современных языках восьмеричные литералы записываются с префиксом `0o` или `0O`: `0o755`.
- В старых вариантах записи (например, в C-подобных средах) литерал с ведущим нулём (`0755`) означал окталь — будьте внимательны при переносе кода.
- Отображение прав доступа в UNIX: `rwxr-xr-x` ↔ 755, где каждая тройка битов соответствует одной восьмеричной цифре.
Арифметика и ограничения:
- Арифметические операции выполняются по тем же правилам позиционной системы, но перенос происходит при достижении 8.
- Цифры 8 и 9 недопустимы в октале — проверяйте ввод.
- Как и в других системах, дробные представления могут быть бесконечными (периодические).
Рекомендации для использования в калькуляторе:
- При вводе целых октальных чисел допускайте только символы 0..7.
- Для удобства преобразований показывайте промежуточные шаги: деление/остатки для целой части, умножение для дробной.
- При работе с двоичными данными предоставьте кнопку или подсказку о группировке по 3 бита.
"""
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,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text(md1, size=16, color="white"),
ft.Text("Перевод из десятичной системы в восьмеричную:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 3.png", expand=True),
border_radius=10,
),
ft.Text("Перевод обратно в десятичную систему:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 4.jpg", expand=True),
border_radius=10,
),
ft.Text("Практическое применение и заметки:", size=16, color="white"),
ft.Text("- Используйте префикс 0o в коде; следите за вводом; отображайте примеры перевода.", size=14, color="white"),
],
)
)]
e.page.update()

View File

@@ -0,0 +1,149 @@
from designer import right_column
import flet as ft
class Button_sedecim_data(ft.CupertinoButton):
def __init__(self, text: str = "Шестнадцатеричная система счисления"):
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def test_data(e, self):
md1 = """
Шестнадцатеричная (hex) система счисления — позиционная система с основанием 16.
В ней используются символы 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F; буквы A..F соответствуют значениям 10..15.
Каждая позиция числа имеет вес 16^k, поэтому, например, 1A₁₆ = 1*16 + 10 = 26₁₀.
Почему hex удобен:
- Одна hex-цифра кодирует ровно 4 бита, поэтому перевод в/из двоичного вида делается группировкой по 4 бита.
- Компактное и читаемое представление двоичных данных (адреса, дампы, цвета и т.д.).
Как хранятся отрицательные числа (аналогично двоичной интерпретации):
1. Прямой код (sign-magnitude, редкость)
Старший бит используется как знак: 0 — положительное, 1 — отрицательное.
Пример (8 бит):
+21: 00010101₂ = 0x15
-21: 10010101₂ = 0x95
Недостатки: два нуля (+0 и -0), сложность арифметики.
2. Обратный код (ones' complement, редко)
Для отрицательного числа инвертируются все биты положительного представления.
+21: 00010101₂ = 0x15
-21 (обратный код): 11101010₂ = 0xEA
Недостатки: две записи нуля, сложная арифметика.
3. Дополнительный код (two's complement, повсеместно)
Для отрицательного числа инвертируются все биты и прибавляется 1.
+21: 00010101₂ = 0x15
-21: инвертируем → 11101010₂ = 0xEA; прибавляем 1 → 11101011₂ = 0xEB
Преимущества: единственный ноль, простая арифметика (сложение/вычитание работают одинаково).
Почему люди пишут "-1A" или "-0x1A":
Человеческая запись с минусом — удобный способ показать знак. В памяти же знак обычно кодируется битами (обычно two's complement).
Префикс `0x` часто используется в коде (например, `0x1A`). В некоторых ассемблерах применяют суффикс `h` (1Ah).
Другие важные тонкости:
- Типы: unsigned (беззнаковый) и signed (знаковый, обычно two's complement).
- Переполнение: при выходе за диапазон типа происходит переполнение, его надо отслеживать.
- Диапазон (8 бит): unsigned 0..255 (0x00..0xFF); two's complement -128..127 (0x80..0x7F).
Пример (8 бит, two's complement):
+5: 00000101₂ = 0x05
-5: инвертируем → 11111010₂ = 0xFA; прибавляем 1 → 11111011₂ = 0xFB
Сложение: 0x05 + 0xFB = 0x100 → 0x00 (перенос игнорируется в 8-битном контексте)
Мантиса и дробные значения в hex:
Дробная hex-цифра имеет вес 16^{-k}. Например: 0xA.F = 10 + 15/16 = 10.9375₁₀.
В двоичной связи: каждая hex-цифра = 4 двоичных разряда, поэтому дробные hex-цифры соответствуют блокам по 4 двоичных дробных бита.
В реальной памяти дробные числа обычно хранятся в двоичном формате (fixed-point или IEEE-754 floating-point),
а hex чаще используется как удобный формат ввода/вывода.
Практические рекомендации:
- Используйте префикс `0x` для явной записи hex в коде.
- При вводе фиксируйте разрядность (например, N hex-цифр) для однозначности знака.
- Для дробей используйте разделитель, понятный интерфейсу (запятая или точка) и интерпретируйте как hex-дробь.
- Учитывайте порядок байтов (endianness) при интерпретации многобайтовых значений.
Таблица соответствия (коротко):
0 = 0 = 0000
1 = 1 = 0001
2 = 2 = 0010
3 = 3 = 0011
4 = 4 = 0100
5 = 5 = 0101
6 = 6 = 0110
7 = 7 = 0111
8 = 8 = 1000
9 = 9 = 1001
A = 10 = 1010
B = 11 = 1011
C = 12 = 1100
D = 13 = 1101
E = 14 = 1110
F = 15 = 1111
Примеры:
255₁₀ = 0xFF
26₁₀ = 0x1A
10101111₂ = AF₁₆
0x1.A = 1 + 10/16 = 1.625₁₀
Короткая справка по Python:
int('1A', 16) # -> 26
hex(255) # -> '0xff'
format(26, 'X') # -> '1A'
Резюме:
Hex — компактный способ записи бинарных данных (1 hex = 4 бита). Отрицательные числа в памяти
обычно представлены в two's complement; hex просто показывает битовый набор в удобном виде.
"""
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,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text(md1, size=16, color="white"),
ft.Text("Перевод из десятичной системы в шестнадцатеричную:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 5.png", expand=True),
border_radius=10,
),
ft.Text("Перевод обратно в десятичную систему:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 6.png", expand=True),
border_radius=10,
),
ft.Text("Практическое применение и заметки:", size=16, color="white"),
ft.Text("- Используйте префикс 0o в коде; следите за вводом; отображайте примеры перевода.", size=14, color="white"),
],
)
)]
e.page.update()

View File

@@ -0,0 +1,54 @@
from designer import right_column
import flet as ft
class Button_text_data(ft.CupertinoButton):
def __init__(self, text: str = "Начало"):
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def test_data(e, self):
md1="""
Система счисления — это способ записи (представления) чисел.
Что под этим подразумевается? Например, вы видите перед собой несколько деревьев. Ваша задача — их посчитать. Для этого можно — загибать пальцы, делать зарубки на камне (одно дерево — один палец\зарубка) или сопоставить 10 деревьям какой-нибудь предмет, например, камень, а единичному экземпляру — палочку и выкладывать их на землю по мере подсчета. В первом случае число представляется, как строка из загнутых пальцев или зарубок, во втором — композиция камней и палочек, где слева — камни, а справа — палочки
Системы счисления подразделяются на позиционные и непозиционные, а позиционные, в свою очередь, — на однородные и смешанные.
Непозиционная — самая древняя, в ней каждая цифра числа имеет величину, не зависящую от её позиции (разряда). То есть, если у вас 5 черточек — то число тоже равно 5, поскольку каждой черточке, независимо от её места в строке, соответствует всего 1 один предмет.
Позиционная система — значение каждой цифры зависит от её позиции (разряда) в числе. Например, привычная для нас 10-я система счисления — позиционная. Рассмотрим число 453. Цифра 4 обозначает количество сотен и соответствует числу 400, 5 — кол-во десяток и аналогично значению 50, а 3 — единиц и значению 3. Как видим — чем больше разряд — тем значение выше. Итоговое число можно представить, как сумму 400+50+3=453.
Однородная система — для всех разрядов (позиций) числа набор допустимых символов (цифр) одинаков. В качестве примера возьмем упоминавшуюся ранее 10-ю систему. При записи числа в однородной 10-й системе вы можете использовать в каждом разряде исключительно одну цифру от 0 до 9, таким образом, допускается число 450 (1-й разряд — 0, 2-й — 5, 3-й — 4), а 4F5 — нет, поскольку символ F не входит в набор цифр от 0 до 9.
Смешанная система — в каждом разряде (позиции) числа набор допустимых символов (цифр) может отличаться от наборов других разрядов. Яркий пример — система измерения времени. В разряде секунд и минут возможно 60 различных символов (от «00» до «59»), в разряде часов 24 разных символа (от «00» до «23»), в разряде суток 365 и т. д.
Аксиома 1: Для каждого натурального числа (n) существует следующее за ним число, обозначаемое как (S(n)) (или (n+1)).
Аксиома 2: Если (S(a)=S(b)), то (a=b).
Аксиома 3: Если (a+b=c), то (S(a+b)=S(c)).
по аналогии (a-b=c) => (b+c=a)
"""
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(md1, size=16, color="white")
],
#width=600,
)
)]
e.page.update()

7
app/src/views.py Normal file
View File

@@ -0,0 +1,7 @@
import flet as ft
from pages.main_page import Main_page
def ViewsHendler(page:ft.Page):
return {
"/": Main_page(page)
}