Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions core/src/bms/player/beatoraja/modmenu/JudgeCountTracker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package bms.player.beatoraja.modmenu;

import bms.model.Mode;
import bms.player.beatoraja.play.JudgeResult;
import org.apache.commons.lang3.tuple.Pair;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Track the current judge count
*/
public class JudgeCountTracker {
// column count
private final int columnCount;
private final int[] scratchKeys;
// (column, judge) -> count
private final Map<Pair<Integer, JudgeResult>, AtomicInteger> counts = new ConcurrentHashMap<>();
// column -> (fast, slow)
private final Map<Integer, Pair<AtomicInteger, AtomicInteger>> fsCounts = new ConcurrentHashMap<>();

public JudgeCountTracker(Mode playMode) {
this.columnCount = playMode.key;
this.scratchKeys = playMode.scratchKey;
for (int i = 0; i < columnCount; i++) {
for (JudgeResult judge : JudgeResult.values()) {
counts.put(Pair.of(i, judge), new AtomicInteger());
}
fsCounts.put(i, Pair.of(new AtomicInteger(), new AtomicInteger()));
}
}

public void track(int lane, int judge, boolean fast, int count) {
JudgeResult judgeResult = JudgeResult.valueOf(judge, fast);
counts.get(Pair.of(lane, judgeResult)).addAndGet(count);
// TODO: Allow user define their own interval?
if (judgeResult != JudgeResult.EARLY_PGREAT && judgeResult != JudgeResult.LATE_PGREAT) {
Pair<AtomicInteger, AtomicInteger> fs = fsCounts.get(lane);
if (fast) {
fs.getLeft().incrementAndGet();
} else {
fs.getRight().incrementAndGet();
}
}
}

public int getCount(int lane, JudgeResult judge) {
return counts.get(Pair.of(lane, judge)).get();
}

public int getFastCount(int lane) {
return fsCounts.get(lane).getLeft().get();
}

public int getSlowCount(int lane) {
return fsCounts.get(lane).getRight().get();
}

public int getColumnCount() {
return columnCount;
}

public int[] getScratchKeys() {
return scratchKeys;
}
}
14 changes: 14 additions & 0 deletions core/src/bms/player/beatoraja/modmenu/JudgeTrainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@

import bms.model.Mode;
import bms.player.beatoraja.play.BMSPlayerRule;
import org.apache.commons.lang3.tuple.Pair;

import java.util.HashMap;
import java.util.Map;

