/** * 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.persistence; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.regex.Pattern; import net.sourceforge.kolmafia.KoLConstants; import net.sourceforge.kolmafia.request.AscensionHistoryRequest; import net.sourceforge.kolmafia.request.AscensionHistoryRequest.AscensionDataField; import net.sourceforge.kolmafia.session.ClanManager; import net.sourceforge.kolmafia.session.ContactManager; public class AscensionSnapshot { public static final int NO_FILTER = 0; public static final int UNKNOWN_PATH = -1; public static final int NOPATH = 998; public static final int TEETOTALER = 1; public static final int BOOZETAFARIAN = 2; public static final int OXYGENARIAN = 3; public static final int BAD_MOON = 999; public static final int BEES_HATE_YOU = 4; public static final int SURPRISING_FIST = 6; public static final int TRENDY = 7; public static final int AVATAR_OF_BORIS = 8; public static final int BUGBEAR_INVASION = 9; public static final int ZOMBIE_SLAYER = 10; public static final int CLASS_ACT = 11; public static final int AVATAR_OF_JARLSBERG = 12; public static final int BIG = 14; public static final int KOLHS = 15; public static final int CLASS_ACT_II = 16; public static final int AVATAR_OF_SNEAKY_PETE = 17; public static final int SLOW_AND_STEADY = 18; public static final int HEAVY_RAINS = 19; public static final int PICKY = 21; public static final int STANDARD = 22; public static final int ACTUALLY_ED_THE_UNDYING = 23; public static final int CRAZY_RANDOM_SUMMER = 24; public static final int COMMUNITY_SERVICE = 25; public static final int AVATAR_OF_WEST_OF_LOATHING = 26; public static final int THE_SOURCE = 27; public static final int NUCLEAR_AUTUMN = 28; public static final int GELATINOUS_NOOB = 29; public static final int UNKNOWN_CLASS = -1; public static final int SEAL_CLUBBER = 1; public static final int TURTLE_TAMER = 2; public static final int PASTAMANCER = 3; public static final int SAUCEROR = 4; public static final int DISCO_BANDIT = 5; public static final int ACCORDION_THIEF = 6; public static final int BORIS = 11; public static final int ZOMBIE_MASTER = 12; public static final int JARLSBERG = 14; public static final int SNEAKY_PETE = 15; public static final int ED = 17; public static final int COW_PUNCHER = 18; public static final int BEAN_SLINGER = 19; public static final int SNAKE_OILER = 20; public static final int NOOB = 23; public static final int UNKNOWN_TYPE = -1; public static final int NORMAL = 1; public static final int HARDCORE = 2; public static final int CASUAL = 3; private static final Map<String, String> ascensionMap = new TreeMap<String, String>(); private static final List ascensionDataList = new ArrayList(); private static final List softcoreAscensionList = new ArrayList(); private static final List hardcoreAscensionList = new ArrayList(); private static final List casualAscensionList = new ArrayList(); private static final Pattern LINK_PATTERN = Pattern.compile( "</?a[^>]+>" ); public static final void clearCache() { // First, initialize all of the lists and // arrays which are used by the request. AscensionSnapshot.ascensionMap.clear(); AscensionSnapshot.ascensionDataList.clear(); AscensionSnapshot.softcoreAscensionList.clear(); AscensionSnapshot.hardcoreAscensionList.clear(); AscensionSnapshot.casualAscensionList.clear(); } public static final void registerMember( final String playerName ) { String lowerCaseName = playerName.toLowerCase(); AscensionSnapshot.ascensionMap.put( lowerCaseName, "" ); } public static final void unregisterMember( final String playerId ) { String lowerCaseName = ContactManager.getPlayerName( playerId ).toLowerCase(); AscensionSnapshot.ascensionMap.remove( lowerCaseName ); } public static final Map<String, String> getAscensionMap() { return AscensionSnapshot.ascensionMap; } public static final String getAscensionData( final int typeFilter, final int mostAscensionsBoardSize, final int mainBoardSize, final int classBoardSize, final int maxAge, final boolean playerMoreThanOnce, boolean localProfileLink ) { AscensionSnapshot.initializeAscensionData(); StringBuffer strbuf = new StringBuffer(); strbuf.append( "<html><head>" ); strbuf.append( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">" ); strbuf.append( "<title>" ); switch ( typeFilter ) { case AscensionSnapshot.NORMAL: strbuf.append( "Normal" ); break; case AscensionSnapshot.HARDCORE: strbuf.append( "Hardcore" ); break; case AscensionSnapshot.CASUAL: strbuf.append( "Casual" ); break; } String clanName = ClanManager.getClanName( true ); strbuf.append( " Ascension Data for " ); strbuf.append( clanName ); strbuf.append( " (" ); strbuf.append( new Date() ); strbuf.append( ")</title>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<style> body, td { font-family: sans-serif; } </style></head><body>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<center><table cellspacing=0 cellpadding=0><tr><td align=center><h2><u>" ); strbuf.append( clanName ); strbuf.append( " (#" ); strbuf.append( ClanManager.getClanId() ); strbuf.append( ")</u></h2></td></tr>" ); strbuf.append( KoLConstants.LINE_BREAK ); // Right below the name of the clan, write the average // number of this kind of ascension. strbuf.append( "<tr><td align=center><h3>Avg: " ); strbuf.append( ( ( typeFilter == AscensionSnapshot.NORMAL ? (float) AscensionSnapshot.softcoreAscensionList.size() : 0.0f ) + AscensionSnapshot.hardcoreAscensionList.size() + AscensionSnapshot.casualAscensionList.size() ) / AscensionSnapshot.ascensionMap.size() ); strbuf.append( "</h3></td></tr></table><br><br>" ); strbuf.append( KoLConstants.LINE_BREAK ); // Next, the ascension leaderboards for most (numeric) // ascensions. strbuf.append( "<table width=500 cellspacing=0 cellpadding=0>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<tr><td style=\"color:white\" align=center bgcolor=blue><b>Most " ); strbuf.append( typeFilter == AscensionSnapshot.NORMAL ? "Normal " : typeFilter == AscensionSnapshot.HARDCORE ? "Hardcore " : "Casual " ); strbuf.append( "Ascensions</b></td></tr><tr><td style=\"padding: 5px; border: 1px solid blue;\"><center><table>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<tr><td align=center><b>Player    </b></td>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<td align=center><b>Ascensions</b></td></tr>" ); strbuf.append( KoLConstants.LINE_BREAK ); // Resort the lists, and print the results to the buffer // so that you have the "most ascensions" leaderboard. AscensionHistoryRequest.setComparator( typeFilter ); Collections.sort( AscensionSnapshot.ascensionDataList ); String leader; for ( int i = 0; i < AscensionSnapshot.ascensionDataList.size() && ( mostAscensionsBoardSize == 0 ? i < 20 : i < mostAscensionsBoardSize ); ++i ) { leader = AscensionSnapshot.ascensionDataList.get( i ).toString(); if ( !localProfileLink ) { leader = AscensionSnapshot.LINK_PATTERN.matcher( leader ).replaceAll( "" ); } strbuf.append( leader ); strbuf.append( KoLConstants.LINE_BREAK ); } strbuf.append( "</table></td></tr></table><br><br>" ); strbuf.append( KoLConstants.LINE_BREAK ); // Finally, the ascension leaderboards for fastest // ascension speed. Do this for all paths individually. if ( typeFilter != AscensionSnapshot.CASUAL ) { strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.GELATINOUS_NOOB, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.NUCLEAR_AUTUMN, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.THE_SOURCE, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.AVATAR_OF_WEST_OF_LOATHING, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.COMMUNITY_SERVICE, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.CRAZY_RANDOM_SUMMER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.ACTUALLY_ED_THE_UNDYING, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.STANDARD, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.PICKY, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.HEAVY_RAINS, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.SLOW_AND_STEADY, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.AVATAR_OF_SNEAKY_PETE, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.CLASS_ACT_II, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.KOLHS, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.BIG, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.AVATAR_OF_JARLSBERG, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.CLASS_ACT, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.ZOMBIE_SLAYER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.BUGBEAR_INVASION, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.AVATAR_OF_BORIS, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.TRENDY, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.SURPRISING_FIST, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.BEES_HATE_YOU, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.BAD_MOON, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.OXYGENARIAN, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.TEETOTALER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.BOOZETAFARIAN, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); } strbuf.append( AscensionSnapshot.getPathedAscensionData( typeFilter, AscensionSnapshot.NOPATH, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</center>" ); return strbuf.toString(); } public static final String getPathedAscensionData( final int typeFilter, final int pathFilter, final int mainBoardSize, final int classBoardSize, final int maxAge, final boolean playerMoreThanOnce, final boolean localProfileLink ) { StringBuffer strbuf = new StringBuffer(); // First, print the table showing the top ascenders // without a class-based filter. strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.NO_FILTER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); // Next, print the nifty disappearing link bar that // is used in the KoL leaderboard frame. strbuf.append( KoLConstants.LINE_BREAK ); // Finally, add in all the breakdown tables, just like // in the KoL leaderboard frame, for class based paths. switch ( pathFilter ) { case AscensionSnapshot.AVATAR_OF_BORIS: case AscensionSnapshot.ZOMBIE_SLAYER: case AscensionSnapshot.AVATAR_OF_JARLSBERG: case AscensionSnapshot.AVATAR_OF_SNEAKY_PETE: case AscensionSnapshot.ACTUALLY_ED_THE_UNDYING: case AscensionSnapshot.GELATINOUS_NOOB: break; case AscensionSnapshot.AVATAR_OF_WEST_OF_LOATHING: strbuf.append( "<br><a class=small href=\"javascript:void(0);\" onClick=\"javascript: var element = document.getElementById('sec" ); strbuf.append( pathFilter ); strbuf.append( "'); element.style.display = element.style.display == 'inline' ? 'none' : 'inline';\">" ); strbuf.append( "hide/show records by class</a><div id=\"sec" ); strbuf.append( pathFilter ); strbuf.append( "\" style=\"display:none\"><br><br>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<table><tr><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.COW_PUNCHER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.BEAN_SLINGER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td></tr><tr><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.SNAKE_OILER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td></tr></table>" ); break; default: strbuf.append( "<br><a class=small href=\"javascript:void(0);\" onClick=\"javascript: var element = document.getElementById('sec" ); strbuf.append( pathFilter ); strbuf.append( "'); element.style.display = element.style.display == 'inline' ? 'none' : 'inline';\">" ); strbuf.append( "hide/show records by class</a><div id=\"sec" ); strbuf.append( pathFilter ); strbuf.append( "\" style=\"display:none\"><br><br>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<table><tr><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.SEAL_CLUBBER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.SAUCEROR, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td></tr><tr><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.TURTLE_TAMER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.DISCO_BANDIT, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td></tr><tr><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.PASTAMANCER, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td><td valign=top>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( AscensionSnapshot.getAscensionData( typeFilter, pathFilter, AscensionSnapshot.ACCORDION_THIEF, mainBoardSize, classBoardSize, maxAge, playerMoreThanOnce, localProfileLink ) ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "</td></tr></table>" ); break; } // Close the disappearing section and return the complete // code for this path filter. strbuf.append( "</div><br><br>" ); return strbuf.toString(); } public static final String getAscensionData( final int typeFilter, final int pathFilter, final int classFilter, final int mainBoardSize, final int classBoardSize, final int maxAge, final boolean playerMoreThanOnce, boolean localProfileLink ) { StringBuffer strbuf = new StringBuffer(); AscensionDataField[] fields = null; switch ( typeFilter ) { case AscensionSnapshot.NORMAL: fields = new AscensionDataField[ AscensionSnapshot.softcoreAscensionList.size() ]; AscensionSnapshot.softcoreAscensionList.toArray( fields ); break; case AscensionSnapshot.HARDCORE: fields = new AscensionDataField[ AscensionSnapshot.hardcoreAscensionList.size() ]; AscensionSnapshot.hardcoreAscensionList.toArray( fields ); break; case AscensionSnapshot.CASUAL: fields = new AscensionDataField[ AscensionSnapshot.casualAscensionList.size() ]; AscensionSnapshot.casualAscensionList.toArray( fields ); break; } // First, retrieve all the ascensions which // satisfy the current filter so that the // total count can be displayed in the header. List resultsList = new ArrayList(); if ( fields == null ) { return ""; } for ( int i = 0; i < fields.length; ++i ) { if ( fields[ i ].matchesFilter( typeFilter, pathFilter, classFilter, maxAge ) ) { resultsList.add( fields[ i ] ); } } // Next, retrieve only the top ten list so that // a maximum of ten elements are printed. List leaderList = new ArrayList(); int leaderListSize = classFilter == AscensionSnapshot.NO_FILTER ? ( mainBoardSize == 0 ? 10 : mainBoardSize ) : classBoardSize == 0 ? 5 : classBoardSize; fields = new AscensionDataField[ resultsList.size() ]; resultsList.toArray( fields ); for ( int i = 0; i < fields.length && leaderList.size() < leaderListSize; ++i ) { if ( !leaderList.contains( fields[ i ] ) || playerMoreThanOnce ) { leaderList.add( fields[ i ] ); } } // Now that the data has been retrieved, go ahead // and print the table header data. strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<table width=500 cellspacing=0 cellpadding=0>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<tr><td style=\"color:white\" align=center bgcolor=blue><b>" ); switch ( classFilter ) { case NO_FILTER: strbuf.append( "Fastest " ); strbuf.append( typeFilter == AscensionSnapshot.NORMAL ? "Normal " : typeFilter == AscensionSnapshot.HARDCORE ? "Hardcore " : "Casual " ); strbuf.append( pathFilter == AscensionSnapshot.NO_FILTER ? "" : pathFilter == AscensionSnapshot.NOPATH ? "No-Path " : pathFilter == AscensionSnapshot.TEETOTALER ? "Teetotaler " : pathFilter == AscensionSnapshot.BOOZETAFARIAN ? "Boozetafarian " : pathFilter == AscensionSnapshot.OXYGENARIAN ? "Oxygenarian " : pathFilter == AscensionSnapshot.BAD_MOON ? "Bad Moon " : pathFilter == AscensionSnapshot.BEES_HATE_YOU ? "Bees Hate You " : pathFilter == AscensionSnapshot.SURPRISING_FIST ? "Way of the Surprising Fist " : pathFilter == AscensionSnapshot.TRENDY ? "Trendy " : pathFilter == AscensionSnapshot.AVATAR_OF_BORIS ? "Avatar of Boris " : pathFilter == AscensionSnapshot.BUGBEAR_INVASION ? "Bugbear Invasion " : pathFilter == AscensionSnapshot.ZOMBIE_SLAYER ? "Zombie Slayer " : pathFilter == AscensionSnapshot.CLASS_ACT ? "Class Act " : pathFilter == AscensionSnapshot.AVATAR_OF_JARLSBERG ? "Avatar of Jarlsberg " : pathFilter == AscensionSnapshot.BIG ? "BIG! " : pathFilter == AscensionSnapshot.KOLHS ? "KOLHS " : pathFilter == AscensionSnapshot.CLASS_ACT_II ? "Class Act II: A Class For Pigs " : pathFilter == AscensionSnapshot.AVATAR_OF_SNEAKY_PETE ? "Avatar of Sneaky Pete " : pathFilter == AscensionSnapshot.SLOW_AND_STEADY ? "Slow and Steady " : pathFilter == AscensionSnapshot.HEAVY_RAINS ? "Heavy Rains " : pathFilter == AscensionSnapshot.PICKY ? "Picky " : pathFilter == AscensionSnapshot.STANDARD ? "Standard " : pathFilter == AscensionSnapshot.ACTUALLY_ED_THE_UNDYING ? "Actually Ed the Undying " : pathFilter == AscensionSnapshot.CRAZY_RANDOM_SUMMER ? "One Crazy Random Summer " : pathFilter == AscensionSnapshot.COMMUNITY_SERVICE ? "Community Service " : pathFilter == AscensionSnapshot.AVATAR_OF_WEST_OF_LOATHING ? "Avatar of West of Loathing " : pathFilter == AscensionSnapshot.THE_SOURCE ? "The Source " : pathFilter == AscensionSnapshot.NUCLEAR_AUTUMN ? "Nuclear Autumn " : pathFilter == AscensionSnapshot.GELATINOUS_NOOB ? "Gelatinous Noob " : "" ); strbuf.append( "Ascensions (Out of " ); strbuf.append( resultsList.size() ); strbuf.append( ")" ); break; case SEAL_CLUBBER: strbuf.append( "Seal Clubber" ); break; case TURTLE_TAMER: strbuf.append( "Turtle Tamer" ); break; case PASTAMANCER: strbuf.append( "Pastamancer" ); break; case SAUCEROR: strbuf.append( "Sauceror" ); break; case DISCO_BANDIT: strbuf.append( "Disco Bandit" ); break; case ACCORDION_THIEF: strbuf.append( "Accordion Thief" ); break; case COW_PUNCHER: strbuf.append( "Cow Puncher" ); break; case BEAN_SLINGER: strbuf.append( "Bean Slinger" ); break; case SNAKE_OILER: strbuf.append( "Snake Oiler" ); break; } strbuf.append( "</b></td></tr><tr><td style=\"padding: 5px; border: 1px solid blue;\"><center><table>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<tr><td align=center><b>Player    </b></td>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<td align=center><b>Days</b></td>" ); strbuf.append( KoLConstants.LINE_BREAK ); strbuf.append( "<td align=center><b>Adventures</b></td></tr>" ); strbuf.append( KoLConstants.LINE_BREAK ); // Now, print the actual table data inside, using // the top ten list. String leader; for ( int i = 0; i < leaderListSize && i < leaderList.size(); ++i ) { leader = leaderList.get( i ).toString(); if ( !localProfileLink ) { leader = AscensionSnapshot.LINK_PATTERN.matcher( leader ).replaceAll( "" ); } strbuf.append( leader ); strbuf.append( KoLConstants.LINE_BREAK ); } strbuf.append( "</table></td></tr></table>" ); strbuf.append( KoLConstants.LINE_BREAK ); return strbuf.toString(); } private static final void initializeAscensionData() { // If the ascension lists have already been initialized, // then return from this method call. if ( !AscensionSnapshot.ascensionDataList.isEmpty() ) { return; } // If the lists are not initialized, then go ahead and // load the appropriate data into them. String[] names = new String[ AscensionSnapshot.ascensionMap.size() ]; AscensionSnapshot.ascensionMap.keySet().toArray( names ); AscensionHistoryRequest request; AscensionDataField[] fields; for ( int i = 0; i < names.length; ++i ) { request = AscensionHistoryRequest.getInstance( names[ i ], ContactManager.getPlayerId( names[ i ] ), (String) AscensionSnapshot.ascensionMap.get( names[ i ] ) ); AscensionSnapshot.ascensionDataList.add( request ); fields = new AscensionDataField[ request.getAscensionData().size() ]; request.getAscensionData().toArray( fields ); for ( int j = 0; j < fields.length; ++j ) { if ( fields[ j ].matchesFilter( AscensionSnapshot.NORMAL, AscensionSnapshot.NO_FILTER, AscensionSnapshot.NO_FILTER, 0 ) ) { AscensionSnapshot.softcoreAscensionList.add( fields[ j ] ); } else if ( fields[ j ].matchesFilter( AscensionSnapshot.HARDCORE, AscensionSnapshot.NO_FILTER, AscensionSnapshot.NO_FILTER, 0 ) ) { AscensionSnapshot.hardcoreAscensionList.add( fields[ j ] ); } else { AscensionSnapshot.casualAscensionList.add( fields[ j ] ); } } } // Now that you've retrieved all the data from all the // players, sort the lists for easier loading later. Collections.sort( AscensionSnapshot.softcoreAscensionList ); Collections.sort( AscensionSnapshot.hardcoreAscensionList ); Collections.sort( AscensionSnapshot.casualAscensionList ); } }