changeset 465:7b9ff7b1df24

Re #394: Make requirements (or factory) more closely match Rollcall methods * Make UnitRequiresAtLeastNUnitsRequirementFactory handle "alternatives" (Rollcall's "-1,X|Y" notation) * Make RequiresAtLeastNUnitsRequirement handle alternatives/multiple unit types in one limit * Move some useful code up the classes
author IBBoard <dev@ibboard.co.uk>
date Sat, 24 Mar 2012 20:33:11 +0000
parents 59e1fb8a476a
children bdfa314789cc
files API/Factories/Requirement/UnitRequiresAtLeastNUnitsRequirementFactory.cs API/Objects/Requirement/AbstractUnitRequirement.cs API/Objects/Requirement/RequiresAtLeastNUnitsRequirement.cs API/Objects/Requirement/RequiresNUnitsForMObjectsRequirement.cs
diffstat 4 files changed, 96 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/API/Factories/Requirement/UnitRequiresAtLeastNUnitsRequirementFactory.cs	Sat Mar 24 16:40:01 2012 +0000
+++ b/API/Factories/Requirement/UnitRequiresAtLeastNUnitsRequirementFactory.cs	Sat Mar 24 20:33:11 2012 +0000
@@ -4,6 +4,7 @@
 using System;
 using IBBoard.WarFoundry.API.Objects;
 using IBBoard.WarFoundry.API.Objects.Requirement;
+using System.Collections.Generic;
 
 namespace IBBoard.WarFoundry.API.Factories.Requirement
 {
@@ -28,8 +29,10 @@
 			//Do nothing special
 		}
 
-		public string AppliesToID {
-			get {
+		public string AppliesToID
+		{
+			get
+			{
 				return UnitRequiresAtLeastNUnitsRequirement.REQUIREMENT_ID;
 			}
 		}
@@ -47,13 +50,8 @@
 			foreach (string requirement in data.Split('|'))
 			{
 				string[] requirementParts = requirement.Split(':');
-				string unitID = requirementParts[0];
-				UnitType unitType = raceFactory.GetUnitType(unitID, race);
-
-				if (unitType == null)
-				{
-					throw new InvalidRequirementException(String.Format("Invalid unit type '{0}' for 'Requires at least N units' requirement", unitID));
-				}
+				string unitIDs = requirementParts[0];
+				UnitType[] unitTypes = GetUnitTypes(unitIDs, race, raceFactory);
 
 				if (requirementParts.Length == 2)
 				{
@@ -61,19 +59,38 @@
 
 					try
 					{
-						req.AddUnitTypeRequirement(unitType, Int32.Parse(amount));
+						req.AddUnitTypeRequirement(Int32.Parse(amount), unitTypes);
 					}
 					catch (FormatException)
 					{
-						throw new InvalidRequirementException(String.Format("Invalid amount '{0}' for unit type '{1}' for 'Requires at least N units' requirement", amount, unitID));
+						throw new InvalidRequirementException(String.Format("Invalid amount '{0}' for unit types '{1}' for 'Requires at least N units' requirement", amount, unitIDs));
 					}
 				}
 				else
 				{
-					req.AddUnitTypeRequirement(unitType);
+					req.AddUnitTypeRequirement(unitTypes);
 				}
 			}
 		}
+
+		private UnitType[] GetUnitTypes<SOURCE_FILE_TYPE, ENTRY_TYPE>(string data, Race race, IRaceFactory<SOURCE_FILE_TYPE, ENTRY_TYPE> raceFactory)
+		{
+			List<UnitType> unitTypes = new List<UnitType>();
+
+			foreach (string unitID in data.Split(';'))
+			{
+				UnitType unitType = raceFactory.GetUnitType(unitID, race);
+	
+				if (unitType == null)
+				{
+					throw new InvalidRequirementException(String.Format("Invalid unit type '{0}' for 'Requires at least N units' requirement", unitID));
+				}
+
+				unitTypes.Add(unitType);
+			}
+
+			return unitTypes.ToArray();
+		}
 	}
 }
 
--- a/API/Objects/Requirement/AbstractUnitRequirement.cs	Sat Mar 24 16:40:01 2012 +0000
+++ b/API/Objects/Requirement/AbstractUnitRequirement.cs	Sat Mar 24 20:33:11 2012 +0000
@@ -157,6 +157,23 @@
 			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;
@@ -177,6 +194,19 @@
 		}
 
 		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);
+		}
 	}
 }
 
--- a/API/Objects/Requirement/RequiresAtLeastNUnitsRequirement.cs	Sat Mar 24 16:40:01 2012 +0000
+++ b/API/Objects/Requirement/RequiresAtLeastNUnitsRequirement.cs	Sat Mar 24 20:33:11 2012 +0000
@@ -85,7 +85,7 @@
 			
 			foreach (UnitCountRequirementData requirement in ConstraintTypes)
 			{
-				if (GetUnitTypeCount(toArmy, requirement.UnitType, wfObject) < requirement.Count)
+				if (GetUnitTypesCount(toArmy, requirement.UnitTypes, wfObject) < requirement.Count)
 				{
 					isValid = Validation.Failed;
 					break;
@@ -96,7 +96,7 @@
 		}
 
 		/// <summary>
-		/// Adds a requirement for there to be at least minCount of a given UnitType
+		/// Adds a requirement for there to be at least minCount of a given UnitType, allowing any number of of this UnitType.
 		/// </summary>
 		/// <param name='unitType'>
 		/// The unit type to require.
@@ -106,11 +106,11 @@
 		/// </param>
 		public void AddUnitTypeRequirement(UnitType unitType, int minCount)
 		{
-			ConstraintTypes.Add(new UnitCountRequirementData(unitType, minCount));
+			AddUnitTypeRequirement(minCount, unitType);
 		}
 
 		/// <summary>
-		/// Adds a requirement for there to be one or more of a given UnitType
+		/// Adds a requirement for there to be one or more of a given UnitType, allowing any number of of this UnitType.
 		/// </summary>
 		/// <param name='unitType'>
 		/// The unit type to require.
@@ -121,6 +121,34 @@
 		}
 
 		/// <summary>
