-
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add item/stack count calculations (part of next master branch update)
- Loading branch information
1 parent
3aa8fce
commit 21c8bf4
Showing
3 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/item/Container.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.tisawesomeness.minecord.mc.item; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
/** | ||
* A container that can hold one or more stacks of Minecraft items. | ||
*/ | ||
@Getter | ||
@RequiredArgsConstructor | ||
public enum Container { | ||
STACK(1), | ||
CHEST(27), | ||
DOUBLE_CHEST(2 * 27), | ||
CHEST_SHULKER(27 * 27), | ||
DOUBLE_CHEST_SHULKER(2 * 27 * 27); | ||
|
||
private final int slots; | ||
} |
102 changes: 102 additions & 0 deletions
102
minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/item/ItemCount.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package com.tisawesomeness.minecord.mc.item; | ||
|
||
import lombok.Getter; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.List; | ||
|
||
/** | ||
* A specific number of Minecraft items. Item count may be negative. | ||
*/ | ||
public class ItemCount { | ||
|
||
private final long itemCount; | ||
@Getter private final int stackSize; | ||
|
||
/** | ||
* Creates a new item count. | ||
* @param itemCount number of starting items | ||
* @param stackSize stack size of the item | ||
* @throws IllegalArgumentException if the stack size is not within 1-64 | ||
*/ | ||
public ItemCount(long itemCount, int stackSize) { | ||
this.itemCount = itemCount; | ||
if (stackSize < 1 || 64 < stackSize) { | ||
throw new IllegalArgumentException("stackSize must be between 1 and 64 but was " + stackSize); | ||
} | ||
this.stackSize = stackSize; | ||
|
||
} | ||
|
||
/** | ||
* Creates a new item count with the added items and same stack size. | ||
* @param items number of items to add | ||
* @return new item count | ||
*/ | ||
public ItemCount addItems(long items) { | ||
return new ItemCount(itemCount + items, stackSize); | ||
} | ||
/** | ||
* Creates a new item count with the added stacks and same stack size. | ||
* @param stacks number of stacks to add | ||
* @return new item count | ||
*/ | ||
public ItemCount addStacks(long stacks) { | ||
return addItems(stackSize * stacks); | ||
} | ||
/** | ||
* Creates a new item count, adding the given number of containers, keeping the same stack size. | ||
* @param container container holding the items | ||
* @param count number of containers to add | ||
* @return new item count | ||
*/ | ||
public ItemCount addContainers(Container container, long count) { | ||
return addStacks(container.getSlots() * count); | ||
} | ||
|
||
/** | ||
* @return item count | ||
*/ | ||
public long getCount() { | ||
return itemCount; | ||
} | ||
|
||
/** | ||
* Gets the exact number of containers needed to hold this item count. | ||
* @param container container holding the items | ||
* @return number of containers, possibly fractional | ||
*/ | ||
public double getExact(Container container) { | ||
return (double) itemCount / (stackSize * container.getSlots()); | ||
} | ||
|
||
/** | ||
* Computes a combination of containers that holds this item count. | ||
* Containers with higher capacities are prioritized. | ||
* <br>Example: 1863 items is equal to 1 chest, 2 stacks, 7 items. | ||
* @param containers containers allowed to be used | ||
* @return list of length {@code containers.size() + 1}, each element is the amount of containers necessary in | ||
* descending order, and one extra element at the end for leftover items (above example would return | ||
* {@code [1, 2, 7]}) | ||
*/ | ||
public List<Long> distribute(Collection<Container> containers) { | ||
long stacks = itemCount / stackSize; | ||
long items = itemCount % stackSize; | ||
|
||
List<Long> list = new ArrayList<>(); | ||
for (int i = Container.values().length - 1; i >= 0; i--) { | ||
Container container = Container.values()[i]; | ||
if (containers.contains(container)) { | ||
|
||
list.add(stacks / container.getSlots()); | ||
stacks %= container.getSlots(); | ||
|
||
} | ||
} | ||
|
||
list.add(items); | ||
return list; | ||
} | ||
|
||
} |
116 changes: 116 additions & 0 deletions
116
minecord-bot/src/test/java/com/tisawesomeness/minecord/mc/item/ItemCountTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package com.tisawesomeness.minecord.mc.item; | ||
|
||
import com.tisawesomeness.minecord.util.Mth; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
import java.util.EnumSet; | ||
import java.util.Set; | ||
|
||
import static org.assertj.core.api.Assertions.*; | ||
|
||
public class ItemCountTest { | ||
|
||
@ParameterizedTest | ||
@ValueSource(longs = {0, 1, 5, 65}) | ||
public void testNew(long count) { | ||
assertThat(new ItemCount(count, 64).getCount()) | ||
.isEqualTo(count); | ||
} | ||
@ParameterizedTest | ||
@ValueSource(ints = {0, 65}) | ||
public void testNewInvalid(int stackSize) { | ||
assertThatThrownBy(() -> new ItemCount(0, stackSize)) | ||
.isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(longs = {-1, 0, 1, 65}) | ||
public void testAddItems(long count) { | ||
assertThat(new ItemCount(5, 64).addItems(count).getCount()) | ||
.isEqualTo(5 + count); | ||
} | ||
@ParameterizedTest | ||
@CsvSource({ | ||
"0, 64, 1, 64", | ||
"2, 1, 5, 7", | ||
"37, 16, 5, 117", | ||
"15, 64, -2, -113" | ||
}) | ||
public void testAddStacks(long initialCount, int stackSize, long stacks, long expectedCount) { | ||
assertThat(new ItemCount(initialCount, stackSize).addStacks(stacks).getCount()) | ||
.isEqualTo(expectedCount); | ||
} | ||
@ParameterizedTest | ||
@CsvSource({ | ||
"0, 64, STACK, 1, 64", | ||
"0, 64, CHEST, -2, -3456", | ||
"7, 16, DOUBLE_CHEST, 5, 4327", | ||
"-165, 64, CHEST_SHULKER, 1, 46491", | ||
"9164, 64, DOUBLE_CHEST_SHULKER, 3, 289100" | ||
}) | ||
public void testAddContainers(long initialCount, int stackSize, Container container, long count, long expectedCount) { | ||
assertThat(new ItemCount(initialCount, stackSize).addContainers(container, count).getCount()) | ||
.isEqualTo(expectedCount); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource({ | ||
"0, 64, STACK, 0.0", | ||
"32, 64, STACK, 0.5", | ||
"63, 64, STACK, 0.984375", | ||
"64, 64, STACK, 1.0", | ||
"128, 64, STACK, 2.0", | ||
"-63, 64, STACK, -0.984375", | ||
"2, 16, STACK, 0.125", | ||
"83, 1, STACK, 83.0", | ||
"27000, 64, CHEST, 15.625", | ||
"27000, 64, DOUBLE_CHEST, 7.8125", | ||
"139968, 64, CHEST_SHULKER, 3.0", | ||
"93312, 64, DOUBLE_CHEST_SHULKER, 1.0" | ||
}) | ||
public void testExact(long count, int stackSize, Container container, double expected) { | ||
assertThat(new ItemCount(count, stackSize).getExact(container)) | ||
.isCloseTo(expected, within(Mth.EPSILON)); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource({ | ||
"0, 64, 0, 0", | ||
"2, 64, 0, 2", | ||
"2, 1, 2, 0", | ||
"69, 64, 1, 5", | ||
"1863, 64, 29, 7", | ||
"-1863, 64, -29, -7" | ||
}) | ||
public void testDistributeStack(long count, int stackSize, long stacks, long items) { | ||
assertThat(new ItemCount(count, stackSize).distribute(EnumSet.of(Container.STACK))) | ||
.containsExactly(stacks, items); | ||
} | ||
@ParameterizedTest | ||
@CsvSource({ | ||
"0, 64, 0, 0, 0", | ||
"27, 1, 1, 0, 0", | ||
"1863, 64, 1, 2, 7", | ||
"-1863, 64, -1, -2, -7" | ||
}) | ||
public void testDistributeChest(long count, int stackSize, long chests, long stacks, long items) { | ||
assertThat(new ItemCount(count, stackSize).distribute(EnumSet.of(Container.STACK, Container.CHEST))) | ||
.containsExactly(chests, stacks, items); | ||
} | ||
@ParameterizedTest | ||
@CsvSource({ | ||
"0, 64, 0, 0, 0, 0, 0, 0", | ||
"99999, 64, 1, 0, 1, 1, 23, 31", | ||
"-99999, 64, -1, 0, -1, -1, -23, -31" | ||
}) | ||
public void testDistributeAll(long count, int stackSize, long doubleChestShulkers, long chestShulkers, | ||
long doubleChests, long chests, long stacks, long items) { | ||
Set<Container> containers = EnumSet.of(Container.STACK, Container.CHEST, Container.DOUBLE_CHEST, | ||
Container.CHEST_SHULKER, Container.DOUBLE_CHEST_SHULKER); | ||
assertThat(new ItemCount(count, stackSize).distribute(containers)) | ||
.containsExactly(doubleChestShulkers, chestShulkers, doubleChests, chests, stacks, items); | ||
} | ||
|
||
} |