Skip to content
This repository has been archived by the owner on Jan 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1082 from xZise/appraisal-improvement
Browse files Browse the repository at this point in the history
Fix appraisal measurement and other improvements
  • Loading branch information
nahojjjen committed Jun 17, 2020
2 parents 86f25c9 + 9d0b61a commit 547830c
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,11 @@ public void screenTouched() {
// Although, it's entirely possible for the user to touch the area below (or above) GoIV an unlimited number
// of times without actually ever starting the appraisal process

if (numTouches == 2) { // Second touch is usually the "Appraise" menu item.
if ((numTouches > 2) && (!autoAppraisalDone)) {
// Signal to the user that we're now looking for the first appraisal phase.
for (OnAppraisalEventListener eventListener : eventListeners) {
eventListener.highlightActiveUserInterface();
}
} else if ((numTouches > 2) && (!autoAppraisalDone)) {
// Scan Appraisal text after the configured delay.
autoScreenScanner.post();
}
Expand Down Expand Up @@ -104,9 +103,10 @@ private void addStatScanResult(@Nullable IVCombination combination) {
stamina = combination.sta;
staminaValid = true;
autoAppraisalDone = true;
for (OnAppraisalEventListener eventListener : eventListeners) {
eventListener.refreshSelection();
}
}
// Refresh the selection
for (OnAppraisalEventListener eventListener : eventListeners) {
eventListener.refreshSelection();
}
}

Expand Down Expand Up @@ -143,6 +143,7 @@ private class ScreenScan implements Runnable {

void post() {
barData = null;
retries = 0;
handler.removeCallbacks(this);
handler.postDelayed(this, initialDelay);
}
Expand All @@ -161,77 +162,107 @@ private void initScreen(Bitmap screen) {

Timber.d("Appraisal speech bubble top: %d", offset);

this.barLength = (int) (screen.getWidth() * 0.33f);
// Prevent rounding errors, especially as it gets multiplied by 15 again later
this.stepWidth = screen.getWidth() / 15.0f * 0.33f;
this.barStart = (int) (screen.getWidth() * 0.136f);

// We are at the top of the speech bubble, we can now just use the relative values from here
offset -= (int) (screen.getWidth() * 0.06f); // Offset should be now just below the first bar
this.barCenter = new int[STAT_COUNT];
for (int i = STAT_COUNT - 1; i >= 0; i--) {
boolean inside = false;
int bottom = -1;
do {
color = screen.getPixel((int) (this.barStart + this.stepWidth), offset);
if (!inside && color != COLOR_WHITE) {
bottom = offset;
inside = true;
}
offset -= 1;
}
while ((color == COLOR_WHITE) ^ inside);
// offset = top y of bar, bottom = bottom y of bar
this.barCenter[i] = offset + (bottom - offset) / 2;
offset -= (int) (screen.getWidth() * 0.06f);
Timber.d("Appraisal stat bar #%d: x=%d, y=%d", i, barStart, this.barCenter[i]);
// A vertical line through this point should go through the stat box
x = (int) (screen.getWidth() * 0.2f);
do {
color = screen.getPixel(x, offset);
offset--;
}
while (color != COLOR_WHITE);

this.barData = new int[3][this.barLength];
int left = x;
do {
color = screen.getPixel(left, offset);
left--;
}
while (color == COLOR_WHITE);
do {
x++;
color = screen.getPixel(x, offset);
}
while (color == COLOR_WHITE);
int boxWidth = x - left;
this.barLength = (int) (boxWidth * 0.762f);
this.barStart = left + (boxWidth - this.barLength) / 2;

// Arbitrary limit, each "step" should've at least a width of 3, otherwise there is something wrong.
if (this.barLength >= 15 * 3) {

int barSpacing = (int) (boxWidth * 0.22f);
this.barCenter = new int[STAT_COUNT];
int y = offset + barSpacing / 2;
for (int i = STAT_COUNT - 1; i >= 0; i--) {
y -= barSpacing;
this.barCenter[i] = y;
Timber.d("Appraisal stat bar #%d: y=%d", i, this.barCenter[i]);
}

// Prevent rounding errors, especially as it gets multiplied by 15 again later
this.stepWidth = this.barLength / 15.0f;
this.barData = new int[3][this.barLength];
} else {
this.barData = null;
}
}

@Override
public void run() {
Bitmap screen = screenGrabber.grabScreen();
if (screen != null) {
if (barData == null) {
initScreen(screen);
try {
initScreen(screen);
} catch (IllegalArgumentException e) {
this.barData = null; // Clear barData because there was an error
}
}

boolean change = false;
for (int i = this.barData.length - 1; i >= 0; i--) {
int[] buffer = new int[this.barLength];
screen.getPixels(buffer, 0, this.barLength, this.barStart, this.barCenter[i], this.barLength, 1);
if (!Arrays.equals(buffer, this.barData[i])) {
Timber.d("Appraisal stat bar #%d has changed", i);
change = true;
this.barData[i] = buffer;
boolean change;
if (this.barData != null) {
change = false;
for (int i = this.barData.length - 1; i >= 0; i--) {
int[] buffer = new int[this.barLength];
screen.getPixels(buffer, 0, this.barLength, this.barStart, this.barCenter[i], this.barLength, 1);
if (!Arrays.equals(buffer, this.barData[i])) {
Timber.d("Appraisal stat bar #%d has changed", i);
change = true;
this.barData[i] = buffer;
}
}
} else {
change = true;
}

if (change && retries < SCANRETRIES) {
retries++;
handler.postDelayed(this, RETRYDELAY);
} else {
int[] width = new int[this.barData.length];
// It scans them from the bottom to the top, so invert it either here to below in the creation
for (int i = 0; i < this.barData.length; i++) {
int color;
// The "do {} while" below loop increments it at least once
width[i] = -1;
do {
width[i]++;
color = this.barData[i][(int) (width[i] * this.stepWidth)];
}
while (OcrHelper.isInColorRange(color , COLOR_ORANGE, ALLOWED_DISTANCE));

if (OcrHelper.isInColorRange(color , COLOR_RED, ALLOWED_DISTANCE)) {
width[i] = 15;
} else if (!OcrHelper.isInColorRange(color, COLOR_GRAY, ALLOWED_DISTANCE)) {
Timber.d("Invalid scan on bar #%d (color %08x)", i, color);
width = null;
break;
int[] width;
if (this.barData == null) {
width = null;
} else {
width = new int[this.barData.length];
// It scans them from the bottom to the top, so invert it either here to below in the creation
for (int i = 0; i < this.barData.length; i++) {
int color;
// The "do {} while" below loop increments it at least once
width[i] = -1;
do {
width[i]++;
color = this.barData[i][(int) ((width[i] + 0.5) * this.stepWidth)];
}
while (OcrHelper.isInColorRange(color, COLOR_ORANGE, ALLOWED_DISTANCE));

if (OcrHelper.isInColorRange(color, COLOR_RED, ALLOWED_DISTANCE)) {
width[i] = 15;
} else if (!OcrHelper.isInColorRange(color, COLOR_GRAY, ALLOWED_DISTANCE)) {
Timber.d("Invalid scan on bar #%d (color %08x)", i, color);
width = null;
break;
}
}
}

if (width == null) {
addStatScanResult(null);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,20 @@ public void onCreate(@NonNull View rootView) {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (!insideUpdate) {
if (appraisalManager.attack != atkSeek.getProgress()) {
appraisalManager.attackValid = true;
}
appraisalManager.attack = atkSeek.getProgress();
if (appraisalManager.defense != defSeek.getProgress()) {
appraisalManager.defenseValid = true;
}
appraisalManager.defense = defSeek.getProgress();
if (appraisalManager.stamina != staSeek.getProgress()) {
appraisalManager.staminaValid = true;
}
appraisalManager.stamina = staSeek.getProgress();
updateIVPreviewInButton();
updateValueTexts();
}
updateValueTexts();
}

@Override
Expand Down Expand Up @@ -187,39 +195,42 @@ private void updateIVPreviewInButton() {

@OnCheckedChanged({R.id.atkEnabled, R.id.defEnabled, R.id.staEnabled})
public void onEnabled() {
atkSeek.setEnabled(atkEnabled.isChecked());
defSeek.setEnabled(defEnabled.isChecked());
staSeek.setEnabled(staEnabled.isChecked());
if (!insideUpdate) {
appraisalManager.attackValid = atkEnabled.isChecked();
appraisalManager.defenseValid = defEnabled.isChecked();
appraisalManager.staminaValid = staEnabled.isChecked();
updateIVPreviewInButton();
}
}

@Override
public void refreshSelection() {
setSpinnerSelection();
spinnerLayout.setBackground(null);
updateIVPreviewInButton();
}

/**
* Updates the checkboxes, labels and IV preview in the button.
*/
private void updateValueTexts() {
atkValue.setText(String.valueOf(appraisalManager.attack));
defValue.setText(String.valueOf(appraisalManager.defense));
staValue.setText(String.valueOf(appraisalManager.stamina));
atkEnabled.setChecked(appraisalManager.attackValid);
defEnabled.setChecked(appraisalManager.defenseValid);
staEnabled.setChecked(appraisalManager.staminaValid);
updateIVPreviewInButton();
}

/**
* Sets the progress bars and calls {@code updateValueTexts()}, mainly used to update it from the outside.
*/
private void setSpinnerSelection() {
insideUpdate = true;
updateValueTexts();
atkSeek.setProgress(appraisalManager.attack);
defSeek.setProgress(appraisalManager.defense);
staSeek.setProgress(appraisalManager.stamina);
atkEnabled.setChecked(appraisalManager.attackValid);
defEnabled.setChecked(appraisalManager.defenseValid);
staEnabled.setChecked(appraisalManager.staminaValid);
onEnabled();
insideUpdate = false;
}

Expand Down
44 changes: 10 additions & 34 deletions app/src/main/res/layout/fraction_appraisal.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,29 +81,21 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/atkEnabled"
android:text="@string/atk"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:text="@string/atk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/atkHeader"
app:layout_constraintBottom_toBottomOf="@+id/atkEnabled"
app:layout_constraintTop_toTopOf="@+id/atkEnabled"
app:layout_constraintStart_toEndOf="@+id/atkEnabled"
android:layout_marginStart="8dp"/>
<SeekBar
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="@+id/atkSeek"
android:layout_weight="1"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toEndOf="@+id/atkHeader"
app:layout_constraintStart_toEndOf="@+id/atkEnabled"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="@+id/atkHeader"
app:layout_constraintTop_toTopOf="@+id/atkHeader"
app:layout_constraintBottom_toBottomOf="@+id/atkEnabled"
app:layout_constraintTop_toTopOf="@+id/atkEnabled"
android:max="15"
app:layout_constraintEnd_toStartOf="@+id/atkValue"/>
<TextView
Expand All @@ -120,26 +112,18 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/defEnabled"
android:text="@string/def"
app:layout_constraintTop_toBottomOf="@+id/atkEnabled"
app:layout_constraintStart_toStartOf="@+id/atkEnabled"/>
<TextView
android:text="@string/def"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/defHeader"
app:layout_constraintStart_toEndOf="@+id/defEnabled"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="@+id/defEnabled"
app:layout_constraintTop_toTopOf="@+id/defEnabled"/>
<SeekBar
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="@+id/defSeek"
android:layout_weight="1"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="@+id/atkSeek"
app:layout_constraintBottom_toBottomOf="@+id/defHeader"
app:layout_constraintTop_toTopOf="@+id/defHeader"
app:layout_constraintBottom_toBottomOf="@+id/defEnabled"
app:layout_constraintTop_toTopOf="@+id/defEnabled"
android:max="15"
app:layout_constraintEnd_toStartOf="@+id/defValue"/>
<TextView
Expand All @@ -154,28 +138,20 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/staEnabled"
android:text="@string/sta"
app:layout_constraintStart_toStartOf="@+id/defEnabled"
app:layout_constraintTop_toBottomOf="@+id/defEnabled"
android:layout_marginBottom="4dp"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:text="@string/sta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/staHeader"
app:layout_constraintStart_toEndOf="@+id/staEnabled"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="@+id/staEnabled"
app:layout_constraintTop_toTopOf="@+id/staEnabled"/>
<SeekBar
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="@+id/staSeek"
android:layout_weight="1"
app:layout_constraintStart_toStartOf="@+id/defSeek"
android:layout_marginEnd="8dp"
app:layout_constraintTop_toTopOf="@+id/staHeader"
app:layout_constraintBottom_toBottomOf="@+id/staHeader"
app:layout_constraintTop_toTopOf="@+id/staEnabled"
app:layout_constraintBottom_toBottomOf="@+id/staEnabled"
android:max="15"
app:layout_constraintEnd_toStartOf="@+id/staValue"/>
<TextView
Expand Down

0 comments on commit 547830c

Please sign in to comment.