From 52039e9804783305eeafa0c8bc804f391aad0a70 Mon Sep 17 00:00:00 2001 From: ScarletRedMan Date: Thu, 11 Jan 2024 18:01:58 +0700 Subject: [PATCH] Implemented SequentialFillingPicker --- .../picker/model/type/SlotLimit.java | 2 +- .../service/impl/picker/ItemWrapper.java | 26 ++++++++++ .../picker/service/impl/picker/Picker.java | 12 +++++ .../service/impl/picker/RoomWrapper.java | 41 ++++++++++++++++ .../impl/picker/SequentialFillingPicker.java | 48 +++++++++++++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/ru/dragonestia/picker/service/impl/picker/ItemWrapper.java create mode 100644 app/src/main/java/ru/dragonestia/picker/service/impl/picker/Picker.java create mode 100644 app/src/main/java/ru/dragonestia/picker/service/impl/picker/RoomWrapper.java create mode 100644 app/src/main/java/ru/dragonestia/picker/service/impl/picker/SequentialFillingPicker.java diff --git a/app/src/main/java/ru/dragonestia/picker/model/type/SlotLimit.java b/app/src/main/java/ru/dragonestia/picker/model/type/SlotLimit.java index 62e419b..d5a11ba 100644 --- a/app/src/main/java/ru/dragonestia/picker/model/type/SlotLimit.java +++ b/app/src/main/java/ru/dragonestia/picker/model/type/SlotLimit.java @@ -7,7 +7,7 @@ import java.beans.Transient; @Getter public class SlotLimit { - private final static int UNLIMITED_VALUE = -1; + public final static int UNLIMITED_VALUE = -1; private final int slots; diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/picker/ItemWrapper.java b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/ItemWrapper.java new file mode 100644 index 0000000..029de6a --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/ItemWrapper.java @@ -0,0 +1,26 @@ +package ru.dragonestia.picker.service.impl.picker; + +import ru.dragonestia.picker.model.type.SlotLimit; + +public interface ItemWrapper { + + String getIdentifier(); + + int countUnits(); + + int maxUnits(); + + default boolean isFull() { + return maxUnits() != SlotLimit.UNLIMITED_VALUE && countUnits() >= maxUnits(); + } + + default boolean isEmpty() { + return countUnits() == 0; + } + + default boolean canAddUnits(int amount) { + return maxUnits() == SlotLimit.UNLIMITED_VALUE || countUnits() + amount < maxUnits(); + } + + ITEM getItem(); +} diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/picker/Picker.java b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/Picker.java new file mode 100644 index 0000000..273011e --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/Picker.java @@ -0,0 +1,12 @@ +package ru.dragonestia.picker.service.impl.picker; + +import java.util.Collection; + +public interface Picker { + + void add(ITEM item); + + void remove(ITEM item); + + ITEM pick(Collection units); +} diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/picker/RoomWrapper.java b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/RoomWrapper.java new file mode 100644 index 0000000..28a9f9c --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/RoomWrapper.java @@ -0,0 +1,41 @@ +package ru.dragonestia.picker.service.impl.picker; + +import ru.dragonestia.picker.model.Room; + +import java.util.function.Supplier; + +public class RoomWrapper implements ItemWrapper { + + private final Room room; + private final Supplier userCountSupplier; + + public RoomWrapper(Room room, Supplier userCountSupplier) { + this.room = room; + this.userCountSupplier = userCountSupplier; + } + + @Override + public String getIdentifier() { + return room.getId(); + } + + @Override + public int countUnits() { + return userCountSupplier.get(); + } + + @Override + public int maxUnits() { + return room.getSlots().getSlots(); + } + + @Override + public Room getItem() { + return room; + } + + @Override + public boolean canAddUnits(int amount) { + return ItemWrapper.super.canAddUnits(amount) && !room.isLocked(); + } +} diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/picker/SequentialFillingPicker.java b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/SequentialFillingPicker.java new file mode 100644 index 0000000..c95b3dd --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/service/impl/picker/SequentialFillingPicker.java @@ -0,0 +1,48 @@ +package ru.dragonestia.picker.service.impl.picker; + +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.User; +import ru.dragonestia.picker.repository.UserRepository; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +public class SequentialFillingPicker implements Picker { + + private final UserRepository userRepository; + private final Map wrappers = new LinkedHashMap<>(); + + public SequentialFillingPicker(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public void add(Room room) { + synchronized (wrappers) { + wrappers.put(room.getId(), new RoomWrapper(room, () -> userRepository.usersOf(room).size())); + } + } + + @Override + public void remove(Room room) { + synchronized (wrappers) { + wrappers.remove(room.getId()); + } + } + + @Override + public Room pick(Collection users) { + int amount = users.size(); + + synchronized (wrappers) { + for (var wrapper: wrappers.values()) { + if (wrapper.canAddUnits(amount)) continue; + + return wrapper.getItem(); + } + } + + throw new RuntimeException("There are no rooms available"); + } +}