changeset 489:aac77204ae0e

Re #410: Create "N units per M models in parent unit" requirement * Add methods to Army and ArmyCategory to get units of a given type * Implement validation on "N models in parent for M units" requirement
author IBBoard <dev@ibboard.co.uk>
date Sun, 29 Jul 2012 15:31:09 +0100
parents c082a312a741
children e35fc85eda2b
files API/Objects/Army.cs API/Objects/ArmyCategory.cs API/Objects/Requirement/UnitRequiresNParentModelsForMUnitsRequirement.cs
diffstat 3 files changed, 130 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/API/Objects/Army.cs	Sun Jul 29 14:16:14 2012 +0100
+++ b/API/Objects/Army.cs	Sun Jul 29 15:31:09 2012 +0100
@@ -67,7 +67,7 @@
 		{
 			get
 			{
-				if (categories==null)
+				if (categories == null)
 				{
 					categories = new Dictionary<Category, ArmyCategory>();
 					Category[] raceCats = Race.Categories;
@@ -79,9 +79,9 @@
 						Category raceCat = raceCats[i];
 						cat = new ArmyCategory(this, raceCat);
 						categories[raceCat] = cat;
-						cat.PointsValueChanged+= PointsValueChangedMethod;
-						cat.UnitAdded+=new ObjectAddDelegate(Army_UnitAdded);
-						cat.UnitRemoved+=new ObjectRemoveDelegate(Army_UnitRemoved);
+						cat.PointsValueChanged += PointsValueChangedMethod;
+						cat.UnitAdded += new ObjectAddDelegate(Army_UnitAdded);
+						cat.UnitRemoved += new ObjectRemoveDelegate(Army_UnitRemoved);
 					}
 				}
 				
@@ -91,7 +91,7 @@
 
 		public ArmyCategory[] Categories
 		{
-			get 
+			get
 			{
 				return DictionaryUtils.ToArray<Category, ArmyCategory>(ArmyCategories);
 			}
@@ -104,7 +104,7 @@
 
 		public GameSystem GameSystem
 		{
-			get { return (armyRace!=null ? armyRace.GameSystem : null); }
+			get { return (armyRace != null ? armyRace.GameSystem : null); }
 		}
 
 		protected void OnUnitAdded(Unit unit)
@@ -117,7 +117,7 @@
 
 		protected void OnUnitRemoved(Unit unit)
 		{
-			if (UnitRemoved!=null)
+			if (UnitRemoved != null)
 			{
 				UnitRemoved(unit);
 			}
@@ -125,7 +125,7 @@
 
 		private void OnPointsValueChanged(double oldValue, double newValue)
 		{
-			if (PointsValueChanged!=null)
+			if (PointsValueChanged != null)
 			{
 				PointsValueChanged(this, oldValue, newValue);
 			}
@@ -139,7 +139,7 @@
 				double oldPoints = pointsTotal;
 				pointsTotal = value;
 
-				if (oldPoints!=pointsTotal)
+				if (oldPoints != pointsTotal)
 				{
 					OnPointsValueChanged(oldPoints, pointsTotal);
 				}
@@ -192,7 +192,7 @@
 		{
 			List<Unit> fullList = new List<Unit>();
 
-			foreach(ArmyCategory cat in Categories)
+			foreach (ArmyCategory cat in Categories)
 			{
 				fullList.AddRange(cat.GetUnits());
 			}
@@ -200,17 +200,29 @@
 			return fullList.ToArray();
 		}
 
+		public Unit[] GetUnits(UnitType unitType)
+		{
+			List<Unit> fullList = new List<Unit>();
+			
+			foreach (ArmyCategory cat in Categories)
+			{
+				fullList.AddRange(cat.GetUnits(unitType));
+			}
+			
+			return fullList.ToArray();
+		}
+
 		public int MaxPoints
 		{
 			get { return maxPoints; }
-			set 
+			set
 			{
 				if (value > 0)
 				{
 					int oldPoints = maxPoints;
 					maxPoints = value;
 
-					if (MaxPointsValueChanged != null)
+					if (MaxPointsValueChanged != null)
 					{
 						MaxPointsValueChanged(this, oldPoints, maxPoints);
 					}
@@ -231,7 +243,7 @@
 
 				foreach (ArmyCategory cat in Categories)
 				{
-					points+= cat.Points;
+					points += cat.Points;
 				}
 
 				TotalPoints = points;
@@ -244,7 +256,7 @@
 
 			foreach (ArmyCategory cat in Categories)
 			{
-				count+= cat.GetUnitTypeCount(unitType);
+				count += cat.GetUnitTypeCount(unitType);
 			}
 
 			return count;
@@ -268,17 +280,17 @@
 			unit.UnitSizeChanged -= HandleUnitUnitSizeChanged;
 		}
 
-		private void HandleUnitUnitEquipmentAmountChanged (WarFoundryObject obj, double oldValue, double newValue)
+		private void HandleUnitUnitEquipmentAmountChanged(WarFoundryObject obj, double oldValue, double newValue)
 		{
 			OnArmyCompositionChanged();
 		}
 
-		private void HandleUnitUnitSizeChanged (WarFoundryObject obj, int oldValue, int newValue)
+		private void HandleUnitUnitSizeChanged(WarFoundryObject obj, int oldValue, int newValue)
 		{
 			OnArmyCompositionChanged();
 		}
 
-		public ICollection<IRequirement> GetRequirements ()
+		public ICollection<IRequirement> GetRequirements()
 		{
 			return Race.GetRequirements();
 		}
--- a/API/Objects/ArmyCategory.cs	Sun Jul 29 14:16:14 2012 +0100
+++ b/API/Objects/ArmyCategory.cs	Sun Jul 29 15:31:09 2012 +0100
@@ -26,7 +26,7 @@
 		{
 			parentArmy = army;
 			category = cat;
-			cat.NameChanged+=new StringValChangedDelegate(cat_NameChanged);
+			cat.NameChanged += new StringValChangedDelegate(cat_NameChanged);
 			PointsValueChangedMethod = new DoubleValChangedDelegate(PointsValueChangedHandler);
 			units = new List<Unit>();
 			unitTypes = new Dictionary<string,int>();
@@ -57,7 +57,7 @@
 		public override string Name
 		{
 			get { return category.Name; }
-			set 
+			set
 			{
 				category.Name = value;
 			}
@@ -69,11 +69,11 @@
 			//List<FailedUnitRequirement> failedReqs = ParentArmy.CanAddUnit(unit);
 			units.Add(unit);
 			unit.Category = this;
-			unit.PointsValueChanged+= PointsValueChangedMethod;
+			unit.PointsValueChanged += PointsValueChangedMethod;
 			int unitTypeCount;
 			unitTypes.TryGetValue(unit.UnitType.ID, out unitTypeCount);
-			unitTypes[unit.UnitType.ID] = (int)unitTypeCount + 1;
-			TotalPoints+= unit.Points;
+			unitTypes[unit.UnitType.ID] = unitTypeCount + 1;
+			TotalPoints += unit.Points;
 			OnUnitAdded(unit);
 		}
 
@@ -82,15 +82,15 @@
 			//TODO: Put back a similar check
 			//List<FailedUnitRequirement> failedReqs = ParentArmy.CanRemoveUnit(unit);
 			units.Remove(unit);
-			unitTypes[unit.UnitType.ID] = ((int)unitTypes[unit.UnitType.ID])-1;
-			TotalPoints-= unit.Points;
-			unit.PointsValueChanged-= PointsValueChangedMethod;
+			unitTypes[unit.UnitType.ID] = unitTypes[unit.UnitType.ID] - 1;
+			TotalPoints -= unit.Points;
+			unit.PointsValueChanged -= PointsValueChangedMethod;
 			OnUnitRemoved(unit);
 		}
 
 		public int GetUnitTypeCount(UnitType unitType)
 		{
-			return unitTypes.ContainsKey(unitType.ID) ? (int)unitTypes[unitType.ID] : 0;
+			return unitTypes.ContainsKey(unitType.ID) ? unitTypes[unitType.ID] : 0;
 		}
 
 		public Unit[] GetUnits()
@@ -98,6 +98,19 @@
 			return units.ToArray();
 		}
 
+		public Unit[] GetUnits(UnitType unitType)
+		{
+			List<Unit> filteredUnits = new List<Unit>();
+			foreach (Unit unit in units)
+			{
+				if (unit.UnitType.Equals(unitType))
+				{
+					filteredUnits.Add(unit);
+				}
+			}
+			return filteredUnits.ToArray();
+		}
+
 		public Unit[] GetMainUnits()
 		{
 			List<Unit> mainUnits = new List<Unit>();
@@ -116,12 +129,12 @@
 		private double TotalPoints
 		{
 			get { return pointsTotal; }
-			set 
+			set
 			{
 				double oldVal = pointsTotal;
 				pointsTotal = value;
 
-				if (oldVal!=pointsTotal)
+				if (oldVal != pointsTotal)
 				{
 					OnPointsValueChanged(oldVal, pointsTotal);
 				}
@@ -138,7 +151,7 @@
 			if (obj is Unit)
 			{
 				double diff = newVal - oldVal;
-				TotalPoints+= diff;
+				TotalPoints += diff;
 			}
 		}
 
@@ -160,7 +173,7 @@
 
 		protected virtual void OnPointsValueChanged(double oldValue, double newValue)
 		{
-			if (PointsValueChanged!=null)
+			if (PointsValueChanged != null)
 			{
 				PointsValueChanged(this, oldValue, newValue);
 			}
--- a/API/Objects/Requirement/UnitRequiresNParentModelsForMUnitsRequirement.cs	Sun Jul 29 14:16:14 2012 +0100
+++ b/API/Objects/Requirement/UnitRequiresNParentModelsForMUnitsRequirement.cs	Sun Jul 29 15:31:09 2012 +0100
@@ -3,6 +3,8 @@
 // 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 IBBoard.WarFoundry.API.Objects.Requirement.Context;
+using System.Collections.Generic;
+using IBBoard.Collections;
 
 namespace IBBoard.WarFoundry.API.Objects.Requirement
 {
@@ -84,11 +86,6 @@
 			this.ConstraintTypes.Add(new UnitCountRequirementData(unitType, 1, 1));
 		}
 
-		protected override string GetFailedRequirementsString(Army army)
-		{
-			return "";
-		}
-
 		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
 		{
 			UnitType unitType = GetUnitTypeFromObject(toAdd);
@@ -171,7 +168,79 @@
 
 		public override Validation ValidatesArmy(Army army)
 		{
-			throw new System.NotImplementedException();
+			bool isApplicable = false;
+			Validation result = Validation.Passed;
+
+			foreach (Unit unit in army.GetUnits(AllowedObject))
+			{
+				Unit parentUnit = unit.ParentUnit;
+				isApplicable = isApplicable || (parentUnit != null && IsUnitTypeLimited(parentUnit.UnitType));
+				if (isApplicable && !ValidatesUnitInArmy(unit, parentUnit, army))
+				{
+					result = Validation.Failed;
+					break;
+				}
+			}
+
+			return isApplicable ? result : Validation.NotApplicable;
+		}
+
+		private bool ValidatesUnitInArmy(Unit unit, Unit parentUnit, Army army)
+		{			
+			bool isValid = true;
+			int allowedTypeCount = GetChildCountFromUnit(parentUnit); 
+		
+			foreach (UnitCountRequirementData limit in ConstraintTypes)
+			{
+				int limitedTypeCount = parentUnit.Size;
+			
+				if (!IsValidByRequirement(limit, allowedTypeCount, limitedTypeCount))
+				{
+					isValid = false;
+					break;
+				}
+			}
+			
+			return isValid;
+		}
+
+		protected override string ValidationFailedMessage
+		{
+			get
+			{
+				List<String> parentsList = new List<string>();
+
+				foreach (UnitCountRequirementData limit in ConstraintTypes)
+				{
+					parentsList.Add(String.Format("{0} × {1} for every {2} model in a parent unit of {3}", limit.AllowsCount, AllowedObject.Name, limit.Count, limit.UnitType.Name));
+				}
+
+				return String.Format("Army can only contain {0}: {{0}}.", String.Join(", ", parentsList.ToArray()));
+			}
+		}
+		
+		protected override string GetFailedRequirementsString(Army army)
+		{
+			return String.Join("; ", GetFailedValidationRequirements(army).ToArray());
+		}
+		
+		private List<string> GetFailedValidationRequirements(Army army)
+		{
+			List<string> failures = new List<string>();
+			SimpleSet<Unit> parentUnits = new SimpleSet<Unit>();
+
+			foreach (Unit unit in army.GetUnits(AllowedObject))
+			{
+				Unit parentUnit = unit.ParentUnit;
+				if (parentUnit != null && !parentUnits.Contains(parentUnit) && IsUnitTypeLimited(parentUnit.UnitType) && !ValidatesUnitInArmy(unit, parentUnit, army))
+				{
+					parentUnits.Add(parentUnit);
+					int allowedTypeCount = GetChildCountFromUnit(parentUnit); 
+					failures.Add(String.Format("{0} has {1} for {2}", parentUnit.Name, allowedTypeCount, parentUnit.Size));
+				}
+			}
+			
+			return failures;
 		}
 
 		protected override int GetObjectCountFromArmy(Army toArmy)