/* Copyright (c) 2008-2010, developers of the Ascension Log Visualizer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package com.googlecode.logVisualizer.logData.logSummary; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import com.googlecode.logVisualizer.logData.Item; import com.googlecode.logVisualizer.logData.LogDataHolder; import com.googlecode.logVisualizer.logData.MPGain; import com.googlecode.logVisualizer.logData.Skill; import com.googlecode.logVisualizer.logData.Statgain; import com.googlecode.logVisualizer.logData.consumables.Consumable; import com.googlecode.logVisualizer.logData.consumables.Consumable.ConsumableVersion; import com.googlecode.logVisualizer.logData.turn.TurnInterval.FreeRunaways; import com.googlecode.logVisualizer.util.DataNumberPair; /** * This is a data container class for various summaries on ascension logs. This * class merely holds the data and accessing methods to it, the calculation of * these summaries is being done in the {@link SummaryDataCalculator} class. * <p> * Note that depending on how detailed the ascension log (or in this case the * turn rundown log) is, some of these data summary calculations might not * capture all the possible data or none at all. For these cases this class * makes it possible to set the summaries manually. * <p> * All methods in this class throw a {@link NullPointerException} if a null * object reference is passed in any parameter. */ public class LogSummaryData { private final List<Consumable> consumablesUsed; private final List<Item> droppedItems; private final List<Skill> skillsCast; private final List<AreaStatgains> areasStatgains; private final List<DataNumberPair<String>> turnsPerArea; private final List<LevelData> levels; private List<DataNumberPair<String>> familiarUsage; private List<DataNumberPair<String>> huntedCombats; private List<DataNumberPair<String>> disintegratedCombats; private List<DataNumberPair<String>> semirares; private List<DataNumberPair<String>> badmoonAdventures; private final ConsumptionSummary consumptionSummary; private final FreeRunaways freeRunaways; private final Sewer sewer; private final Goatlet goatlet; private final InexplicableDoor nesRealm; private final QuestTurncounts questTurncounts; private Statgain totalStatgains; private Statgain combatsStatgains; private Statgain noncombatsStatgains; private Statgain othersStatgains; private final MPGain mpGains = new MPGain(); private final MeatSummary meatSummary; private int totalAmountSkillCasts; private int totalMPUsed; private int totalMeatGain; private int totalMeatSpent; private int totalTurnsFromRollover; private int totalTurnsCombat; private int totalTurnsNoncombat; private int totalTurnsOther; /** * Constructs an ascension log summary. A summaries will be calculated as * good as possible from the given data. * * @param logData * The ascension log. */ public LogSummaryData(final LogDataHolder logData) { if (logData == null) { throw new NullPointerException("Log data holder must not be null."); } final SummaryDataCalculator data = new SummaryDataCalculator(logData); this.areasStatgains = AreaStatgains.getSortedAreaStatgains( logData.getTurnsSpent(), new Comparator<AreaStatgains>() { @Override public int compare(final AreaStatgains o1, final AreaStatgains o2) { return o2.getStatgain().getTotalStatgain() - o1.getStatgain().getTotalStatgain(); } }); this.turnsPerArea = data.getTurnsPerArea(); Collections.sort(this.turnsPerArea, new Comparator<DataNumberPair<String>>() { @Override public int compare(final DataNumberPair<String> o1, final DataNumberPair<String> o2) { // Reverse order, so that the list starts with the // highest // element. Also, in case of a tie, sort alphabetically. int diff = o2.compareTo(o1); if (diff == 0) { diff = o1.getData().compareToIgnoreCase( o2.getData()); } return diff; } }); this.consumablesUsed = new ArrayList<>( data.getConsumablesUsed()); Collections.sort(this.consumablesUsed, new Comparator<Consumable>() { @Override public int compare(final Consumable o1, final Consumable o2) { // Reverse order, so that the list starts with the highest // element. return o2.compareTo(o1); } }); this.droppedItems = new ArrayList<>(data.getDroppedItems()); Collections.sort(this.droppedItems, new Comparator<Item>() { @Override public int compare(final Item o1, final Item o2) { // Reverse order, so that the list starts with the highest // element. return o2.getAmount() - o1.getAmount(); } }); this.skillsCast = new ArrayList<>(data.getSkillsCast()); Collections.sort(this.skillsCast, new Comparator<Skill>() { @Override public int compare(final Skill o1, final Skill o2) { // Reverse order, so that the list starts with the highest // element. return o2.compareTo(o1); } }); this.familiarUsage = data.getFamiliarUsage(); Collections.sort(this.familiarUsage, new Comparator<DataNumberPair<?>>() { @Override public int compare(final DataNumberPair<?> o1, final DataNumberPair<?> o2) { // Reverse order, so that the list starts with the // highest // element. return o2.compareTo(o1); } }); this.levels = data.getLevelData(); this.huntedCombats = data.getHuntedCombats(); this.disintegratedCombats = data.getDisintegratedCombats(); this.semirares = data.getSemirares(); this.badmoonAdventures = data.getBadmoonAdventures(); this.consumptionSummary = data.getConsumptionSummary(); this.freeRunaways = data.getFreeRunaways(); this.sewer = data.getSewer(); this.goatlet = data.getGoatlet(); this.nesRealm = data.get8BitRealm(); this.questTurncounts = data.getQuestTurncounts(); this.totalStatgains = data.getTotalStatgains(); this.combatsStatgains = data.getCombatsStatgains(); this.noncombatsStatgains = data.getNoncombatsStatgains(); this.othersStatgains = data.getOthersStatgains(); this.mpGains.setMPGains(data.getMPGains()); this.meatSummary = data.getMeatSummary(); this.totalAmountSkillCasts = data.getTotalAmountSkillCasts(); this.totalMPUsed = data.getTotalMPUsed(); this.totalMeatGain = data.getTotalMeatGain(); this.totalMeatSpent = data.getTotalMeatSpent(); this.totalTurnsFromRollover = data.getTotalTurnsFromRollover(); this.totalTurnsCombat = data.getTotalTurnsCombat(); this.totalTurnsNoncombat = data.getTotalTurnsNoncombat(); this.totalTurnsOther = data.getTotalTurnsOther(); } /** * @return A sorted list of areas and the turns spent in them. This list * starts with the area that has the highest amount turns. */ public List<DataNumberPair<String>> getTurnsPerArea() { return this.turnsPerArea; } /** * @return A sorted list of all consumables used. This list starts with the * consumable that was used the most. */ public List<Consumable> getAllConsumablesUsed() { return this.consumablesUsed; } /** * @return A sorted list of all food consumables used. This list starts with * the consumable that was used the most. */ public List<Consumable> getFoodConsumablesUsed() { final List<Consumable> consumables = new ArrayList<>( this.consumablesUsed.size()); for (final Consumable c : this.consumablesUsed) { if (c.getConsumableVersion() == ConsumableVersion.FOOD) { consumables.add(c); } } return consumables; } /** * @return A sorted list of all booze consumables used. This list starts * with the consumable that was used the most. */ public List<Consumable> getBoozeConsumablesUsed() { final List<Consumable> consumables = new ArrayList<>( this.consumablesUsed.size()); for (final Consumable c : this.consumablesUsed) { if (c.getConsumableVersion() == ConsumableVersion.BOOZE) { consumables.add(c); } } return consumables; } /** * @return A sorted list of all spleen consumables used. This list starts * with the consumable that was used the most. */ public List<Consumable> getSpleenConsumablesUsed() { final List<Consumable> consumables = new ArrayList<>( this.consumablesUsed.size()); for (final Consumable c : this.consumablesUsed) { if (c.getConsumableVersion() == ConsumableVersion.SPLEEN) { consumables.add(c); } } return consumables; } /** * @return A sorted list of all other consumables used. This list starts * with the consumable that was used the most. */ public List<Consumable> getOtherConsumablesUsed() { final List<Consumable> consumables = new ArrayList<>( this.consumablesUsed.size()); for (final Consumable c : this.consumablesUsed) { if (c.getConsumableVersion() == ConsumableVersion.OTHER) { consumables.add(c); } } return consumables; } /** * @return A sorted list of all items dropped during this ascension. This * list starts with the item that dropped the most. */ public List<Item> getDroppedItems() { return this.droppedItems; } /** * @return A sorted list of all skills cast during this ascension. This list * starts with the skill that was cast the most. */ public List<Skill> getSkillsCast() { return this.skillsCast; } /** * @return A sorted list of all area statgains during this ascension. This * list starts with the area statgain that had the highest total * statgains. */ public List<AreaStatgains> getAreasStatgains() { return this.areasStatgains; } /** * @return A read-only list of all levels. No guarantees are made concerning * it's order. */ public List<LevelData> getLevelData() { return Collections.unmodifiableList(this.levels); } /** * @param familiarUsage * All used familiars and how often they were used to set. */ public void setFamiliarUsage( final List<DataNumberPair<String>> familiarUsage) { if (familiarUsage == null) { throw new NullPointerException( "Familiar usage list must not be null."); } this.familiarUsage = familiarUsage; } /** * @return A sorted list of all used familiars and how often they were used. * This list starts with the familiar that was used the most. */ public List<DataNumberPair<String>> getFamiliarUsage() { return this.familiarUsage; } /** * @param huntedCombats * All started hunts on combats to set. */ public void setHuntedCombats( final List<DataNumberPair<String>> huntedCombats) { if (huntedCombats == null) { throw new NullPointerException( "Hunted combats list must not be null."); } this.huntedCombats = huntedCombats; } /** * @return A sorted list of all started hunts on combats. This list starts * with the hunt that was started the earliest. */ public List<DataNumberPair<String>> getHuntedCombats() { return this.huntedCombats; } /** * @param disintegratedCombats * All disintegrated combats to set. */ public void setDisintegratedCombats( final List<DataNumberPair<String>> disintegratedCombats) { if (disintegratedCombats == null) { throw new NullPointerException( "Disintegrated combats list must not be null."); } this.disintegratedCombats = disintegratedCombats; } /** * @return A sorted list of all disintegrated combats. This list starts with * the earliest disintegrated combat. */ public List<DataNumberPair<String>> getDisintegratedCombats() { return this.disintegratedCombats; } /** * @param semirares * All encountered semirares to set. */ public void setSemirares(final List<DataNumberPair<String>> semirares) { if (semirares == null) { throw new NullPointerException("Semirares list must not be null."); } this.semirares = semirares; } /** * @return A sorted list of all encountered semirares. This list starts with * the semirare that was encountered the earliest. */ public List<DataNumberPair<String>> getSemirares() { return this.semirares; } /** * @param badmoonAdventures * All encountered Bad Moon adventures to set. */ public void setBadmoonAdventures( final List<DataNumberPair<String>> badmoonAdventures) { if (badmoonAdventures == null) { throw new NullPointerException( "Bad Moon adventures list must not be null."); } this.badmoonAdventures = badmoonAdventures; } /** * @return A list of all Bad Moon adventures. */ public List<DataNumberPair<String>> getBadmoonAdventures() { return this.badmoonAdventures; } /** * @return A summary on consumables used during the ascension. */ public ConsumptionSummary getConsumptionSummary() { return this.consumptionSummary; } /** * @return The free runaways over the whole ascension. */ public FreeRunaways getFreeRunaways() { return this.freeRunaways; } /** * @return The RNG data of the sewer. */ public Sewer getSewer() { return this.sewer; } /** * @return The RNG data of the Goatlet. */ public Goatlet getGoatlet() { return this.goatlet; } /** * @return The RNG data of the 8-Bit Realm. */ public InexplicableDoor get8BitRealm() { return this.nesRealm; } /** * @return The quest turncounts. */ public QuestTurncounts getQuestTurncounts() { return this.questTurncounts; } /** * @return The total mp gains collected during this ascension. */ public MPGain getMPGains() { return this.mpGains; } /** * @return The meat per level summary. */ public MeatSummary getMeatSummary() { return this.meatSummary; } /** * @param stats * The total amount of statgains to set. */ public void setTotalStatgains(final Statgain stats) { this.totalStatgains = stats; } /** * @return The total amount of substats collected during this ascension. */ public Statgain getTotalStatgains() { return this.totalStatgains; } /** * @param stats * The amount of combat statgains to set. */ public void setCombatsStatgains(final Statgain stats) { this.combatsStatgains = stats; } /** * @return The total amount of substats from combats collected during this * ascension. */ public Statgain getCombatsStatgains() { return this.combatsStatgains; } /** * @param stats * The amount of noncombat statgains to set. */ public void setNoncombatsStatgains(final Statgain stats) { this.noncombatsStatgains = stats; } /** * @return The total amount of substats from noncombats collected during * this ascension. */ public Statgain getNoncombatsStatgains() { return this.noncombatsStatgains; } /** * @param stats * The amount of other statgains to set. */ public void setOthersStatgains(final Statgain stats) { this.othersStatgains = stats; } /** * @return The total amount of substats from other encounters collected * during this ascension. */ public Statgain getOthersStatgains() { return this.othersStatgains; } /** * @return The total amount of substats from food collected during this * ascension. */ public Statgain getFoodConsumablesStatgains() { return this.consumptionSummary.getFoodConsumablesStatgains(); } /** * @return The total amount of substats from booze collected during this * ascension. */ public Statgain getBoozeConsumablesStatgains() { return this.consumptionSummary.getBoozeConsumablesStatgains(); } /** * @return The total amount of substats from used consumables collected * during this ascension. */ public Statgain getUsedConsumablesStatgains() { return this.consumptionSummary.getUsedConsumablesStatgains(); } /** * @param totalAmountSkillsCast * The total amount of skill casts to set. * @throws IllegalArgumentException * if totalAmountSkillCasts is below 0 */ public void setTotalAmountSkillCasts(final int totalAmountSkillCasts) { if (totalAmountSkillCasts < 0) { throw new IllegalArgumentException("Amount must not be below 0."); } this.totalAmountSkillCasts = totalAmountSkillCasts; } /** * @return The total amount of skill casts. */ public int getTotalAmountSkillCasts() { return this.totalAmountSkillCasts; } /** * @param totalAmountMP * The total amount of MP spent on skills to set. * @throws IllegalArgumentException * if totalMPUsed is below 0 */ public void setTotalMPUsed(final int totalMPUsed) { if (totalMPUsed < 0) { throw new IllegalArgumentException("MP used must not be below 0."); } this.totalMPUsed = totalMPUsed; } /** * @return The total amount of MP spent on skills. */ public int getTotalMPUsed() { return this.totalMPUsed; } /** * @param totalMeatGain * The total amount of meat gathered to set. * @throws IllegalArgumentException * if totalMeatGain is below 0 */ public void setTotalMeatGain(final int totalMeatGain) { if (totalMeatGain < 0) { throw new IllegalArgumentException("Meat gain must not be below 0."); } this.totalMeatGain = totalMeatGain; } /** * @return The total amount of meat gathered. */ public int getTotalMeatGain() { return this.totalMeatGain; } /** * @param totalMeatGain * The total amount of meat spent to set. * @throws IllegalArgumentException * if totalMeatGain is below 0 */ public void setTotalMeatSpent(final int totalMeatSpent) { if (totalMeatSpent < 0) { throw new IllegalArgumentException( "Meat spent must not be below 0."); } this.totalMeatSpent = totalMeatSpent; } /** * @return The total amount of meat spent. */ public int getTotalMeatSpent() { return this.totalMeatSpent; } /** * @return The total amount of turns gained from food. */ public int getTotalTurnsFromFood() { return this.consumptionSummary.getTotalTurnsFromFood(); } /** * @return The total amount of turns gained from booze. */ public int getTotalTurnsFromBooze() { return this.consumptionSummary.getTotalTurnsFromBooze(); } /** * @return The total amount of turns gained from spleen and other sources. */ public int getTotalTurnsFromOther() { return this.consumptionSummary.getTotalTurnsFromOther(); } /** * @param totalTurnsFromRollover * The total amount of turns gained from rollover to set. * @throws IllegalArgumentException * if totalTurnsFromRollover is below 0 */ public void setTotalTurnsFromRollover(final int totalTurnsFromRollover) { if (totalTurnsFromRollover < 0) { throw new IllegalArgumentException("Turn gain must not be below 0."); } this.totalTurnsFromRollover = totalTurnsFromRollover; } /** * @return The total amount of turns gained from rollover. */ public int getTotalTurnsFromRollover() { return this.totalTurnsFromRollover; } /** * @param totalTurnsCombat * The total amount of combat turns to set. * @throws IllegalArgumentException * if totalTurnsCombat is below 0 */ public void setTotalTurnsCombat(final int totalTurnsCombat) { if (totalTurnsCombat < 0) { throw new IllegalArgumentException( "Turn spent must not be below 0."); } this.totalTurnsCombat = totalTurnsCombat; } /** * @return The total amount of combat turns. */ public int getTotalTurnsCombat() { return this.totalTurnsCombat; } /** * @param totalTurnsNoncombat * The total amount of noncombat turns to set. * @throws IllegalArgumentException * if totalTurnsNoncombat is below 0 */ public void setTotalTurnsNoncombat(final int totalTurnsNoncombat) { if (totalTurnsNoncombat < 0) { throw new IllegalArgumentException( "Turn spent must not be below 0."); } this.totalTurnsNoncombat = totalTurnsNoncombat; } /** * @return The total amount of noncombat turns. */ public int getTotalTurnsNoncombat() { return this.totalTurnsNoncombat; } /** * @param totalTurnsOther * The total amount of other (smithing, mixing, cooking, etc.) * turns to set. * @throws IllegalArgumentException * if totalTurnsOther is below 0 */ public void setTotalTurnsOther(final int totalTurnsOther) { if (totalTurnsOther < 0) { throw new IllegalArgumentException( "Turn spent must not be below 0."); } this.totalTurnsOther = totalTurnsOther; } /** * @return The total amount of other (smithing, mixing, cooking, etc.) * turns. */ public int getTotalTurnsOther() { return this.totalTurnsOther; } }