public class JudgeTrainer {
public static final String[] JUDGE_OPTIONS = new String[]{
"EASY", "NORMAL", "HARD", "VERY_HARD"
};
private static boolean active;
private static int judgeRank = 0;
// NOTE: judgeCountTracker must have an initialized value to allow mod menu draw the table
private static volatile JudgeCountTracker judgeCountTracker = new JudgeCountTracker(Mode.BEAT_7K);

public static boolean isActive() {
return active;
Expand Down Expand Up @@ -37,5 +43,13 @@ public static int getJudgeWindowRate(Mode mode) {
BMSPlayerRule rule = BMSPlayerRule.getBMSPlayerRule(mode);
return rule.judge.windowrule.judgerank[3 - judgeRank];
}

public static void setJudgeCountTracker(JudgeCountTracker judgeCountTracker) {
JudgeTrainer.judgeCountTracker = judgeCountTracker;
}

public static JudgeCountTracker getJudgeCountTracker() {
return judgeCountTracker;
}
}

79 changes: 79 additions & 0 deletions core/src/bms/player/beatoraja/modmenu/JudgeTrainerMenu.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,47 @@
package bms.player.beatoraja.modmenu;

import bms.player.beatoraja.play.JudgeResult;
import imgui.ImGui;
import imgui.flag.ImGuiCond;
import imgui.flag.ImGuiTableFlags;
import imgui.flag.ImGuiWindowFlags;
import imgui.type.ImBoolean;
import imgui.type.ImInt;

import java.util.Arrays;

import static bms.player.beatoraja.modmenu.ImGuiRenderer.windowHeight;
import static bms.player.beatoraja.modmenu.ImGuiRenderer.windowWidth;

public class JudgeTrainerMenu {
private static ImBoolean OVERRIDE_CHART_JUDGE = new ImBoolean(false);
private static ImInt OVERRIDE_JUDGE_RANK = new ImInt(0);

private enum JudgeCountRow {
PGREAT("PGREAT", new JudgeResult[]{JudgeResult.EARLY_PGREAT, JudgeResult.LATE_PGREAT}),
GREAT("GREAT", new JudgeResult[]{JudgeResult.EARLY_GREAT, JudgeResult.LATE_GREAT}),
GOOD("GOOD", new JudgeResult[]{JudgeResult.EARLY_GOOD, JudgeResult.LATE_GOOD}),
BAD("BAD", new JudgeResult[]{JudgeResult.EARLY_BAD, JudgeResult.LATE_BAD}),
POOR("POOR", new JudgeResult[]{JudgeResult.EARLY_POOR, JudgeResult.LATE_POOR}),
EPOOR("EPOOR", new JudgeResult[]{JudgeResult.EARLY_MISS});

private final String name;
private final JudgeResult[] correspondingJudgeResults;

JudgeCountRow(String name, JudgeResult[] correspondingJudgeResults) {
this.name = name;
this.correspondingJudgeResults = correspondingJudgeResults;
}

public String getName() {
return name;
}

public JudgeResult[] getCorrespondingJudgeResults() {
return correspondingJudgeResults;
}
}

public static void show(ImBoolean showJudgeTrainer) {
float relativeX = windowWidth * 0.455f;
float relativeY = windowHeight * 0.04f;
Expand All @@ -25,7 +54,57 @@ public static void show(ImBoolean showJudgeTrainer) {
if (ImGui.combo("judge", OVERRIDE_JUDGE_RANK, JudgeTrainer.JUDGE_OPTIONS)) {
JudgeTrainer.setJudgeRank(OVERRIDE_JUDGE_RANK.get());
}
renderJudgeCountTable();
ImGui.end();
}
}

private static void renderJudgeCountTable() {
JudgeCountTracker tracker = JudgeTrainer.getJudgeCountTracker();
int columnCount = tracker.getColumnCount();
int[] scratchKeys = tracker.getScratchKeys();
if (ImGui.beginTable("Judge Count", columnCount + 1, ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY, 0, ImGui.getTextLineHeight() * 20)) {
ImGui.tableSetupColumn("/");
for (int i = 0; i < columnCount; i++) {
int finalI = i;
boolean isScratchKey = Arrays.stream(scratchKeys).anyMatch(lane -> lane == finalI);
if (isScratchKey) {
ImGui.tableSetupColumn(String.format("%d(SC)", i));
} else {
ImGui.tableSetupColumn(String.valueOf(i));
}
}
ImGui.tableHeadersRow();
// Judgements
for (JudgeCountRow row : JudgeCountRow.values()) {
ImGui.tableNextRow();
ImGui.tableNextColumn();
ImGui.text(row.getName());
for (int i = 0;i < columnCount; ++i) {
ImGui.tableNextColumn();
int finalI = i;
int count = Arrays.stream(row.getCorrespondingJudgeResults())
.mapToInt(judgeResult -> tracker.getCount(finalI, judgeResult))
.sum();
ImGui.text(String.valueOf(count));
}
}
// Fast/Slow
ImGui.tableNextRow();
ImGui.tableNextColumn();
ImGui.text("Fast");
for (int i = 0;i < columnCount; ++i) {
ImGui.tableNextColumn();
ImGui.text(String.valueOf(tracker.getFastCount(i)));
}
ImGui.tableNextRow();
ImGui.tableNextColumn();
ImGui.text("Slow");
for (int i = 0;i < columnCount; ++i) {
ImGui.tableNextColumn();
ImGui.text(String.valueOf(tracker.getSlowCount(i)));
}
ImGui.endTable();
}
}
}
6 changes: 6 additions & 0 deletions core/src/bms/player/beatoraja/play/JudgeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.Arrays;
import java.util.stream.IntStream;

import bms.player.beatoraja.modmenu.JudgeCountTracker;
import bms.player.beatoraja.modmenu.JudgeTrainer;
import com.badlogic.gdx.utils.FloatArray;

import bms.model.*;
Expand Down Expand Up @@ -35,6 +37,7 @@ public class JudgeManager {
* 現在の判定カウント内訳
*/
private ScoreData score = new ScoreData();
private JudgeCountTracker judgeCountTracker;

/**
* 現在のコンボ数
Expand Down Expand Up @@ -146,6 +149,8 @@ public void init(BMSModel model, PlayerResource resource) {
score = new ScoreData(orgmode);
score.setNotes(model.getTotalNotes());
score.setSha256(model.getSHA256());
judgeCountTracker = new JudgeCountTracker(orgmode);
JudgeTrainer.setJudgeCountTracker(judgeCountTracker);
ghost = new int[model.getTotalNotes()];
for (int i=0; i<ghost.length; i++) {
ghost[i] = 4;
Expand Down Expand Up @@ -706,6 +711,7 @@ private void updateMicro(LaneState state, Note n, long mtime, int judge, long mf
}
n.setMicroPlayTime(mfast);
score.addJudgeCount(judge, mfast >= 0, 1);
judgeCountTracker.track(state.lane, judge, mfast >= 0, 1);

if (judge < 4) {
recentJudgesIndex = (recentJudgesIndex + 1) % recentJudges.length;
Expand Down
56 changes: 56 additions & 0 deletions core/src/bms/player/beatoraja/play/JudgeResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package bms.player.beatoraja.play;

public enum JudgeResult {
EARLY_PGREAT("EARLY_PGREAT", 6),
LATE_PGREAT("LATE_PGREAT", 7),
EARLY_GREAT("EARLY_GREAT", 8),
LATE_GREAT("LATE_GREAT", 9),
EARLY_GOOD("EARLY_GOOD", 10),
LATE_GOOD("LATE_GOOD", 11),
EARLY_BAD("EARLY_BAD", 12),
LATE_BAD("LATE_BAD", 13),
EARLY_POOR("EARLY_POOR", 14),
LATE_POOR("LATE_POOR", 15),
EARLY_MISS("EARLY_MISS", 16),
LATE_MISS("LATE_MISS", 17);

private final String name;
private final int value;

JudgeResult(String name, int value) {
this.name = name;
this.value = value;
}

public static JudgeResult valueOf(int value, boolean isFast) {
return switch (value) {
case 0 -> isFast ? EARLY_PGREAT : LATE_PGREAT;
case 1 -> isFast ? EARLY_GREAT : LATE_GREAT;
case 2 -> isFast ? EARLY_GOOD : LATE_GOOD;
case 3 -> isFast ? EARLY_BAD : LATE_BAD;
case 4 -> isFast ? EARLY_POOR : LATE_POOR;
case 5 -> isFast ? EARLY_MISS : LATE_MISS;
case 6 -> EARLY_PGREAT;
case 7 -> LATE_PGREAT;
case 8 -> EARLY_GREAT;
case 9 -> LATE_GREAT;
case 10 -> EARLY_GOOD;
case 11 -> LATE_GOOD;
case 12 -> EARLY_BAD;
case 13 -> LATE_BAD;
case 14 -> EARLY_POOR;
case 15 -> LATE_POOR;
case 16 -> EARLY_MISS;
case 17 -> LATE_MISS;
default -> throw new IllegalArgumentException();
};
}

public String getName() {
return name;
}

public int getValue() {
return value;
}
}