/// <summary> /// Validate model /// </summary> /// <param name="validationContext"></param> /// <returns></returns> public IEnumerable <ValidationResult> Validate(ValidationContext validationContext) { var results = new List <ValidationResult>(); if (this.Parent.GetType() != typeof(CropActivityManageProduct)) { string[] memberNames = new string[] { "Parent model" }; results.Add(new ValidationResult("A crop activity task must be placed immediately below a CropActivityManageProduct model component", memberNames)); } CropActivityManageProduct ProductParent = Parent as CropActivityManageProduct; foreach (CropActivityFee item in Apsim.Children(this, typeof(CropActivityFee))) { if (!ProductParent.IsTreeCrop) { if (item.PaymentStyle == CropPaymentStyleType.perTree) { string[] memberNames = new string[] { item.Name + ".PaymentStyle" }; results.Add(new ValidationResult("The payment style " + item.PaymentStyle.ToString() + " is not supported for crops defined non tree crops", memberNames)); } } } return(results); }
private void OnCLEMInitialiseActivity(object sender, EventArgs e) { BankAccount = Resources.FindResourceType <Finance, FinanceType>(this, AccountName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.ReportErrorAndStop); managingParent = FindAncestor <CropActivityManageProduct>(); if (managingParent != null) { relatesToResourceName = managingParent.StoreItemName; } }
/// <summary> /// Method to adjust area planted if crop has a area planted multiplier /// </summary> /// <param name="cropProduct">The crop product details to define final land area</param> private void AdjustLand(CropActivityManageProduct cropProduct) { // is this using available land and not yet assigned, or not using available land if (Area == 0 || !UseAreaAvailable) { // is the requested land different to land currently provided double areaneeded = UseAreaAvailable ? LinkedLandItem.AreaAvailable : (AreaRequested * cropProduct.PlantedMultiplier) - Area; if (areaneeded != 0) { if (areaneeded > 0) { ResourceRequestList = new List <ResourceRequest> { new ResourceRequest() { Resource = LinkedLandItem, AllowTransmutation = false, Required = areaneeded, ResourceType = typeof(Land), ResourceTypeName = LandItemNameToUse, ActivityModel = this, Category = TransactionCategory, FilterDetails = null, RelatesToResource = cropProduct.LinkedResourceItem.Name } }; if (!UseAreaAvailable & LinkedLandItem != null) { CheckResources(ResourceRequestList, Guid.NewGuid()); TakeResources(ResourceRequestList, false); //Now the Land has been allocated we have an Area //Assign the area actually got after taking it. It might be less than AreaRequested (if partial) Area += ResourceRequestList.FirstOrDefault().Provided; } else { Area += areaneeded; } } else { // excess land for planting can be reterned to land resource // careful that this doesn't get taken by a use all available elewhere if you want it back again. if (LinkedLandItem != null) { LinkedLandItem.Add(-areaneeded, this, cropProduct.LinkedResourceItem.Name, this.TransactionCategory); Area += areaneeded; } } } } }
/// <inheritdoc/> public override List <ResourceRequest> GetResourcesNeededForActivity() { if (this.TimingOK) { List <ResourceRequest> resourcesNeeded = new List <ResourceRequest>(); double sumneeded; switch (PaymentStyle) { case CropPaymentStyleType.Fixed: sumneeded = Amount; break; case CropPaymentStyleType.perUnitOfLand: CropActivityManageCrop cropParent = FindAncestor <CropActivityManageCrop>(); sumneeded = cropParent.Area * Amount; break; case CropPaymentStyleType.perHa: cropParent = FindAncestor <CropActivityManageCrop>(); CropActivityManageProduct productParent = FindAncestor <CropActivityManageProduct>(); sumneeded = cropParent.Area * productParent.UnitsToHaConverter * Amount; break; case CropPaymentStyleType.perTree: cropParent = FindAncestor <CropActivityManageCrop>(); productParent = FindAncestor <CropActivityManageProduct>(); sumneeded = productParent.TreesPerHa * cropParent.Area * productParent.UnitsToHaConverter * Amount; break; default: throw new Exception(String.Format("PaymentStyle ({0}) is not supported for ({1}) in ({2})", PaymentStyle, Name, this.Name)); } resourcesNeeded.Add(new ResourceRequest() { Resource = BankAccount, AllowTransmutation = false, Required = sumneeded, ResourceType = typeof(Finance), ResourceTypeName = AccountName, ActivityModel = this, FilterDetails = null, RelatesToResource = relatesToResourceName, Category = TransactionCategory } ); return(resourcesNeeded); } return(null); }
/// <summary> /// Validate model /// </summary> /// <param name="validationContext"></param> /// <returns></returns> public IEnumerable <ValidationResult> Validate(ValidationContext validationContext) { var results = new List <ValidationResult>(); CropActivityManageProduct productParent = FindAncestor <CropActivityManageProduct>(); if (!productParent.IsTreeCrop) { if (this.PaymentStyle == CropPaymentStyleType.perTree) { string[] memberNames = new string[] { this.Name + ".PaymentStyle" }; results.Add(new ValidationResult("The payment style " + this.PaymentStyle.ToString() + " is not supported for crops defined as non tree crops", memberNames)); } } return(results); }
/// <summary> /// Validate model /// </summary> /// <param name="validationContext"></param> /// <returns></returns> public IEnumerable <ValidationResult> Validate(ValidationContext validationContext) { var results = new List <ValidationResult>(); // check that this activity has a parent of type CropActivityManageProduct Model current = this; while (current.GetType() != typeof(ZoneCLEM)) { if (current.GetType() == typeof(CropActivityManageProduct)) { ManageProductActivity = current as CropActivityManageProduct; } current = current.Parent as Model; } if (ManageProductActivity == null) { string[] memberNames = new string[] { "CropActivityManageProduct parent" }; results.Add(new ValidationResult("This crop timer be below a parent of the type Crop Activity Manage Product", memberNames)); } return(results); }
/// <summary> /// Determines how much labour is required from this activity based on the requirement provided /// </summary> /// <param name="requirement">The details of how labour are to be provided</param> /// <returns></returns> public override double GetDaysLabourRequired(LabourRequirement requirement) { double daysNeeded; double numberUnits; switch (requirement.UnitType) { case LabourUnitType.Fixed: daysNeeded = requirement.LabourPerUnit; break; case LabourUnitType.perHa: CropActivityManageCrop cropParent = Apsim.Parent(this, typeof(CropActivityManageCrop)) as CropActivityManageCrop; CropActivityManageProduct productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = cropParent.Area * productParent.UnitsToHaConverter / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perTree: cropParent = Apsim.Parent(this, typeof(CropActivityManageCrop)) as CropActivityManageCrop; productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = productParent.TreesPerHa * cropParent.Area * productParent.UnitsToHaConverter / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perKg: productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = productParent.AmountHarvested; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perUnit: productParent = Apsim.Parent(this, typeof(CropActivityManageProduct)) as CropActivityManageProduct; numberUnits = productParent.AmountHarvested / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; default: throw new Exception(String.Format("LabourUnitType {0} is not supported for {1} in {2}", requirement.UnitType, requirement.Name, this.Name)); } return(daysNeeded); }
/// <summary> /// Determines how much labour is required from this activity based on the requirement provided /// </summary> /// <param name="requirement">The details of how labour are to be provided</param> /// <returns></returns> public override GetDaysLabourRequiredReturnArgs GetDaysLabourRequired(LabourRequirement requirement) { double numberUnits; double daysNeeded; switch (requirement.UnitType) { case LabourUnitType.Fixed: daysNeeded = requirement.LabourPerUnit; break; case LabourUnitType.perUnitOfLand: CropActivityManageCrop cropParent = FindAncestor <CropActivityManageCrop>(); numberUnits = cropParent.Area; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perHa: cropParent = FindAncestor <CropActivityManageCrop>(); CropActivityManageProduct productParent = FindAncestor <CropActivityManageProduct>(); numberUnits = cropParent.Area * productParent.UnitsToHaConverter / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perTree: cropParent = FindAncestor <CropActivityManageCrop>(); productParent = FindAncestor <CropActivityManageProduct>(); numberUnits = productParent.TreesPerHa * cropParent.Area * productParent.UnitsToHaConverter / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perKg: productParent = FindAncestor <CropActivityManageProduct>(); numberUnits = productParent.AmountHarvested; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; case LabourUnitType.perUnit: productParent = FindAncestor <CropActivityManageProduct>(); numberUnits = productParent.AmountHarvested / requirement.UnitSize; if (requirement.WholeUnitBlocks) { numberUnits = Math.Ceiling(numberUnits); } daysNeeded = numberUnits * requirement.LabourPerUnit; break; default: throw new Exception(String.Format("LabourUnitType {0} is not supported for {1} in {2}", requirement.UnitType, requirement.Name, this.Name)); } return(new GetDaysLabourRequiredReturnArgs(daysNeeded, this.Category, RelatesToResourceName)); }
/// <summary> /// Method to determine resources required for this activity in the current month /// </summary> /// <returns>List of required resource requests</returns> public override List <ResourceRequest> GetResourcesNeededForActivity() { ResourceRequestList = null; if (this.TimingOK) { // get all crop fees for task foreach (CropActivityFee item in Apsim.Children(this, typeof(CropActivityFee))) { if (ResourceRequestList == null) { ResourceRequestList = new List <ResourceRequest>(); } double sumneeded = 0; switch (item.PaymentStyle) { case CropPaymentStyleType.Fixed: sumneeded = item.Amount; break; case CropPaymentStyleType.perHa: CropActivityManageCrop CropParent = Parent.Parent as CropActivityManageCrop; CropActivityManageProduct ProductParent = Parent as CropActivityManageProduct; sumneeded = CropParent.Area * ProductParent.UnitsToHaConverter * item.Amount; break; case CropPaymentStyleType.perTree: CropParent = Parent.Parent as CropActivityManageCrop; ProductParent = Parent as CropActivityManageProduct; sumneeded = ProductParent.TreesPerHa * CropParent.Area * ProductParent.UnitsToHaConverter * item.Amount; break; default: throw new Exception(String.Format("PaymentStyle ({0}) is not supported for ({1}) in ({2})", item.PaymentStyle, item.Name, this.Name)); } ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = false, Required = sumneeded, ResourceType = typeof(Finance), ResourceTypeName = "General account", ActivityModel = this, FilterDetails = null, Reason = item.Name } ); } // for each labour item specified foreach (var item in labour) { double daysNeeded = 0; switch (item.UnitType) { case LabourUnitType.Fixed: daysNeeded = item.LabourPerUnit; break; case LabourUnitType.perHa: CropActivityManageCrop CropParent = Parent.Parent as CropActivityManageCrop; CropActivityManageProduct ProductParent = Parent as CropActivityManageProduct; daysNeeded = Math.Ceiling(CropParent.Area * ProductParent.UnitsToHaConverter / item.UnitSize) * item.LabourPerUnit; break; case LabourUnitType.perTree: CropParent = Parent.Parent as CropActivityManageCrop; ProductParent = Parent as CropActivityManageProduct; daysNeeded = Math.Ceiling(ProductParent.TreesPerHa * CropParent.Area * ProductParent.UnitsToHaConverter / item.UnitSize) * item.LabourPerUnit; break; default: throw new Exception(String.Format("LabourUnitType {0} is not supported for {1} in {2}", item.UnitType, item.Name, this.Name)); } if (daysNeeded > 0) { if (ResourceRequestList == null) { ResourceRequestList = new List <ResourceRequest>(); } ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = false, Required = daysNeeded, ResourceType = typeof(Labour), ResourceTypeName = "", ActivityModel = this, FilterDetails = new List <object>() { item } } ); } } } return(ResourceRequestList); }
/// <inheritdoc/> public override List <ResourceRequest> GetResourcesNeededForActivity() { if (this.TimingOK) { List <ResourceRequest> resourcesNeeded = new List <ResourceRequest>(); double sumneeded; switch (PaymentStyle) { case CropPaymentStyleType.Fixed: sumneeded = Amount; break; case CropPaymentStyleType.perUnitOfLand: CropActivityManageCrop cropParent = FindAncestor <CropActivityManageCrop>(); sumneeded = cropParent.Area * Amount; break; case CropPaymentStyleType.perHa: cropParent = FindAncestor <CropActivityManageCrop>(); CropActivityManageProduct productParent = FindAncestor <CropActivityManageProduct>(); sumneeded = cropParent.Area * productParent.UnitsToHaConverter * Amount; break; case CropPaymentStyleType.perTree: cropParent = FindAncestor <CropActivityManageCrop>(); productParent = FindAncestor <CropActivityManageProduct>(); sumneeded = productParent.TreesPerHa * cropParent.Area * productParent.UnitsToHaConverter * Amount; break; default: throw new Exception(String.Format("PaymentStyle ({0}) is not supported for ({1}) in ({2})", PaymentStyle, Name, this.Name)); } resourcesNeeded.Add(new ResourceRequest() { Resource = BankAccount, AllowTransmutation = false, Required = sumneeded, ResourceType = typeof(Finance), ResourceTypeName = AccountName, ActivityModel = this, FilterDetails = null, RelatesToResource = relatesToResourceName, Category = TransactionCategory } ); if (managingParent.CurrentlyManaged) { if (sumneeded > 0) { Status = ActivityStatus.Success; } else { Status = ActivityStatus.NotNeeded; } } else { Status = ActivityStatus.Warning; if (!timingIssueReported) { Summary.WriteMessage(this, $"The harvest timer for crop task [a={this.NameWithParent}] did not allow the task to be performed. This is likely due to insufficient time between rotating to a crop and the next harvest date.", MessageType.Warning); timingIssueReported = true; } } return(resourcesNeeded); } return(null); }