Skip to content

Commit

Permalink
releaseb add predictions
Browse files Browse the repository at this point in the history
  • Loading branch information
Sammers21 committed Apr 20, 2024
1 parent 6441dd4 commit 847cade
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 37 deletions.
10 changes: 10 additions & 0 deletions src/io/github/sammers/pla/blizzard/Cutoffs.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class Cutoffs implements JsonConvertable {
public final String region;
public final String season;
public final Map<String, Long> cutoffs;
public final Map<String, Long> cutoffsPredictions = new HashMap<>();
public final Long timestamp;
public final Map<String, Long> spotsCounts = new HashMap<>();
public final Map<String, Long> spotWithNoAlts = new HashMap<>();
Expand All @@ -38,6 +39,10 @@ public Cutoffs(
this.spotWithNoAlts.putAll(spotWithNoAlts);
}

public void setPrediction(String bracket, long rating) {
cutoffsPredictions.put(bracket, rating);
}

public void setSpotWithNoAlts(String bracket, long count) {
spotWithNoAlts.put(bracket, (long)count);
}
Expand Down Expand Up @@ -148,6 +153,11 @@ public JsonObject toJson() {
.put("spotWithNoAlts", new JsonObject(spotWithNoAlts.entrySet().stream().map(x -> Map.entry(x.getKey(), x.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));
}

public JsonObject toJsonWithPredictions() {
return toJson()
.put("predictions", new JsonObject(cutoffsPredictions.entrySet().stream().map(x -> Map.entry(x.getKey(), x.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));
}

public static Cutoffs fromJson(JsonObject json) {
return new Cutoffs(
json.getString("region"),
Expand Down
156 changes: 122 additions & 34 deletions src/io/github/sammers/pla/db/Snapshot.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.sammers.pla.db;


import io.github.sammers.pla.Main;
import io.github.sammers.pla.blizzard.Cutoffs;
import io.github.sammers.pla.blizzard.Realms;
Expand All @@ -21,6 +20,8 @@

public record Snapshot(List<Character> characters, Long timestamp, String region, String dateTime) implements Resp {

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Snapshot.class);

public List<Character> findChar(String fullName) {
return characters.stream().filter(c -> c.fullName().equals(fullName)).toList();
}
Expand All @@ -44,41 +45,127 @@ public Snapshot filter(final List<String> specs) {
boolean res = false;
for (String spec : specs) {
res = res || c.fullSpec().toLowerCase().replaceAll(" ", "").replaceAll("'", "")
.contains(spec.toLowerCase().replaceAll(" ", "").replaceAll("'", ""));
.contains(spec.toLowerCase().replaceAll(" ", "").replaceAll("'", ""));
}
return res;
}).sorted(Comparator.comparing(Character::rating).reversed()).toList();
return new Snapshot(chars, timestamp, region, dateTime);
}

public JsonObject toJson(Long page) {
List<JsonObject> chars = characters.stream().skip((page - 1) * 100L).limit(100).map(JsonConvertable::toJson).toList();
List<JsonObject> chars = characters.stream().skip((page - 1) * 100L).limit(100).map(JsonConvertable::toJson)
.toList();
return new JsonObject()
.put("characters", new JsonArray(chars))
.put("timestamp", timestamp)
.put("date_time", dateTime)
.put("region", region)
.put("page", page)
.put("total_pages", Calculator.totalPages(this.characters().size(), 100))
.put("last_seen", Main.PRETTY_TIME.format(new Date(timestamp)));
.put("characters", new JsonArray(chars))
.put("timestamp", timestamp)
.put("date_time", dateTime)
.put("region", region)
.put("page", page)
.put("total_pages", Calculator.totalPages(this.characters().size(), 100))
.put("last_seen", Main.PRETTY_TIME.format(new Date(timestamp)));
}

public JsonObject toJson() {
List<JsonObject> chars = characters.stream().map(JsonConvertable::toJson).toList();
return new JsonObject()
.put("characters", new JsonArray(chars))
.put("timestamp", timestamp)
.put("date_time", dateTime)
.put("region", region)
.put("last_seen", Main.PRETTY_TIME.format(new Date(timestamp)));
.put("characters", new JsonArray(chars))
.put("timestamp", timestamp)
.put("date_time", dateTime)
.put("region", region)
.put("last_seen", Main.PRETTY_TIME.format(new Date(timestamp)));
}

public static Snapshot fromJson(JsonObject entries) {
Long ts = entries.getLong("timestamp");
Instant instant = Instant.ofEpochMilli(ts);
ZonedDateTime zonedDateTime = instant.atZone(UTC);
String format = Main.DATA_TIME.format(zonedDateTime);
return new Snapshot(entries.getJsonArray("characters").stream().map(x -> (JsonObject) x).map(Character::fromJson).toList(), ts, entries.getString("region"), format);
return new Snapshot(
entries.getJsonArray("characters").stream().map(x -> (JsonObject) x).map(Character::fromJson).toList(),
ts, entries.getString("region"), format);
}

public void predictCutoffs(String bracket, Cutoffs cutoffs) {
if (cutoffs == null) {
return;
}
if (bracket.equals(THREE_V_THREE)) {
Map<Integer, List<Character>> countedAlready = new HashMap<>();
Character last = null;
Long spots = cutoffs.spotWithNoAlts.get("ARENA_3v3");
for (int i = 0; i < characters.size() && countedAlready.size() < spots; i++) {
last = characters.get(i);
Character finalLast = last;
Integer petHash = last.pethash().map(p -> p == -1 ? finalLast.fullNameWSpec().hashCode() : p)
.orElse(last.fullNameWSpec().hashCode());
countedAlready.compute(petHash, (k, v) -> {
if (v == null) {
v = new ArrayList<>();
}
v.add(finalLast);
return v;
});
}
if (last != null) {
cutoffs.setPrediction("ARENA_3v3", last.rating());
} else {
log.error("No characters found for 3v3");
}
} else if (bracket.equals(RBG)) {
Map<Integer, List<Character>> countedAlready = new HashMap<>();
Character last = null;
Long spots = cutoffs.spotWithNoAlts.get("BATTLEGROUNDS/alliance");
for (int i = 0; i < characters.size() && countedAlready.size() < spots; i++) {
last = characters.get(i);
Character finalLast = last;
Integer petHash = last.pethash().map(p -> p == -1 ? finalLast.fullNameWSpec().hashCode() : p)
.orElse(last.fullNameWSpec().hashCode());
countedAlready.compute(petHash, (k, v) -> {
if (v == null) {
v = new ArrayList<>();
}
v.add(finalLast);
return v;
});
}
if (last != null) {
cutoffs.setPrediction("BATTLEGROUNDS/alliance", last.rating());
cutoffs.setPrediction("BATTLEGROUNDS/horde", last.rating());
} else {
log.error("No characters found for RBG");
}
} else if (bracket.equals(SHUFFLE)) {
Map<String, Map<Integer, List<Character>>> countedAlready = new HashMap<>();
Map<String, Character> last = new HashMap<>();
for (Character ch : characters) {
String fullSpec = ch.fullSpec();
String specCode = Cutoffs.specCodeByFullName(fullSpec);
Long spots = cutoffs.spotWithNoAlts.get("SHUFFLE/" + specCode);
Map<Integer, List<Character>> countedG = countedAlready.get(specCode);
if (countedG != null && countedG.size() >= spots) {
continue;
}
Integer petHash = ch.pethash().map(p -> p == -1 ? ch.fullNameWSpec().hashCode() : p)
.orElse(ch.fullNameWSpec().hashCode());
countedAlready.compute(specCode, (k, v) -> {
if (v == null) {
v = new HashMap<>();
}
v.compute(petHash, (k1, v1) -> {
if (v1 == null) {
v1 = new ArrayList<>();
}
v1.add(ch);
return v1;
});
return v;
});
last.put(specCode, ch);
}
last.forEach((spec, ch) -> {
cutoffs.setPrediction("SHUFFLE/" + spec, ch.rating());
});
}
}

public Snapshot applyCutoffs(String bracket, Cutoffs cutoffs) {
Expand All @@ -99,12 +186,12 @@ public Snapshot applyCutoffs(String bracket, Cutoffs cutoffs) {
List<Character> charsInCutoff = chars.stream().filter(Character::inCutoff).toList();
cutoffs.setSpotCount("ARENA_3v3", charsWithCutoff.intValue());
Map<Integer, List<Character>> petHashes = charsInCutoff.stream()
.collect(Collectors.groupingBy(ch -> {
if (ch.pethash().isEmpty() || ch.pethash().get() == -1) {
return ch.fullNameWSpec().hashCode();
}
return ch.pethash().get();
}));
.collect(Collectors.groupingBy(ch -> {
if (ch.pethash().isEmpty() || ch.pethash().get() == -1) {
return ch.fullNameWSpec().hashCode();
}
return ch.pethash().get();
}));
cutoffs.setSpotWithNoAlts("ARENA_3v3", petHashes.size());
return new Snapshot(chars, this.timestamp(), this.region(), this.dateTime());
} else if (bracket.equals(RBG)) {
Expand All @@ -119,13 +206,13 @@ public Snapshot applyCutoffs(String bracket, Cutoffs cutoffs) {
}
}).collect(Collectors.toList());
Map<Integer, List<Character>> petHashes = chars.stream()
.filter(Character::inCutoff)
.collect(Collectors.groupingBy(ch -> {
if (ch.pethash().isEmpty() || ch.pethash().get() == -1) {
return ch.fullNameWSpec().hashCode();
}
return ch.pethash().get();
}));
.filter(Character::inCutoff)
.collect(Collectors.groupingBy(ch -> {
if (ch.pethash().isEmpty() || ch.pethash().get() == -1) {
return ch.fullNameWSpec().hashCode();
}
return ch.pethash().get();
}));
cutoffs.setSpotCount("BATTLEGROUNDS/alliance", charsWithCutoff.intValue());
cutoffs.setSpotCount("BATTLEGROUNDS/horde", charsWithCutoff.intValue());
cutoffs.setSpotWithNoAlts("BATTLEGROUNDS/alliance", petHashes.size());
Expand All @@ -147,7 +234,8 @@ public Snapshot applyCutoffs(String bracket, Cutoffs cutoffs) {
if (v == null) {
v = new HashMap<>();
}
Integer petHash = ch.pethash().map(p -> p == -1 ? ch.fullNameWSpec().hashCode() : p).orElse(ch.fullNameWSpec().hashCode());
Integer petHash = ch.pethash().map(p -> p == -1 ? ch.fullNameWSpec().hashCode() : p)
.orElse(ch.fullNameWSpec().hashCode());
v.compute(petHash, (k1, v1) -> {
if (v1 == null) {
v1 = new ArrayList<>();
Expand All @@ -163,10 +251,10 @@ public Snapshot applyCutoffs(String bracket, Cutoffs cutoffs) {
}
}).collect(Collectors.toList());
specCodeAndSpotCount.entrySet()
.forEach((var cutoff) -> {
cutoffs.setSpotWithNoAlts("SHUFFLE/" + cutoff.getKey(), petHashes.get(cutoff.getKey()).size());
cutoffs.setSpotCount("SHUFFLE/" + cutoff.getKey(), cutoff.getValue().intValue());
});
.forEach((var cutoff) -> {
cutoffs.setSpotWithNoAlts("SHUFFLE/" + cutoff.getKey(), petHashes.get(cutoff.getKey()).size());
cutoffs.setSpotCount("SHUFFLE/" + cutoff.getKey(), cutoff.getValue().intValue());
});
return new Snapshot(chars, this.timestamp(), this.region(), this.dateTime());
}
return this;
Expand Down
2 changes: 1 addition & 1 deletion src/io/github/sammers/pla/http/Http.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void start() {
JsonObject res = new JsonObject().put("2v2", twos).put("3v3", threes).put("rbg", rbgs).put("shuffle", shuffle);
Cutoffs cutoffs = ladder.regionCutoffFromDb.get(region);
if (cutoffs != null) {
res.put("cutoffs", cutoffs.toJson());
res.put("cutoffs", cutoffs.toJsonWithPredictions());
}
ctx.response().end(res.encode());
});
Expand Down
11 changes: 9 additions & 2 deletions src/io/github/sammers/pla/logic/Ladder.java
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,15 @@ private Completable loadCutoffsFromDb(String region) {
log.info("Load cutoffs from DB for region " + region);
return db.getLastCutoffs(realRegion(region)).map(cutoffs -> {
if (cutoffs.isPresent()) {
regionCutoffFromDb.put(oldRegion(region), cutoffs.get());
regionCutoffFromDb.put(realRegion(region), cutoffs.get());
Cutoffs ctf = cutoffs.get();
List.of(TWO_V_TWO, THREE_V_THREE, RBG, SHUFFLE).forEach(bracket -> {
Snapshot s = refs.refByBracket(bracket, region).get();
if (s != null) {
s.predictCutoffs(bracket, ctf);
}
});
regionCutoffFromDb.put(oldRegion(region), ctf);
regionCutoffFromDb.put(realRegion(region), ctf);
}
return cutoffs;
}).doOnSuccess(cutoffs -> log.info("Cutoffs from DB for region={} has been loaded", region))
Expand Down

0 comments on commit 847cade

Please sign in to comment.