+		/// Adds a requirement for there to be one or more of the given UnitTypes, allowing any number of of this UnitType. If multiple unit types
+		/// are supplied here then they are treated as alternatives (so "unitType1, unitType2" requires one of either type).
+		/// </summary>
+		/// <param name='unitType'>
+		/// The unit type or types to require.
+		/// </param>
+		public void AddUnitTypeRequirement(params UnitType[] unitTypes)
+		{
+			AddUnitTypeRequirement(1, unitTypes);
+		}
+
+		/// <summary>
+		/// Adds a requirement for there to be minCount or more of the given UnitTypes, allowing any number of of this UnitType. If multiple unit types
+		/// are supplied here then they are treated as alternatives (so "unitType1, unitType2" requires one of either type).
+		/// </summary>
+		/// <param name="minCount">
+		/// The number of units to be allowed for each 1 of unitType
+		/// </param>
+		/// <param name='unitType'>
+		/// The unit type or types to require.
+		/// </param>
+		public void AddUnitTypeRequirement(int minCount, params UnitType[] unitTypes)
+		{
+			ConstraintTypes.Add(new UnitCountRequirementData(unitTypes, minCount));
+		}
+
+
+		/// <summary>
 		/// Checks whether the supplied army is currently valid according to this requirement.
 		/// </summary>
 		/// <returns>
@@ -140,7 +168,7 @@
 
 				foreach (UnitCountRequirementData requirement in ConstraintTypes)
 				{
-					if (toValidate.GetUnitTypeCount(requirement.UnitType) < requirement.Count)
+					if (GetUnitTypesCount(toValidate, requirement.UnitTypes) < requirement.Count)
 					{
 						isValid = Validation.Failed;
 						break;
@@ -166,11 +194,11 @@
 
 			foreach (UnitCountRequirementData requirement in ConstraintTypes)
 			{
-				int unitCount = army.GetUnitTypeCount(requirement.UnitType);
+				int unitCount = GetUnitTypesCount(army, requirement.UnitTypes);
 
 				if (unitCount < requirement.Count)
 				{
-					failures.Add(requirement.Count + " × " + requirement.UnitType.Name + " (have " + unitCount + ")");
+					failures.Add(requirement.Count + " × " + GetUnitTypeList(requirement) + " (have " + unitCount + ")");
 				}
 			}
 
@@ -188,11 +216,11 @@
 
 			foreach (UnitCountRequirementData requirement in ConstraintTypes)
 			{
-				int unitCount = GetUnitTypeCount(army, requirement.UnitType, toAdd);
+				int unitCount = GetUnitTypesCount(army, requirement.UnitTypes, toAdd);
 
 				if (unitCount < requirement.Count)
 				{
-					failures.Add(requirement.Count + " × " + requirement.UnitType.Name + " (would have " + unitCount + ")");
+					failures.Add(requirement.Count + " × " + GetUnitTypeList(requirement) + " (would have " + unitCount + ")");
 				}
 			}
 
--- a/API/Objects/Requirement/RequiresNUnitsForMObjectsRequirement.cs	Sat Mar 24 16:40:01 2012 +0000
+++ b/API/Objects/Requirement/RequiresNUnitsForMObjectsRequirement.cs	Sat Mar 24 20:33:11 2012 +0000
@@ -50,19 +50,6 @@
 			return failures;
 		}
 
-		private 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);
-		}
-
 		private bool IsValidByRequirement(IWarFoundryObject wfObject, Army toArmy, UnitCountRequirementData limit, int allowedTypeCount)
 		{
 			int limitedTypeCount = GetUnitTypesCount(toArmy, limit.UnitTypes, wfObject);
@@ -101,18 +88,6 @@
 			return canAdd;
 		}
 
-		private int GetUnitTypesCount(Army toArmy, UnitType[] unitTypes, IWarFoundryObject wfObject)
-		{
-			int count = 0;
-
-			foreach (UnitType unitType in unitTypes)
-			{
-				count += GetUnitTypeCount(toArmy, unitType, wfObject);
-			}
-
-			return count;
-		}
-
 		private int GetAllowedObjectCount(Army toArmy, OBJECT_TYPE obj, IWarFoundryObject wfObject)
 		{
 			return GetObjectCountFromArmy(toArmy, obj) + GetCountFromObject(wfObject, obj);
@@ -177,11 +152,6 @@
 
 		protected abstract int GetAllowedObjectCount(Army army);
 
-		private int GetUnitTypesCount(Army army, UnitType[] unitTypes)
-		{
-			return GetUnitTypesCount(army, unitTypes, null);
-		}
-
 		/// <summary>
 		/// Adds a requirement for there to be at least minCount of a given UnitType, allowing allowedCount of this UnitType
 		/// </summary>