/*
* EU3History.java
*
* Created on May 9, 2007, 1:33 PM
*/
package eug.specific.eu3;
import eug.shared.GenericObject;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Class which deals with EU3 histories, such as are found in the history
* subfolder or in saved games.
* @since EUGFile 1.04.00pre1
* @author Michael Myers
*/
public final class EU3History {
private EU3History() { }
/**
* Comparator for EU3 date strings, like 1492.1.1 .
*/
public static final DateComparator DATE_COMPARATOR = new DateComparator();
// private static final Comparator<GenericObject> DATE_OBJECT_COMPARATOR =
// new Comparator<GenericObject>() {
//
// private final Map<String, String[]> splitMap =
// new HashMap<String, String[]>(100);
//
// private final String[] split(final String s) {
// String[] split = splitMap.get(s);
// if (split == null) {
// split = s.split("\\.");
// splitMap.put(s, split);
// }
// return split;
// }
//
// private final Map<String, Integer> intMap =
// new HashMap<String, Integer>(100);
//
// private final Integer getInt(final String s) {
// Integer i = intMap.get(s);
// if (i == null) {
// i = Integer.valueOf(s);
// intMap.put(s, i);
// }
// return i;
// }
//
// public final int compare(final GenericObject o1, final GenericObject o2) {
// final String[] s1Split = split(o1.name);
// final String[] s2Split = split(o2.name);
//
// int ret = getInt(s1Split[0]).compareTo(getInt(s2Split[0]));
// if (ret != 0)
// return ret;
//
// ret = getInt(s1Split[1]).compareTo(getInt(s2Split[1]));
// if (ret != 0)
// return ret;
//
// return getInt(s1Split[2]).compareTo(getInt(s2Split[2]));
// }
// };
private static final Pattern DATE_PATTERN =
Pattern.compile("[0-9]{1,4}\\.[0-9]{1,2}\\.[0-9]{1,2}");
public static final GenericObject getHistObject(final GenericObject history, String name) {
if (history == null)
return null;
GenericObject value = history.getChild(name);
String lastDate = "0.0.0";
for (GenericObject date : history.children) {
if (!DATE_PATTERN.matcher(date.name).matches()) {
if (!date.name.equals("advisor"))
System.err.println(date.name + " is not a valid date");
continue;
}
if (DATE_COMPARATOR.compare(date.name, lastDate) >= 0) {
GenericObject newVal = date.getChild(name);
if (newVal != null) {
value = newVal;
lastDate = date.name;
}
}
}
return value;
}
public static final GenericObject getHistObject(final GenericObject history, String name, String date) {
if (history == null)
return null;
GenericObject value = history.getChild(name);
String lastDate = "0.0.0";
for (GenericObject dateObj : history.children) {
if (!DATE_PATTERN.matcher(dateObj.name).matches()) {
if (!dateObj.name.equals("advisor"))
System.err.println(dateObj.name + " is not a valid date");
continue;
}
if (DATE_COMPARATOR.compare(dateObj.name, lastDate) >= 0 &&
DATE_COMPARATOR.compare(dateObj.name, date) <= 0) {
// The new date is after the old date and before or equal to the target date
GenericObject newVal = dateObj.getChild(name);
if (newVal != null) {
value = newVal;
lastDate = dateObj.name;
}
}
}
return value;
}
public static final String getHistString(final GenericObject history, String name) {
if (history == null)
return null;
String value = history.getString(name);
String lastDate = "0.0.0";
for (GenericObject date : history.children) {
if (!DATE_PATTERN.matcher(date.name).matches()) {
if (!date.name.equals("advisor"))
System.err.println(date.name + " is not a valid date");
continue;
}
if (DATE_COMPARATOR.compare(date.name, lastDate) >= 0) {
String newVal = date.getString(name);
if (newVal.length() != 0) {
value = newVal;
lastDate = date.name;
}
}
}
return value;
}
public static final String getHistString(final GenericObject history, String name, String date) {
if (history == null)
return null;
String value = history.getString(name);
String lastDate = "0.0.0";
for (GenericObject dateObj : history.children) {
if (!DATE_PATTERN.matcher(dateObj.name).matches()) {
if (!dateObj.name.equals("advisor"))
System.err.println(dateObj.name + " is not a valid date");
continue;
}
if (DATE_COMPARATOR.compare(dateObj.name, lastDate) >= 0 &&
DATE_COMPARATOR.compare(dateObj.name, date) <= 0) {
// The new date is after the old date and before or equal to the target date
String newVal = dateObj.getString(name);
if (newVal.length() != 0) {
value = newVal;
lastDate = dateObj.name;
}
}
}
return value;
}
/** @since EUGFile 1.05.00pre1 */
public static final List<String> getHistStrings(final GenericObject history, String name, String date) {
if (history == null)
return null;
final List<String> values = history.getStrings(name);
for (GenericObject dateObj : history.children) {
if (!DATE_PATTERN.matcher(dateObj.name).matches()) {
if (!dateObj.name.equals("advisor"))
System.err.println(dateObj.name + " is not a valid date");
continue;
}
if (DATE_COMPARATOR.compare(dateObj.name, date) <= 0) {
// The new date is before or equal to the target date
String value = dateObj.getString(name);
if (value.length() != 0) {
values.add(value);
}
}
}
return values;
}
/** @since EUGFile 1.05.00pre1 */
public static final List<String> isCoreOf(final GenericObject history, String date) {
return getHistStrings(history, date, "add_core", "remove_core");
}
/**
* Searches through a history object and finds all strings that have been
* added by the <code>adder</code> string and not removed by the
* <code>remover</code> string. Examples of adder/remover pairs include
* "add_core"/"remove_core" in province histories and
* "add_attacker"/"rem_attacker" in war histories.
* @param history the history object to search through.
* @param date the last date that is checked. Anything added or removed
* after this date is not considered.
* @param adder the string that signals that something has been added.
* @param remover the string that signals that something has been removed.
* @return the list of strings that have been added but not removed. This
* could be, for example, the list of country tags that have cores on a
* particular province.
* @since EUGFIle 1.07.00pre1
*/
public static final List<String> getHistStrings(
final GenericObject history,
final String date,
final String adder,
final String remover)
{
if (history == null)
return null;
final List<String> values = history.getStrings(adder);
for (GenericObject dateObj : history.children) {
if (!DATE_PATTERN.matcher(dateObj.name).matches()) {
if (!"advisor".equals(dateObj.name))
System.err.println(dateObj.name + " is not a valid date");
continue;
}
if (DATE_COMPARATOR.compare(dateObj.name, date) <= 0) {
values.removeAll(dateObj.getStrings(remover));
values.addAll(dateObj.getStrings(adder));
}
}
return values;
}
public static final class DateComparator implements Comparator<String> {
public DateComparator() {
}
private final Map<String, String[]> splitMap = new HashMap<String, String[]>(100);
private final Pattern dot = Pattern.compile("\\.");
private final String[] split(final String s) {
String[] split = splitMap.get(s);
if (split == null) {
split = dot.split(s);
splitMap.put(s, split);
}
return split;
}
private final Map<String, Integer> intMap = new HashMap<String, Integer>(100);
private final Integer getInt(final String s) {
Integer i = intMap.get(s);
if (i == null) {
i = Integer.valueOf(s);
intMap.put(s, i);
}
return i;
}
public final int compare(final String s1, final String s2) {
final String[] s1Split = split(s1);
final String[] s2Split = split(s2);
int ret = getInt(s1Split[0]).compareTo(getInt(s2Split[0]));
if (ret != 0) {
return ret;
}
ret = getInt(s1Split[1]).compareTo(getInt(s2Split[1]));
if (ret != 0) {
return ret;
}
return getInt(s1Split[2]).compareTo(getInt(s2Split[2]));
}
/**
* Returns <code>true</code> if <code>date1</code> is before
* <code>date2</code>.
*/
public boolean isBefore(final String date1, final String date2) {
return compare(date1, date2) < 0;
}
}
}