Commit 177981b7 authored by Tanita's avatar Tanita

Initial commit

parents
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
\ No newline at end of file
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<component name="libraryTable">
<library name="gson-2.11.0">
<CLASSES>
<root url="jar://$PROJECT_DIR$/src/lib/gson-2.11.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="corretto-11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/cw-auction.iml" filepath="$PROJECT_DIR$/cw-auction.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="gson-2.11.0" level="project" />
</component>
</module>
\ No newline at end of file
[
{
"id": "A001",
"name": "Антикварная ваза",
"price": 850.2,
"init_price": 350.2,
"state": "sold",
"honorary_code": "945c9ebadaa75e17900ebdf4712ec"
},
{
"id": "B001",
"name": "Картина Жайляу",
"price": 1200.4,
"init_price": 800.4,
"state": "sold",
"honorary_code": "4e59511072b366f04b44e298315c7258"
},
{
"id": "C001",
"name": "Коллекционная монета",
"price": 1500.0,
"init_price": 1500.0,
"state": "sold",
"honorary_code": "a179dfe31ac72c667643611e9f794ef6"
},
{
"id": "D001",
"name": "Столовое серебро",
"price": 3000.1,
"init_price": 3000.1,
"state": "in_stock"
},
{
"id": "123QWE",
"name": "статуя кошки",
"price": 400.0,
"init_price": 300.0,
"state": "sold",
"honorary_code": "d3963f2b58bd7573307c84947de772"
},
{
"id": "nt12",
"name": "карта Мира",
"price": 340.0,
"init_price": 340.0,
"state": "in_stock"
},
{
"id": "ER122",
"name": "куртка ДжейЛо",
"price": 1700.0,
"init_price": 1000.0,
"state": "sold",
"honorary_code": "a8bdcfb4609092c10ebbe872c21113d"
}
]
\ No newline at end of file
[
{
"id": "A001",
"name": "Антикварная ваза",
"price": 850.2,
"init_price": 350.2,
"state": {
"title": "sold"
},
"honorary_code": "945c9ebadaa75e17900ebdf4712ec"
},
{
"id": "B001",
"name": "Картина Жайляу",
"price": 1200.4,
"init_price": 800.4,
"state": {
"title": "sold"
},
"honorary_code": "4e59511072b366f04b44e298315c7258"
},
{
"id": "C001",
"name": "Коллекционная монета",
"price": 1500.0,
"init_price": 1500.0,
"state": {
"title": "sold"
},
"honorary_code": "a179dfe31ac72c667643611e9f794ef6"
},
{
"id": "D001",
"name": "Столовое серебро",
"price": 3000.1,
"init_price": 3000.1,
"state": {
"title": "in_stock"
}
},
{
"id": "123QWE",
"name": "статуя кошки",
"price": 400.0,
"init_price": 300.0,
"state": {
"title": "sold"
},
"honorary_code": "d3963f2b58bd7573307c84947de772"
},
{
"id": "nt12",
"name": "карта Мира",
"price": 340.0,
"init_price": 340.0,
"state": {
"title": "in_stock"
}
},
{
"id": "ER122",
"name": "куртка ДжейЛо",
"price": 1700.0,
"init_price": 1000.0,
"state": {
"title": "sold"
},
"honorary_code": "a8bdcfb4609092c10ebbe872c21113d"
}
]
\ No newline at end of file
package application;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import model.Product;
import models.ProductCollection;
import repositories.ProductRepository;
import java.io.IOException;
import java.util.Scanner;
public class Auction {
private final Menu menu = new Menu();
private final ProductCreator creator = new ProductCreator();
private ProductCollection collection;
private ProductRepository repository;
private Scanner scanner = new Scanner(System.in);
public Auction(ProductCollection collection, ProductRepository repository) {
this.collection = collection;
this.repository = repository;
}
public void start() {
while (true) {
printProducts();
System.out.println("0. Добавить новый товар");
System.out.println();
int choice = menu.selectOption("Выберите товар или 0 для добавления нового товара: ", 0, collection.size());
if (choice == 0) {
Product newProduct = creator.createProduct();
collection.add(newProduct);
repository.save(collection);
continue;
}
if (choice < 1 || choice > collection.size()) {
System.out.println("неверный номер товара");
continue;
}
Product product = collection.get(choice - 1);
boolean back = false;
while (!back) {
System.out.println("\n" + product);
System.out.println("1. Выставить на аукцион");
System.out.println("2. Поднять цену");
System.out.println("3. Выдать победителю");
System.out.println("4. Снять с аукциона");
System.out.println("5. Отобразить инфо по товару");
System.out.println("6. Вернуться в список товаров");
switch (menu.selectOption("Что Вы хотите сделать (введите номер)", 1, 6)) {
case 1:
product.startSale();
break;
case 2:
product.raisePrice();
break;
case 3:
product.giveToWinner();
break;
case 4:
product.withdraw();
break;
case 5:
product.toString();
break;
case 6:
back = true;
}
repository.save(collection);
}
if (!menu.confirm("Продолжить аукцион?")) {
saveReport();
break;
}
}
}
private void printProducts() {
System.out.println("\n Список товаров:");
System.out.printf("%-4s | %-10s | %-25s | %-10s | %-15s | %s\n",
"#", "ID", "Название", "Цена", "Состояние", "Почетный код");
System.out.println("-----------------------------------------------------------------------------------");
for (int i = 0; i < collection.size(); i++) {
Product p = collection.get(i);
System.out.printf("%-4d | %-10s | %-25s | %-10.2f | %-15s | %s\n",
i + 1, p.getId(), p.getName(), p.getPrice(), p.getState().getTitle(),
p.getHonoraryCode());
}
}
private void saveReport() {
Product[] products = collection.getAllProducts();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
application.utils.FileWriter writer = new application.utils.FileWriter();
try {
Product[] snapshot = new Product[products.length];
for (int i = 0; i < products.length; i++) {
Product p = products[i];
Product clone = new Product();
clone.setId(p.getId());
clone.setName(p.getName());
clone.setPrice(p.getPrice());
clone.setInitPrice(p.getInitPrice());
clone.setHonoraryCode(p.getHonoraryCode());
clone.setState(p.getState());
snapshot[i] = clone;
}
writer.write("resources/products_after_auction.json", gson.toJson(snapshot));
} catch (IOException e) {
System.out.println("Ошибка при сохранении полного списка: " + e.getMessage());
}
}
}
package application;
import models.ProductCollection;
import repositories.ProductRepository;
public class Main {
public static void main(String[] args) {
String filePath = "resources/products.json";
ProductRepository repository = new ProductRepository(filePath);
ProductCollection collection = repository.getGoods();
if (collection.size() == 0) {
System.out.println("Файл пуст или не найден. Добавьте хотя бы один товар.");
}
Auction auction = new Auction(collection, repository);
auction.start();
}
}
package application;
import java.util.Scanner;
public class Menu {
private final Scanner scanner = new Scanner(System.in);
public int selectOption(String option, int min, int max) {
while (true) {
System.out.print(option + " (" + min + " и " + max + "): ");
try {
int choice = Integer.parseInt(scanner.nextLine());
if (choice >= min || choice <= max)
return choice;
} catch (Exception e) {
System.out.println(" Ввести нужно число от " + min + " до " + max);
}
System.out.println("Неверный ввод. Повторите попытку!");
}
}
public boolean confirm(String option) {
System.out.print(option + "(Y/N): ");
return scanner.nextLine().trim().equalsIgnoreCase("Y");
}
}
package application;
import model.Product;
import java.util.Scanner;
public class ProductCreator {
private final Scanner scanner = new Scanner(System.in);
public Product createProduct() {
double price = -1;
System.out.print("ID: ");
String id = scanner.nextLine();
System.out.print("Название: ");
String name = scanner.nextLine();
while (name.isBlank()) {
System.out.print("Название: ");
name = scanner.nextLine().trim();
if (name.isBlank()) {
System.out.println("Название не может быть пустым.");
}
}
while (price < 0) {
System.out.print("Цена (неотрицательная): ");
try {
price = Double.parseDouble(scanner.nextLine());
if (price < 0) {
System.out.println("Цена не может быть отрицательной.");
}
} catch (NumberFormatException e) {
System.out.println("Введите корректное число.");
}
}
return new Product(id, name, price);
}
}
package model;
import com.google.gson.annotations.SerializedName;
import models.ProductState;
import models.StockState;
public class Product {
private String id;
private String name;
private double price;
@SerializedName("init_price")
private double initPrice;
private ProductState state;
@SerializedName("honorary_code")
private String honoraryCode;
public Product(String id, String name, double price) {
this.id = id;
this.name = name;
this.initPrice = price;
this.price = price;
this.state = new StockState();
}
public Product() {
}
public String getId() {
return id;
}
public double getInitPrice() {
return initPrice;
}
public void setInitPrice(double initPrice) {
this.initPrice = initPrice;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public ProductState getState() {
return state;
}
public void setState(ProductState state) {
this.state = state;
}
public String getHonoraryCode() {
return honoraryCode;
}
public void setHonoraryCode(String honoraryCode) {
this.honoraryCode = honoraryCode;
}
@Override
public String toString() {
return String.format("%-10s | %-25s | %10.2f | %-15s | %s", id, name, price, state.getTitle(), honoraryCode);
}
public void startSale(){
state.startSale(this);
}
public void raisePrice(){
state.raisePrice(this);
}
public void withdraw(){
state.withdraw(this);
}
public void giveToWinner(){
state.giveToWinner(this);
}
}
package models;
import model.Product;
public class ProductCollection {
private Product[] products;
public ProductCollection() {
products = new Product[0];
}
public Product[] getAllProducts() {
return products;
}
public void add(Product product) {
Product[] newProducts = new Product[products.length + 1];
System.arraycopy(products, 0, newProducts, 0, products.length);
newProducts[products.length] = product;
products = newProducts;
}
public Product get(int index) {
return products[index];
}
public int size() {
return products.length;
}
}
package models;
import model.Product;
public abstract class ProductState {
private final String title;
protected ProductState(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public abstract void startSale(Product product);
public abstract void raisePrice(Product product);
public abstract void withdraw(Product product);
public abstract void giveToWinner(Product product);
}
package models;
import services.CodeGenerator;
import model.Product;
public class SaleState extends ProductState {
public SaleState() {
super("for_sale");
}
@Override
public void giveToWinner(Product product) {
if(product.getPrice()==0) {
System.out.println("Ошибка: Нельзя отдать товар бесплатно");
return;
}
product.setState(new SoldState());
product.setHonoraryCode(CodeGenerator.generateHonoraryCode(product));
System.out.println("Товар продан.");
}
@Override
public void raisePrice(Product product) {
product.setPrice(product.getPrice() + 100);
System.out.println("Цена лота увеличена до: " + product.getPrice());
}
@Override
public void startSale(Product product) {
System.out.println("Ошибка: Товар уже на аукционе!");
}
@Override
public void withdraw(Product product) {
if (product.getPrice() == product.getInitPrice()) {
product.setState(new StockState());
System.out.println("Товар возвращен на склад!");
}else{
System.out.println("Ошибка: Товар уже в резерве!");
}
}
}
package models;
import model.Product;
public class SoldState extends ProductState{
public SoldState() {
super("sold");
}
@Override
public void giveToWinner(Product product) {
System.out.println("Ошибка: Товар уже выдан");
}
@Override
public void raisePrice(Product product) {
System.out.println("Ошибка: Нельзя повысить цену! Товар продан");
}
@Override
public void startSale(Product product) {
System.out.println("Ошибка: Товар уже продан");
}
@Override
public void withdraw(Product product) {
System.out.println("Ошибка: Нельзя снять с аукциона! Товар продан");
}
}
package models;
import model.Product;
public class StockState extends ProductState{
public StockState() {
super("in_stock");
}
@Override
public void giveToWinner(Product product) {
System.out.println("Ошибка: Нельзя отдать товар со склада!");
}
@Override
public void raisePrice(Product product) {
System.out.println("Ошибка: Нельзя поднять цену. Товар не на аукционе!");
}
@Override
public void startSale(Product product) {
product.setState(new SaleState());
System.out.println("Товар выставлен на аукцион!");
}
@Override
public void withdraw(Product product) {
System.out.println("Ошибка: Нельзя снять с аукциона: товар не на торгах!");
}
}
package repositories;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import application.utils.FileReader;
import application.utils.FileWriter;
import model.Product;
import models.ProductCollection;
import models.ProductState;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ProductRepository {
private final Gson gson = new GsonBuilder()
.registerTypeAdapter(ProductState.class, new ProductStateDeserialize())
.registerTypeAdapter(ProductState.class, new ProductStateSerialize())
.setPrettyPrinting()
.create();
private final String path;
private final FileReader fileReader = new FileReader();
private final FileWriter fileWriter = new FileWriter();
public ProductRepository(String filePath) {
this.path = filePath;
}
public ProductCollection getGoods() {
try {
Path filePath = Paths.get(path);
if (!Files.exists(filePath)) return new ProductCollection();
String json = fileReader.read(path);
if (json.isBlank()) return new ProductCollection();
Product[] products = gson.fromJson(json, Product[].class);
return convertToCollection(products);
} catch (IOException e) {
e.printStackTrace();
return new ProductCollection();
}
}
public void save(ProductCollection collection) {
try {
Product[] raw = collection.getAllProducts();
Product[] prepared = new Product[raw.length];
for (int i = 0; i < raw.length; i++) {
Product original = raw[i];
Product clone = new Product();
clone.setId(original.getId());
clone.setName(original.getName());
clone.setPrice(original.getPrice());
clone.setInitPrice(original.getInitPrice());
clone.setHonoraryCode(original.getHonoraryCode());
clone.setState(original.getState());
prepared[i] = clone;
}
String json = gson.toJson(prepared);
fileWriter.write(path, json);
} catch (IOException e) {
System.out.println("Ошибка записи: " + e.getMessage());
}
}
private ProductCollection convertToCollection(Product[] products) {
ProductCollection collection = new ProductCollection();
if (products != null) {
for (Product p : products) {
if (p.getPrice() == 0 && p.getInitPrice() > 0) {
p.setPrice(p.getInitPrice());
}
collection.add(p);
}
}
return collection;
}
}
package repositories;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import models.SaleState;
import models.ProductState;
import models.SoldState;
import models.StockState;
import java.lang.reflect.Type;
public class ProductStateDeserialize implements JsonDeserializer<ProductState> {
public ProductState deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String type = json.getAsString();
switch (type){
case "for_sale":
return new SaleState();
case "in_stock":
return new StockState();
case "sold":
return new SoldState();
default:
throw new JsonParseException("Unknown state type: " + type);
}
}
}
package repositories;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import models.ProductState;
import java.lang.reflect.Type;
public class ProductStateSerialize implements JsonSerializer<ProductState> {
public JsonElement serialize(ProductState src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.getTitle());
}
}
package services;
public class BronzeCodeStrategy extends CodeStrategy {
@Override
public String generate(String productId) {
return CodeGenerator.makeCode("Bronze-" + productId);
}
}
package services;
import model.Product;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CodeGenerator {
public static String generateHonoraryCode(Product p) {
CodeStrategy strategy;
double price = p.getPrice();
if (price >= 1000) {
strategy = new GoldCodeStrategy();
} else if (price >= 500) {
strategy = new SilverCodeStrategy();
} else {
strategy = new BronzeCodeStrategy();
}
return strategy.generate(p.getId());
}
public static String makeCode(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
return convertToString(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "";
}
}
private static String convertToString(byte[] array) {
return IntStream.range(0, array.length)
.map(i -> array[i] < 0 ? array[i] + 256 : array[i])
.mapToObj(Integer::toHexString)
.collect(Collectors.joining());
}
}
package services;
public abstract class CodeStrategy {
public abstract String generate(String productId);
}
package services;
public class GoldCodeStrategy extends CodeStrategy {
public String generate(String productId) {
return CodeGenerator.makeCode("Gold-" + productId);
}
}
package services;
public class SilverCodeStrategy extends CodeStrategy {
public String generate(String productId) {
return CodeGenerator.makeCode("Silver-" + productId);
}
}
package application.utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileReader
{
public String read(String value) throws IOException
{
Path path = Paths.get(value);
byte[] bytes = Files.readAllBytes(path);
return new String(bytes).intern();
}
}
package application.utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileUtils
{
public boolean exists(String value)
{
Path path = Paths.get(value);
return Files.exists(path);
}
public void create(String value) throws IOException
{
Path path = Paths.get(value);
Files.createFile(path);
}
}
package application.utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class FileWriter
{
public void write(String path, String value) throws IOException
{
Files.write
(
Paths.get(path),
value.getBytes(),
StandardOpenOption.CREATE
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment