Skip to content
99 changes: 99 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/Controller/Model.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package by.Dzenia.docks_and_hobos.Controller;
import by.Dzenia.docks_and_hobos.Persons.Cargo;
import by.Dzenia.docks_and_hobos.Persons.Tunnel;
import by.Dzenia.docks_and_hobos.RunnableObjects.Dock;
import by.Dzenia.docks_and_hobos.RunnableObjects.Hobos;
import by.Dzenia.docks_and_hobos.RunnableObjects.ShipGenerator;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;


public class Model {
private final Tunnel tunnel;
private final Hobos hobos;
private final ShipGenerator shipGenerator;
private final ArrayList<Cargo> cargos;
private final ArrayList<Dock> docks;

public Model(Tunnel tunnel, Hobos hobos, ShipGenerator shipGenerator, ArrayList<Cargo> cargos, ArrayList<Dock> docks) {
this.tunnel = tunnel;
this.hobos = hobos;
this.shipGenerator = shipGenerator;
this.cargos = cargos;
this.docks = docks;
}

public Model(String pathToJson) throws IOException {
String jsonContent = new String(Files.readAllBytes(Paths.get(pathToJson)));
JSONObject jsonObject = new JSONObject(jsonContent);
JSONObject generatorJson = jsonObject.getJSONObject("generator");
int generatingTime = Integer.parseInt(generatorJson.get("generating_time").toString());
JSONObject ship = jsonObject.getJSONObject("ship");
int shipCapacityMin = Integer.parseInt(ship.get("ship_capacity_min").toString());
int shipCapacityMax = Integer.parseInt(ship.get("ship_capacity_max").toString());
this.shipGenerator = new ShipGenerator(generatingTime, shipCapacityMin, shipCapacityMax, this);
JSONArray cargoTypes = (JSONArray) ship.get("cargo_types");
cargos = new ArrayList<>();
for (Object cargoType : cargoTypes) {
cargos.add(new Cargo(cargoType.toString()));
}
JSONObject tunnel = jsonObject.getJSONObject("tunnel");
int maxShips = Integer.parseInt(tunnel.get("max_ships").toString());
this.tunnel = new Tunnel(maxShips);
this.docks = new ArrayList<>();
JSONArray docksArray = jsonObject.getJSONArray("docks");
for (Object dockObject : docksArray) {
JSONObject dock = (JSONObject) dockObject;
int speed = Integer.parseInt(dock.get("unloading_speed").toString());
JSONObject dockCapacity = dock.getJSONObject("dock_capacity");
HashMap<String, Integer> capacities = new HashMap<>();
Map<String, Object> mp = dockCapacity.toMap();
Set<String> keys = dockCapacity.toMap().keySet();
for (String cargoType: keys) {
capacities.put(cargoType, (Integer)mp.get(cargoType));
}
docks.add(new Dock(speed, capacities, this));
}
JSONObject hobosJson = jsonObject.getJSONObject("hobos");
this.hobos = new Hobos(hobosJson.getJSONObject("ingredients_count")
.toMap()
.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> (Integer)entry.getValue()
)),
hobosJson.getJSONObject("hobos_stealing_time")
.toMap()
.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> (Integer)entry.getValue()
)),
(int)hobosJson.get("eating_time"), this);
}

public Tunnel getTunnel() {
return tunnel;
}

public Hobos getHobos() {
return hobos;
}

public ShipGenerator getShipGenerator() {
return shipGenerator;
}

public ArrayList<Cargo> getCargos() {
return cargos;
}

public ArrayList<Dock> getDocks() {
return docks;
}
}
34 changes: 34 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/Controller/Program.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package by.Dzenia.docks_and_hobos.Controller;
import by.Dzenia.docks_and_hobos.RunnableObjects.Dock;
import java.io.IOException;
import java.util.ArrayList;

public class Program implements Runnable{
private final Model model;
public Program(String pathToFile) throws IOException {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем помечать его Runnable если это нигде не используется?

this.model = new Model(pathToFile);
}

public void start() {
run();
}
@Override
public void run() {
ArrayList<Thread> threads = new ArrayList<>();
threads.add(new Thread(model.getShipGenerator()));
for (Dock dock: model.getDocks()) {
threads.add(new Thread(dock));
}
threads.add(new Thread(model.getHobos()));
for (Thread thread: threads) {
thread.start();
}
for (Thread thread: threads) {
try {
thread.join();
} catch (InterruptedException ignored) {

}
}
}
}
55 changes: 55 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/CustomLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package by.Dzenia.docks_and_hobos;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.*;

