diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/caching/Cache.java b/src/main/java/ca/recrown/islandsurvivalcraft/caching/Cache.java new file mode 100644 index 0000000..983b5fc --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/caching/Cache.java @@ -0,0 +1,40 @@ +package ca.recrown.islandsurvivalcraft.caching; + +import java.util.HashMap; +import java.util.PriorityQueue; + +public class Cache { + private final int maxCacheSize; + private final HashMap> dataCache; + private final PriorityQueue ids; + + public Cache(int maxCacheSize) { + dataCache = new HashMap<>(maxCacheSize); + ids = new PriorityQueue<>(maxCacheSize); + this.maxCacheSize = maxCacheSize; + } + + public CacheValue retrieveCache(Identifier identifier) { + if (dataCache.containsKey(identifier)) { + ids.remove(identifier); + dataCache.get(identifier); + CacheValue val = dataCache.get(identifier); + val.getValue(); + ids.add(val.identifier); + return dataCache.get(identifier); + } + if (ids.size() >= maxCacheSize) { + dataCache.remove(ids.poll()); + } + CacheValue value = new CacheValue<>(identifier); + ids.add(identifier); + dataCache.put(identifier, value); + + return value; + } + + public void clearCache() { + ids.clear(); + dataCache.clear(); + } +} \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/caching/CacheValue.java b/src/main/java/ca/recrown/islandsurvivalcraft/caching/CacheValue.java new file mode 100644 index 0000000..5b00335 --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/caching/CacheValue.java @@ -0,0 +1,25 @@ +package ca.recrown.islandsurvivalcraft.caching; + +public class CacheValue { + private ValueType value; + protected final Identifier identifier; + private boolean fresh = true; + + public CacheValue(Identifier identifier) { + this.identifier = identifier; + } + + public boolean isEmpty() { + return fresh; + } + + public void setValue(ValueType value) { + this.fresh = false; + this.value = value; + } + + public ValueType getValue() { + identifier.usage++; + return value; + } +} \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/caching/CoordinateIdentifier.java b/src/main/java/ca/recrown/islandsurvivalcraft/caching/CoordinateIdentifier.java new file mode 100644 index 0000000..1f5bafd --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/caching/CoordinateIdentifier.java @@ -0,0 +1,28 @@ +package ca.recrown.islandsurvivalcraft.caching; + +import java.util.Objects; + +public class CoordinateIdentifier extends Identifier { + private final int x; + private final int y; + + public CoordinateIdentifier(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CoordinateIdentifier) { + CoordinateIdentifier other = (CoordinateIdentifier) obj; + return x == other.x && y == other.y; + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + +} \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/caching/Identifier.java b/src/main/java/ca/recrown/islandsurvivalcraft/caching/Identifier.java new file mode 100644 index 0000000..20df26b --- /dev/null +++ b/src/main/java/ca/recrown/islandsurvivalcraft/caching/Identifier.java @@ -0,0 +1,16 @@ +package ca.recrown.islandsurvivalcraft.caching; + +public abstract class Identifier implements Comparable { + protected int usage; + + @Override + public abstract boolean equals(Object obj); + + @Override + public abstract int hashCode(); + + @Override + public int compareTo(Identifier o) { + return usage - o.usage; + } +} \ No newline at end of file diff --git a/src/test/java/ca/recrown/islandsurvivalcraft/caching/CacheTest.java b/src/test/java/ca/recrown/islandsurvivalcraft/caching/CacheTest.java new file mode 100644 index 0000000..95fe019 --- /dev/null +++ b/src/test/java/ca/recrown/islandsurvivalcraft/caching/CacheTest.java @@ -0,0 +1,63 @@ +package ca.recrown.islandsurvivalcraft.caching; + +import static org.junit.Assert.assertSame; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +@TestInstance(Lifecycle.PER_CLASS) +public class CacheTest { + Cache integerCache; + + @BeforeAll + public void setUp() { + integerCache = new Cache<>(3); + } + + @AfterEach + public void cleanUp() { + integerCache.clearCache(); + } + + @Test + public void testBasicCaching() { + CoordinateIdentifier coordsA = new CoordinateIdentifier(3, 0); + CoordinateIdentifier coordsB = new CoordinateIdentifier(4, 0); + + CacheValue val = integerCache.retrieveCache(coordsA); + assertTrue(val.isEmpty()); + val.setValue(0); + assertFalse(val.isEmpty()); + assertSame(val, integerCache.retrieveCache(coordsA)); + + val = integerCache.retrieveCache(coordsB); + assertTrue(val.isEmpty()); + val.setValue(1); + assertFalse(val.isEmpty()); + assertSame(val, integerCache.retrieveCache(coordsB)); + } + + @Test + public void testUsageBasedClean() { + integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).setValue(1); + integerCache.retrieveCache(new CoordinateIdentifier(2, 0)).setValue(2); + integerCache.retrieveCache(new CoordinateIdentifier(3, 0)).setValue(3); + + integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).getValue(); + + integerCache.retrieveCache(new CoordinateIdentifier(4, 0)).setValue(4); + + assertEquals(1, integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).getValue()); + + assertFalse(integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).isEmpty()); + + integerCache.retrieveCache(new CoordinateIdentifier(5, 0)).setValue(5); + assertFalse(integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).isEmpty()); + } +} \ No newline at end of file diff --git a/src/test/java/ca/recrown/islandsurvivalcraft/caching/CoordinateIdentifierTest.java b/src/test/java/ca/recrown/islandsurvivalcraft/caching/CoordinateIdentifierTest.java new file mode 100644 index 0000000..c188971 --- /dev/null +++ b/src/test/java/ca/recrown/islandsurvivalcraft/caching/CoordinateIdentifierTest.java @@ -0,0 +1,32 @@ +package ca.recrown.islandsurvivalcraft.caching; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +@TestInstance(Lifecycle.PER_CLASS) +public class CoordinateIdentifierTest { + Cache integerCache; + + @BeforeAll + public void setUp() { + integerCache = new Cache<>(4); + } + + @AfterEach + public void cleanUp() { + integerCache.clearCache(); + } + + @Test + public void testIdentityChecking() { + integerCache.retrieveCache(new CoordinateIdentifier(1, 2)).setValue(8); + integerCache.retrieveCache(new CoordinateIdentifier(1, 2)).setValue(4); + + assertEquals(4, integerCache.retrieveCache(new CoordinateIdentifier(1, 2)).getValue()); + } +} \ No newline at end of file