TurnReportCollector.java :  » Game » joverseer » org » joverseer » tools » turnReport » Java Open Source

Java Open Source » Game » joverseer 
joverseer » org » joverseer » tools » turnReport » TurnReportCollector.java
package org.joverseer.tools.turnReport;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;

import org.apache.log4j.Logger;
import org.joverseer.domain.Army;
import org.joverseer.domain.ArmyElementType;
import org.joverseer.domain.ArmySizeEnum;
import org.joverseer.domain.Artifact;
import org.joverseer.domain.Challenge;
import org.joverseer.domain.Character;
import org.joverseer.domain.CharacterDeathReasonEnum;
import org.joverseer.domain.Combat;
import org.joverseer.domain.Company;
import org.joverseer.domain.Encounter;
import org.joverseer.domain.FortificationSizeEnum;
import org.joverseer.domain.HarborSizeEnum;
import org.joverseer.domain.NationEconomy;
import org.joverseer.domain.NationMessage;
import org.joverseer.domain.NationRelations;
import org.joverseer.domain.PlayerInfo;
import org.joverseer.domain.PopulationCenter;
import org.joverseer.domain.PopulationCenterSizeEnum;
import org.joverseer.domain.SpellProficiency;
import org.joverseer.game.Game;
import org.joverseer.game.Turn;
import org.joverseer.game.TurnElementsEnum;
import org.joverseer.metadata.GameMetadata;
import org.joverseer.metadata.domain.Hex;
import org.joverseer.metadata.domain.HexSideElementEnum;
import org.joverseer.metadata.domain.HexSideEnum;
import org.joverseer.metadata.domain.Nation;
import org.joverseer.metadata.domain.NationAllegianceEnum;
import org.joverseer.support.Container;
import org.joverseer.support.GameHolder;
import org.joverseer.support.NationMap;
import org.joverseer.support.StringUtils;
import org.joverseer.support.info.InfoUtils;
import org.joverseer.support.infoSources.XmlTurnInfoSource;
import org.joverseer.support.infoSources.spells.DerivedFromSpellInfoSource;
import org.joverseer.support.readers.pdf.CombatArmy;
import org.joverseer.support.readers.pdf.CombatWrapper;
import org.joverseer.tools.infoCollectors.artifacts.ArtifactInfoCollector;
import org.joverseer.tools.infoCollectors.artifacts.ArtifactWrapper;
import org.joverseer.tools.infoCollectors.characters.AdvancedCharacterWrapper;
import org.joverseer.tools.infoCollectors.characters.CharacterInfoCollector;

public class TurnReportCollector {

