Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@ bin/
.vscode/

### Mac OS ###
.DS_Store
.DS_Store
CLAUDE.md
12 changes: 12 additions & 0 deletions Task_2_2_1/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf

# These are Windows script files and should use crlf
*.bat text eol=crlf

# Binary files should be left untouched
*.jar binary

5 changes: 5 additions & 0 deletions Task_2_2_1/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle

# Ignore Gradle build output directory
build
58 changes: 58 additions & 0 deletions Task_2_2_1/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/9.0.0/userguide/building_java_projects.html in the Gradle documentation.
*/

plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
id 'jacoco'
}

repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}

dependencies {
// Use JUnit Jupiter for testing.
testImplementation libs.junit.jupiter

testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// This dependency is used by the application.
implementation libs.guava
implementation 'com.google.code.gson:gson:2.11.0'
}

// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

application {
// Define the main class for the application.
mainClass = 'org.example.Main'
}

tasks.named('test') {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}

apply plugin: 'jacoco'


jacocoTestReport {

dependsOn test
reports {
xml.required = true


}
}
48 changes: 48 additions & 0 deletions Task_2_2_1/app/src/main/java/org/example/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.example;

import org.example.config.PizzeriaConfig;
import org.example.exception.ConfigLoadException;
import org.example.exception.PizzeriaInterruptException;

/**
* Main.
*/
public class Main {
/**
* Запуск.
*
* @param args аргументы
*/
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
switch (ex) {
case ConfigLoadException e ->
System.err.println("Ошибка конфигурации " + e.getMessage());
case PizzeriaInterruptException e ->
System.err.println(thread.getName() + " Прерывание " + e.getMessage());
default ->
System.err.println(thread.getName() + " Ошибка " + ex.getMessage());
}
});

try {
PizzeriaConfig config = PizzeriaConfig.load("/config.json");
System.out.println("Пиццерия открывается!");
System.out.println("Пекарей: " + config.bakers.length);
System.out.println("Курьеров: " + config.couriers.length);
System.out.println("Вместимость склада: " + config.storageCapacity);
System.out.println("Время работы: " + config.workingTimeMs + " мс");
System.out.println("Заказов: " + config.orders.length);
System.out.println();

Pizzeria pizzeria = new Pizzeria(config);
pizzeria.start();
} catch (ConfigLoadException e) {
System.err.println("Ошибка конфигурации " + e.getMessage());
} catch (PizzeriaInterruptException e) {
System.err.println("Прерывание работы " + e.getMessage());
} catch (Exception e) {
System.err.println("Какая-то ошибка " + e.getMessage());
}
}
}
108 changes: 108 additions & 0 deletions Task_2_2_1/app/src/main/java/org/example/Pizzeria.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package org.example;

import java.util.ArrayList;
import java.util.List;
import org.example.config.PizzeriaConfig;
import org.example.order.Order;
import org.example.order.OrderQueue;
import org.example.order.OrderState;
import org.example.storage.Storage;
import org.example.worker.Baker;
import org.example.worker.Courier;

