# README
Calculator-2.0
Этот проект представляет собой простой API калькулятора, написанный на Go. API позволяет выполнять базовые арифметические операции над математическими выражениями.
Как это всё работает?
- Пользователь вводит выражение
- Выражение попадает в Оркестратор, а он дает его CalculateHandler
- CalculateHandler вызывает функцию Calc и дает ей введенное выражение
- CalculateHandler получает обратно мапу, где ключ - id подвыражения, а значение - само подвыражение
- CalculateHandler отправляет пользователю id последнего подвыражения, формирует задачи для Агента и запускает его
- Агент запускается сразу в нескольких горутинах, каждая горутина берет задание и решает его, если в операнде есть id, то заменить его значением из мапы(подробнее ниже)
- Агент отправляет результаты в Оркестратор в ResultHandler
- ResulHandler уведомляет пользователя, что выражение решено Пользователь может в процессе вычисления (или после него) запрашивать как весь список подвыражений, так и одно подвыражение по его id(как запускать проект рассказано ниже )
Подробнее о работе API
Здесь будет рассказано о некоторых моментах работы API
Разбиение на подвыражения функцией Calc
Функция Calc запрашивается CalculateHandler, проводит главные проверки на ошибки в записи выражения и самое главное разбивает все выражение на подвыражения.
Выражение разбивается на подзадачи. Подзадаче "операнд1 операция операнд2" присваивается id("id"+порядковый номер подзадачи), на который и заменяется подзадача в выражении. Подзадача и ее id добавляются в мапу mapid, в CalculateHandler возвращается эта самая мапа.
Паралельное решение подзадач Агентом
Так как у нас есть ограничение на количество запущенных горутин, то нам надо в случае не хватки их изначального количества, запустить новые, но опять не больше установленного значения.
Но как решать подзадачи где какой-либо из операндов с "id"? Для этого результат каждой подзадачи помимо отправки в Оркестратор ResultHandler сохраняется в мапе valmap.
В valmap по ключу, в виде id всех подзадач, присваивается значение "no". Если один из операндов(или оба) содержат "id", то идет проверка, не заменились ли значения по ключу(id подзадачи) на число, если значение до сих пор "no", то ждем немного времени и проверяем заново. Если значение не "no", а число, то меняем операнд-ы на новое значение. Дальше, когда операнды только числа, вычисляем результат подзадачи и меняем в valmap[id подзадачи] значение на результат подзадачи. Такие действия выполняются со всеми горутинами
Установка и запуск
Установка
- Перейдите в директорию, в которую хотите уставновить проект:
откройте терминал и прописывайте
cd ..
, пока не окажетесь в директории диска нажмите правой кнопкой мыши по папке, в которую хотите установить проект, скопируйте строчку расположение введитеcd
+скопированное расположение++имя папки(пробел только после cd) - Введите
git clone https://github.com/Reit437/Calculator-2.0.git
- Введите
go get github.com/Reit437/Calculator-2.0
- Введите
go mod tidy
Готово! Проект установлен
Запуск
Запуск через терминал
- Если вы закрыи терминал, то откройте его и повторите 1 пункт из Установки, если не не закрывали, то введите
cd Calculator-2.0
- Введите в терминал
go run ./cmd/app/main.go
- Откройте GitBash и введите(поле expression можно менять как угодно):
curl --location 'http://localhost:5000/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data '{
"expression": "1.2 + ( -8 * 9 / 7 + 56 - 7 ) * 8 - 35 + 74 / 41 - 8"
}'
Вы получите обратно id, это id по которому вы сможете получить ответ на всё выражение ВАЖНО! Пробелы в вашем выражении должны быть строго как в образце сверху иначе будет ошибка.
- Пока будет решаться выражение вы можете ввести(в GitBash):
1.curl --location 'localhost/api/v1/expressions'
, чтобы посмотреть все сформированные подзадачи
2.curl --location 'localhost/api/v1/expressions/id1'
, чтобы посмотреть определенную подзадачу(можете менять id1 на любой id, но строго в таком формате)
-
После надписи в терминале "Выражение решено", можете ввести команду 4.2 с id, который вам дали при вводе выражения и увидеть ответ
-
Для запуска тестов:
- Для тестов Calc введите:
go test -v ./pkg/calc
- Для тестов CalculateHandler и ExpressionsHandler введите:
go test -v ./internal/app
- Для тестов Calc введите:
-
Для изменения переменных среды откройте файл в
/internal/config/variables.env
и измените их
Примеры работы
Правильная работа программы
- Обычное выражение:
Ответ поcurl --location 'http://localhost:5000/api/v1/calculate' \ --header 'Content-Type: application/json' \ --data '{ "expression": "2 + 2 * 2" }'
curl --location 'localhost/api/v1/expressions/id2'
:{ "expression": { "Id": "id2", "status": "solved", "result": "6.000" } }
- Выражение со скобками:
Ответ поcurl --location 'http://localhost:5000/api/v1/calculate' \ --header 'Content-Type: application/json' \ --data '{ "expression": "2 + 2 * 2 / ( 8 * 5 )" }'
curl --location 'localhost/api/v1/expressions/id4'
:{ "expression": { "Id": "id4", "status": "solved", "result": "2.100" } }
- Сложное выражение со скобками отрицательными числами и дробными числами:
Ответ поcurl --location 'http://localhost:5000/api/v1/calculate' \ --header 'Content-Type: application/json' \ --data '{ "expression": "1.2 + ( -8 * 9 / 7 + 56 - 7 ) * 8 - 35 + 74 / 41 - 8" }'
curl --location 'localhost/api/v1/expressions/id10'
:{ "expression": { "Id": "id10", "status": "solved", "result": "269.710" } }
- Ошибочное выражение:
Ответ:curl --location 'http://localhost:5000/api/v1/calculate' \ --header 'Content-Type: application/json' \ --data '{ "expression": "2 + 2 * * 2 / ( 8 * 5 )" }'
Невалидные данные