/** * 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.ArrayList; import java.util.Calendar; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sourceforge.kolmafia.KoLCharacter; import net.sourceforge.kolmafia.KoLmafia; import net.sourceforge.kolmafia.RequestThread; public class StandardRequest extends GenericRequest { // Types: "Items", Bookshelf Books", "Skills", "Familiars", "Clan Items". private final static List<String> itemMap = new ArrayList<String>(); private final static List<String> bookshelfMap = new ArrayList<String>(); private final static List<String> familiarMap = new ArrayList<String>(); private final static List<String> skillMap = new ArrayList<String>(); private final static List<String> clanMap = new ArrayList<String>(); // There is a Miscellaneous category that doesn't seem useful private static boolean running = false; private static boolean initialized = false; public static void reset() { StandardRequest.initialized = false; StandardRequest.itemMap.clear(); StandardRequest.bookshelfMap.clear(); StandardRequest.familiarMap.clear(); StandardRequest.skillMap.clear(); StandardRequest.clanMap.clear(); } public static void initialize() { if ( !StandardRequest.initialized && !GenericRequest.passwordHash.equals( "" ) && KoLCharacter.getLimitmode() == null ) { RequestThread.postRequest( new StandardRequest() ); } } private static List<String> typeToList( final String type ) { return type.equals( "Items" ) ? StandardRequest.itemMap : type.equals( "Bookshelf Books" ) ? StandardRequest.bookshelfMap : type.equals( "Skills" ) ? StandardRequest.skillMap : type.equals( "Familiars" ) ? StandardRequest.familiarMap : type.equals( "Clan Items" ) ? StandardRequest.clanMap : null; } private static boolean isNotRestricted( final List<String> list, final String key ) { StandardRequest.initialize(); return list.indexOf( key.toLowerCase() ) == -1; } public static boolean isNotRestricted( final String type, final String key ) { if ( !KoLCharacter.getRestricted() ) { return true; } List<String> list = StandardRequest.typeToList( type ); return list != null && StandardRequest.isNotRestricted( list, key ); } public static boolean isAllowed( String type, final String key ) { if ( KoLCharacter.isTrendy() && !TrendyRequest.isTrendy( type, key ) ) { return false; } if ( !KoLCharacter.getRestricted() ) { return true; } return StandardRequest.isAllowedInStandard( type, key ); } public static boolean isAllowedInStandard( String type, final String key ) { if ( type.equals( "Bookshelf" ) ) { type = "Bookshelf Books"; } else if ( type.equals( "Clan Item" ) ) { type = "Clan Items"; } if ( type.equals( "Bookshelf Books" ) ) { // Work around a KoL bug: most restricted books are // listed both under Bookshelf Books and Items, but // 3 are listed under only one or the other. return StandardRequest.isNotRestricted( "Bookshelf Books", key ) && StandardRequest.isNotRestricted( "Items", key ); } List<String> list = StandardRequest.typeToList( type ); return list != null && StandardRequest.isNotRestricted( list, key ); } public StandardRequest() { super( "standard.php" ); // Two years before current year Calendar calendar = Calendar.getInstance(); int year = calendar.get( Calendar.YEAR ); this.addFormField( "date", String.valueOf( year - 2 ) + "-01-02" ); // Must use GET this.constructURLString( this.getFullURLString(), false ); } @Override protected boolean retryOnTimeout() { return true; } @Override public void run() { if ( StandardRequest.running ) { return; } StandardRequest.running = true; KoLmafia.updateDisplay( "Seeing what's still unrestricted today..." ); super.run(); StandardRequest.running = false; } @Override protected boolean processOnFailure() { return true; } @Override public void processResults() { if ( this.responseText.equals( "" ) ) { KoLmafia.updateDisplay( "KoL returned a blank page. Giving up." ); KoLmafia.forceContinue(); StandardRequest.initialized = true; return; } StandardRequest.parseResponse( this.getURLString(), this.responseText ); KoLmafia.updateDisplay( "Done checking allowed items." ); } // <b>Bookshelf Books</b><p><span class="i">, </span><span class="i">Gygaxian Libram, </span> // <span class="i">Libram of BRICKOs, </span><span class="i">Libram of Candy Heart Summoning, </span> // <span class="i">Libram of Divine Favors, </span><span class="i">Libram of Love Songs, </span> // <span class="i">McPhee's Grimoire of Hilarious Object Summoning, </span><span class="i">Tome of Clip Art, </span> // <span class="i">Tome of Snowcone Summoning, </span> // <span class="i">Tome of Sugar Shummoning</span><p> // <b>Skills</b> private static final Pattern STANDARD_PATTERN = Pattern.compile( "<b>(.*?)</b><p>(.*?)<p>" ); private static final Pattern OBJECT_PATTERN = Pattern.compile( "<span class=\"i\">(.*?)(, )?</span>" ); public static final void parseResponse( final String location, final String responseText ) { TrendyRequest.reset(); Matcher matcher = StandardRequest.STANDARD_PATTERN.matcher( responseText ); while ( matcher.find() ) { String type = matcher.group( 1 ); List<String> list = StandardRequest.typeToList( type ); if ( list == null ) { continue; } Matcher objectMatcher = StandardRequest.OBJECT_PATTERN.matcher( matcher.group( 2 ) ); while ( objectMatcher.find() ) { String object = objectMatcher.group( 1 ).trim().toLowerCase(); if ( object.length() > 0 ) { list.add( object ); } } } // Buggy items that should be on the list but aren't. if ( !itemMap.isEmpty() ) { itemMap.add( "actual reality goggles" ); } StandardRequest.initialized = true; } public static final boolean registerRequest( final String urlString ) { if ( !urlString.startsWith( "standard.php" ) ) { return false; } // We don't need to register this in the gCLI or the session log return true; } }