public class CustomLogger extends Logger {
private static CustomLogger instance;
private static final int FILE_COUNT = 5;
private static final int MAX_FILE_SIZE_BYTES = 100_000;
protected CustomLogger(String name, String resourceBundleName) {
super(name, resourceBundleName);
}
public static CustomLogger getLogger(String name) {
if (instance == null) {
instance = new CustomLogger(name, null);
instance.configureLogger();
}
return instance;
}

private String getLogFileName() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String timestamp = dateFormat.format(new Date());
return "lab-02/by/Dzenia/docks_and_hobos/logs/log_" + timestamp + ".log";

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Никогда не вшивайте имена в код, сделайте какой-нибудь доп параметр.

}
private void configureLogger() {
setLevel(Level.CONFIG);
try {
// Используем FileHandler с шаблоном времени для имени файла
String logFilePath = getLogFileName();
FileHandler fileHandler = new FileHandler(logFilePath, MAX_FILE_SIZE_BYTES, FILE_COUNT, false);
fileHandler.setFormatter(new CustomFormatter());
addHandler(fileHandler);

ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(new CustomFormatter());
addHandler(consoleHandler);
} catch (IOException e) {
e.printStackTrace();
}
}

static class CustomFormatter extends Formatter {
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public String format(LogRecord record) {
return dateFormat.format(new Date(record.getMillis())) +
" " +
record.getLevel() +
" " +
record.getMessage() + "\n";
}
}
}
15 changes: 15 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package by.Dzenia.docks_and_hobos;
import by.Dzenia.docks_and_hobos.Controller.Program;
import java.io.IOException;
import java.util.logging.*;
public class Main {
private static final Logger logger = CustomLogger.getLogger("all");
public static void main(String[] args) throws IOException {
if (args.length != 1) {
throw new IllegalArgumentException("Must be only one arg!");
}
logger.log(Level.CONFIG, "Path=" + args[0]);
Program program = new Program(args[0]);
program.start();
}
}
13 changes: 13 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/Persons/Cargo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package by.Dzenia.docks_and_hobos.Persons;

public class Cargo {
private final String type;

public Cargo(String type) {
this.type = type;
}

public String getType() {
return type;
}
}
19 changes: 19 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/Persons/Ship.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package by.Dzenia.docks_and_hobos.Persons;

public class Ship {
private final Cargo cargo;
private final int weight;

public Ship(String cargoType, int weight) {
cargo = new Cargo(cargoType);
this.weight = weight;
}

public Cargo getCargo() {
return cargo;
}

public int getWeight() {
return weight;
}
}
31 changes: 31 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/Persons/Tunnel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package by.Dzenia.docks_and_hobos.Persons;
import by.Dzenia.docks_and_hobos.CustomLogger;
import java.util.*;
import java.util.logging.Level;

public class Tunnel {

private final Queue<Ship> queue = new LinkedList<>();
private final int maxShips;
private final CustomLogger logger = CustomLogger.getLogger("all");

public Tunnel(int maxShips) {
this.maxShips = maxShips;
}

public synchronized void addShip(Ship ship) {
if (queue.size() == maxShips) {
logger.log(Level.INFO, "Ship go down with cargo=" + ship.getCargo().getType() + ", weight=" + ship.getWeight());
return;
}
queue.add(ship);
notify();
}

public synchronized Ship getShip() throws InterruptedException {
if (queue.isEmpty()) {
wait();
}
return queue.remove();
}
}
70 changes: 70 additions & 0 deletions lab-02/by/Dzenia/docks_and_hobos/RunnableObjects/Dock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package by.Dzenia.docks_and_hobos.RunnableObjects;

import by.Dzenia.docks_and_hobos.Controller.Model;
import by.Dzenia.docks_and_hobos.CustomLogger;
import by.Dzenia.docks_and_hobos.Persons.Ship;

import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import static java.lang.Math.max;
import static java.lang.Math.min;

public class Dock implements Runnable {
private final HashMap<String, Integer> dockCapacity;
private final HashMap<String, Integer> currentWeight = new HashMap<>();
private final Logger logger = CustomLogger.getLogger("all");
private final int speed;
private final Model model;

public Dock(int speed, HashMap<String, Integer> dockCapacity, Model model) {
if (speed <= 0) {
throw new IllegalArgumentException("Speed should be positive");
}
for (Integer capacity: dockCapacity.values()) {
if (capacity < 0) {
throw new IllegalArgumentException("Cargo capacity should be none negative");
}
}
this.dockCapacity = dockCapacity;
this.speed = speed;
this.model = model;
for (String typeCargo: dockCapacity.keySet()) {
currentWeight.put(typeCargo, 0);
}
}

public synchronized Integer stealCargo(String cargo, Integer count) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут лучше тогда тоже указывать synchronized (currentWeight).

if (!currentWeight.containsKey(cargo)) {
return 0;
}
Integer was = currentWeight.get(cargo);
currentWeight.put(cargo, max(was - count, 0));
return was - currentWeight.get(cargo);
}


private void shipUnloading(Ship ship) throws InterruptedException {
logger.log(Level.INFO, "Ship come to dock cargo=" + ship.getCargo().getType() + ", weight=" + ship.getWeight());
Thread.sleep((int)(ship.getWeight() / speed) * 1000);
synchronized (currentWeight) {
Integer weight = currentWeight.get(ship.getCargo().getType());
currentWeight.put(ship.getCargo().getType(), min(
dockCapacity.get(ship.getCargo().getType()),
weight + (Integer) ship.getWeight()
));
}
}

@Override
public void run() {
while (true) {
try {
shipUnloading(model.getTunnel().getShip());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
Loading