-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5982cc1
commit 1039481
Showing
28 changed files
with
1,311 additions
and
0 deletions.
There are no files selected for viewing
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,16 @@ | ||
plugins { | ||
id 'java' | ||
} | ||
|
||
group 'com.github.paul1365972' | ||
version '1.0.0' | ||
|
||
sourceCompatibility = 1.8 | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
testImplementation group: 'junit', name: 'junit', version: '4.12' | ||
} |
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 @@ | ||
rootProject.name = 'LoRDeckCoder' |
59 changes: 59 additions & 0 deletions
59
src/main/java/io/github/paul1365972/lordeckcoder/LoRDeckCoder.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,59 @@ | ||
package io.github.paul1365972.lordeckcoder; | ||
|
||
import io.github.paul1365972.lordeckcoder.coder.FormatVersion; | ||
import io.github.paul1365972.lordeckcoder.coder.LoRCoder; | ||
import io.github.paul1365972.lordeckcoder.coder.LoRDecoder; | ||
import io.github.paul1365972.lordeckcoder.exceptions.LoRCodingException; | ||
import io.github.paul1365972.lordeckcoder.objects.impl.LoRCard; | ||
import io.github.paul1365972.lordeckcoder.objects.impl.LoRDeck; | ||
import io.github.paul1365972.lordeckcoder.util.Base32; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.util.function.Supplier; | ||
|
||
public class LoRDeckCoder { | ||
|
||
private static final LoRDecoder<LoRDeck> BASIC_DECODER = LoRDecoder.from(LoRDeck::new, | ||
(deck, set, factionId, cardNumber, amount) -> | ||
deck.addCards(new LoRCard(set, factionId, cardNumber), amount) | ||
); | ||
|
||
public static LoRDeck toDeck(String code) throws LoRCodingException { | ||
return toDeck(code, BASIC_DECODER); | ||
} | ||
|
||
public static <T> T toDeck(String code, LoRDecoder<T> decoder) throws LoRCodingException { | ||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
Base32.decode(code, baos::write); | ||
return toDeck(baos.toByteArray(), decoder); | ||
} | ||
|
||
public static LoRDeck toDeck(byte[] bytes) throws LoRCodingException { | ||
return toDeck(bytes, BASIC_DECODER); | ||
} | ||
|
||
public static <T> T toDeck(byte[] bytes, LoRDecoder<T> decoder) throws LoRCodingException { | ||
return LoRCoder.decode(bytesToSupplier(bytes), decoder); | ||
} | ||
|
||
public static String toCode(LoRDeck deck, FormatVersion formatVersion) throws LoRCodingException { | ||
return Base32.encode(bytesToSupplier(toCodeBytes(deck, formatVersion))); | ||
} | ||
|
||
public static byte[] toCodeBytes(LoRDeck deck, FormatVersion formatVersion) throws LoRCodingException { | ||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
LoRCoder.encode(deck, formatVersion, baos::write); | ||
return baos.toByteArray(); | ||
} | ||
|
||
private static Supplier<Byte> bytesToSupplier(byte[] bytes) { | ||
return new Supplier<Byte>() { | ||
int index = 0; | ||
|
||
@Override | ||
public Byte get() { | ||
return index < bytes.length ? bytes[index++] : null; | ||
} | ||
}; | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/io/github/paul1365972/lordeckcoder/coder/FormatVersion.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,54 @@ | ||
package io.github.paul1365972.lordeckcoder.coder; | ||
|
||
import java.util.Objects; | ||
|
||
public class FormatVersion { | ||
|
||
public static final FormatVersion F01V01 = new FormatVersion(1, 1); | ||
public static final FormatVersion LIVE = F01V01, PBE = F01V01, EXPERIMENTAL = F01V01; | ||
|
||
|
||
private byte formatVersion; | ||
|
||
public FormatVersion(byte formatVersion) { | ||
this.formatVersion = formatVersion; | ||
} | ||
|
||
public FormatVersion(int format, int version) { | ||
this((byte) ((version << 4) | format)); | ||
} | ||
|
||
public byte getPacked() { | ||
return formatVersion; | ||
} | ||
|
||
public int getFormat() { | ||
return formatVersion & 0xF; | ||
} | ||
|
||
public int getVersion() { | ||
return (formatVersion >> 4) & 0xF; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "FormatVersion{" + | ||
"format=" + getFormat() + | ||
", version=" + getVersion() + | ||
'}'; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
FormatVersion that = (FormatVersion) o; | ||
return getPacked() == that.getPacked(); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(getPacked()); | ||
} | ||
|
||
} |
43 changes: 43 additions & 0 deletions
43
src/main/java/io/github/paul1365972/lordeckcoder/coder/LoRCoder.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,43 @@ | ||
package io.github.paul1365972.lordeckcoder.coder; | ||
|
||
import io.github.paul1365972.lordeckcoder.exceptions.LoRCodingException; | ||
import io.github.paul1365972.lordeckcoder.exceptions.LoRUnsupportedFormatException; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRCardI; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRDeckI; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRFactionI; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.function.Consumer; | ||
import java.util.function.Supplier; | ||
|
||
public class LoRCoder { | ||
|
||
private static final Map<FormatVersion, LoRFormatter> FORMATS = new HashMap<>(); | ||
|
||
static { | ||
register(new LoRFormat01Ver01()); | ||
} | ||
|
||
public static <T> T decode(Supplier<Byte> bytes, LoRDecoder<T> decoder) throws LoRCodingException { | ||
FormatVersion formatVersion = new FormatVersion(bytes.get()); | ||
return get(formatVersion).decode(bytes, decoder); | ||
} | ||
|
||
public static <T extends LoRCardI<U>, U extends LoRFactionI> void encode(LoRDeckI<T, U> deck, FormatVersion formatVersion, Consumer<Byte> builder) throws LoRUnsupportedFormatException { | ||
builder.accept(formatVersion.getPacked()); | ||
get(formatVersion).encode(deck, builder); | ||
} | ||
|
||
public static LoRFormatter get(FormatVersion formatVersion) throws LoRUnsupportedFormatException { | ||
LoRFormatter formatter = FORMATS.get(formatVersion); | ||
if (formatter == null) | ||
throw new LoRUnsupportedFormatException("Unsupported Deck Format/Version " + formatVersion.getFormat() + "/" + formatVersion.getVersion()); | ||
return formatter; | ||
} | ||
|
||
public static void register(LoRFormatter formatter) { | ||
FORMATS.put(formatter.getFormatVersion(), formatter); | ||
} | ||
|
||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/io/github/paul1365972/lordeckcoder/coder/LoRDecoder.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,31 @@ | ||
package io.github.paul1365972.lordeckcoder.coder; | ||
|
||
import io.github.paul1365972.lordeckcoder.exceptions.LoRCodingException; | ||
|
||
import java.util.function.Function; | ||
|
||
public interface LoRDecoder<T> { | ||
|
||
static <T> LoRDecoder<T> from(Function<FormatVersion, T> deckFactory, CardAccumulator<T> accumulator) { | ||
return new LoRDecoder<T>() { | ||
@Override | ||
public T createDeck(FormatVersion formatVersion) { | ||
return deckFactory.apply(formatVersion); | ||
} | ||
|
||
@Override | ||
public void addCard(T deck, int set, int factionId, int cardNumber, int amount) throws LoRCodingException { | ||
accumulator.accept(deck, set, factionId, cardNumber, amount); | ||
} | ||
}; | ||
} | ||
|
||
T createDeck(FormatVersion formatVersion) throws LoRCodingException; | ||
|
||
void addCard(T deck, int set, int factionId, int cardNumber, int amount) throws LoRCodingException; | ||
|
||
@FunctionalInterface | ||
interface CardAccumulator<T> { | ||
void accept(T deck, int set, int factionId, int cardNumber, int amount) throws LoRCodingException; | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
src/main/java/io/github/paul1365972/lordeckcoder/coder/LoRFormat01Ver01.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,75 @@ | ||
package io.github.paul1365972.lordeckcoder.coder; | ||
|
||
import io.github.paul1365972.lordeckcoder.exceptions.LoRCodingException; | ||
import io.github.paul1365972.lordeckcoder.exceptions.LoRIllegalFormatException; | ||
import io.github.paul1365972.lordeckcoder.exceptions.LoRUnsupportedFormatException; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRCardI; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRDeckI; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRFactionI; | ||
import io.github.paul1365972.lordeckcoder.util.CheckedSupplier; | ||
import io.github.paul1365972.lordeckcoder.util.VarInt; | ||
|
||
import java.math.BigInteger; | ||
import java.util.*; | ||
import java.util.function.Consumer; | ||
import java.util.function.Supplier; | ||
|
||
public class LoRFormat01Ver01 implements LoRFormatter { | ||
|
||
public static final FormatVersion FORMAT_VERSION = new FormatVersion(1, 1); | ||
|
||
public <T, U> T decode(Supplier<Byte> bytes, LoRDecoder<T> deserializer) throws LoRCodingException { | ||
CheckedSupplier<BigInteger, LoRCodingException> supplier = () -> Optional | ||
.ofNullable(VarInt.toBigInt(bytes)) | ||
.orElseThrow(() -> new LoRIllegalFormatException("Reached end of stream unexpectedly")); | ||
|
||
T deck = deserializer.createDeck(FORMAT_VERSION); | ||
try { | ||
for (int cards = 3; cards > 0; cards--) { | ||
int setFactionGroups = supplier.get().intValueExact(); | ||
for (int i = 0; i < setFactionGroups; i++) { | ||
int setFactionLength = supplier.get().intValueExact(); | ||
int set = supplier.get().intValueExact(); | ||
int faction = supplier.get().intValueExact(); | ||
for (int j = 0; j < setFactionLength; j++) { | ||
int cardNumber = supplier.get().intValueExact(); | ||
deserializer.addCard(deck, set, faction, cardNumber, cards); | ||
} | ||
} | ||
} | ||
} catch (ArithmeticException e) { | ||
throw new LoRUnsupportedFormatException("VarInt-Optimization overflowed"); | ||
} | ||
return deck; | ||
} | ||
|
||
@Override | ||
public <T extends LoRCardI<U>, U extends LoRFactionI> void encode(LoRDeckI<T, U> deck, Consumer<Byte> builder) { | ||
Consumer<BigInteger> consumer = varInt -> VarInt.toBytes(varInt, builder); | ||
|
||
Map<Integer, List<T>> amountCardsMap = new HashMap<>(); | ||
deck.getCards().forEach((card, amount) -> amountCardsMap.computeIfAbsent(amount, k -> new ArrayList<>()).add(card)); | ||
for (int amount = 3; amount >= 1; amount--) { | ||
List<T> cards = amountCardsMap.getOrDefault(amount, Collections.emptyList()); | ||
Map<SetFaction, List<T>> setFactionCardsMap = new HashMap<>(); | ||
cards.forEach(card -> setFactionCardsMap.computeIfAbsent(new SetFaction(card.getSet(), card.getFaction()), k -> new ArrayList<>()).add(card)); | ||
consumer.accept(BigInteger.valueOf(setFactionCardsMap.size())); | ||
setFactionCardsMap.entrySet().stream() | ||
.sorted(Comparator.comparing(entry -> entry.getValue().size())) | ||
.forEach(entry -> { | ||
consumer.accept(BigInteger.valueOf(entry.getValue().size())); | ||
consumer.accept(BigInteger.valueOf(entry.getKey().getSet())); | ||
consumer.accept(BigInteger.valueOf(entry.getKey().getFaction().getId())); | ||
entry.getValue().stream() | ||
.sorted(Comparator.comparing(LoRCardI::getCardCode)) | ||
.forEach(card -> consumer.accept(BigInteger.valueOf(card.getCardNumber()))); | ||
}); | ||
} | ||
} | ||
|
||
@Override | ||
public FormatVersion getFormatVersion() { | ||
return FORMAT_VERSION; | ||
} | ||
|
||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/io/github/paul1365972/lordeckcoder/coder/LoRFormatter.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 io.github.paul1365972.lordeckcoder.coder; | ||
|
||
import io.github.paul1365972.lordeckcoder.exceptions.LoRCodingException; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRCardI; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRDeckI; | ||
import io.github.paul1365972.lordeckcoder.objects.LoRFactionI; | ||
|
||
import java.util.function.Consumer; | ||
import java.util.function.Supplier; | ||
|
||
public interface LoRFormatter { | ||
|
||
<T, U> T decode(Supplier<Byte> bytes, LoRDecoder<T> decoder) throws LoRCodingException; | ||
|
||
<T extends LoRCardI<U>, U extends LoRFactionI> void encode(LoRDeckI<T, U> deck, Consumer<Byte> builder); | ||
|
||
FormatVersion getFormatVersion(); | ||
|
||
} |
37 changes: 37 additions & 0 deletions
37
src/main/java/io/github/paul1365972/lordeckcoder/coder/SetFaction.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,37 @@ | ||
package io.github.paul1365972.lordeckcoder.coder; | ||
|
||
import io.github.paul1365972.lordeckcoder.objects.LoRFactionI; | ||
|
||
import java.util.Objects; | ||
|
||
class SetFaction { | ||
private int set; | ||
private LoRFactionI faction; | ||
|
||
public SetFaction(int set, LoRFactionI faction) { | ||
this.set = set; | ||
this.faction = Objects.requireNonNull(faction); | ||
} | ||
|
||
public int getSet() { | ||
return set; | ||
} | ||
|
||
public LoRFactionI getFaction() { | ||
return faction; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
SetFaction that = (SetFaction) o; | ||
return getSet() == that.getSet() && | ||
getFaction() == that.getFaction(); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(getSet(), getFaction()); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/io/github/paul1365972/lordeckcoder/exceptions/LoRCodingException.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,21 @@ | ||
package io.github.paul1365972.lordeckcoder.exceptions; | ||
|
||
public class LoRCodingException extends Exception { | ||
|
||
public LoRCodingException() { | ||
super(); | ||
} | ||
|
||
public LoRCodingException(String message) { | ||
super(message); | ||
} | ||
|
||
public LoRCodingException(String message, Throwable cause) { | ||
super(message, cause); | ||
} | ||
|
||
public LoRCodingException(Throwable cause) { | ||
super(cause); | ||
} | ||
|
||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/io/github/paul1365972/lordeckcoder/exceptions/LoRIllegalFormatException.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,21 @@ | ||
package io.github.paul1365972.lordeckcoder.exceptions; | ||
|
||
public class LoRIllegalFormatException extends LoRCodingException { | ||
|
||
public LoRIllegalFormatException() { | ||
super(); | ||
} | ||
|
||
public LoRIllegalFormatException(String message) { | ||
super(message); | ||
} | ||
|
||
public LoRIllegalFormatException(String message, Throwable cause) { | ||
super(message, cause); | ||
} | ||
|
||
public LoRIllegalFormatException(Throwable cause) { | ||
super(cause); | ||
} | ||
|
||
} |
Oops, something went wrong.