/** * Copyright (c) 2005-2017, KoLmafia development team * http://kolmafia.sourceforge.net/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * [1] Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * [2] Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * [3] Neither the name "KoLmafia" nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package net.sourceforge.kolmafia.request; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sourceforge.kolmafia.KoLConstants; import net.sourceforge.kolmafia.KoLConstants.MafiaState; import net.sourceforge.kolmafia.KoLmafia; import net.sourceforge.kolmafia.RequestLogger; import net.sourceforge.kolmafia.session.MoneyMakingGameManager; import net.sourceforge.kolmafia.utilities.StringUtilities; import net.sourceforge.kolmafia.webui.MoneyMakingGameDecorator; public class MoneyMakingGameRequest extends GenericRequest { public static final Pattern FROM_PATTERN = Pattern.compile( "from=(\\d*)" ); public static final Pattern WHICHBET_PATTERN = Pattern.compile( "whichbet=(\\d*)" ); public static final Pattern BETID_PATTERN = Pattern.compile( "betid=(\\d*)" ); public static final Pattern LOWER_PATTERN = Pattern.compile( "lower=(\\d*)" ); public static final Pattern HIGHER_PATTERN = Pattern.compile( "higher=(\\d*)" ); public static final String getLower( final String urlString ) { Matcher matcher = LOWER_PATTERN.matcher( urlString ); return matcher.find() ? matcher.group(1) : null; } public static final String getHigher( final String urlString ) { Matcher matcher = HIGHER_PATTERN.matcher( urlString ); return matcher.find() ? matcher.group(1) : null; } public static final int parseInteger( final Pattern pattern, final String urlString ) { Matcher matcher = pattern.matcher( urlString ); return matcher.find() ? StringUtilities.parseInt( matcher.group(1) ) : -1; } public static final int getFrom( final String urlString ) { return MoneyMakingGameRequest.parseInteger( FROM_PATTERN, urlString ); } public static final String getFromString( final String urlString ) { int from = getFrom( urlString ); return from == 0 ? "inventory" : from == 1 ? "storage" : null; } public static final int getWhichBet( final String urlString ) { return MoneyMakingGameRequest.parseInteger( WHICHBET_PATTERN, urlString ); } public static final int getBetId( final String urlString ) { return MoneyMakingGameRequest.parseInteger( BETID_PATTERN, urlString ); } public static final int VISIT = 1; public static final int SEARCH = 2; public static final int MAKE_BET = 3; public static final int RETRACT_BET = 4; public static final int TAKE_BET = 5; public static final int INVENTORY = 0; public static final int STORAGE = 1; private final int action; public MoneyMakingGameRequest() { super( "bet.php" ); this.action = MoneyMakingGameRequest.VISIT; } public MoneyMakingGameRequest( final int action, final int arg1 ) { super( "bet.php" ); this.action = action; switch ( action ) { case MoneyMakingGameRequest.VISIT: case MoneyMakingGameRequest.SEARCH: case MoneyMakingGameRequest.MAKE_BET: case MoneyMakingGameRequest.TAKE_BET: // These don't make sense break; case MoneyMakingGameRequest.RETRACT_BET: this.addFormField( "action", "retract" ); this.addFormField( "betid", String.valueOf( arg1 ) ); break; } } public MoneyMakingGameRequest( final int action, final int arg1, final int arg2 ) { super( "bet.php" ); this.action = action; switch ( action ) { case MoneyMakingGameRequest.VISIT: case MoneyMakingGameRequest.RETRACT_BET: // These don't make sense break; case MoneyMakingGameRequest.SEARCH: this.addFormField( "action", "search" ); this.addFormField( "lower", String.valueOf( arg1 ) ); this.addFormField( "higher", String.valueOf( arg2 ) ); break; case MoneyMakingGameRequest.MAKE_BET: this.addFormField( "action", "makebet" ); this.addFormField( "howmuch", String.valueOf( arg1 ) ); this.addFormField( "from", String.valueOf( arg2 ) ); break; case MoneyMakingGameRequest.TAKE_BET: this.addFormField( "action", "bet" ); this.addFormField( "whichbet", String.valueOf( arg1 ) ); this.addFormField( "from", String.valueOf( arg2 ) ); this.addFormField( "confirm", "on" ); break; } } @Override protected boolean shouldFollowRedirect() { return true; } @Override public void processResults() { String responseText = this.responseText; if ( responseText.indexOf( "You can't gamble without a casino pass." ) != -1 ) { KoLmafia.updateDisplay( MafiaState.ERROR, "You don't have a casino pass." ); return; } MoneyMakingGameRequest.parseResponse( this.getURLString(), responseText, true ); String error = null; switch ( this.action ) { case MoneyMakingGameRequest.VISIT: case MoneyMakingGameRequest.SEARCH: break; case MoneyMakingGameRequest.MAKE_BET: error = MoneyMakingGameRequest.makeBetErrorMessage( responseText ); break; case MoneyMakingGameRequest.RETRACT_BET: error = MoneyMakingGameRequest.retractBetErrorMessage( responseText ); break; case MoneyMakingGameRequest.TAKE_BET: error = MoneyMakingGameRequest.takeBetErrorMessage( responseText ); break; } if ( error != null ) { KoLmafia.updateDisplay( MafiaState.ERROR, error ); } } private static String makeBetErrorMessage( final String responseText ) { // You can't make a wager for less than 1,000 Meat. Sad, but // true. if ( responseText.indexOf( "can't make a wager" ) != -1 ) { return "You must bet at least 1,000 meat."; } // You open your wallet and proudly pull out Meat. The old man // gives you a funny look, and you start to sweat. After // rifling through your pockets for a few awkward moments, you // realize that you just don't have enough data. I mean, // Meat. To make that wager. // // After a wait that seems to take forever, the old man turns // to you and says, "Sorry, kid, but Hagnk's secretary says // that you don't have enough Meat to make that big of a // wager. Care to try again?" if ( responseText.indexOf( "don't have enough" ) != -1 ) { return "You don't have enough meat."; } // You can't have more than five bets running at one // time. Strange, but true. if ( responseText.indexOf( "Strange, but true" ) != -1 ) { return "You can only have five bets at a time."; } return null; } private static String retractBetErrorMessage( final String responseText ) { // You don't have a bet with that ID. Likely, someone already // took it. if ( responseText.indexOf( "don't have a bet with that ID" ) != -1 ) { return "Could not retract bet."; } return null; } private static String takeBetErrorMessage( final String responseText ) { // The old man looks at you quizzically. "There's no bet // like that anywhere in our records. Maybe someone else got to // it before you could." if ( responseText.indexOf( "no bet like that" ) != -1 ) { return "Could not take bet."; } // You rifle through your wallet, but can't seem to fish out // enough Meat to afford the wager. You'll have to try // something cheaper. // // "Sorry, kid," the old man says to // you. "Hagnk's secretary says that you don't have enough // to take that bet." if ( responseText.indexOf( "fish out enough" ) != -1 || responseText.indexOf( "don't have enough" ) != -1) { return "You don't have enough meat."; } return null; } public static final void parseResponse( final String urlString, final String responseText, final boolean internal ) { if ( !urlString.startsWith( "bet.php" ) ) { return; } // In registerRequest, we saved the amount we were betting. // Detect if our bet was rejected outright and forget the // pending bet, if so. if ( MoneyMakingGameManager.makingBet != 0 && MoneyMakingGameRequest.makeBetErrorMessage( responseText ) != null ) { MoneyMakingGameManager.makingBet = 0; } // Parse my bets from responseText MoneyMakingGameManager.parseMyBets( responseText, internal ); // Parse offered bets from responseText MoneyMakingGameManager.parseOfferedBets( responseText ); // When you make a bet, you are redirected from the URL you // submitted to make it to bet.php if ( responseText.indexOf( "You make a bet." ) != -1 ) { MoneyMakingGameManager.makeBet( responseText ); MoneyMakingGameManager.makingBet = 0; return; } String action = GenericRequest.getAction( urlString ); // We have nothing else to do for simple visits. if ( action == null ) { return; } if ( action.equals( "retract" ) ) { MoneyMakingGameManager.retractBet( urlString, responseText ); return; } if ( action.equals( "bet" ) ) { MoneyMakingGameManager.takeBet( urlString, responseText ); return; } } public static final boolean registerRequest( final String urlString ) { if ( !urlString.startsWith( "bet.php" ) ) { return false; } String action = GenericRequest.getAction( urlString ); // We have nothing special to do for simple visits. if ( action == null ) { return true; } String message = null; if ( action.equals( "makebet" ) ) { String from = getFromString( urlString ); int howmuch = GenericRequest.getHowMuch( urlString ); if ( from == null || howmuch < 0 ) { return true; } // Remember that we're making a bet MoneyMakingGameManager.makingBet = howmuch; message = "Betting " + KoLConstants.COMMA_FORMAT.format( howmuch ) + " meat from " + from; } else if ( action.equals( "retract" ) ) { // bet.php?action=retract&betid=58251236&pwd int betid = getBetId( urlString ); if ( betid < 0 ) { return true; } message = "Retracting bet " + betid; } else if ( action.equals( "bet" ) ) { // Log when the bet is resolved return true; } else if ( action.equals( "search" ) ) { String minimum = getLower( urlString ); String maximum = getHigher( urlString ); MoneyMakingGameDecorator.setLimits( minimum, maximum ); return true; } else { return true; } RequestLogger.printLine( message ); RequestLogger.updateSessionLog( message ); return true; } }