diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 00000000..c009ab52
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 00000000..712ab9d9
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..accd6296
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 00000000..797acea5
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 32f74df9..2ace37f6 100644
--- a/README.md
+++ b/README.md
@@ -1,82 +1 @@
-# Тестовое задание для Java стажеров
-
-Привет!
-
-Мы ищем стажера, который в перспективе станет Junior Java-разработчиком в нашей команде.
-Чтобы понять, что мы подходим друг другу, предлагаем вам написать простое web-приложение. Такое задание поможет нам понять, что вы:
-
-* можете понимать поставленную задачу;
-* умеете находить необходимую техническую информацию для реализации решения;
-* просто умеете кодить.
-
-На задание у вас уйдет ориентировочно один-два вечера. Главное условие — решение должно быть написано с использованием платформы JVM. Библиотеки и фреймворки можно выбирать на свой вкус.
-
-## Что нужно сделать
-
-Реализовать приложение для автоматизации учёта носков на складе магазина. Кладовщик должен иметь возможность:
-
-* учесть приход и отпуск носков;
-* узнать общее количество носков определенного цвета и состава в данный момент времени.
-
-Внешний интерфейс приложения представлен в виде HTTP API (REST, если хочется).
-
-## Список URL HTTP-методов
-
-### POST /api/socks/income
-
-Регистрирует приход носков на склад.
-
-Параметры запроса передаются в теле запроса в виде JSON-объекта со следующими атрибутами:
-
-* color — цвет носков, строка (например, black, red, yellow);
-* cottonPart — процентное содержание хлопка в составе носков, целое число от 0 до 100 (например, 30, 18, 42);
-* quantity — количество пар носков, целое число больше 0.
-
-Результаты:
-
-* HTTP 200 — удалось добавить приход;
-* HTTP 400 — параметры запроса отсутствуют или имеют некорректный формат;
-* HTTP 500 — произошла ошибка, не зависящая от вызывающей стороны (например, база данных недоступна).
-
-### POST /api/socks/outcome
-
-Регистрирует отпуск носков со склада. Здесь параметры и результаты аналогичные, но общее количество носков указанного цвета и состава не увеличивается, а уменьшается.
-
-### GET /api/socks
-
-Возвращает общее количество носков на складе, соответствующих переданным в параметрах критериям запроса.
-
-Параметры запроса передаются в URL:
-
-* color — цвет носков, строка;
-* operation — оператор сравнения значения количества хлопка в составе носков, одно значение из: moreThan, lessThan, equal;
-* cottonPart — значение процента хлопка в составе носков из сравнения.
-
-Результаты:
-
-* HTTP 200 — запрос выполнен, результат в теле ответа в виде строкового представления целого числа;
-* HTTP 400 — параметры запроса отсутствуют или имеют некорректный формат;
-* HTTP 500 — произошла ошибка, не зависящая от вызывающей стороны (например, база данных недоступна).
-
-Примеры запросов:
-
-* /api/socks?color=red&operation=moreThan&cottonPart=90 — должен вернуть общее количество красных носков с долей хлопка более 90%;
-* /api/socks?color=black&operation=lessThan?cottonPart=10 — должен вернуть общее количество черных носков с долей хлопка менее 10%.
-
-Для хранения данных системы можно использовать любую реляционную базу данных. Схему БД желательно хранить в репозитории в любом удобном виде.
-
-## Как это сделать
-
-Мы ждем, что решение будет:
-
-* написано на языке Java;
-* standalone - состоять из одного выполняемого компонента верхнего уровня;
-* headless - без UI;
-* оформлено как форк к репозитарию и создан пул реквест.
-
-Будет плюсом, если:
-
-* приложение будет основано на Spring(Boot) Framework;
-* для версионирования схемы базы данных будет использоваться Liquibase или Flyway;
-* база данных будет подниматься рядом с приложением в докер-контейнере;
-* приложение будет развернуто на любом облачном сервисе, например Heroku, и его API будет доступно для вызова.
+Считает носки гет и пост запросами с помощью сервлетов и джетти
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..dea40267
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+
+ raif
+ raif
+ 1.0
+
+
+ 11
+ 11
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-server
+ 9.3.0.M0
+
+
+
+ org.eclipse.jetty
+ jetty-webapp
+ 9.3.0.M0
+
+
+
+ com.googlecode.json-simple
+ json-simple
+ 1.1.1
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.3
+
+
+ maven-assembly-plugin
+
+
+
+ jar-with-dependencies
+
+ ${basedir}
+ serverSocks
+ false
+
+
+ main.Main
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/serverSocks.jar b/serverSocks.jar
new file mode 100644
index 00000000..dca7a19d
Binary files /dev/null and b/serverSocks.jar differ
diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java
new file mode 100644
index 00000000..460f9821
--- /dev/null
+++ b/src/main/java/main/Main.java
@@ -0,0 +1,27 @@
+package main;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import servlets.*;
+import socks.*;
+
+
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ SocksService socksService=new SocksService();
+
+ ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.addServlet(new ServletHolder(new ShowServlet(socksService)),"/show");
+ context.addServlet(new ServletHolder(new IncomeServlet(socksService)), "/api/socks/income");
+ context.addServlet(new ServletHolder(new OutcomeServlet(socksService)), "/api/socks/outcome");
+ context.addServlet(new ServletHolder(new SocksServlet(socksService)), "/api/socks");
+
+ Server server = new Server(8080);
+ server.setHandler(context);
+
+ server.start();
+ server.join();
+ }
+}
diff --git a/src/main/java/servlets/IncomeServlet.java b/src/main/java/servlets/IncomeServlet.java
new file mode 100644
index 00000000..03ce5036
--- /dev/null
+++ b/src/main/java/servlets/IncomeServlet.java
@@ -0,0 +1,101 @@
+package servlets;
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import socks.Socks;
+import socks.SocksService;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class IncomeServlet extends HttpServlet {
+ private final SocksService socksService;
+
+ public IncomeServlet(SocksService socksService){
+ this.socksService=socksService;
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ //super.doPost(req, resp);
+ JSONParser parser=new JSONParser();
+ JSONObject jsonObject;
+ try {
+ jsonObject=(JSONObject)parser.parse(getBody(req));
+ }catch (Exception e){
+ throw new RuntimeException();
+ }
+ Socks socks=new Socks(jsonObject);
+
+ //пустые параметры
+ if(socks.getColor()==null||socks.getCottonPart()==null||
+ socks.getQuantity()==null){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ //содержание хлопка
+ if(socks.getCottonPart()<0 || socks.getCottonPart()>100){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ //Отрицательное число
+ if(socks.getQuantity()<=0){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+
+ if(socksService.addSocks(socks)){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_OK);
+ }else{
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ }
+ }
+ //сам не знаю как объект json обработать в строку нашел на сайте
+ // https://question-it.com/questions/192029/poluchenie-dannyh-iz-vhodjaschego-json-v-servlete-java
+ public static String getBody(HttpServletRequest request) {
+
+ String body = null;
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = null;
+
+ try {
+ InputStream inputStream = request.getInputStream();
+ if (inputStream != null) {
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ char[] charBuffer = new char[128];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ } else {
+ stringBuilder.append("");
+ }
+ } catch (IOException ex) {
+ // throw ex;
+ return "";
+ } finally {
+ if (bufferedReader != null) {
+ try {
+ bufferedReader.close();
+ } catch (IOException ex) {
+
+ }
+ }
+ }
+
+ body = stringBuilder.toString();
+ return body;
+ }
+}
+
diff --git a/src/main/java/servlets/OutcomeServlet.java b/src/main/java/servlets/OutcomeServlet.java
new file mode 100644
index 00000000..0733d828
--- /dev/null
+++ b/src/main/java/servlets/OutcomeServlet.java
@@ -0,0 +1,101 @@
+package servlets;
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import socks.Socks;
+import socks.SocksService;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class OutcomeServlet extends HttpServlet {
+ private final SocksService socksService;
+
+ public OutcomeServlet(SocksService socksService){
+ this.socksService=socksService;
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ //просматриваем json
+ JSONParser parser=new JSONParser();
+ JSONObject jsonObject;
+ try {
+ jsonObject=(JSONObject)parser.parse(getBody(req));
+ }catch (Exception e){
+ throw new RuntimeException();
+ }
+ Socks socks=new Socks(jsonObject);
+
+ //пустые параметры
+ if(socks.getColor()==null||socks.getCottonPart()==null||
+ socks.getQuantity()==null){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ //содержание хлопка
+ if(socks.getCottonPart()<0 || socks.getCottonPart()>100){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ //Отрицательное число
+ if(socks.getQuantity()<=0){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+
+ if(socksService.delSocks(socks)){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_OK);
+ }else{
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ }
+ }
+ //сам не знаю как объект json обработать в строку нашел на сайте
+ // https://question-it.com/questions/192029/poluchenie-dannyh-iz-vhodjaschego-json-v-servlete-java
+ public static String getBody(HttpServletRequest request) {
+
+ String body = null;
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = null;
+
+ try {
+ InputStream inputStream = request.getInputStream();
+ if (inputStream != null) {
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ char[] charBuffer = new char[128];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ } else {
+ stringBuilder.append("");
+ }
+ } catch (IOException ex) {
+ // throw ex;
+ return "";
+ } finally {
+ if (bufferedReader != null) {
+ try {
+ bufferedReader.close();
+ } catch (IOException ex) {
+
+ }
+ }
+ }
+
+ body = stringBuilder.toString();
+ return body;
+ }
+}
+
diff --git a/src/main/java/servlets/ShowServlet.java b/src/main/java/servlets/ShowServlet.java
new file mode 100644
index 00000000..7ede979c
--- /dev/null
+++ b/src/main/java/servlets/ShowServlet.java
@@ -0,0 +1,23 @@
+package servlets;
+
+import socks.SocksService;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class ShowServlet extends HttpServlet {
+ private final SocksService socksService;
+
+ public ShowServlet(SocksService socksService){
+ this.socksService=socksService;
+ }
+ public void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/html;charset=utf-8");
+ response.getWriter().print(socksService);
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+}
diff --git a/src/main/java/servlets/SocksServlet.java b/src/main/java/servlets/SocksServlet.java
new file mode 100644
index 00000000..be2000ca
--- /dev/null
+++ b/src/main/java/servlets/SocksServlet.java
@@ -0,0 +1,46 @@
+package servlets;
+import socks.SocksService;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class SocksServlet extends HttpServlet{
+ private final SocksService socksService;
+
+ public SocksServlet(SocksService socksService){
+ this.socksService=socksService;
+ }
+
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+ String color=req.getParameter("color");
+ String operation=req.getParameter("operation");
+ Long cottonPart=Long.parseLong(req.getParameter("cottonPart"));
+
+ //пустые параметры
+ if(color==null||operation==null||cottonPart==null){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ //содержание хлопка
+ if(cottonPart<0 || cottonPart>100){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ //Корректная операция
+ if(!operation.equals("moreThan")&& !operation.equals("lessThan")&& !operation.equals("equal")){
+ resp.setContentType("text/html;charset=utf-8");
+ resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ //отобразить кол-во нужных носков
+ resp.setContentType("text/html;charset=utf-8");
+ resp.getWriter().print(socksService.get(color,operation,cottonPart));
+ resp.setStatus(HttpServletResponse.SC_OK);
+ }
+}
diff --git a/src/main/java/socks/Socks.java b/src/main/java/socks/Socks.java
new file mode 100644
index 00000000..e08af217
--- /dev/null
+++ b/src/main/java/socks/Socks.java
@@ -0,0 +1,60 @@
+package socks;
+
+import org.json.simple.JSONObject;
+
+public class Socks {
+ String color;
+ Long cottonPart;
+ Long quantity;
+
+ public String getColor() {
+ return color;
+ }
+
+ public Long getCottonPart() {
+ return cottonPart;
+ }
+
+ public Long getQuantity() {
+ return quantity;
+ }
+
+ public Socks(String color, Long cottonPart, Long quantity){
+ this.color=color;
+ this.cottonPart=cottonPart;
+ this.quantity=quantity;
+ }
+ public Socks(JSONObject jsonObject){
+ this.color=(String)jsonObject.get("color");
+ this.cottonPart=(Long) jsonObject.get("cottonPart");
+ this.quantity=(Long) jsonObject.get("quantity");
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Socks socks = (Socks) o;
+ if(color.equals(socks.color))
+ if(cottonPart.equals(socks.cottonPart))
+ return true;
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = color != null ? color.hashCode() : 0;
+ result = 31 * result + cottonPart.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Socks{" +
+ "color='" + color + '\'' +
+ ", cottonPart=" + cottonPart +
+ ", hash= "+hashCode()+
+ '}';
+ }
+}
diff --git a/src/main/java/socks/SocksService.java b/src/main/java/socks/SocksService.java
new file mode 100644
index 00000000..03a0e907
--- /dev/null
+++ b/src/main/java/socks/SocksService.java
@@ -0,0 +1,59 @@
+package socks;
+
+
+import java.util.*;
+
+public class SocksService {
+ private final Map socksMap;
+
+ public SocksService(){
+ socksMap=new HashMap<>();
+ }
+
+ public boolean addSocks(Socks socks){
+ if(socks.quantity<=0)
+ return false;
+ if(socksMap.containsKey(socks)){
+ socksMap.put(socks,socksMap.get(socks)+socks.quantity);
+ return true;
+ } else{
+ socksMap.put(socks,socks.quantity);
+ return true;
+ }
+ }
+ public boolean delSocks(Socks socks){
+ if(socks.quantity<=0)
+ return false;
+ if(socksMap.containsKey(socks)){
+ if(socks.quantitycottonPart)
+ result+=socksMap.get(socks);
+ } else if(operation.equals(("lessThan"))){
+ if(socks.cottonPart