/*
* ChooserUtilities.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Current Version: $Revision$
* Copyright 2005 Andrew Wilson <nuance@sourceforge.net>
*/
package pcgen.core.chooser;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import pcgen.base.formula.Formula;
import pcgen.cdom.base.CDOMObject;
import pcgen.cdom.base.ChooseDriver;
import pcgen.cdom.base.ChooseInformation;
import pcgen.cdom.content.CNAbility;
import pcgen.cdom.reference.CDOMSingleRef;
import pcgen.core.Ability;
import pcgen.core.AbilityCategory;
import pcgen.core.AbilityUtilities;
import pcgen.core.PlayerCharacter;
import pcgen.core.SettingsHandler;
import pcgen.core.Skill;
/**
* The guts of chooser moved from PObject
*
* @author Andrew Wilson
*/
public class ChooserUtilities
{
/**
* Deal with CHOOSE tags. The actual items the choice will be made from are
* based on the choiceString, as applied to current character. Choices
* already made (getAssociatedList) are indicated in the selectedList. This
* method may also be used to build a list of choices available and choices
* already made by passing false in the process parameter
*
* @param availableList
* the list of things not already chosen
* @param selectedList
* the list of things already chosen
* @param aPC
* the PC that owns the Ability
* @param addIt
* Whether to add or remove a choice from this Ability
* @param category
* The AbilityCategory whose pool will be charged for the ability
* (if any). May be null.
*
* @return true if we processed the list of choices, false if we used the
* routine to build the list of choices without processing them.
*/
public static boolean modChoices(final ChooseDriver aPObject,
List availableList, final List selectedList, final PlayerCharacter aPC,
final boolean addIt, final AbilityCategory category)
{
availableList.clear();
selectedList.clear();
List reservedList = new ArrayList();
ChoiceManagerList aMan = getConfiguredController(aPObject, aPC,
category, reservedList);
if (aMan == null)
{
return false;
}
aMan.getChoices(aPC, availableList, selectedList);
if (!availableList.isEmpty() || !selectedList.isEmpty())
{
if (addIt)
{
final List newSelections =
aMan.doChooser(aPC, availableList,
selectedList, reservedList);
return aMan.applyChoices(aPC, newSelections);
}
else
{
aMan.doChooserRemove(aPC, availableList, selectedList,
reservedList);
}
return true;
}
return false;
}
public static <T> ChoiceManagerList<T> getConfiguredController(
final ChooseDriver aPObject, final PlayerCharacter aPC,
final AbilityCategory category, List<String> reservedList)
{
ChoiceManagerList aMan = getChoiceManager(aPObject, aPC);
if (aMan == null)
{
return null;
}
if (aPObject instanceof CNAbility)
{
CNAbility driver = (CNAbility) aPObject;
Ability a = driver.getAbility();
AbilityCategory cat;
if (category == null)
{
cat =
SettingsHandler.getGame().getAbilityCategory(
a.getCategory());
}
else
{
cat = category;
}
aMan.setController(new AbilityChooseController(a, cat, aPC, aMan));
List<CNAbility> abilities = aPC.getMatchingCNAbilities(a);
for (CNAbility cna : abilities)
{
reservedList.addAll(aPC.getAssociationList(cna));
}
}
else if (aPObject instanceof Skill)
{
Skill s = (Skill) aPObject;
aMan.setController(new SkillChooseController(s, aPC));
}
return aMan;
}
/**
* Restrict the available choices to what is allowed by the ability
* category.
*
* @param availableList
* The list of available choices, will be modified.
* @param category
* The ability category
* @param ability
* The ability the choices are for.
*/
private static void modifyAvailChoicesForAbilityCategory(
List availableList, AbilityCategory category, Ability ability)
{
AbilityCategory cat;
if (category == null)
{
cat =
SettingsHandler.getGame().getAbilityCategory(
ability.getCategory());
}
else
{
cat = category;
}
if (!cat.hasDirectReferences())
{
// Do nothing if there aren't any restrictions
return;
}
Set<String> allowedSet = new HashSet<>();
for (CDOMSingleRef<Ability> ref : cat.getAbilityRefs())
{
if (ref.contains(ability))
{
List<String> choices = new ArrayList<>();
AbilityUtilities.getUndecoratedName(ref.getLSTformat(false), choices);
allowedSet.addAll(choices);
}
}
if (allowedSet.isEmpty())
{
// Do nothing if there aren't any restrictions
return;
}
// Remove any non allowed choices from the list
for (Iterator iterator = availableList.iterator(); iterator.hasNext();)
{
Object obj = iterator.next();
String key;
if (obj instanceof CDOMObject)
{
key = ((CDOMObject) obj).getKeyName();
}
else
{
key = obj.toString();
}
if (!allowedSet.contains(key))
{
iterator.remove();
}
}
}
/**
* Make a ChoiceManager Object for the chooser appropriate for
* aPObject.getChoiceString();
*
* @param aPObject
* @param aPC
*
* @return an initialized ChoiceManager
*/
public static ChoiceManagerList getChoiceManager(ChooseDriver aPObject,
PlayerCharacter aPC)
{
ChooseInformation<?> chooseInfo = aPObject.getChooseInfo();
if (chooseInfo != null)
{
Formula selectionsPerUnitCost = aPObject.getSelectFormula();
int cost = selectionsPerUnitCost.resolve(aPC, "").intValue();
return chooseInfo.getChoiceManager(aPObject, cost);
}
return null;
}
}