/**
* Пиццерия.
*/
public class Pizzeria {
private final OrderQueue orderQueue;
private final Storage storage;
private final List<Thread> bakerThreads;
private final List<Thread> courierThreads;
private final PizzeriaConfig config;

/**
* Конструктор пиццерии.
*
* @param config конфигурация пиццерии
*/
public Pizzeria(PizzeriaConfig config) {
this.config = config;
this.orderQueue = new OrderQueue();
this.storage = new Storage(config.storageCapacity);
this.bakerThreads = new ArrayList<>();
this.courierThreads = new ArrayList<>();
}

/**
* Запускает пиццерии.
*/
public void start() {
// запуск пекарей
for (PizzeriaConfig.BakerConfig bc : config.bakers) {
Baker baker = new Baker(bc.name, bc.cookingTimeMs, orderQueue, storage);
Thread thread = new Thread(baker, "Baker-" + bc.name);
bakerThreads.add(thread);
thread.start();
}

// запуск курьеров
for (PizzeriaConfig.CourierConfig cc : config.couriers) {
Courier courier = new Courier(cc.name, cc.trunkCapacity, storage);
Thread thread = new Thread(courier, "Courier-" + cc.name);
courierThreads.add(thread);
thread.start();
}

// заказы в очередь
for (PizzeriaConfig.OrderConfig oc : config.orders) {
Order order = new Order(oc.id);
order.setState(OrderState.QUEUED);
orderQueue.put(order);
}

try {
Thread.sleep(config.workingTimeMs);
} catch (InterruptedException e) {
System.err.println("Pizzeria рабочее время прервано досрочно");
Thread.currentThread().interrupt();
}

System.out.println("=== Пиццерия закрывается. Приём заказов остановлен. ===");
shutdown();
}

/**
* Завершает работу пиццерии.
*/
private void shutdown() {
// закрываем очередь
orderQueue.shutdown();

// ждём пекарей
for (Thread t : bakerThreads) {
try {
t.join();
} catch (InterruptedException e) {
System.err.println("Pizzeria прерывание при ожидании пекаря "
+ t.getName());
Thread.currentThread().interrupt();
}
}
System.out.println("Все пекари завершили работу.");

// закрываем склад
storage.shutdown();

// ждём курьеров
for (Thread t : courierThreads) {
try {
t.join();
} catch (InterruptedException e) {
System.err.println("Pizzeri прерывание при ожидании курьера "
+ t.getName());
Thread.currentThread().interrupt();
}
}
System.out.println("Все курьеры завершили работу. Пиццерия закрыта.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.example.config;

import com.google.gson.Gson;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import org.example.exception.ConfigLoadException;

/**
* Конфигурация пиццерии из JSON.
*/
public class PizzeriaConfig {

/**
* Конфиг пекаря.
*/
public static class BakerConfig {
public String name;
public int cookingTimeMs;
}

/**
* Конфиг курьера.
*/
public static class CourierConfig {
public String name;
public int trunkCapacity;
}

/**
* Конфиг заказа.
*/
public static class OrderConfig {
public int id;
}

public BakerConfig[] bakers;
public CourierConfig[] couriers;
public int storageCapacity;
public int workingTimeMs;
public OrderConfig[] orders;

/**
* Загрузка конфига.
*
* @param resourcePath путь к файлу
* @return конфигурация
*/
public static PizzeriaConfig load(String resourcePath) {
InputStream stream = PizzeriaConfig.class.getResourceAsStream(resourcePath);
if (stream == null) {
throw new ConfigLoadException("Файл не найден: " + resourcePath);
}
Reader reader = new InputStreamReader(stream);
Gson gson = new Gson();
return gson.fromJson(reader, PizzeriaConfig.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.example.exception;

/**
* Ошибка загрузки конфигурации.
*/
public class ConfigLoadException extends RuntimeException {
/**
* Конструктор.
*
* @param message сообщение
*/
public ConfigLoadException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.example.exception;

/**
* Ошибка прерывания работы пиццерии.
*/
public class PizzeriaInterruptException extends RuntimeException {
/**
* Конструктор.
*
* @param message сообщение
* @param cause причина
*/
public PizzeriaInterruptException(String message, Throwable cause) {
super(message, cause);
}
}
46 changes: 46 additions & 0 deletions Task_2_2_1/app/src/main/java/org/example/order/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.example.order;

/**
* Заказ на пиццу.
*/
public class Order {
private final int id;
private OrderState state;

/**
* Конструктор заказ.
*
* @param id номер заказа
*/
public Order(int id) {
this.id = id;
}

/**
* Геттер номера.
*
* @return номер заказа
*/
public int getId() {
return id;
}

/**
* Состояние заказа.
*
* @return текущее состояние
*/
public OrderState getState() {
return state;
}

/**
* Сеттер состояния.
*
* @param state новое состояние
*/
public void setState(OrderState state) {
this.state = state;
System.out.println("[" + id + "] " + state);
}
}
Loading
Loading