private void OnCLEMAnimalSell(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); int trucks = 0; double saleValue = 0; double saleWeight = 0; int head = 0; double aESum = 0; // get current untrucked list of animals flagged for sale List <Ruminant> herd = this.CurrentHerd(false).Where(a => a.SaleFlag != HerdChangeReason.None).OrderByDescending(a => a.Weight).ToList(); if (trucking == null) { // no trucking just sell head = herd.Count(); if (herd.Count() > 0) { SetStatusSuccess(); } foreach (var ind in herd) { aESum += ind.AdultEquivalent; saleValue += ind.BreedParams.ValueofIndividual(ind, PurchaseOrSalePricingStyleType.Sale); saleWeight += ind.Weight; ruminantHerd.RemoveRuminant(ind, this); } } else { // if sale herd > min loads before allowing sale if (herd.Select(a => a.Weight / 450.0).Sum() / trucking.Number450kgPerTruck >= trucking.MinimumTrucksBeforeSelling) { // while truck to fill while (herd.Select(a => a.Weight / 450.0).Sum() / trucking.Number450kgPerTruck > trucking.MinimumLoadBeforeSelling) { bool nonloaded = true; trucks++; double load450kgs = 0; // while truck below carrying capacity load individuals foreach (var ind in herd) { if (load450kgs + (ind.Weight / 450.0) <= trucking.Number450kgPerTruck) { nonloaded = false; head++; aESum += ind.AdultEquivalent; load450kgs += ind.Weight / 450.0; saleValue += ind.BreedParams.ValueofIndividual(ind, PurchaseOrSalePricingStyleType.Sale); saleWeight += ind.Weight; ruminantHerd.RemoveRuminant(ind, this); //TODO: work out what to do with suckling calves still with mothers if mother sold. } } if (nonloaded) { Summary.WriteWarning(this, String.Format("There was a problem loading the sale truck as sale individuals did not meet the loading criteria for breed [r={0}]", this.PredictedHerdBreed)); break; } herd = this.CurrentHerd(false).Where(a => a.SaleFlag != HerdChangeReason.None).OrderByDescending(a => a.Weight).ToList(); } // create trucking emissions if (trucks > 0) { SetStatusSuccess(); } trucking.ReportEmissions(trucks, true); } } if (bankAccount != null && head > 0) //(trucks > 0 || trucking == null) { ResourceRequest expenseRequest = new ResourceRequest { ActivityModel = this, AllowTransmutation = false }; // calculate transport costs if (trucking != null) { expenseRequest.Required = trucks * trucking.DistanceToMarket * trucking.CostPerKmTrucking; expenseRequest.Reason = "Transport sales"; bankAccount.Remove(expenseRequest); } foreach (RuminantActivityFee item in Apsim.Children(this, typeof(RuminantActivityFee))) { switch (item.PaymentStyle) { case AnimalPaymentStyleType.Fixed: expenseRequest.Required = item.Amount; break; case AnimalPaymentStyleType.perHead: expenseRequest.Required = head * item.Amount; break; case AnimalPaymentStyleType.perAE: expenseRequest.Required = aESum * item.Amount; break; case AnimalPaymentStyleType.ProportionOfTotalSales: expenseRequest.Required = saleValue * item.Amount; break; default: throw new Exception(String.Format("PaymentStyle ({0}) is not supported for ({1}) in ({2})", item.PaymentStyle, item.Name, this.Name)); } expenseRequest.Reason = item.Name; // uses bank account specified in the RuminantActivityFee item.BankAccount.Remove(expenseRequest); } // add and remove from bank if (saleValue > 0) { bankAccount.Add(saleValue, this, this.PredictedHerdName + " sales"); } } }
private void OnCLEMAnimalSell(object sender, EventArgs e) { Status = ActivityStatus.NoTask; int trucks = 0; double saleValue = 0; double saleWeight = 0; int head = 0; double aESum = 0; // only perform this activity if timing ok, or selling required as a result of forces destock List <Ruminant> herd = new List <Ruminant>(); if (this.TimingOK || this.CurrentHerd(false).Where(a => a.SaleFlag == HerdChangeReason.DestockSale).Any()) { this.Status = ActivityStatus.NotNeeded; // get current untrucked list of animals flagged for sale herd = this.CurrentHerd(false).Where(a => a.SaleFlag != HerdChangeReason.None).OrderByDescending(a => a.Weight).ToList(); } // no individuals to sell if (herd.Count == 0) { return; } List <Ruminant> soldIndividuals = new List <Ruminant>(); if (trucking == null) { // no trucking just sell SetStatusSuccess(); foreach (var ind in herd) { aESum += ind.AdultEquivalent; var pricing = ind.BreedParams.ValueofIndividual(ind, PurchaseOrSalePricingStyleType.Sale); if (pricing != null) { saleValue += pricing.CalculateValue(ind); } saleWeight += ind.Weight; soldIndividuals.Add(ind); HerdResource.RemoveRuminant(ind, this); head++; } } else { // if sale herd > min loads before allowing sale if (herd.Select(a => a.Weight / 450.0).Sum() / trucking.Number450kgPerTruck >= trucking.MinimumTrucksBeforeSelling) { // while truck to fill while (herd.Select(a => a.Weight / 450.0).Sum() / trucking.Number450kgPerTruck > trucking.MinimumLoadBeforeSelling) { bool nonloaded = true; trucks++; double load450kgs = 0; // while truck below carrying capacity load individuals foreach (var ind in herd) { if (load450kgs + (ind.Weight / 450.0) <= trucking.Number450kgPerTruck) { nonloaded = false; head++; aESum += ind.AdultEquivalent; load450kgs += ind.Weight / 450.0; var pricing = ind.BreedParams.ValueofIndividual(ind, PurchaseOrSalePricingStyleType.Sale); if (pricing != null) { saleValue += pricing.CalculateValue(ind); } saleWeight += ind.Weight; soldIndividuals.Add(ind); HerdResource.RemoveRuminant(ind, this); //TODO: work out what to do with suckling calves still with mothers if mother sold. } } if (nonloaded) { Summary.WriteWarning(this, String.Format("There was a problem loading the sale truck as sale individuals did not meet the loading criteria for breed [r={0}]", this.PredictedHerdBreed)); break; } herd = this.CurrentHerd(false).Where(a => a.SaleFlag != HerdChangeReason.None).OrderByDescending(a => a.Weight).ToList(); } // create trucking emissions trucking.ReportEmissions(trucks, true); // if sold all Status = (this.CurrentHerd(false).Where(a => a.SaleFlag != HerdChangeReason.None).Count() == 0) ? ActivityStatus.Success : ActivityStatus.Warning; } } if (bankAccount != null && head > 0) //(trucks > 0 || trucking == null) { ResourceRequest expenseRequest = new ResourceRequest { ActivityModel = this, AllowTransmutation = false }; // calculate transport costs if (trucking != null) { expenseRequest.Required = trucks * trucking.DistanceToMarket * trucking.CostPerKmTrucking; expenseRequest.Category = trucking.TransactionCategory; bankAccount.Remove(expenseRequest); } // perform payments by transaction grouping // uses a list of individuals that were taken from the herd // calculate aEsum and saleValue form the above list for use below // currently done above but can be shifted to calc from grouped indiv // add and remove from bank if (saleValue > 0) { //bankAccount.Add(saleValue, this, this.PredictedHerdName, TransactionCategory); var groupedIndividuals = HerdResource.SummarizeIndividualsByGroups(soldIndividuals, PurchaseOrSalePricingStyleType.Sale); foreach (var item in groupedIndividuals) { foreach (var item2 in item.RuminantTypeGroup) { bankAccount.Add(item2.TotalPrice, this, item.RuminantTypeName, $"{TransactionCategory}.{item2.GroupName}"); } } } // perform activity fee payments foreach (RuminantActivityFee item in this.FindAllChildren <RuminantActivityFee>()) { switch (item.PaymentStyle) { case AnimalPaymentStyleType.Fixed: expenseRequest.Required = item.Amount; break; case AnimalPaymentStyleType.perHead: expenseRequest.Required = head * item.Amount; break; case AnimalPaymentStyleType.perAE: expenseRequest.Required = aESum * item.Amount; break; case AnimalPaymentStyleType.ProportionOfTotalSales: expenseRequest.Required = saleValue * item.Amount; break; default: throw new Exception(String.Format("PaymentStyle [{0}] is not supported for [{1}] in [{2}]", item.PaymentStyle, item.Name, this.Name)); } expenseRequest.Category = item.TransactionCategory; // uses bank account specified in the RuminantActivityFee item.BankAccount.Remove(expenseRequest); } } }