  public ArrayList<BaseReportObject> CollectNatSells(Turn t) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    ArrayList<Integer> friendlyNations = new ArrayList<Integer>();
    for (PlayerInfo pi : t.getPlayerInfo()) {
      friendlyNations.add(pi.getNationNo());
      NationReport bro = new NationReport();
      bro.setModification(ObjectModificationType.Gained);
      bro.setNationNo(pi.getNationNo());
      bro.setNotes("0");
      ret.add(bro);
    }
    for (Character c : t.getAllCharacters()) {
      if (!friendlyNations.contains(c.getNationNo()))
        continue;
      String cleanOrderResults = c.getCleanOrderResults();
      for (String sell : StringUtils.getRegexMatches(cleanOrderResults, "(\\d+ \\w+ were sold for \\d+ Gold\\.)")) {
        String gold = StringUtils.getUniquePart(sell, "sold for ", "Gold", false, false);
        for (BaseReportObject bro : ret) {
          if (bro.containsNation(c.getNationNo())) {
            int natSell = Integer.parseInt(bro.getNotes());
            natSell += Integer.parseInt(gold);
            bro.setNotes(String.valueOf(natSell));
          }
        }
      }
    }
    ArrayList<BaseReportObject> ret1 = new ArrayList<BaseReportObject>();
    DecimalFormat df = new DecimalFormat("###,##0");
    for (BaseReportObject bro : ret) {
      if (bro.getNotes().equals("0"))
        continue;
      int gold = Integer.parseInt(bro.getNotes());
      bro.setNotes(df.format(gold));
      ret1.add(bro);
    }
    return ret1;
  }

  public ArrayList<BaseReportObject> CollectNonFriendlyChars(Turn t) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    ArrayList<Integer> friendlyNations = new ArrayList<Integer>();
    for (PlayerInfo pi : t.getPlayerInfo()) {
      friendlyNations.add(pi.getNationNo());
    }
    for (Character c : t.getAllCharacters()) {
      if (friendlyNations.contains(c.getNationNo()))
        continue;
      if (c.getHostage() != null && c.getHostage() == true)
        continue;
      if (!c.getDeathReason().equals(CharacterDeathReasonEnum.NotDead))
        continue;
      Army a = t.getArmy(c.getName());
      if (a != null)
        continue;
      if (InfoUtils.isDragon(c.getName()))
        continue;
      CharacterReport cr;
      AdvancedCharacterWrapper acw = CharacterInfoCollector.instance().getCharacterForTurn(c.getName(), t.getTurnNo());
      if (acw.getTurnNo() != t.getTurnNo())
        acw = null;
      if (acw != null) {
        cr = new CharacterReport(acw);
      } else {
        cr = new CharacterReport(c);
      }
      cr.setHexNo(c.getHexNo());
      PopulationCenter pop = t.getPopCenter(c.getHexNo());
      if (pop != null) {
        cr.setNotes("PC: " + popPlusNation(pop));
      }
      if (c.getInfoSource() != null && !XmlTurnInfoSource.class.isInstance(c.getInfoSource())) {
        cr.appendNote(c.getInfoSource().getDescription());
      }
      cr.setModification(ObjectModificationType.Modified);
      ret.add(cr);
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectDragons(Turn t) {
    Nation gameNation = NationMap.getNationFromNo(GameHolder.instance().getGame().getMetadata().getNationNo());
    NationAllegianceEnum gameNationAllegiance = gameNation.getAllegiance();
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>(); // dragons
    // in
    // friendly
    // armies
    for (Army a : t.getArmies()) {
      for (String cn : a.getCharacters()) {
        if (InfoUtils.isDragon(cn)) {
          CharacterReport cr = new CharacterReport();
          cr.setName(cn);
          cr.setHexNo(Integer.parseInt(a.getHexNo()));
          cr.setNationNo(a.getNationNo());
          cr.setNotes("With army " + namePlusNation(a.getCommanderName(), a.getNation()));
          cr.setModification(ObjectModificationType.Gained);
          ret.add(cr);
        }
      }
    }
    // dragons in characters
    for (Character c : t.getCharacters()) {
      if (!InfoUtils.isDragon(c.getName()))
        continue;
      String hexNo = String.valueOf(c.getHexNo());
      if (c.getHexNo() < 1000)
        hexNo = "0" + hexNo;
      ArrayList<Character> chars = t.getCharacters().findAllByProperty("hexNo", c.getHexNo());
      ArrayList<Army> armies = t.getArmies().findAllByProperty("hexNo", hexNo);
      Army army = null;
      boolean existsEnemyArmy = false;
      String enemyArmies = "";
      for (Army a : armies) {
        if (a.getCharacters().contains(c.getName())) {
          army = a;
          break;
        }
        if (!a.getNationAllegiance().equals(gameNationAllegiance)) {
          existsEnemyArmy = true;
          enemyArmies += (enemyArmies.equals("") ? "" : ",") + a.getCommanderName();
        }
      }
      if (army != null)
        continue;
      PopulationCenter pc = t.getPopCenter(c.getHexNo());
      CharacterReport cr = new CharacterReport(c);
      if (existsEnemyArmy) {
        cr.setModification(ObjectModificationType.Lost);
        cr.setNotes("Enemy armies: " + enemyArmies);
      } else {
        cr.setModification(ObjectModificationType.Modified);
      }
      if (pc != null) {
        cr.appendNote(" PC: " + popPlusNation(pc));
      }
      String friendlyChars = "";
      for (Character ch : chars) {
        if (ch == c)
          continue;
        if (ch.getNationNo() != 0 && ch.getNation().getAllegiance().equals(gameNationAllegiance)) {
          friendlyChars += (friendlyChars.equals("") ? "" : ",") + charPlusNation(ch);
        }
      }
      if (!friendlyChars.equals(""))
        cr.appendNote(" Chars: " + friendlyChars);
      for (Encounter e : t.getEncounters().findAllByProperty("hexNo", c.getHexNo())) {
        if (e.getCleanDescription().contains(c.getName())) {
          cr.appendNote(" Encounter: " + e.getCharacter());
        }
      }
      ret.add(cr);
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectSpells(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (PlayerInfo pi : t.getPlayerInfo().getItems()) {
      int nationNo = pi.getNationNo();
      for (Character c : t.getCharacters().getItems()) {
        if (!c.getNationNo().equals(nationNo))
          continue;
        Character pc = p.getCharacters().findFirstByProperty("name", c.getName());
        if (pc == null)
          continue;
        for (SpellProficiency sp : c.getSpells()) {
          boolean found = false;
          for (SpellProficiency sp1 : pc.getSpells()) {
            if (sp.getSpellId() == sp1.getSpellId()) {
              found = true;
              break;
            }
          }
          if (!found) {
            CharacterReport cr = new CharacterReport(c);
            cr.setModification(ObjectModificationType.Gained);
            cr.setNotes("Learnt " + sp.getName() + " at " + sp.getProficiency());
            ret.add(cr);
          }
        }
      }
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectAgentActions(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (PlayerInfo pi : t.getPlayerInfo().getItems()) {
      int nationNo = pi.getNationNo();
      for (Character c : t.getCharacters().getItems()) {
        if (!c.getNationNo().equals(nationNo))
          continue;
        if (!c.getDeathReason().equals(CharacterDeathReasonEnum.NotDead))
          continue;
        Character pc = p.getCharacters().findFirstByProperty("name", c.getName());
        String orderResults = c.getCleanOrderResults();
        String prefix = StringUtils.getFirstWord(orderResults);
        String lprefix = prefix.toLowerCase();
        String lprefixGen = lprefix.equals("she") ? "her" : "his";
        if (orderResults.contains("was ordered to assassinate a character.")) {
          boolean failure = orderResults.contains("was not able to assassinate the character") || orderResults.contains("was not able to complete " + lprefixGen + " mission because the character was too well guarded");
          CharacterReport cr = new CharacterReport(c);
          if (pc != null) {
            cr.setHexNo(pc.getHexNo());
          }
          ret.add(cr);
          if (!failure) {
            String assassinatedChar = StringUtils.getUniquePart(orderResults, "was ordered to assassinate a character.", " was assassinated.", false, false);
            cr.setNotes("Assassinated " + getAdvCharWrapperStr(assassinatedChar, t));
            cr.setModification(ObjectModificationType.Gained);
          } else {
            cr.setNotes("Failed assassination");
            cr.setModification(ObjectModificationType.Lost);
          }
        }
        if (orderResults.contains("was ordered to kidnap a character.")) {
          boolean failure = orderResults.contains("was not able to kidnap the character") || orderResults.contains("was not able to complete " + lprefixGen + " mission because the character was too well guarded");
          String kidnappedChar = StringUtils.getUniquePart(orderResults, "was ordered to kidnap a character.", " was kidnaped.", false, false);
          CharacterReport cr = new CharacterReport(c);
          if (pc != null) {
            cr.setHexNo(pc.getHexNo());
          }
          ret.add(cr);
          if (!failure) {
            cr.setNotes("Kidnapped " + getAdvCharWrapperStr(kidnappedChar, t));
            cr.setModification(ObjectModificationType.Gained);
          } else {
            cr.setNotes("Failed kidnap");
            cr.setModification(ObjectModificationType.Lost);
          }
        }
        if (orderResults.contains("was ordered to sabotage the fortifications.")) {
          boolean failure = orderResults.contains("was not able to sabotage the fortifications") || orderResults.contains("was not able to complete " + lprefixGen + " mission because the character was too well guarded");
          CharacterReport cr = new CharacterReport(c);
          if (pc != null) {
            cr.setHexNo(pc.getHexNo());
          }
          ret.add(cr);
          if (!failure) {
            String pop = StringUtils.getUniquePart(orderResults, "The fortifications were sabotaged at", "\\.", false, false);
            cr.setNotes("Sab Fort at " + popPlusNation(pop, t));
            PopulationCenter pp = p.getPopCenter(pop);
            PopulationCenter cp = t.getPopCenter(pop);
            cr.appendNote(pp.getFortification().getRenderString() + "" + cp.getFortification().getRenderString());
            cr.setModification(ObjectModificationType.Gained);
          } else {
            cr.setNotes("Failed sab fort");
            cr.setModification(ObjectModificationType.Lost);
          }
        }
        if (orderResults.contains("was ordered to sabotage the harbor/port")) {
          boolean failure = orderResults.contains("was not able to sabotage the Harbor") || orderResults.contains("was not able to sabotage the Port");
          CharacterReport cr = new CharacterReport(c);
          if (pc != null) {
            cr.setHexNo(pc.getHexNo());
          }
          ret.add(cr);
          if (!failure) {
            String pop = StringUtils.getUniquePart(orderResults, "was sabotaged at ", "\\.", false, false);
            cr.setNotes("Sab Docks at " + popPlusNation(pop, t));
            PopulationCenter pp = p.getPopCenter(pop);
            PopulationCenter cp = t.getPopCenter(pop);
            if (pp != null && cp != null && pp.getHarbor() != null && cp.getHarbor() != null) {
              cr.appendNote(pp.getHarbor().getRenderString() + "" + cp.getHarbor().getRenderString());
            }
            cr.setModification(ObjectModificationType.Gained);
          } else {
            cr.setNotes("Failed sab docks");
            cr.setModification(ObjectModificationType.Lost);
          }
        }
        if (orderResults.contains("was ordered to sabotage a bridge")) {
          boolean failure = orderResults.contains("was not able to sabotage the bridge");
          CharacterReport cr = new CharacterReport(c);
          if (pc != null) {
            cr.setHexNo(pc.getHexNo());
          }
          ret.add(cr);
          if (!failure) {
            String hex = StringUtils.getUniquePart(orderResults, "was sabotaged at ", "\\.", false, false);
            cr.setNotes("Sab Bridge at " + hex);
            cr.setModification(ObjectModificationType.Gained);
          } else {
            cr.setNotes("Failed sab bridge");
            cr.setModification(ObjectModificationType.Lost);
          }
        }
        if (orderResults.contains("was ordered to guard the location")) {
          ArrayList<String> captured = StringUtils.getParts(orderResults, " captured ", " and thwarted \\w+ theft mission\\.", false, false);
          if (captured.size() > 0) {
            CharacterReport cr = new CharacterReport(c);
            if (pc != null) {
              cr.setHexNo(pc.getHexNo());
            }
            ret.add(cr);
            cr.setNotes("Guard loc");
            for (String capt : captured) {
              cr.appendNote("Captured " + capt);
            }
            cr.setModification(ObjectModificationType.Gained);
          }

          if (orderResults.contains("and thwarted his theft mission") || orderResults.contains("and thwarted her theft mission")) {

          }
        }

      }
    }
    return ret;
  }

  public ArrayList<BaseReportObject> collectChallenges(Turn t, Turn p) {
    Nation gameNation = NationMap.getNationFromNo(GameHolder.instance().getGame().getMetadata().getNationNo());
    NationAllegianceEnum gameNationAllegiance = gameNation.getAllegiance();
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (Challenge challenge : t.getChallenges().getItems()) {
      ChallengeReport cr = new ChallengeReport(challenge);
      String victor = challenge.getVictor();
      String loser = challenge.getLoser();
      AdvancedCharacterWrapper v = CharacterInfoCollector.instance().getCharacterForTurn(victor, t.getTurnNo());
      AdvancedCharacterWrapper l = CharacterInfoCollector.instance().getCharacterForTurn(loser, t.getTurnNo() - 1);
      if (l == null)
        l = CharacterInfoCollector.instance().getCharacterForTurn(loser, t.getTurnNo());
      String vn = "";
      String ln = "";
      ObjectModificationType mod = ObjectModificationType.Modified;
      if (l != null && l.getNationNo() != null && l.getNationNo() > 0) {
        Nation n = NationMap.getNationFromNo(l.getNationNo());
        if (n.getAllegiance().equals(gameNationAllegiance))
          mod = ObjectModificationType.Lost;
        cr.addNation(n.getNumber());
        ln = "(" + n.getShortName() + ")";
      }
      if (v != null && v.getNationNo() != null && v.getNationNo() > 0) {
        Nation n = NationMap.getNationFromNo(v.getNationNo());
        if (n.getAllegiance().equals(gameNationAllegiance))
          mod = ObjectModificationType.Gained;
        cr.addNation(n.getNumber());
        vn = "(" + n.getShortName() + ")";
      }
      cr.setModification(mod);
      cr.setName(victor + " vs " + loser);
      cr.appendNote(victor + vn + " won, " + loser + ln + " died");
      ret.add(cr);
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectCharacters(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (PlayerInfo pi : t.getPlayerInfo().getItems()) {
      int nationNo = pi.getNationNo();
      for (Character c : t.getCharacters().getItems()) {
        Character pc = p.getCharacters().findFirstByProperty("name", c.getName());
        if (!c.getNationNo().equals(nationNo))
          continue;
        if (!c.getDeathReason().equals(CharacterDeathReasonEnum.NotDead)) {
          // lost
          CharacterReport cr = new CharacterReport(c);
          if (c.getDeathReason().equals(CharacterDeathReasonEnum.Dead)) {
            if (c.getCleanOrderResults().contains("was killed during combat")) {
              cr.setNotes("Killed in combat");
            } else {
              cr.setNotes(c.getDeathReason().toString());
            }
          } else {
            cr.setNotes(c.getDeathReason().toString());
            if (c.getDeathReason().equals(CharacterDeathReasonEnum.Assassinated)) {
              for (NationMessage nm : t.getAllNationMessages()) {
                if (nm.isAssassinationRumor() && c.getName().equals(nm.getAssassinationTarget())) {
                  cr.appendNote("by " + getAdvCharWrapperStr(nm.getAssassinationAttacker(), t) + " (rumor)");
                  break;
                }
              }
            } else if (c.getDeathReason().equals(CharacterDeathReasonEnum.Challenged)) {
              Challenge challenge = t.findChallenge(c.getName());
              if (challenge != null) {
                cr.appendNote("by " + getAdvCharWrapperStr(challenge.getVictor(), t));
              }
            } else if (c.getDeathReason().equals(CharacterDeathReasonEnum.Cursed)) {
              String cod = c.getCleanOrderResults();
              if (!cod.contains("was killed due to a mysterious and deadly curse")) {
                if (cod.contains("was killed due to a mysterious and severe sickness")) {
                  cr.appendNotePart(" (sickness)");
                } else if (StringUtils.getUniquePart(cod, "was killed due to a ", "weakness", false, false) != null) {
                  cr.appendNotePart(" (weakness)");
                }
              }
            }
          }
          if (pc != null)
            cr.setCharacter(pc);
          cr.setModification(ObjectModificationType.Lost);
          ret.add(cr);
          if (c.getCleanOrderResults().contains("The army commanded by " + c.getName() + " has been disbanded because no suitable commander was present.")) {
            cr.appendNote("Army disbanded");
          }
        } else {
          if (pc == null) {
            // new
            CharacterReport cr = new CharacterReport(c);
            cr.setModification(ObjectModificationType.Gained);
            ret.add(cr);
          } else {
            // check for hostage
            String cleanOrderResults = c.getCleanOrderResults();
            if (c.getHexNo() == 0 && pc.getHexNo() != 0) {
              // hostage or missing
              if (cleanOrderResults.contains("could not escape from being held hostage")) {
                CharacterReport cr = new CharacterReport(c);
                cr.setHexNo(pc.getHexNo());
                cr.setModification(ObjectModificationType.Lost);
                cr.setNotes("Hostage");
                if (cleanOrderResults.contains(c.getName() + " was captured during combat by")) {
                  cr.appendNote("Captured in combat");
                } else if (cleanOrderResults.contains(c.getName() + " was kidnaped.")) {
                  cr.appendNote("Kidnapped");
                  for (NationMessage nm : t.getAllNationMessages()) {
                    if (nm.isKidnapRumor() && c.getName().equals(nm.getKidnapTarget())) {
                      cr.appendNote("by " + getAdvCharWrapperStr(nm.getKidnapAttacker(), t) + " (rumor)");
                    }
                  }
                  if (c.getCleanOrderResults().contains("The army commanded by " + c.getName() + " has been disbanded because no suitable commander was present.")) {
                    cr.appendNote("Army disbanded");
                  }
                }
                ret.add(cr);
              }
            } else if (c.getHexNo() != 0 && pc.getHexNo() == 0) {
              CharacterReport cr = new CharacterReport(c);
              cr.setModification(ObjectModificationType.Gained);
              cr.setNotes("Escaped from hostage");
              ret.add(cr);
            } else if (c.getHealth() != null && c.getHealth() < 100 && c.getHealth() > 0 && pc.getHealth() > c.getHealth()) {
              CharacterReport cr = new CharacterReport(c);
              cr.setModification(ObjectModificationType.Modified);
              cr.setNotes("Injured (" + c.getHealth() + ")");
              if (cleanOrderResults.contains("suffered a loss of health due to a mysterious")) {
                cr.appendNote(" Cursed");
              }
              if (cleanOrderResults.contains("was wounded during combat")) {
                cr.appendNote(" Wounded in combat");
              }
              if (cleanOrderResults.contains("was injured by")) {
                String injuredBy = StringUtils.getUniquePart(cleanOrderResults, "was injured by ", " while performing ", false, false);
                String mission = StringUtils.getUniquePart(cleanOrderResults, " while performing ", " mission\\.", false, false);
                if (injuredBy != null && mission != null) {
                  cr.appendNote(" Injured by " + getAdvCharWrapperStr(injuredBy, t));
                }
              }
              if (c.getMageTotal() > 0 && cleanOrderResults.contains(" suffered a loss of health due to casting two spells.")) {
                cr.appendNote(" Cast two spells");
              }
              if (t.findChallenge(c.getName()) != null) {
                cr.appendNote(" Wounded in challenge");
              }
              ret.add(cr);
            }
          }
        }
      }
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectPopCenters(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (PlayerInfo pi : t.getPlayerInfo().getItems()) {
      int nationNo = pi.getNationNo();
      for (PopulationCenter pc : t.getPopulationCenters().findAllByProperty("nationNo", nationNo)) {
        if (pc.getNationNo() != nationNo)
          continue;
        PopulationCenter ppc = p.getPopulationCenters().findFirstByProperty("hexNo", pc.getHexNo()); // if
        // previous pop was ruins, simulate that it did not exist
        if (pc.getSize().equals(PopulationCenterSizeEnum.ruins))
          continue;
        if (ppc != null && ppc.getSize().equals(PopulationCenterSizeEnum.ruins))
          ppc = null;
        if (ppc == null) {
          PopCenterReport pr = new PopCenterReport(pc);
          pr.setModification(ObjectModificationType.Gained);
          pr.setCreated(true);
          if (pc.getLoyalty() < 16 && pc.getFortification().equals(FortificationSizeEnum.none)) {
            pr.appendNote("Loyalty: " + pc.getLoyalty());
          }
          ret.add(pr);
        } else {
          PopCenterReport pr = GetPopCenterReport(pc, ppc, t, p, nationNo);
          if (pr != null)
            ret.add(pr);
        }
      }
      for (PopulationCenter ppc : p.getPopulationCenters().findAllByProperty("nationNo", nationNo)) {
        if (ppc.getNationNo() != nationNo)
          continue;
        PopulationCenter pc = (PopulationCenter) t.getContainer(TurnElementsEnum.PopulationCenter).findFirstByProperty("hexNo", ppc.getHexNo()); // if
        // previous pop was ruins, simulate that it did not exist
        if (pc == null || pc.getSize().equals(PopulationCenterSizeEnum.ruins)) {
          PopCenterReport pr = new PopCenterReport(ppc);
          pr.setPc(pc);
          pr.setPrevPc(ppc);
          pr.setModification(ObjectModificationType.Lost);
          if (ppc.getCapital())
            pr.appendNote("Capital");
          String destroyed = "Lost";
          Combat combat = (Combat) t.getContainer(TurnElementsEnum.Combat).findFirstByProperty("hexNo", ppc.getHexNo());
          if (combat != null) {
            CombatWrapper cw = new CombatWrapper();
            cw.parseAll(combat.getFirstNarration());
            if (ppc.getName().equals(cw.getPopName())) {
              if ("destroyed".equals(cw.getPopCenterOutcome())) {
                if (ppc.getNation() != null) {
                  destroyed = "Destroyed by ";
                  String destrNations = "";
                  for (Nation n : cw.getNations(ppc.getNation().getAllegiance())) {
                    destrNations += (destrNations.equals("") ? "" : ",") + n.getShortName();
                  }
                  destroyed += destrNations;
                } else {
                  destroyed = "Destroyed";
                }
              }
            }
          }
          pr.appendNote(destroyed);
          ret.add(pr);
        } else {
          if (pc.getNationNo() != nationNo) {
            PopCenterReport pr = GetPopCenterReport(pc, ppc, t, p, nationNo);
            if (pr != null)
              ret.add(pr);
          }
        }
      }
    }
    return ret;
  }

  protected PopCenterReport GetPopCenterReport(PopulationCenter pc, PopulationCenter ppc, Turn turn, Turn previous, int nationNo) {
    // check for modifications
    boolean sizeChanged = !pc.getSize().equals(ppc.getSize());
    boolean fortChanged = !pc.getFortification().equals(ppc.getFortification());
    boolean nationChanged = !pc.getNationNo().equals(ppc.getNationNo());
    boolean portChanged = !pc.getHarbor().equals(ppc.getHarbor());
    boolean hiddenChanged = pc.getHidden() != ppc.getHidden();
    boolean captured = !pc.getNation().getAllegiance().equals(ppc.getNation().getAllegiance()) || (nationChanged && (pc.getNationNo() == 0 || ppc.getNationNo() == 0));
    boolean capturedByEnemy = pc.getNationNo() != nationNo;
    if (sizeChanged || fortChanged || nationChanged || hiddenChanged || captured) {
      PopCenterReport pr = new PopCenterReport(pc);
      pr.setPrevPc(ppc);
      pr.setNationNo(nationNo);
      pr.addNation(pc.getNationNo());
      if (captured) {
        if (capturedByEnemy) {
          pr.setModification(ObjectModificationType.Lost);
        } else {
          pr.setModification(ObjectModificationType.Gained);
        }
      } else {
        pr.setModification(ObjectModificationType.Modified);
      }
      if (pc.getCapital())
        pr.appendNote("Capital");
      if (nationChanged) {

        for (Character pch : previous.getCharactersAtHex(pc.getHexNo())) {
          Character c = turn.getCharByName(pch.getName());
          if (c == null)
            continue;
          String cleanOrderResults = c.getCleanOrderResults();
          if (cleanOrderResults.contains(pc.getName() + " is now under our control")) {
            if (cleanOrderResults.contains("to threaten the population center")) {
              pr.appendNote(" Threatened");
              break;
            }
            if (cleanOrderResults.contains("The loyalty was influenced/reduced at " + pc.getName())) {
              pr.appendNote(" InfOthered");
              break;
            }
          }
        }
        for (Character c : turn.getCharactersAtHex(pc.getHexNo())) {
          String cleanOrderResults = c.getCleanOrderResults();
          if (c.getNationNo().equals(ppc.getNationNo()) && cleanOrderResults.contains(" was ordered to transfer the ownership of the population center.")) {
            pr.appendNote(" Transferred");
            break;
          }
        }
        for (NationMessage nm : turn.getNationMessages(ppc.getNationNo())) {
          if (nm.isInfOtherRumor() && nm.getInfoOtherPop().equals(pc.getName())) {
            pr.appendNote(" InfOthered");
            break;
          }
        }
        Combat combat = (Combat) turn.getContainer(TurnElementsEnum.Combat).findFirstByProperty("hexNo", ppc.getHexNo());
        if (combat != null) {
          CombatWrapper cw = new CombatWrapper();
          cw.parseAll(combat.getFirstNarration());
          if (cw.getPopName().equals(ppc.getName())) {
            if ("captured".equals(cw.getPopCenterOutcome())) {
              pr.appendNote(" Captured");
            }
          }
        }

        pr.appendNote(ppc.getNation().getShortName() + "" + pc.getNation().getShortName());
        pr.addNation(ppc.getNationNo());
        if (sizeChanged) {
          String pcDescr = shortenPopSize(pc.getSize().getRenderString());
          if (!pc.getFortification().equals(FortificationSizeEnum.none))
            pcDescr += "/" + shortenPopFort(pc.getFortification().getRenderString());
          if (pc.getHarbor() != null && !pc.getHarbor().equals(HarborSizeEnum.none))
            pcDescr += "/" + shortenPopDocks(pc.getHarbor().getRenderString());
          String ppcDescr = shortenPopSize(ppc.getSize().getRenderString());
          if (!ppc.getFortification().equals(FortificationSizeEnum.none))
            ppcDescr += "/" + shortenPopFort(ppc.getFortification().getRenderString());
          if (ppc.getHarbor() != null && !ppc.getHarbor().equals(HarborSizeEnum.none))
            ppcDescr += "/" + shortenPopDocks(ppc.getHarbor().getRenderString());
          pr.appendNote(ppcDescr + "" + pcDescr);
        }
      }
      if (hiddenChanged)
        pr.appendNote(pc.getHidden() ? "Hidden" : "Revealed");
      if (sizeChanged && !captured) {
        if (ppc.getSize().getCode() < pc.getSize().getCode()) {
          // check for improve
          for (Character pch : previous.getCharactersAtHex(pc.getHexNo())) {
            Character c = turn.getCharByName(pch.getName());
            if (c == null)
              continue;
            if (c.getNationNo().equals(pc.getNationNo())) {
              if (c.getCleanOrderResults().contains("was ordered to improve the population center size. " + pc.getName() + " was improved ")) {
                pr.appendNote("Improved");
              }
            }
          }
        }
        pr.appendNote(shortenPopSize(ppc.getSize().getRenderString()) + "" + shortenPopSize(pc.getSize().getRenderString()));
      }
      if (fortChanged) {
        if (!captured) {
          if (ppc.getFortification().getSize() < pc.getFortification().getSize()) {
            // check for improve
            for (Character pch : previous.getCharactersAtHex(pc.getHexNo())) {
              Character c = turn.getCharByName(pch.getName());
              if (c == null)
                continue;
              if (c.getNationNo() == pc.getNationNo()) {
                if (c.getCleanOrderResults().contains("was ordered to fortify the population center. The fortifications at " + pc.getName() + " were improved to a ")) {
                  pr.appendNote("Fortified");
                }
              }
            }
          } else {
            for (Character pch : previous.getCharactersAtHex(pc.getHexNo())) {
              Character c = turn.getCharByName(pch.getName());
              if (c == null)
                continue;
              if (c.getNationNo() == pc.getNationNo()) {
                if (c.getCleanOrderResults().contains(" was ordered to remove the fortifications. The fortifications were ")) {
                  pr.appendNote("RemFort");
                }
              }
            }
          }
          pr.appendNote(shortenPopFort(ppc.getFortification().getRenderString()) + "" + shortenPopFort(pc.getFortification().getRenderString()));
        }
      }
      if (portChanged && !captured)
        pr.appendNote(shortenPopDocks(ppc.getHarbor().getRenderString()) + "" + shortenPopDocks(pc.getHarbor().getRenderString()));
      return pr;
    }
    if (pc.getLoyalty() < ppc.getLoyalty()) {
      for (NationMessage nm : turn.getNationMessages(pc.getNationNo())) {
        if (nm.isInfOtherRumor() && nm.getInfoOtherPop().equals(pc.getName())) {
          PopCenterReport pr = new PopCenterReport(pc);
          pr.setModification(ObjectModificationType.Modified);
          pr.setNotes("InfOthered, Loyalty: " + ppc.getLoyalty() + "" + pc.getLoyalty());
          return pr;
        }
      }
    }
    if (pc.getLoyalty() < 16) {
      PopCenterReport pr = new PopCenterReport(pc);
      pr.setModification(ObjectModificationType.Modified);
      if (ppc != null) {
        pr.setNotes("Loyalty: " + ppc.getLoyalty() + "" + pc.getLoyalty() + " (at risk)");
      } else {
        pr.setNotes("Loyalty: " + pc.getLoyalty() + " (at risk)");
      }
      return pr;
    }
    return null;
  }

  public ArrayList<BaseReportObject> collectEncounters(Turn t) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (Encounter e : t.getEncounters().getItems()) {
      Character c = t.getCharByName(e.getCharacter());
      EncounterReport er = new EncounterReport();
      er.setHexNo(e.getHexNo());
      er.setEncounter(e);
      if (c == null) {
        er.setName(e.getCharacter());
      } else {
        er.setName(c.getName());
        er.setNationNo(c.getNationNo());
      }
      if (e.isReacting()) {
        er.setNotes("Reacting");
        if (e.isDragon()) {
          String dragonName = e.getDragonName();
          if (dragonName != null) {
            er.appendNote("Dragon " + dragonName);
          } else {
            er.appendNote("Dragon");
          }
        }
        er.setModification(ObjectModificationType.Gained);
      } else {
        if (e.getCanInvestigate()) {
          er.setNotes("Can investigate");
        } else {
          er.setNotes("Reacted");
        }
        er.setModification(ObjectModificationType.Modified);
      }
      ret.add(er);
    }
    for (NationMessage nm : t.getNationMessages().getItems()) {
      if (nm.isEncounterRumor()) {
        EncounterReport er = new EncounterReport();
        String name = nm.getEncounterCharacter();
        int hexNo = nm.getEncounterHexNo();
        if (t.getEncounter(hexNo, name) != null)
          continue;
        er.setHexNo(hexNo);
        er.setName(getAdvCharWrapperStr(name, t));
        er.setModification(ObjectModificationType.Lost);
        er.setNotes("Rumor");
        ret.add(er);
      }
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectCompanies(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (Company c : t.getCompanies().getItems()) {
      Company pc = p.getCompanies().findFirstByProperty("commander", c.getCommander());
      if (pc == null) {
        CompanyReport cr = new CompanyReport();
        cr.setHexNo(c.getHexNo());
        cr.setName(c.getCommander());
        cr.setModification(ObjectModificationType.Gained);
        cr.appendNote("Members: " + c.getMemberStr());
        addNation(cr, c.getCommander(), t);
        for (String m : c.getMembers())
          addNation(cr, m, t);
        ret.add(cr);
      } else {
        String leftStr = "";
        String joinedStr = "";
        CompanyReport cr = new CompanyReport();
        cr.setHexNo(c.getHexNo());
        cr.setName(c.getCommander());
        cr.setModification(ObjectModificationType.Modified);
        addNation(cr, c.getCommander(), t);
        boolean modified = false;
        for (String cm : c.getMembers()) {
          if (!pc.getMembers().contains(cm)) {
            joinedStr += (joinedStr.equals("") ? "" : ",") + cm;
            modified = true;
            addNation(cr, cm, t);
          }
        }
        for (String cm : pc.getMembers()) {
          if (!c.getMembers().contains(cm)) {
            leftStr += (leftStr.equals("") ? "" : ",") + cm;
            modified = true;
            addNation(cr, cm, p);
          }
        }
        if (modified) {
          if (!joinedStr.equals(""))
            cr.appendNote("Joined: " + joinedStr);
          if (!leftStr.equals(""))
            cr.appendNote("Left: " + leftStr);
          ret.add(cr);
        }
      }
    }
    for (Company pc : p.getCompanies().getItems()) {
      Company c = (Company) t.getContainer(TurnElementsEnum.Company).findFirstByProperty("commander", pc.getCommander());
      if (c == null) {
        CompanyReport cr = new CompanyReport();
        cr.setHexNo(pc.getHexNo());
        cr.setName(pc.getCommander());
        cr.setModification(ObjectModificationType.Lost);
        addNation(cr, pc.getCommander(), p);
        cr.setNotes("Members: " + pc.getMemberStr());
        for (String m : pc.getMembers())
          addNation(cr, m, p);
        ret.add(cr);
      }
    }
    return ret;
  }

  protected void addNation(BaseReportObject ro, String characterName, Turn t) {
    Character c = (Character) t.getContainer(TurnElementsEnum.Character).findFirstByProperty("name", characterName);
    if (c != null)
      ro.addNation(c.getNationNo());
  }

  public ArrayList<BaseReportObject> CollectArtifacts(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    Container<ArtifactWrapper> taws = ArtifactInfoCollector.instance().computeWrappersForTurn(t.getTurnNo());
    Container<ArtifactWrapper> paws = ArtifactInfoCollector.instance().computeWrappersForTurn(p.getTurnNo());
    for (ArtifactWrapper aw : taws.getItems()) {
      if (aw.getTurnNo() != t.getTurnNo())
        continue;
      if (DerivedFromSpellInfoSource.class.isInstance(aw.getInfoSource())) {
        DerivedFromSpellInfoSource s = (DerivedFromSpellInfoSource) aw.getInfoSource();
        ArtifactReport ar = new ArtifactReport();
        ar.setName(aw.getName() + " (" + aw.getNumber() + ")");
        ar.setArtifactNo(aw.getNumber());
        ar.setNationNo(s.getNationNo());
        String owner = aw.getOwner();
        AdvancedCharacterWrapper acw = CharacterInfoCollector.instance().getCharacterForTurn(owner, t.getTurnNo());
        if (acw != null && acw.getNationNo() != null) {
          ar.setNationNo(acw.getNationNo());
        }
        if (owner != null && !owner.equals(""))
          ar.setNotes("Owner: " + owner);
        ar.appendNote(aw.getInfoSource().getDescription());
        ar.setHexNo(aw.getHexNo());
        ar.setModification(ObjectModificationType.Modified);
        ret.add(ar);
        continue;
      }
      ArtifactWrapper paw = paws.findFirstByProperty("number", aw.getNumber());
      if (paw != null && paw.getTurnNo() != p.getTurnNo())
        paw = null;
      if (paw == null) {
        ArtifactReport ar = new ArtifactReport();
        ar.setName(aw.getName() + " (" + aw.getNumber() + ")");
        ar.setArtifactNo(aw.getNumber());
        ar.setNotes(aw.getOwner());
        ar.setNationNo(aw.getNationNo());
        ar.setHexNo(aw.getHexNo());
        ar.setModification(ObjectModificationType.Gained);
        ret.add(ar);
      } else {
        if (paw.getNationNo() != null && !paw.getNationNo().equals(aw.getNationNo())) {
          ArtifactReport ar = new ArtifactReport();
          ar.setArtifactNo(aw.getNumber());
          ar.setName(aw.getName() + " (" + aw.getNumber() + ")");
          ar.setNotes(aw.getOwner());
          ar.setNationNo(aw.getNationNo());
          ar.setHexNo(aw.getHexNo());
          ar.setModification(ObjectModificationType.Modified);
          ar.setNotes(charPlusNation(paw.getOwner(), t) + "  " + charPlusNation(aw.getOwner(), t));
          ret.add(ar);
        }
      }
    }
    for (ArtifactWrapper paw : paws.getItems()) {
      if (paw.getTurnNo() != p.getTurnNo())
        continue;
      if (DerivedFromSpellInfoSource.class.isInstance(paw.getInfoSource()))
        continue;
      ArtifactWrapper aw = taws.findFirstByProperty("number", paw.getNumber());
      if (aw != null && aw.getTurnNo() != t.getTurnNo())
        aw = null;
      if (paw.getNationNo() == null)
        continue;
      if (aw == null) {
        ArtifactReport ar = new ArtifactReport();
        ar.setName(paw.getName() + " (" + paw.getNumber() + ")");
        ar.setArtifactNo(paw.getNumber());
        ar.setNotes(paw.getOwner());
        ar.setNationNo(paw.getNationNo());
        ar.setHexNo(paw.getHexNo());
        ar.setModification(ObjectModificationType.Lost);
        ret.add(ar);
      }
    }
    return ret;
  }

  protected String getArtifactOwner(Nation n, Character c, Artifact a) {
    if (c != null)
      return charPlusNation(c);
    if (n != null)
      n.getName();
    return a.getOwner();
  }

  public ArrayList<BaseReportObject> CollectTransports(Turn t, Turn p) {
    Nation gameNation = NationMap.getNationFromNo(GameHolder.instance().getGame().getMetadata().getNationNo());
    NationAllegianceEnum gameNationAllegiance = gameNation.getAllegiance();

    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (NationMessage nm : t.getNationMessages().getItems()) {
      if (nm.isFriendlyTransportMessage()) {
        TransportReport tr = new TransportReport();
        String msg = nm.getMessage();
        tr.addNation(nm.getFriendlyTrasnportFromNation());
        PopulationCenter pc = t.getPopCenter(nm.getFriendlyTransportDestPop());
        if (pc != null) {
          tr.addNation(pc.getNationNo());
          tr.setHexNo(pc.getHexNo());
          msg = msg.replace(pc.getName(), popPlusNation(pc));
        }
        tr.setNotes(msg);
        tr.setModification(ObjectModificationType.Gained);
        ret.add(tr);
      } else if (nm.isEnemyTransportMessage()) {
        TransportReport tr = new TransportReport();
        String msg = nm.getMessage();
        String fromPop = nm.getEnemyTransportOriginPop();
        String toPop = nm.getEnemyTransportDestPop();
        PopulationCenter fp = t.getPopCenter(fromPop);
        PopulationCenter tp = t.getPopCenter(toPop);
        if (fp != null) {
          tr.addNation(fp.getNationNo());
          msg = msg.replace(fromPop, popPlusNation(fp));
        }
        if (tp != null) {
          tr.addNation(tp.getNationNo());
          msg = msg.replace(toPop, popPlusNation(tp));
          tr.setHexNo(tp.getHexNo());
        }
        if (fp != null && tp != null && fp.getNation().getAllegiance().equals(gameNationAllegiance) && tp.getNation().getAllegiance().equals(gameNationAllegiance)) {
          tr.setModification(ObjectModificationType.Gained);
        } else {
          tr.setModification(ObjectModificationType.Lost);
        }
        tr.setNotes(msg);
        ret.add(tr);
      }
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectGoldSteals(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (NationMessage nm : t.getNationMessages().getItems()) {
      if (nm.isStealRumor()) {
        StealGoldReport r = new StealGoldReport();
        r.addNation(nm.getNationNo());
        r.setModification(ObjectModificationType.Lost);
        r.setGold(nm.getStealAmount());
        r.setStolenFromNation(nm.getNationNo());
        r.setGainedByNation(-1);
        r.setNotes(r.getGold() + " gold");
        r.setHexNo(nm.getX() * 100 + nm.getY());
        ret.add(r);
      }
    }
    for (Character c : t.getCharacters().getItems()) {
      String orderResults = c.getCleanOrderResults();
      int i = orderResults.indexOf(" Gold was stolen at ");
      if (i > -1) {
        int j = i;
        while (java.lang.Character.isDigit(orderResults.charAt(j - 1))) {
          j--;
        }
        String amountStr = orderResults.substring(j, i);
        StealGoldReport sgr = new StealGoldReport();
        Character pc = p.getCharacters().findFirstByProperty("name", c.getName());
        if (pc != null) {
          sgr.setHexNo(pc.getHexNo());
          PopulationCenter ppc = (PopulationCenter) p.getContainer(TurnElementsEnum.PopulationCenter).findFirstByProperty("hexNo", pc.getHexNo());
          if (ppc != null) {
            sgr.setNotes(amountStr + " gold from " + ppc.getNation().getShortName() + " by " + c.getName());
            sgr.setStolenFromNation(ppc.getNationNo());
          } else {
            sgr.setStolenFromNation(-1);
          }
        }
        try {
          sgr.setGold(Integer.parseInt(amountStr));
        } catch (Exception e) {
          sgr.setGold(0);
        }
        sgr.setNationNo(c.getNationNo());
        sgr.setGainedByNation(c.getNationNo());
        sgr.setModification(ObjectModificationType.Gained);
        ret.add(sgr);
      }
    }
    return ret;
  }

  public ArrayList<BaseReportObject> CollectNations(Turn t, Turn p) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (PlayerInfo pi : t.getPlayerInfo().getItems()) {
      NationEconomy e = t.getNationEconomies().findFirstByProperty("nationNo", pi.getNationNo());
      NationEconomy pe = p.getNationEconomies().findFirstByProperty("nationNo", pi.getNationNo());
      if (pe == null)
        continue;
      if (e.getTaxRate() != pe.getTaxRate()) {
        NationReport er = new NationReport();
        er.setNationNo(e.getNationNo());
        er.setNotes("Tax rate: " + pe.getTaxRate() + "" + e.getTaxRate());
        er.setModification(ObjectModificationType.Modified);
        ret.add(er);
      }
      NationRelations nr = t.getNationRelations().findFirstByProperty("nationNo", pi.getNationNo());
      NationRelations pnr = p.getNationRelations().findFirstByProperty("nationNo", pi.getNationNo());
      if (pnr == null)
        continue;
      if (nr.getEliminated() && !pnr.getEliminated()) {
        NationReport er = new NationReport();
        er.setNationNo(nr.getNationNo());
        er.setNotes("Eliminated");
        er.setModification(ObjectModificationType.Lost);
        ret.add(er);
        continue;
      }
      if (!nr.getAllegiance().equals(pnr.getAllegiance())) {
        NationReport er = new NationReport();
        er.setNationNo(nr.getNationNo());
        er.setNotes("Allegiance: " + nr.getAllegiance());
        er.setModification(ObjectModificationType.Modified);
        ret.add(er);
      }
      for (int i = 1; i < 26; i++) {
        if (nr.getRelationsFor(i) != pnr.getRelationsFor(i)) {
          NationReport er = new NationReport();
          er.setNationNo(nr.getNationNo());
          er.setNotes(nr.getRelationsFor(i) + " to " + NationMap.getNationFromNo(i).getName());
          er.setModification(ObjectModificationType.Modified);
          ret.add(er);
        }
      }
      PopulationCenter capital = t.getCapital(pi.getNationNo());
      PopulationCenter pcapital = p.getCapital(pi.getNationNo());
      if (capital != null && pcapital != null && capital.getHexNo() != pcapital.getHexNo()) {
        NationReport er = new NationReport();
        er.setNationNo(nr.getNationNo());
        er.setNotes("Capital moved to " + capital.getHexNo() + " (" + capital.getName() + ")");
        er.setModification(ObjectModificationType.Modified);
        ret.add(er);
      }
    }
    return ret;
  }

  public ArrayList<BaseReportObject> collectUpcomingCombats(Turn t) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    Nation gameNation = NationMap.getNationFromNo(GameHolder.instance().getGame().getMetadata().getNationNo());
    NationAllegianceEnum gameNationAllegiance = gameNation.getAllegiance();
    for (Object ho : GameHolder.instance().getGame().getMetadata().getHexes()) {
      Hex h = (Hex) ho;
      ArrayList<Army> armies = t.getArmies(h.getHexNo());
      if (armies.size() == 0)
        continue;
      PopulationCenter pc = t.getPopCenter(h.getHexNo());
      if (pc != null && pc.getSize() == PopulationCenterSizeEnum.ruins)
        pc = null;
      boolean hasFP = false;
      boolean hasDS = false;
      boolean hasNeutral = false;
      boolean hasFriendlyArmy = false;
      boolean hasNonFriendlyArmy = false;
      boolean landArmies = false;
      boolean navies = false;
      String fps = "";
      String ds = "";
      String neuts = "";
      BaseReportObject bro = new BaseReportObject();
      for (Army a : armies) {
        if (Army.isAnchoredShips(a))
          continue;
        if (a.isNavy()) {
          navies = true;
        } else {
          landArmies = true;
        }
        if (a.getNationNo() != 0 && a.getNationAllegiance().equals(gameNationAllegiance)) {
          bro.addNation(a.getNationNo());
          hasFriendlyArmy = true;
        } else {
          hasNonFriendlyArmy = true;
        }
        if (a.getNationAllegiance().equals(NationAllegianceEnum.FreePeople)) {
          hasFP = true;
          fps += (fps.equals("") ? "" : ", ") + getArmyDescription(a, t);
        }
        if (a.getNationAllegiance().equals(NationAllegianceEnum.DarkServants)) {
          hasDS = true;
          ds += (ds.equals("") ? "" : ", ") + getArmyDescription(a, t);
        }
        if (a.getNationAllegiance().equals(NationAllegianceEnum.Neutral)) {
          hasNeutral = true;
          neuts += (neuts.equals("") ? "" : ", ") + getArmyDescription(a, t);
        }
      }
      if (pc != null && !pc.getNationNo().equals(0)) {
        NationAllegianceEnum pcalleg = pc.getNation().getAllegiance();
        if (pcalleg.equals(gameNationAllegiance) && pc.getNationNo() != 0)
          bro.addNation(pc.getNationNo());
        if (pcalleg.equals(NationAllegianceEnum.FreePeople)) {
          hasFP = true;
          if (fps.equals(""))
            fps = "PC";
        }
        if (pcalleg.equals(NationAllegianceEnum.DarkServants)) {
          hasDS = true;
          if (ds.equals(""))
            ds = "PC";
        }
        if (pcalleg.equals(NationAllegianceEnum.Neutral)) {
          hasNeutral = true;
          if (neuts.equals(""))
            neuts = "PC";
        }
      }
      if (!(hasFP && hasDS || hasFP && hasNeutral || hasDS && hasNeutral))
        continue;
      bro.setHexNo(h.getHexNo());
      String name = "";
      if (hasFP && hasDS) {
        name = fps + " vs " + ds;
        if (hasNeutral) {
          name += " neutrals: " + neuts;
        }
      } else if (hasNeutral) {
        if (hasFP) {
          name = fps + " vs " + neuts;
        } else {
          name = ds + " vs " + neuts;
        }
      } else {
        continue;
      }
      boolean naval = !landArmies && navies;
      if (naval)
        name = "Naval - " + name;
      bro.setName(name);
      if (hasFriendlyArmy) {
        if (hasNonFriendlyArmy) {
          bro.setModification(ObjectModificationType.Modified);
        } else {
          bro.setModification(ObjectModificationType.Gained);
        }
      } else if (hasNonFriendlyArmy) {
        bro.setModification(ObjectModificationType.Lost);
      } else {
        bro.setModification(ObjectModificationType.Modified);
      }
      if (pc != null) {
        bro.appendNote(getPopInfo(pc.getName(), pc.getNation(), pc.getSize().getRenderString(), pc.getFortification().getRenderString()));
      }
      for (Character c : t.getCharactersAtHex(h.getHexNo())) {
        if (InfoUtils.isDragon(c.getName())) {
          boolean foundInArmy = false;
          for (Army a : armies) {
            if (a.getCharacters().contains(c.getName())) {
              bro.appendNote("Dragon " + c.getName() + " w/" + a.getCommanderName());
              foundInArmy = true;
            }
          }
          if (!foundInArmy)
            bro.appendNote("Dragon " + c.getName());
        }
      }
      ret.add(bro);
    }
    return ret;
  }

  protected String getArmyDescription(Army a, Turn t) {
    String ret = a.getCommanderName();
    ret += " (" + a.getNation().getShortName();
    if (a.getElements().size() > 0) {
      ret += " " + a.getENHI() + "EHI";
    } else if (a.getTroopCount() > 0) {
      ret += " " + a.getTroopCount() + "men";
    } else if (!a.getSize().equals(ArmySizeEnum.unknown)) {
      if (a.getSize().equals(ArmySizeEnum.army)) {
        ret += "";
      } else {
        ret += " " + a.getSize() + "";
      }
    }
    if (a.isNavy()) {
      if (a.getElements().size() > 0) {
        ret += " " + a.getNumber(ArmyElementType.Warships) + "WS";
      } else {
        ret += " navy";
      }
    }
    ret += ")";
    return ret;
  }

  public ArrayList<BaseReportObject> CollectCombats(Turn t) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    Nation gameNation = NationMap.getNationFromNo(GameHolder.instance().getGame().getMetadata().getNationNo());
    NationAllegianceEnum gameNationAllegiance = gameNation.getAllegiance();
    for (Combat c : t.getCombats().getItems()) {
      CombatWrapper cw = new CombatWrapper();
      CombatReport cr = null;
      for (int i = 1; i < 26; i++) {
        String r = c.getNarrationForNation(i);
        if (r != null) {
          if (cr != null) {
            cr.addNation(i);
            continue;
          }
          try {
            cw.parseAll(r);
            ArrayList<Integer> nations = new ArrayList<Integer>();
            ArrayList<Integer> winners = new ArrayList<Integer>();
            String commanders = "";
            for (CombatArmy ca : cw.getArmies().getItems()) {
              Nation n = NationMap.getNationFromName(ca.getNation());
              int num = n.getNumber();
              if (!nations.contains(num))
                nations.add(num);
              if (ca.isSurvived()) {
                if (!winners.contains(num))
                  winners.add(num);
              }
              if (ca.getCommanderOutcome() != null && (ca.getCommanderOutcome().equals("captured") || ca.getCommanderOutcome().equals("killed"))) {
                commanders += (commanders.equals("") ? "" : ",") + namePlusNation(ca.getCommanderName(), n) + " " + ca.getCommanderOutcome();
              }
            }
            cr = new CombatReport(c);
            String participants = "";
            cr.addNation(i);
            for (Integer num : nations) {
              // cr.appendNote();
              participants += (participants.equals("") ? "" : ",") + NationMap.getNationFromNo(num).getShortName();
            }
            cr.setParticipants(participants);
            if (cw.getPopName() != null) {
              Nation n = NationMap.getNationFromName(cw.getPopNation());
              cr.setPopInfo(getPopInfo(cw.getPopName(), n, cw.getPopSize(), cw.getPopFort()));
            }
            HashSet<NationAllegianceEnum> winnerAllegiances = new HashSet<NationAllegianceEnum>();
            if (winners.size() > 0) {
              String winStr = "";
              for (Integer num : winners) {
                Nation n = NationMap.getNationFromNo(num);
                winStr += (winStr.equals("") ? "" : ",") + n.getShortName();
                winnerAllegiances.add(n.getAllegiance());
              }
              // cr.appendNote(" Won by:" + winStr);
              cr.setWinners(winStr);
            } else {
              // cr.appendNote("No winners");
              cr.setWinners("No winners");
            }
            String popOutcome;
            if (cw.getPopCenterOutcome() != null && !cw.getPopCenterOutcome().equals("not affected")) {
              popOutcome = " PC " + cw.getPopCenterOutcome();
              if (cw.getPopCenterOutcome().equals("captured")) {
                Nation nn = NationMap.getNationFromName(cw.getPopOutcomeNation());
                if (nn != null) {
                  popOutcome += " by " + nn.getShortName();
                } else {
                  popOutcome += " by " + cw.getPopOutcomeNation();
                }
              }
              // cr.appendNote(popOutcome);
              cr.setPopOutcome(popOutcome);
            } else if (cw.getPopName() != null) {
              popOutcome = " PC not affected";
              // cr.appendNote(popOutcome);
              cr.setPopOutcome(popOutcome);
            }
            if (cw.isNaval())
              cr.appendNote("Naval combat");
            if (!commanders.equals(""))
              cr.appendNote(commanders);
            if (winnerAllegiances.contains(gameNationAllegiance)) {
              cr.setModification(ObjectModificationType.Gained);
            } else if (winnerAllegiances.size() > 0) {
              cr.setModification(ObjectModificationType.Lost);
            } else {
              cr.setModification(ObjectModificationType.Modified);
            }
            ret.add(cr);
          } catch (Exception e) {
            Logger.getLogger(TurnReportCollector.class).error(e);
          }
        }
      }

    }
    return ret;
  }

  protected String getPopInfo(String name, Nation n, String size, String fort) {
    String ret = name + " (";
    if (n != null)
      ret += n.getShortName() + ",";
    ret += shortenPopSize(size);
    if (fort != null) {
      String f = shortenPopFort(fort);
      if (!f.equals("") && !f.equals("None"))
        ret += "/" + f;
    }
    ret += ")";
    return ret;
  }

  public ArrayList<BaseReportObject> collectBridges(Turn t, Turn p) {
    ArrayList<BridgeReport> ret = new ArrayList<BridgeReport>();
    GameMetadata gm = GameHolder.instance().getGame().getMetadata();
    ArrayList<Hex> thc = gm.getHexOverrides(t.getTurnNo()).getItems();
    ArrayList<Hex> phc = gm.getHexOverrides(t.getTurnNo()).getItems();
    HashSet<Integer> hexes = new HashSet<Integer>();
    for (Hex h : thc) {
      hexes.add(h.getHexNo());
    }
    for (Hex h : phc) {
      hexes.add(h.getHexNo());
    }
    for (Integer hexNo : hexes) {
      Hex ch = gm.getHexForTurn(t.getTurnNo(), hexNo);
      Hex ph = gm.getHexForTurn(p.getTurnNo(), hexNo);
      if (ph == ch)
        continue;
      for (HexSideEnum hse : HexSideEnum.values()) {
        boolean cb = ch.getHexSideElements(hse).contains(HexSideElementEnum.Bridge);
        boolean pb = ph.getHexSideElements(hse).contains(HexSideElementEnum.Bridge);
        if (cb != pb) {
          int otherHex = hse.getHexNoAtSide(hexNo);
          boolean found = false;
          for (BridgeReport br : ret) {
            if (br.getHexNo() == otherHex) {
              found = true;
              break;
            }
          }
          if (found)
            continue;
          BridgeReport br = new BridgeReport();
          br.setHexNo(ch.getHexNo());
          if (cb) {
            br.setModification(ObjectModificationType.Gained);
            br.setNotes("Bridge built " + hexNo + "-" + otherHex);
          } else {
            br.setModification(ObjectModificationType.Lost);
            br.setNotes("Bridge destroyed " + hexNo + "-" + otherHex);
          }
          PopulationCenter pc = t.getPopCenter(hexNo);
          if (pc != null)
            br.appendNote(" PC: " + popPlusNation(pc));
          pc = t.getPopCenter(otherHex);
          if (pc != null)
            br.appendNote(popPlusNation(pc));
          ret.add(br);
        }
      }
    }
    for (NationMessage nm : t.getNationMessages().getItems()) {
      if (nm.isBridgeSabotagedRumor()) {
        String location = nm.getBridgeSabotagedLocation();
        int hexNo = -1;
        try {
          hexNo = Integer.parseInt(location);
        } catch (Exception exc) {
        }
        PopulationCenter pc;
        if (hexNo != -1) {
          pc = t.getPopCenter(hexNo);
        } else {
          pc = t.getPopCenter(location);
          hexNo = pc.getHexNo();
        }
        BridgeReport br = new BridgeReport();
        br.setHexNo(hexNo);
        br.setModification(ObjectModificationType.Lost);
        br.setNotes("Sabotage rumor");
        if (pc != null)
          br.appendNote(" PC: " + pc.getName() + "(" + pc.getNation().getShortName() + ")");
        ret.add(br);
      }
    }
    ArrayList<BaseReportObject> ret2 = new ArrayList<BaseReportObject>();
    for (BridgeReport br : ret)
      ret2.add(br);
    return ret2;
  }

  protected String getAdvCharWrapperStr(String name, Turn t) {
    AdvancedCharacterWrapper acw = CharacterInfoCollector.instance().getCharacterForTurn(name, t.getTurnNo());
    if (acw == null)
      return name;
    Nation n = NationMap.getNationFromNo(acw.getNationNo());
    return namePlusNation(name, n);
  }

  protected String popPlusNation(PopulationCenter pc) {
    return namePlusNation(pc.getName(), pc.getNation());
  }

  protected String popPlusNation(String name, Turn t) {
    PopulationCenter pc = t.getPopCenter(name);
    if (pc == null)
      return name;
    return namePlusNation(pc.getName(), pc.getNation());
  }

  protected String charPlusNation(Character c) {
    return namePlusNation(c.getName(), c.getNation());
  }

  protected String charPlusNation(String name, Turn t) {
    Character c = t.getCharByName(name);
    if (c == null)
      return name;
    return charPlusNation(c);
  }

  protected String namePlusNation(String name, Nation n) {
    if (n == null || n.getNumber() == 0)
      return name;
    return name + "(" + n.getShortName() + ")";
  }

  public String renderCollection(String title, ArrayList<BaseReportObject> reports) {
    return renderCollection(title, null, reports);
  }

  public String renderCollection(String title, String comments, ArrayList<BaseReportObject> reports) {
    Collections.sort(reports);
    String ret = "<b style='font-size:11pt'> " + title + "</b>";
    if (comments != null)
      ret += "<i> - " + comments + "</i><br/>";
    if (reports.size() == 0)
      return ret + "-" + "<br/>";
    ret += "<table style='border-style:solid; border-width:1px' cellspacing=0 cellpadding=2>";
    for (int i = 0; i < reports.size(); i++) {
      BaseReportObject bro = reports.get(i);
      String color = "#DDFFDD";
      if (bro.getModification().equals(ObjectModificationType.Lost))
        color = "#FFDDDD";
      if (bro.getModification().equals(ObjectModificationType.Modified))
        color = "#FFFFDD";
      ret += "<tr style='background-color:" + color + ";'>" + bro.getHtmlString() + "</tr>";
    }
    ret += "</table>";
    return ret;
  }

  public String renderStealsSummary(ArrayList<BaseReportObject> steals) {
    if (steals.size() == 0)
      return "";
    int goldGained = 0;
    int goldLost = 0;
    for (BaseReportObject bro : steals) {
      StealGoldReport sgr = (StealGoldReport) bro;
      if (sgr.getModification().equals(ObjectModificationType.Gained)) {
        goldGained += sgr.getGold();
      } else {
        goldLost += sgr.getGold();
      }
    }
    DecimalFormat df = new DecimalFormat("###,##0");
    return "<div style='font-family:Tahoma; font-size:11pt'><b>" + "Total gold gained: " + df.format(goldGained) + "<br/>" + "Total gold lost: " + df.format(goldLost) + "</b></div>";
  }

  public String renderCharsSummary(ArrayList<BaseReportObject> chars) {
    if (chars.size() == 0)
      return "";
    int charsGained = 0;
    int charsLost = 0;
    for (BaseReportObject bro : chars) {
      CharacterReport cr = (CharacterReport) bro;
      if (cr.getModification().equals(ObjectModificationType.Gained)) {
        charsGained++;
      } else if (cr.getModification().equals(ObjectModificationType.Lost)) {
        charsLost++;
      }
    }
    return "<div style='font-family:Tahoma; font-size:11pt'><b>" + "New chars: " + charsGained + "<br/>" + "Lost chars: " + charsLost + "</b></div>";
  }

  public String renderPopsSummary(ArrayList<BaseReportObject> pops) {
    if (pops.size() == 0)
      return "";
    int campsCreated = 0;
    HashMap<PopulationCenterSizeEnum, Integer> gains = new HashMap<PopulationCenterSizeEnum, Integer>();
    HashMap<PopulationCenterSizeEnum, Integer> losses = new HashMap<PopulationCenterSizeEnum, Integer>();
    for (PopulationCenterSizeEnum s : PopulationCenterSizeEnum.values()) {
      gains.put(s, 0);
      losses.put(s, 0);
    }
    int taxBaseDelta = 0;
    for (BaseReportObject bro : pops) {
      PopCenterReport pcr = (PopCenterReport) bro;
      if (pcr.getModification().equals(ObjectModificationType.Gained) && pcr.getPc() != null && pcr.getPc().getSize().equals(PopulationCenterSizeEnum.camp) && pcr.isCreated()) {
        campsCreated++;
      }
      if (pcr.getModification().equals(ObjectModificationType.Gained)) {
        int g = gains.get(pcr.getPc().getSize());
        g++;
        gains.put(pcr.getPc().getSize(), g);
        taxBaseDelta += Math.max(pcr.getPc().getSize().getCode() - 1, 0);
      } else if (pcr.getModification().equals(ObjectModificationType.Lost)) {
        int l = losses.get(pcr.getPrevPc().getSize());
        l++;
        losses.put(pcr.getPrevPc().getSize(), l);
        taxBaseDelta -= Math.max(pcr.getPrevPc().getSize().getCode() - 1, 0);
      } else if (pcr.getModification().equals(ObjectModificationType.Modified) && pcr.getPrevPc() != null) {
        int pcTaxBase = Math.max(pcr.getPc().getSize().getCode() - 1, 0);
        int prevTaxBase = Math.max(pcr.getPrevPc().getSize().getCode() - 1, 0);
        taxBaseDelta += pcTaxBase - prevTaxBase;
      }
    }
    String gstr = "";
    String lstr = "";
    for (PopulationCenterSizeEnum s : PopulationCenterSizeEnum.values()) {
      if (s.equals(PopulationCenterSizeEnum.ruins))
        continue;
      int g = gains.get(s);
      int l = losses.get(s);
      if (g > 0)
        gstr += (gstr.equals("") ? "" : ", ") + s.getRenderString() + ": " + g;
      if (l > 0)
        lstr += (lstr.equals("") ? "" : ", ") + s.getRenderString() + ": " + l;
    }
    return "<div style='font-family:Tahoma; font-size:11pt'><b>" + "Camps created: " + campsCreated + "<br/>" + "Gains: " + gstr + "<br/>" + "Losses: " + lstr + "<br/>" + "Tax base delta: " + taxBaseDelta + "</b></div>";
  }

  public ArrayList<BaseReportObject> filterReports(ArrayList<BaseReportObject> reports, int nationNo) {
    ArrayList<BaseReportObject> ret = new ArrayList<BaseReportObject>();
    for (BaseReportObject bro : reports) {
      if (nationNo == -1 || bro.containsNation(nationNo))
        ret.add(bro);
    }
    return ret;
  }

  protected String shortenPopDocks(String popDocks) {
    if (popDocks.equals("-"))
      popDocks = "None";
    return popDocks;
  }

  protected String shortenPopSize(String popSize) {
    if (popSize.equals("Major Town"))
      popSize = "MT";
    if (popSize.equals("Town"))
      popSize = "T";
    if (popSize.equals("Village"))
      popSize = "Vil";
    return popSize;
  }

  protected String shortenPopFort(String popFort) {
    if (popFort.equals("-"))
      popFort = "None";
    if (popFort.equals("Fort"))
      popFort = "F";
    if (popFort.equals("Tower"))
      popFort = "T";
    if (popFort.equals("Citadel"))
      popFort = "Cit";
    return popFort;
  }

  public String renderReport() {
    try {
      String ret = "";
      Game g = GameHolder.instance().getGame();
      Turn t = g.getTurn();
      Turn p = g.getTurn(t.getTurnNo() - 1);
      if (p == null)
        return "";
      ArrayList<BaseReportObject> reports;
      ret += "<div style='font-family:MS Sans Serif; font-size:11pt'>";
      try {
        reports = CollectNations(t, p);
        ret += renderCollection("Nations", "Relation, allegiance and tax rate changes", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectNatSells(t);
        ret += renderCollection("Sells", "Gold sold per nation", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectCharacters(t, p);
        ret += renderCollection("Characters", "New, lost and injured characters", reports);
        ret += renderCharsSummary(reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectPopCenters(t, p);
        ret += renderCollection("Pop Centers", "New, gained, lost or changed pop centers", reports);
        ret += renderPopsSummary(reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectCompanies(t, p);
        ret += renderCollection("Companies", "New, disbanded or changed companies", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectArtifacts(t, p);
        ret += renderCollection("Artifacts", "Gained, lost, transfered or located artifacts", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = collectChallenges(t, p);
        ret += renderCollection("Challenges", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectCombats(t);
        ret += renderCollection("Combats", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectGoldSteals(t, p);
        ret += renderCollection("Gold Steals", reports);
        ret += renderStealsSummary(reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectAgentActions(t, p);
        ret += renderCollection("Agent Actions", "Actions by friendly agents (assassinations, kidnaps, sabotages)", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectTransports(t, p);
        ret += renderCollection("Nation Transports", "Gold and product transports and transport rumors", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectSpells(t, p);
        ret += renderCollection("Spells", "Spells learnt", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = collectBridges(t, p);
        ret += renderCollection("Bridges", "Bridges built or destroyed", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectNonFriendlyChars(t);
        ret += renderCollection("Other Characters", "Non-friendly characters reported (excluding army commanders)", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = collectEncounters(t);
        ret += renderCollection("Encounters", "Encounters and encounter rumors", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = CollectDragons(t);
        ret += renderCollection("Dragons", "Dragons in armies or pop centers", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/>";
      try {
        reports = collectUpcomingCombats(t);
        ret += renderCollection("Upcoming Combats", "Hexes where combat may occur", reports);
      } catch (RuntimeException e) {
        e.printStackTrace();
      }
      ret += "<br/><i>Green: positive events<br/>Red: negative events<br/>Yellow: other</i>";
      return ret;
    } catch (Exception exc) {
      exc.printStackTrace();
      Logger.getLogger(TurnReportCollector.class).error(exc.getLocalizedMessage());
      return "";
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.