Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* CrystalBallManager * unused urlString parameter this was there because I initially thought that any request not in adventure.php or fight.php wouldn't affect predictions It's worth noting that while that assertion ended up not being true, we'll most likely end up needing to use it again later. This is because relying on KoLAdventure.lastLocationName is error prone, because we only want to list visits to adventure.php locations, and KoLAdventure.lastLocationName currently includes locations such as cellar.php. (I guess we could also try to spot them at the start of the method...) * move isCrystalBallX methods to CrystalBallManager * isCrystalBallX methods test * Collection.forEach doesn't like concurrent modifications * fight tests * update test name Co-authored-by: Samuel Gaus <sam@gaus.co.uk>
- Loading branch information
Showing
14 changed files
with
367 additions
and
75 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
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
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
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
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
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
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
174 changes: 174 additions & 0 deletions
174
src/net/sourceforge/kolmafia/session/CrystalBallManager.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,174 @@ | ||
package net.sourceforge.kolmafia.session; | ||
|
||
import java.util.HashMap; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
import net.sourceforge.kolmafia.KoLAdventure; | ||
import net.sourceforge.kolmafia.KoLCharacter; | ||
import net.sourceforge.kolmafia.MonsterData; | ||
import net.sourceforge.kolmafia.combat.MonsterStatusTracker; | ||
import net.sourceforge.kolmafia.persistence.AdventureQueueDatabase; | ||
import net.sourceforge.kolmafia.preferences.Preferences; | ||
|
||
public final class CrystalBallManager { | ||
private static final Pattern[] CRYSTAL_BALL_PATTERNS = { | ||
Pattern.compile("your next fight will be against <b>an? (.*?)</b>"), | ||
Pattern.compile("next monster in this (?:zone is going to|area will) be <b>an? (.*?)</b>"), | ||
Pattern.compile("Look out, there's <b>an? (.*?)</b> right around the next corner"), | ||
Pattern.compile("There's a little you fighting a little <b>(.*?)</b>"), | ||
Pattern.compile("How do you feel about fighting <b>an? (.*?)</b>\\? Coz that's"), | ||
Pattern.compile("the next monster in this area will be <b>an? (.*?)</b>"), | ||
Pattern.compile("and see a tiny you fighting a tiny <b>(.*?)</b> in a tiny"), | ||
Pattern.compile("it looks like there's <b>an? (.*?)</b> prowling around"), | ||
Pattern.compile("and see yourself running into <b>an? (.*?)</b> soon"), | ||
Pattern.compile("showing you an image of yourself fighting <b>an? (.*?)</b>"), | ||
Pattern.compile("if you stick around here you're going to run into <b>an? (.*?)</b>") | ||
}; | ||
|
||
public static class Prediction implements Comparable<Prediction> { | ||
public final int turnCount; | ||
public final String location; | ||
public final String monster; | ||
|
||
private Prediction(final int turnCount, final String location, final String monster) { | ||
this.turnCount = turnCount; | ||
this.location = location; | ||
this.monster = monster; | ||
} | ||
|
||
@Override | ||
public int compareTo(final Prediction o) { | ||
if (this.turnCount != o.turnCount) { | ||
return Integer.valueOf(this.turnCount).compareTo(o.turnCount); | ||
} | ||
|
||
return this.location.compareTo(o.location); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.turnCount + ":" + this.location + ":" + this.monster; | ||
} | ||
} | ||
|
||
public static final Map<String, Prediction> predictions = new HashMap<>(); | ||
|
||
public static void reset() { | ||
CrystalBallManager.predictions.clear(); | ||
|
||
String[] predictions = Preferences.getString("crystalBallPredictions").split("\\|"); | ||
|
||
for (final String prediction : predictions) { | ||
String[] parts = prediction.split(":", 3); | ||
|
||
if (parts.length < 3) { | ||
continue; | ||
} | ||
|
||
try { | ||
CrystalBallManager.predictions.put( | ||
parts[1], new Prediction(Integer.parseInt(parts[0]), parts[1], parts[2])); | ||
} catch (NumberFormatException e) { | ||
continue; | ||
} | ||
} | ||
} | ||
|
||
private static void updatePreference() { | ||
List<String> predictions = | ||
CrystalBallManager.predictions.values().stream() | ||
.sorted() | ||
.map(p -> p.toString()) | ||
.collect(Collectors.toList()); | ||
|
||
Preferences.setString("crystalBallPredictions", String.join("|", predictions)); | ||
} | ||
|
||
/** Parses an in-combat miniature crystal ball prediction. */ | ||
public static void parseCrystalBall(final String responseText) { | ||
String predictedMonster = parseCrystalBallMonster(responseText); | ||
|
||
if (predictedMonster == null) { | ||
return; | ||
} | ||
|
||
String lastAdventureName = KoLAdventure.lastLocationName; | ||
|
||
CrystalBallManager.predictions.put( | ||
lastAdventureName, | ||
new Prediction(KoLCharacter.getCurrentRun(), lastAdventureName, predictedMonster)); | ||
|
||
updatePreference(); | ||
|
||
AdventureQueueDatabase.enqueue(KoLAdventure.lastVisitedLocation(), predictedMonster); | ||
} | ||
|
||
private static String parseCrystalBallMonster(final String responseText) { | ||
for (Pattern p : CRYSTAL_BALL_PATTERNS) { | ||
Matcher matcher = p.matcher(responseText); | ||
if (matcher.find()) { | ||
return matcher.group(1); | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public static void updateCrystalBallPredictions() { | ||
if (KoLAdventure.lastVisitedLocation() == null) { | ||
return; | ||
} | ||
|
||
String lastAdventureName = KoLAdventure.lastLocationName; | ||
|
||
final Iterator<Prediction> it = CrystalBallManager.predictions.values().iterator(); | ||
while (it.hasNext()) { | ||
Prediction prediction = it.next(); | ||
|
||
if (!prediction.location.equals(lastAdventureName) | ||
&& prediction.turnCount + 2 <= KoLCharacter.getCurrentRun()) { | ||
it.remove(); | ||
} | ||
} | ||
|
||
updatePreference(); | ||
} | ||
|
||
// EncounterManager methods | ||
|
||
public static boolean isCrystalBallZone(final String zone) { | ||
for (final Prediction prediction : CrystalBallManager.predictions.values()) { | ||
if (prediction.location.equalsIgnoreCase(zone)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public static boolean isCrystalBallMonster() { | ||
return CrystalBallManager.isCrystalBallMonster( | ||
MonsterStatusTracker.getLastMonsterName(), Preferences.getString("nextAdventure")); | ||
} | ||
|
||
public static boolean isCrystalBallMonster(final MonsterData monster, final String zone) { | ||
return CrystalBallManager.isCrystalBallMonster(monster.getName(), zone); | ||
} | ||
|
||
public static boolean isCrystalBallMonster(final String monster, final String zone) { | ||
// There's no message to check for so assume the correct monster in the correct zone is from the | ||
// crystal ball | ||
for (final Prediction prediction : CrystalBallManager.predictions.values()) { | ||
if (prediction.monster.equalsIgnoreCase(monster) | ||
&& prediction.location.equalsIgnoreCase(zone)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} |
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
Oops, something went wrong.