mirror of
https://github.com/Horizontal42/summarum.git
synced 2026-11-10 21:31:59 +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
|
# Summarum
|
||||||
|
|
||||||
|
[Русский](README.ru.md)
|
||||||
|
|
||||||
**A calculator that works like a notepad.** Type what you're thinking — every line
|
**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.
|
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