Skip to content

Commit

Permalink
Merge pull request #95 from ExeRSolver/calibration-enhancements
Browse files Browse the repository at this point in the history
Calibration enhancements
  • Loading branch information
Ninjabrain1 authored Jun 3, 2024
2 parents 65bcda6 + d313a3e commit 7085c7e
Show file tree
Hide file tree
Showing 24 changed files with 237 additions and 102 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,10 @@
<artifactId>jna-platform</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math4-legacy</artifactId>
<version>4.0-beta1</version>
</dependency>
</dependencies>
</project>
69 changes: 53 additions & 16 deletions src/main/java/ninjabrainbot/gui/frames/CalibrationDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import ninjabrainbot.model.datastate.calibrator.ICalibratorFactory;
import ninjabrainbot.model.datastate.endereye.IEnderEyeThrow;
import ninjabrainbot.util.I18n;
import org.apache.commons.statistics.distribution.ChiSquaredDistribution;

public class CalibrationDialog extends ThemedDialog {

Expand All @@ -46,18 +47,22 @@ public class CalibrationDialog extends ThemedDialog {
final Histogram hist;
final JPanel rightPanel;
final JLabel std;
final JLabel confidenceInterval;
static final int errorAreaWidth = 100;
static final int errorAreaHeight = 80;
private final IActionExecutor actionExecutor;
private final boolean isManualCalibrator;

public CalibrationDialog(StyleManager styleManager, NinjabrainBotPreferences preferences, ICalibratorFactory calibratorFactory, IActionExecutor actionExecutor, JFrame owner) {
super(styleManager, preferences, owner, getTitle(preferences));
public CalibrationDialog(StyleManager styleManager, NinjabrainBotPreferences preferences, ICalibratorFactory calibratorFactory, IActionExecutor actionExecutor, JFrame owner, boolean isManualCalibrator) {
super(styleManager, preferences, owner, getTitle(preferences, isManualCalibrator));
this.actionExecutor = actionExecutor;
styleManager.registerThemedDialog(this);
this.styleManager = styleManager;
this.preferences = preferences;
this.owner = owner;
this.isManualCalibrator = isManualCalibrator;
actionExecutor.disable();
calibrator = disposeHandler.add(calibratorFactory.createCalibrator(isBoatCalibrator(preferences)));
calibrator = disposeHandler.add(calibratorFactory.createCalibrator(isBoatCalibrator(preferences), isManualCalibrator));

JPanel panel2 = new JPanel();
panel2.setOpaque(false);
Expand All @@ -68,8 +73,12 @@ public CalibrationDialog(StyleManager styleManager, NinjabrainBotPreferences pre
panel.setBorder(new EmptyBorder(OptionsFrame.PADDING, OptionsFrame.PADDING, OptionsFrame.PADDING, OptionsFrame.PADDING));
add(panel);

labels = new InstructionLabel[] { new InstructionLabel(styleManager, I18n.get("calibrator.command_label")), new InstructionLabel(styleManager, I18n.get("calibrator.throw_label")),
new InstructionLabel(styleManager, I18n.get("calibrator.measure_label")), };
if (isManualCalibrator)
labels = new InstructionLabel[] { new InstructionLabel(styleManager, I18n.get("calibrator.command_label_manual")), new InstructionLabel(styleManager, I18n.get("calibrator.throw_label_manual")),
new InstructionLabel(styleManager, I18n.get("calibrator.measure_label")), };
else
labels = new InstructionLabel[] { new InstructionLabel(styleManager, I18n.get("calibrator.command_label")), new InstructionLabel(styleManager, I18n.get("calibrator.throw_label")),
new InstructionLabel(styleManager, I18n.get("calibrator.measure_label")), };
ThemedLabel explanation = new ThemedLabel(styleManager, "<html><div style='text-align: center;'>" + I18n.get("calibrator.explanation") + "</div></html>") {
@Override
public int getTextSize(SizePreference p) {
Expand All @@ -83,22 +92,30 @@ public int getTextSize(SizePreference p) {
panel.add(l);
}
errors = new ErrorTextArea(styleManager, new JTextArea());
errors.setPreferredSize(new Dimension(errorAreaWidth, errorAreaWidth));
errors.setPreferredSize(new Dimension(errorAreaWidth, errorAreaHeight));
rightPanel = new JPanel();
rightPanel.setOpaque(false);
rightPanel.setLayout(new GridLayout(3, 1, 0, 0));
rightPanel.setLayout(new GridLayout(5, 1, 0, 0));
std = new ThemedLabel(styleManager);
std.setOpaque(false);
std.setPreferredSize(new Dimension(errorAreaWidth, errorAreaWidth));
std.setPreferredSize(new Dimension(errorAreaWidth, 40));
confidenceInterval = new ThemedLabel(styleManager);
confidenceInterval.setOpaque(false);
confidenceInterval.setPreferredSize(new Dimension(errorAreaWidth, 40));
JLabel l1 = new ThemedLabel(styleManager, I18n.get("calibrator.l1"));
JLabel ciLabel = new ThemedLabel(styleManager, I18n.get("calibrator.confidence_interval"));
JButton done = new FlatButton(styleManager, I18n.get("calibrator.done"));
done.addActionListener(p -> done());
l1.setHorizontalAlignment(SwingConstants.CENTER);
ciLabel.setHorizontalAlignment(SwingConstants.CENTER);
std.setHorizontalAlignment(SwingConstants.CENTER);
confidenceInterval.setHorizontalAlignment(SwingConstants.CENTER);
rightPanel.add(l1);
rightPanel.add(std);
rightPanel.add(ciLabel);
rightPanel.add(confidenceInterval);
rightPanel.add(done);
hist = new Histogram(styleManager, -0.03f, 0.03f, 11);
hist = new Histogram(styleManager, 11);
panel2.add(errors, BorderLayout.LINE_START);
panel2.add(hist, BorderLayout.CENTER);
panel2.add(rightPanel, BorderLayout.LINE_END);
Expand All @@ -108,17 +125,19 @@ public int getTextSize(SizePreference p) {

public void startCalibrating() {
std.setText("-");
confidenceInterval.setText("(-, -)");
setHighlighted(0);
}

private void done() {
if (calibrator.isStrongholdDetermined()) {
float std = (float) calibrator.getSTD(preferences.mcVersion.get());
if (isBoatCalibrator(preferences)) {
if (isBoatCalibrator(preferences))
preferences.sigmaBoat.set(std);
} else {
else if (isManualCalibrator)
preferences.sigmaManual.set(std);
else
preferences.sigma.set(std);
}
}
dispose();
}
Expand All @@ -132,7 +151,7 @@ private void setHighlighted(int i) {

private void updateUI() {
int stage = 0;
if (calibrator.isReady()) {
if (calibrator.isReadyToCalibrate()) {
if (calibrator.getNumThrows() > 0) {
stage = 2;
} else {
Expand All @@ -145,7 +164,9 @@ private void updateUI() {

private void updateHistogram() {
if (calibrator.isStrongholdDetermined()) {
std.setText(String.format("%.4f", calibrator.getSTD(preferences.mcVersion.get())));
double sampleSTD = calibrator.getSTD(preferences.mcVersion.get());
std.setText(String.format(isBoatCalibrator(preferences) ? "%.5f" : "%.4f", sampleSTD));
confidenceInterval.setText(getConfidenceInterval(sampleSTD));
StringBuilder b = new StringBuilder();
double[] angleErrors = calibrator.getErrors(preferences.mcVersion.get());
IReadOnlyList<IEnderEyeThrow> eyeThrows = calibrator.getThrows();
Expand Down Expand Up @@ -175,12 +196,28 @@ private void updateHistogram() {
}
}

private String getConfidenceInterval(double sampleSTD) {
int degreesOfFreedom = calibrator.getThrows().size() - 1;
ChiSquaredDistribution chiSquared = ChiSquaredDistribution.of(degreesOfFreedom);

double significanceLevel = 0.25;
double lowerBound = sampleSTD * Math.sqrt(degreesOfFreedom / chiSquared.inverseCumulativeProbability(1 - significanceLevel / 2));
double upperBound = sampleSTD * Math.sqrt(degreesOfFreedom / chiSquared.inverseCumulativeProbability(significanceLevel / 2));

return String.format(isBoatCalibrator(preferences) ? "(%.5f, %.5f)" : "(%.4f, %.4f)", lowerBound, upperBound);
}

private static boolean isBoatCalibrator(NinjabrainBotPreferences preferences) {
return preferences.usePreciseAngle.get();
}

private static String getTitle(NinjabrainBotPreferences preferences) {
return I18n.get("calibrator.title") + (isBoatCalibrator(preferences) ? String.format(" (%s)", I18n.get("settings.boat_standard_deviation")) : "");
private static String getTitle(NinjabrainBotPreferences preferences, boolean isManualCalibrator) {
if (isBoatCalibrator(preferences))
return I18n.get("calibrator.title_boat");
else if (isManualCalibrator)
return I18n.get("calibrator.title_manual");
else
return I18n.get("calibrator.title");
}

@Override
Expand Down
40 changes: 30 additions & 10 deletions src/main/java/ninjabrainbot/gui/options/Histogram.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class Histogram extends ThemedPanel {

private int[] counts;
private int maxCount;
private final float min;
private final float max;
private float min;
private float max;
private final int numBins;

final ArrayList<JLabel> ticks;
Expand All @@ -28,26 +28,44 @@ public class Histogram extends ThemedPanel {

private final WrappedColor histCol;
private final WrappedColor lineCol;
private final StyleManager styleManager;

public Histogram(StyleManager styleManager, float min, float max, int numBins) {
public Histogram(StyleManager styleManager, int numBins) {
super(styleManager);
this.min = min;
this.max = max;
this.numBins = numBins;
counts = new int[numBins];
maxCount = 0;
ticks = new ArrayList<>();
floatTicks = new ArrayList<>();
addTick(styleManager, 0);
addTick(styleManager, min);
addTick(styleManager, max);

histCol = styleManager.currentTheme.COLOR_SATURATED;
lineCol = styleManager.currentTheme.COLOR_DIVIDER_DARK;
this.styleManager = styleManager;
}

private void addTick(StyleManager styleManager, float tick) {
ThemedLabel l = new ThemedLabel(styleManager, "" + tick);
private void updateBounds(double[] angleErrors) {
max = 0;
for (double error : angleErrors) {
double positiveError = Math.abs(error);
int digits = (int) Math.floor(Math.log10(positiveError));
float roundedError = (float) (Math.ceil(positiveError / Math.pow(10, digits)) * Math.pow(10, digits));
max = Math.max(max, roundedError);
}
min = -max;
}

private void updateTicks() {
this.removeAll();
ticks.clear();
floatTicks.clear();

addTick(0);
addTick(min);
addTick(max);
}

private void addTick(float tick) {
ThemedLabel l = new ThemedLabel(this.styleManager, "" + tick);
ticks.add(l);
floatTicks.add(tick);
add(l);
Expand Down Expand Up @@ -94,6 +112,8 @@ public void updateColors() {
public void setData(double[] angleErrors) {
counts = new int[numBins];
maxCount = 0;
updateBounds(angleErrors);
updateTicks();
for (double d : angleErrors) {
addData((float) d);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import ninjabrainbot.event.DisposeHandler;
import ninjabrainbot.gui.buttons.FlatButton;
import ninjabrainbot.gui.components.layout.StackPanel;
import ninjabrainbot.gui.components.panels.ThemedPanel;
import ninjabrainbot.gui.components.preferences.CheckboxPanel;
import ninjabrainbot.gui.components.preferences.DoublePreferencePanel;
import ninjabrainbot.gui.components.preferences.FloatPreferencePanel;
Expand Down Expand Up @@ -61,10 +60,22 @@ public int getTextSize(SizePreference p) {
return p.TEXT_SIZE_SMALL;
}
};
calibrateButton.addActionListener(p -> startCalibrating());
calibrateButton.addActionListener(p -> startCalibrating(false));
calibrateButton.setAlignmentX(0.5f);
column1.add(calibrateButton);
column1.add(new FloatPreferencePanel(styleManager, I18n.get("settings.standard_deviation_manual"), preferences.sigmaManual));

FloatPreferencePanel sigmaManualPanel = new FloatPreferencePanel(styleManager, I18n.get("settings.standard_deviation_manual"), preferences.sigmaManual);
column1.add(sigmaManualPanel);
JButton manualCalibrateButton = new FlatButton(styleManager, I18n.get("settings.calibrate_standard_deviation_manual")) {
@Override
public int getTextSize(SizePreference p) {
return p.TEXT_SIZE_SMALL;
}
};
manualCalibrateButton.addActionListener(p -> startCalibrating(true));
manualCalibrateButton.setAlignmentX(0.5f);
column1.add(manualCalibrateButton);

column1.add(new CheckboxPanel(styleManager, I18n.get("settings.enable_standard_deviation_toggle"), preferences.useAltStd));
sigmaAlt = new FloatPreferencePanel(styleManager, I18n.get("settings.alt_standard_deviation"), preferences.sigmaAlt);
sigmaAlt.setEnabled(preferences.useAltStd.get());
Expand All @@ -83,10 +94,11 @@ public int getTextSize(SizePreference p) {

disposeHandler.add(preferences.useAltStd.whenModified().subscribeEDT(this::setAltSigmaEnabled));
disposeHandler.add(preferences.sigma.whenModified().subscribeEDT(sigmaPanel::updateValue));
disposeHandler.add(preferences.sigmaManual.whenModified().subscribeEDT(sigmaManualPanel::updateValue));
}

private void startCalibrating() {
CalibrationDialog d = new CalibrationDialog(styleManager, preferences, calibratorFactory, actionExecutor, owner);
private void startCalibrating(boolean isManualCalibrator) {
CalibrationDialog d = new CalibrationDialog(styleManager, preferences, calibratorFactory, actionExecutor, owner, isManualCalibrator);
d.setLocation(owner.getX() - 140, owner.getY() + 30);
styleManager.init();
SwingUtilities.invokeLater(() -> d.setVisible(true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public BoatMeasurementOptionsPanel(StyleManager styleManager, NinjabrainBotPrefe
column1.add(boatErrorLimit);

sigmaBoat = new FloatPreferencePanel(styleManager, I18n.get("settings.boat_standard_deviation"), preferences.sigmaBoat);
sigmaBoat.setDecimals(5);
column1.add(sigmaBoat);

disposeHandler.add(preferences.usePreciseAngle.whenModified().subscribeEDT(this::setPreciseAngleEnabled));
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ninjabrainbot/io/KeyPresser.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ public void paste(String s) throws InterruptedException {
robot.keyPress(CTRL_KEYCODE);
Thread.sleep(50);
robot.keyPress(KeyEvent.VK_V);
Thread.sleep(60);
robot.keyRelease(CTRL_KEYCODE);
Thread.sleep(50);
robot.keyRelease(KeyEvent.VK_V);
}

public void releaseF3C() {
robot.keyRelease(KeyEvent.VK_F3);
public void releaseC() {
robot.keyRelease(KeyEvent.VK_C);
}

Expand Down
Loading

0 comments on commit 7085c7e

Please sign in to comment.