mirror of
https://github.com/Horizontal42/summarum.git
synced 2026-11-11 02:12:00 +03:00
add Russian translations for README and ARCHITECTURE
This commit is contained in:
parent
f55266f70b
commit
041a0f4983
3 changed files with 255 additions and 0 deletions
120
ARCHITECTURE.ru.md
Normal file
120
ARCHITECTURE.ru.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# Архитектура
|
||||
|
||||
[English](ARCHITECTURE.md)
|
||||
|
||||
Приложение состоит из двух частей: **движок вычислений на TypeScript + UI** в WebView2
|
||||
и тонкая **оболочка на Rust** (Tauri 2) для всего, что касается ОС.
|
||||
|
||||
```
|
||||
src/
|
||||
engine/ сам калькулятор (чистый TS, без DOM)
|
||||
lexer.ts строка → сырые лексемы (числа, слова, символы)
|
||||
vocab-data.ts таблицы слов en+ru: единицы, валюты, операторы
|
||||
vocab.ts объединённый поиск по таблицам
|
||||
unitdata.ts коэффициенты конвертации (базовые единицы на измерение)
|
||||
extraunits.ts скорость/давление/энергия/мощность/частота/топливо + крипто
|
||||
registry.ts фраза → токен; строится один раз при запуске
|
||||
tokenizer.ts лексемы + реестр → семантические токены
|
||||
parser.ts токены → AST (Pratt-парсер, терпимый к «мусору»)
|
||||
evaluator.ts AST + контекст документа → значения с единицами
|
||||
formatter.ts значения → строки для отображения
|
||||
datetime.ts карта часовых поясов, календарная арифметика
|
||||
index.ts фасад SumEngine + API расширений + итоги листа
|
||||
ui/
|
||||
editor.ts обвязка CodeMirror 6: подсветка, оверлей результатов, копирование
|
||||
app.css темы (светлая/тёмная через CSS-переменные)
|
||||
main.ts запуск приложения: документы, настройки, строка статуса, dnd
|
||||
storage.ts команды Tauri / запасной вариант на localStorage
|
||||
extensions.ts запускает пользовательские .js-файлы через движок
|
||||
i18n.ts строки интерфейса (en/ru)
|
||||
src-tauri/
|
||||
src/main.rs трей, скрытие в трей, команды хранилища, загрузка курсов
|
||||
(open.er-api.com + CoinGecko) с кэшем, резервные копии,
|
||||
миграция папки данных, открытие файлов
|
||||
```
|
||||
|
||||
## Как строка превращается в результат
|
||||
|
||||
1. **Lexer** разбивает `"5 дюймов в см"` на лексемы: `5`, `дюймов`, `в`, `см`.
|
||||
Тот же lexer сегментирует фразы из словаря, чтобы совпадение было последовательным.
|
||||
2. **Registry** хранит все фразы, которые понимает движок, по первой лексеме.
|
||||
Побеждает наиболее длинное совпадение; регистрозависимые записи (`m` vs `M`, `kB`)
|
||||
проверяются раньше регистронезависимых, а неоднозначная нижняя форма (`mm` vs `Mm`)
|
||||
просто не получает нечувствительный к регистру запасной вариант.
|
||||
3. **Tokenizer** проходит по лексемам, спрашивает реестр и выдаёт типизированные токены.
|
||||
Несколько контекстных хаков: например, `in` сразу после числа в конце строки
|
||||
означает дюймы (`6 ft 3 in`).
|
||||
4. **Parser** — Pratt-парсер, терпимый к шуму: неизвестные слова отбрасываются
|
||||
до разбора (поэтому `потратил 20 на пиццу плюс 5` работает) — кроме слов
|
||||
сразу после оператора конвертации, которые могут называть часовой пояс.
|
||||
Приоритет от наименьшего к наибольшему: конвертации на уровне строки →
|
||||
поразрядные → аддитивные → мультипликативные (включая `20% от x`) →
|
||||
унарные → постфиксные (единицы, `%`, `!`, `^`) → первичные.
|
||||
5. **Evaluator** вычисляет тройки `{ value: Decimal, unit }`. Операнды одного
|
||||
измерения конвертируются через базовые единицы (`toBase`/`fromBase`);
|
||||
температуры несут смещение, единицы расхода топлива могут быть обратными
|
||||
(mpg ↔ л/100км). Контекст документа предоставляет переменные и результаты
|
||||
предыдущих строк для `сумма`/`avg`/`prev`.
|
||||
6. **Formatter** отображает значение в формате единицы, с точностью и группировкой
|
||||
из настроек, или в hex/binary/дроби/римских цифрах и т.д.
|
||||
|
||||
Числа — `decimal.js` везде, никаких артефактов двоичной арифметики.
|
||||
|
||||
## Как добавлять вещи
|
||||
|
||||
**Единицу** — добавь строку в `UNIT_DATA` в `unitdata.ts` (id, измерение, коэффициент
|
||||
к базовой единице измерения) и её названия в `vocab-data.ts` в соответствующей
|
||||
категории (`"myunit.variants": "name,names,имя"`, `"myunit.format": "sym"`).
|
||||
Для совершенно нового измерения расширь объединение `Dimension` в `types.ts`
|
||||
и используй `extraunits.ts` — фразы живут прямо там.
|
||||
|
||||
**Валюту** — фиатные коды берутся из таблицы `Currency` в `vocab-data.ts`;
|
||||
крипто идёт в `CRYPTO` в `extraunits.ts` (код, id CoinGecko, фразы, снимок цены)
|
||||
плюс зеркальный список в `src-tauri/src/main.rs`.
|
||||
|
||||
**Оператор/функцию** — зарегистрируй фразу в `buildRegistry()` (`registry.ts`),
|
||||
добавь токен/узел AST если нужен новый синтаксис, реализуй в `evaluator.ts`.
|
||||
Большинство слов-операторов — это данные, а не код.
|
||||
|
||||
**Город часового пояса** — одна строка в карте `Z` в `datetime.ts`.
|
||||
|
||||
## Подводные камни движка
|
||||
|
||||
- Конфликты фраз реальны: одиночные буквы регистрозависимы по замыслу
|
||||
(`m` метр / `M` миллион, `k` тысяча / `K` кельвин). Генерация префиксов
|
||||
фильтруется там, где пересекается со словами — например, секунды получают
|
||||
только ms/µs/ns/ps, потому что символ «аттосекунды» затенил бы слово `as`.
|
||||
- `и`/`или` двойного назначения: `и` складывает (`5 и 3` = 8), `или` — побитовое.
|
||||
`от/без/на` работают только с процентом в левой части; иначе это просто текст.
|
||||
- Курсы валют — «единиц за 1 USD»; соотношение единицы валюты вычисляется при
|
||||
токенизации из текущей карты курсов, поэтому обновление курсов пересчитывает
|
||||
всё при следующей оценке.
|
||||
- Реестр не пересобирается никогда; расширения мутируют его (добавляют фразы/функции)
|
||||
при запуске.
|
||||
|
||||
## Особенности UI
|
||||
|
||||
- CodeMirror встраивает свою базовую тему во время выполнения *после* `app.css`,
|
||||
поэтому всё, что должно побеждать (отступ контента для колонки результатов,
|
||||
цвет курсора), живёт в расширении `EditorView.theme(...)`, а не в стилях.
|
||||
- Колонка результатов — абсолютно позиционированный оверлей; каждый результат
|
||||
размещается по координатам `view.lineBlockAt(...)` и перерисовывается при
|
||||
прокрутке/изменении геометрии. Клик для копирования читает `data-value`.
|
||||
- Оценка движка синхронная на каждое нажатие клавиши — полный разбор листа
|
||||
занимает менее миллисекунды, поэтому нет дебаунса и воркеров.
|
||||
|
||||
## Хранилище
|
||||
|
||||
- `settings.json` всегда находится в `%APPDATA%/app.summarum.calc`.
|
||||
- `documents.json` (все листы) + `backups/` живут либо там, либо в папке данных,
|
||||
выбранной пользователем (путь хранится в настройках).
|
||||
- Ежедневный снимок при запуске (`backups/documents-YYYY-MM-DD.json`, хранится 14);
|
||||
удалённые листы становятся `.numi`-файлами в `backups/deleted/` и удаляются по возрасту.
|
||||
Сохранение откладывается на 400 мс.
|
||||
|
||||
## Тесты
|
||||
|
||||
`npm test` запускает ~94 vitest-кейса по движку (`src/engine/*.test.ts`):
|
||||
все классы выражений, оба языка, детерминированные инжектированные курсы,
|
||||
плюс набор регрессий по всем известным исправленным багам.
|
||||
UI проверяется вручную; движок — там где живёт вся сложность.
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
# Summarum
|
||||
|
||||
[Русский](README.ru.md)
|
||||
|
||||
**A calculator that works like a notepad.** Type what you're thinking — every line
|
||||
gets a live answer in the right column. No buttons, no formula syntax, just text.
|
||||
|
||||
|
|
|
|||
133
README.ru.md
Normal file
133
README.ru.md
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# Summarum
|
||||
|
||||
[English](README.md)
|
||||
|
||||
**Калькулятор, который работает как блокнот.** Пишешь что думаешь — каждая строка сразу даёт ответ в правой колонке. Никаких кнопок, никакого синтаксиса формул, просто текст.
|
||||
|
||||
```
|
||||
# Поездка в Лиссабон
|
||||
билеты $420
|
||||
отель $95 * 4 ночи
|
||||
еда 30€ в день * 4 дня и музеи 25€
|
||||
итого → $1,066.97
|
||||
|
||||
5 дюймов в см → 12.7 cm
|
||||
100 км/ч в миль/ч → 62.14 mph
|
||||
$2000 в рублях → 144,060 ₽
|
||||
скидка 20% от 1500 → 1,200
|
||||
сегодня + 6 недель → 22 Июля 2026
|
||||
время в Токио → 14:25
|
||||
```
|
||||
|
||||
Работает на **английском и русском одновременно**: `5 метров в см`, `20$ в евро`, `сумма` — переключать язык не нужно.
|
||||
|
||||
## Установка
|
||||
|
||||
Скачай последний `Summarum_*_x64-setup.exe` из [Releases](../../releases), запусти — готово. Весь установщик около 2 МБ.
|
||||
|
||||
Требования:
|
||||
|
||||
- **Windows 10 (1803+) или Windows 11**, 64-бит.
|
||||
- **[WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)** —
|
||||
уже встроен в Windows 11 и большинство обновлённых Windows 10; если отсутствует,
|
||||
установщик скачает его автоматически.
|
||||
- Интернет нужен только для живых курсов валют — всё остальное работает офлайн
|
||||
(курсы берутся из кэша или встроенного снимка).
|
||||
|
||||
## Что понимает
|
||||
|
||||
**Обычная математика** — `2 + 2`, `8 / (45 - 20%)`, скобки, `^`, `sqrt`, `sin`,
|
||||
факториалы. Точная десятичная арифметика: `0.1 + 0.2` это `0.3`, а не `0.30000000000000004`.
|
||||
|
||||
**Слова как операторы** — `12 плюс 4`, `20 делить на 4`, `5 и 3`. Текст вокруг
|
||||
математики игнорируется: `потратил 20 на пиццу и 5 на кофе` даст 25.
|
||||
|
||||
**Единицы** — длина, масса, объём, площадь, температура, время, углы, данные
|
||||
(`1 ГиБ в МБ`), CSS px/em, скорость, давление, энергия, мощность, частота, расход топлива:
|
||||
|
||||
```
|
||||
6 футов в метрах 1 атм в мм рт.ст. 8 л/100км в mpg
|
||||
2 часа 30 мин в мин 150 л.с. в кВт 32 px в em
|
||||
```
|
||||
|
||||
**Деньги** — ~150 валют и топ-20 криптовалют с живыми курсами
|
||||
(обновляются раз в час, кэшируются для офлайна). `$100 + 20%`, `5 eth в USD`,
|
||||
`9800 рублей в долларах`.
|
||||
|
||||
**Проценты по-человечески** — `20% от 80`, `скидка 20% от 1500`, `5 это сколько % от 25`,
|
||||
`20% от какого числа равно 30`.
|
||||
|
||||
**Даты и время** — `сегодня + 2 недели`, `завтра - сегодня`, `время в Нью-Йорке`,
|
||||
`сейчас в unix`, `1750000000 как дата`.
|
||||
|
||||
**Для программистов** — `0xFF & 0x0F`, `1 << 4`, `255 в hex`, `в binary`,
|
||||
плюс `в дроби` (0.75 → 3/4) и `в roman` (2026 → MMXXVI).
|
||||
|
||||
**Листы с переменными** — переменные (`аренда = $500`), нарастающие итоги
|
||||
(`сумма`, `avg`, `prev`), заголовки `#`, комментарии `//`. Строка статуса всегда
|
||||
показывает итог листа; выдели несколько строк — увидишь их сумму.
|
||||
|
||||
## Удобные мелочи
|
||||
|
||||
- **Ctrl+Alt+N** (настраивается — поле в настройках записывает нажатые клавиши)
|
||||
показывает/скрывает окно из любого места. Закрытие прячет в трей.
|
||||
- **Клик по результату** копирует его. Копирование строки копирует её *вместе с ответом*
|
||||
(`аренда * 3 = $1,500`). **Ctrl+Shift+C** копирует весь лист с ответами.
|
||||
- **Потяни разделитель** чтобы изменить ширину колонки результатов.
|
||||
- **Брось файл `.numi`, `.sum`, `.txt` или `.md`** в окно — откроется как лист.
|
||||
- **Резервные копии автоматические**: ежедневный снимок всех листов (хранятся 14 дней),
|
||||
удалённые листы лежат в корзине 14 дней (настраивается) — верни перетащив обратно.
|
||||
Настройки → Backups откроет папку.
|
||||
- **Папка данных настраивается** — укажи OneDrive/Dropbox и листы синхронизируются
|
||||
между машинами.
|
||||
- Светлая/тёмная тема, интерфейс en/ru, настраиваемая точность и разделители.
|
||||
|
||||
## Расширения
|
||||
|
||||
Брось `.js`-файл в папку расширений (Настройки → Extensions folder) и перезапусти.
|
||||
API совместим с расширениями Numi:
|
||||
|
||||
```js
|
||||
numi.setVariable("ндс", { double: 20 });
|
||||
numi.addUnit({ id: "этаж", phrases: "этаж,этажей", baseUnitId: "meter",
|
||||
format: "эт", ratio: 3 });
|
||||
numi.addFunction({ id: "гипот", phrases: "гипот" },
|
||||
(v) => ({ double: Math.hypot(v[0].double, v[1].double) }));
|
||||
```
|
||||
|
||||
Тогда `5 этажей в метрах` → `15 m` и `гипот(3; 4)` → `5`.
|
||||
|
||||
## Баги и идеи
|
||||
|
||||
Открой [issue](../../issues). Строка того что написал и что ожидал увидеть — достаточно.
|
||||
|
||||
## Для разработчиков
|
||||
|
||||
Устройство движка, структура проекта и как добавлять единицы/валюты:
|
||||
см. [ARCHITECTURE.ru.md](ARCHITECTURE.ru.md).
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm test # тесты движка
|
||||
npm run tauri dev # запустить приложение
|
||||
npm run tauri build # собрать установщик
|
||||
```
|
||||
|
||||
Для сборки нужны:
|
||||
|
||||
- [Node.js](https://nodejs.org/) 22.6 или новее
|
||||
- [Rust](https://rustup.rs/) (stable, MSVC toolchain)
|
||||
- [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
|
||||
с компонентом «Desktop development with C++» (нужен линковщик MSVC)
|
||||
- Если что-то не собирается — см. [Tauri prerequisites](https://tauri.app/start/prerequisites/)
|
||||
|
||||
Стек: [Tauri 2](https://tauri.app) + TypeScript + CodeMirror 6.
|
||||
|
||||
## Благодарности
|
||||
|
||||
Вдохновлён отличным [Numi](https://numi.app) от Дмитрия Николаева —
|
||||
если ты на macOS, купи его. Summarum — независимый проект, написанный с нуля для Windows.
|
||||
|
||||
## Лицензия
|
||||
|
||||
[MIT](LICENSE)
|
||||
Loading…
Add table
Reference in a new issue