Mercurial > repos > IBBoard.WarFoundry.API
view API/Objects/Requirement/AbstractUnitRequirement.cs @ 487:248df19652f9
Re #410: Create "N units per M models in parent unit" requirement
* Add null adding context
* Add initial skeleton of "N units per M models in parent unit" requirement
* Update use of context
* Standardise some of "is applicable" testing
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Fri, 27 Jul 2012 20:31:12 +0100 |
parents | e0641e0eb86c |
children |
line wrap: on
line source
// This file (AbstractRequirement.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2011 IBBoard // // The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license. using System; using System.Collections.Generic; using IBBoard.WarFoundry.API.Objects.Requirement.Context; namespace IBBoard.WarFoundry.API.Objects.Requirement { public abstract class AbstractUnitRequirement<OBJECT_TYPE> : IRequirement where OBJECT_TYPE : IWarFoundryObject { private List<UnitCountRequirementData> requiredTypes; private OBJECT_TYPE allowedObject; public AbstractUnitRequirement(OBJECT_TYPE allowedObject, params UnitType[] requiredUnitTypes) { this.allowedObject = allowedObject; requiredTypes = new List<UnitCountRequirementData>(); foreach (UnitType unitType in requiredUnitTypes) { AddUnitTypeRequirement(unitType); } } public abstract string RequirementID { get; } protected List<UnitCountRequirementData> ConstraintTypes { get { return requiredTypes; } } public abstract void AddUnitTypeRequirement(UnitType unitType); public override bool Equals(object obj) { if (obj == null) { return false; } else if (obj.GetType().Equals(this.GetType())) { return TypeEquals((AbstractUnitRequirement<OBJECT_TYPE>)obj); } else { return false; } } protected virtual bool TypeEquals(AbstractUnitRequirement<OBJECT_TYPE> obj) { AbstractUnitRequirement<OBJECT_TYPE> otherReq = obj as AbstractUnitRequirement<OBJECT_TYPE>; if (!this.AllowedObject.Equals(otherReq.AllowedObject)) { return false; } else if (!Collections.Collections.AreEqual(ConstraintTypes, otherReq.ConstraintTypes)) { return false; } else { return true; } } public override int GetHashCode() { int hash = GetType().FullName.GetHashCode() + AllowedObject.GetHashCode(); foreach (UnitCountRequirementData limit in ConstraintTypes) { hash += limit.GetHashCode(); } return hash; } /// <summary> /// A wrapper method that supplies a default "null context" to determines whether this requirement is applicable to the specified object and/or the specified army /// </summary> /// <returns> /// <c>true</c> if this instance is applicable to the specified toObjectAdded or toArmy (or both); otherwise, <c>false</c>. /// </returns> /// <param name='toObjectAdded'> /// The WarFoundry object being added /// </param> /// <param name='toArmy'> /// The army the object is being added to /// </param> protected bool IsApplicable(IWarFoundryObject toObjectAdded, Army toArmy) { return IsApplicable(toObjectAdded, toArmy, new NullAddingContext()); } /// <summary> /// Determines whether this requirement is independantly applicable to the specified object or the specified army. /// </summary> /// <returns> /// <c>true</c> if this instance is applicable to the specified toObjectAdded or toArmy (or both); otherwise, <c>false</c>. /// </returns> /// <param name='toObjectAdded'> /// The WarFoundry object being added /// </param> /// <param name='toArmy'> /// The army the object is being added to /// </param> /// <param name='context'> /// The context for adding the object /// </param> protected bool IsApplicable(IWarFoundryObject toObjectAdded, Army toArmy, AddingContext context) { return IsApplicableToBoth(toObjectAdded, toArmy, context) || IsApplicable(toArmy, context) || IsApplicable(toObjectAdded, context); } /// <summary> /// Determines whether this requirement is applicable the specified army in the given context /// </summary> /// <returns> /// <c>true</c> if this requirement is applicable to the specified army in the given context; otherwise, <c>false</c>. /// </returns> /// <param name='toArmy'> /// The army that an object is being added to /// </param> /// <param name='context'> /// The context for adding the object /// </param> protected virtual bool IsApplicable(Army toArmy, AddingContext context) { return false; } /// <summary> /// Determines whether this requirement is applicable the specified object in the given context. /// </summary> /// <returns> /// <c>true</c> if this requirement is applicable the specified object in the context; otherwise, <c>false</c>. /// </returns> /// <param name='toObject'> /// The object being added to an army /// </param> /// <param name='context'> /// The context for adding the object /// </param> protected virtual bool IsApplicable(IWarFoundryObject toObject, AddingContext context) { return false; } /// <summary> /// Determines whether this instance is applicable to both the specified object and army in the given context. /// </summary> /// <returns> /// <c>true</c> if this instance is applicable to both the specified object and army in the given context; otherwise, <c>false</c>. /// </returns> /// <param name='toObject'> /// The object being added to an army /// </param> /// <param name='toArmy'> /// The army that an object is being added to /// </param> /// <param name='context'> /// The context for adding the object /// </param> protected virtual bool IsApplicableToBoth(IWarFoundryObject toObjectAdded, Army toArmy, AddingContext context) { return false; } public string GetValidationMessage(Army army) { string message = ""; Validation result = ValidatesArmy(army); if (!Validates.AsOkay(result)) { message = GetValidationFailedMessage(army); } return message; } protected virtual string ValidationFailedMessage { get { return "Army must contain: {0}."; } } private string GetValidationFailedMessage(Army army) { return String.Format(ValidationFailedMessage, GetFailedRequirementsString(army)); } protected abstract string GetFailedRequirementsString(Army army); public string GetAllowsAddingMessage(IWarFoundryObject toAdd, Army toArmy) { return GetAllowsAddingMessage(toAdd, toArmy, new NullAddingContext()); } public string GetAllowsAddingMessage(IWarFoundryObject toAdd, Army toArmy, AddingContext context) { string message = ""; Validation result = AllowsAdding(toAdd, toArmy, context); if (!Validates.AsOkay(result)) { message = GetAllowsAddingFailedMessage(toAdd, toArmy, context); } return message; } protected virtual string AllowsAddingFailedMessage { get { return ValidationFailedMessage; } } protected string GetAllowsAddingFailedMessage(IWarFoundryObject toAdd, Army toArmy, AddingContext context) { return String.Format(AllowsAddingFailedMessage, GetFailedAddingRequirementsString(toAdd, toArmy, context)); } protected abstract string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context); /// <summary> /// Checks whether the supplied WarFoundryObject can be added to the supplied army. /// </summary> /// <returns> /// A <code>Validation</code> enum to show the result of the validation /// </returns> /// <param name='wfObject'> /// The object that we want to add. This may be involved in the check, or it may not affect the evaluation of the requirement /// </param> /// <param name='toArmy'> /// The army to add the object to. /// </param> public Validation AllowsAdding(IWarFoundryObject wfObject, Army toArmy) { return AllowsAdding(wfObject, toArmy, new NullAddingContext()); } /// <summary> /// Checks whether the supplied WarFoundryObject can be added to the supplied army. /// </summary> /// <returns> /// A <code>Validation</code> enum to show the result of the validation /// </returns> /// <param name='wfObject'> /// The object that we want to add. This may be involved in the check, or it may not affect the evaluation of the requirement /// </param> /// <param name='toArmy'> /// The army to add the object to. /// </param> /// <param name='context'>The context for the action (may be null)</param> public Validation AllowsAdding(IWarFoundryObject wfObject, Army toArmy, AddingContext context) { return IsApplicable(wfObject, toArmy, context) ? CheckAllowsAdding(wfObject, toArmy, context) : Validation.NotApplicable; } protected abstract Validation CheckAllowsAdding(IWarFoundryObject wfObject, Army toArmy, AddingContext context); public abstract Validation ValidatesArmy(Army army); protected UnitType GetUnitTypeFromObject(IWarFoundryObject toObject) { UnitType unitType = null; if (toObject is UnitType) { unitType = (UnitType)toObject; } else if (toObject is Unit) { unitType = ((Unit)toObject).UnitType; } return unitType; } protected int GetUnitTypeCount(Army toArmy, UnitType unitType, IWarFoundryObject wfObject) { return toArmy.GetUnitTypeCount(unitType) + GetCountFromObject(wfObject, unitType); } protected int GetUnitTypesCount(Army army, UnitType[] unitTypes) { return GetUnitTypesCount(army, unitTypes, null); } protected int GetUnitTypesCount(Army toArmy, UnitType[] unitTypes, IWarFoundryObject wfObject) { int count = 0; foreach (UnitType unitType in unitTypes) { count += GetUnitTypeCount(toArmy, unitType, wfObject); } return count; } protected int GetCountFromObject(IWarFoundryObject wfObject, UnitType limitedType) { return (limitedType.Equals(wfObject) || (wfObject is Unit && ((Unit)wfObject).UnitType.Equals(limitedType))) ? 1 : 0; } protected int GetObjectCount(Army toArmy, IWarFoundryObject wfObject) { return GetObjectCountFromArmy(toArmy) + GetObjectCountFromObject(wfObject); } protected abstract int GetObjectCountFromArmy(Army toArmy); protected abstract int GetObjectCountFromArmy(Army toArmy, OBJECT_TYPE obj); protected virtual int GetObjectCountFromObject(IWarFoundryObject wfObject) { return allowedObject.Equals(wfObject) ? 1 : 0; } public OBJECT_TYPE AllowedObject { get { return allowedObject; } } protected string GetUnitTypeList(UnitCountRequirementData limit) { List<String> namesList = new List<String>(); foreach (UnitType unitType in limit.UnitTypes) { namesList.Add(unitType.Name); } string[] names = namesList.ToArray(); return String.Join(" or ", names); } protected bool IsUnitTypeLimited(UnitType unitType) { foreach (UnitCountRequirementData requirement in requiredTypes) { if (Arrays.Contains(requirement.UnitTypes, unitType)) { return true; } } return false; } } }