// Management events ....................................................... /// <summary> /// Add animal cohorts /// </summary> /// <param name="CohortsInfo"></param> /// <param name="iDOY"></param> /// <param name="fLatitude"></param> /// <param name="newGroups"></param> public void AddCohorts(TCohortsInfo CohortsInfo, int iDOY, double fLatitude, List<int> newGroups) { TAnimalParamSet mainGenotype; TAgeInfo[] AgeInfo; TAnimalInits AnimalInits; int iNoCohorts; double fSurvival; int iDaysSinceShearing; double fMeanNormalWt; double fMeanFleeceWt; double fBaseWtScalar; double fFleeceWtScalar; int iTotalAnimals; int iMateDOY; double fLowCondition; double fLowFoetuses; double fHighCondition; double fHighFoetuses; double fCondition; double fTrialFoetuses; double[] fPregRate = new double[4]; //TConceptionArray; int[] iShiftNumber = new int[4]; bool bLactationDone; double fLowChill; double fLowOffspring; double fHighChill; double fHighOffspring; double fChillIndex; double fTrialOffspring; double[] fLactRate = new double[4]; int iCohort; int iPreg; int iLact; int groupIndex; if (CohortsInfo.iNumber > 0) { mainGenotype = getGenotype(CohortsInfo.sGenotype); AgeInfo = new TAgeInfo[CohortsInfo.iMaxYears + 1]; for (int i = 0; i < CohortsInfo.iMaxYears + 1; i++) AgeInfo[i] = new TAgeInfo(); iNoCohorts = CohortsInfo.iMaxYears - CohortsInfo.iMinYears + 1; fSurvival = 1.0 - mainGenotype.AnnualDeaths(false); if (mainGenotype.Animal == GrazType.AnimalType.Cattle) iDaysSinceShearing = 0; else if (bIsGiven(CohortsInfo.fMeanGFW) && (CohortsInfo.iFleeceDays == 0)) iDaysSinceShearing = Convert.ToInt32(Math.Truncate(365.25 * CohortsInfo.fMeanGFW / mainGenotype.PotentialGFW)); else iDaysSinceShearing = CohortsInfo.iFleeceDays; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { //Proportion of all stock in this age cohort if (fSurvival >= 1.0) AgeInfo[iCohort].fPropn = 1.0 / iNoCohorts; else AgeInfo[iCohort].fPropn = (1.0 - fSurvival) * Math.Pow(fSurvival, iCohort - CohortsInfo.iMinYears) / (1.0 - Math.Pow(fSurvival, iNoCohorts)); AgeInfo[iCohort].iAgeDays = Convert.ToInt32(Math.Truncate(365.25 * iCohort) + CohortsInfo.iAgeOffsetDays); // Normal weight for age AgeInfo[iCohort].fNormalBaseWt = GrowthCurve(AgeInfo[iCohort].iAgeDays, CohortsInfo.ReproClass, mainGenotype); // Estimate a default fleece weight based on time since shearing AgeInfo[iCohort].fFleeceWt = TAnimalParamSet.fDefaultFleece(mainGenotype, AgeInfo[iCohort].iAgeDays, CohortsInfo.ReproClass, iDaysSinceShearing); } // Re-scale the fleece-free and fleece weights fMeanNormalWt = 0.0; fMeanFleeceWt = 0.0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fMeanNormalWt = fMeanNormalWt + AgeInfo[iCohort].fPropn * AgeInfo[iCohort].fNormalBaseWt; fMeanFleeceWt = fMeanFleeceWt + AgeInfo[iCohort].fPropn * AgeInfo[iCohort].fFleeceWt; } if ((CohortsInfo.fMeanGFW > 0.0) && (fMeanFleeceWt > 0.0)) fFleeceWtScalar = CohortsInfo.fMeanGFW / fMeanFleeceWt; else fFleeceWtScalar = 1.0; if (!bIsGiven(CohortsInfo.fMeanGFW)) CohortsInfo.fMeanGFW = fMeanFleeceWt; if (bIsGiven(CohortsInfo.fMeanLiveWt)) fBaseWtScalar = (CohortsInfo.fMeanLiveWt - CohortsInfo.fMeanGFW) / fMeanNormalWt; else if (bIsGiven(CohortsInfo.fCondScore)) fBaseWtScalar = TAnimalParamSet.CondScore2Condition(CohortsInfo.fCondScore); else fBaseWtScalar = 1.0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].fBaseWeight = AgeInfo[iCohort].fNormalBaseWt * fBaseWtScalar; AgeInfo[iCohort].fFleeceWt = AgeInfo[iCohort].fFleeceWt * fFleeceWtScalar; } // Numbers in each age cohort iTotalAnimals = 0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].iNumbers[0, 0] = Convert.ToInt32(Math.Truncate(AgeInfo[iCohort].fPropn * CohortsInfo.iNumber)); iTotalAnimals += AgeInfo[iCohort].iNumbers[0, 0]; } for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) if (iTotalAnimals < CohortsInfo.iNumber) { AgeInfo[iCohort].iNumbers[0, 0]++; iTotalAnimals++; } // Pregnancy and lactation if ((CohortsInfo.ReproClass == GrazType.ReproType.Empty) || (CohortsInfo.ReproClass == GrazType.ReproType.EarlyPreg) || (CohortsInfo.ReproClass == GrazType.ReproType.LatePreg)) { // Numbers with each number of foetuses if ((CohortsInfo.iDaysPreg > 0) && (CohortsInfo.fFoetuses > 0.0)) { iMateDOY = 1 + (iDOY - CohortsInfo.iDaysPreg + 364) % 365; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].iAgeAtMating = AgeInfo[iCohort].iAgeDays - CohortsInfo.iDaysPreg; AgeInfo[iCohort].fSizeAtMating = GrowthCurve(AgeInfo[iCohort].iAgeAtMating, CohortsInfo.ReproClass, mainGenotype) / mainGenotype.fSexStdRefWt(CohortsInfo.ReproClass); } // binary search for the body condition at mating that yields the desired pregnancy rate fLowCondition = 0.60; fLowFoetuses = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fLowCondition, 0); fHighCondition = 1.40; fHighFoetuses = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fHighCondition, 0); if (fLowFoetuses > CohortsInfo.fFoetuses) fCondition = fLowCondition; else if (fHighFoetuses < CohortsInfo.fFoetuses) fCondition = fHighCondition; else { do { fCondition = 0.5 * (fLowCondition + fHighCondition); fTrialFoetuses = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fCondition, 0); if (fTrialFoetuses < CohortsInfo.fFoetuses) fLowCondition = fCondition; else fHighCondition = fCondition; } while (Math.Abs(fTrialFoetuses - CohortsInfo.fFoetuses) >= 1.0E-5); //until (Abs(fTrialFoetuses-CohortsInfo.fFoetuses) < 1.0E-5); } // Compute final pregnancy rates and numbers for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fPregRate = getOffspringRates(mainGenotype, fLatitude, iMateDOY, AgeInfo[iCohort].iAgeAtMating, AgeInfo[iCohort].fSizeAtMating, fCondition); for (iPreg = 1; iPreg <= 3; iPreg++) iShiftNumber[iPreg] = Convert.ToInt32(Math.Round(fPregRate[iPreg] * AgeInfo[iCohort].iNumbers[0, 0])); for (iPreg = 1; iPreg <= 3; iPreg++) { AgeInfo[iCohort].iNumbers[iPreg, 0] += iShiftNumber[iPreg]; AgeInfo[iCohort].iNumbers[0, 0] -= iShiftNumber[iPreg]; } } } // if (iDaysPreg > 0) and (fFoetuses > 0.0) // Numbers with each number of suckling young // Different logic for sheep and cattle: // - for sheep, first assume average body condition at conception and vary // the chill index. If that doesn't work, fix the chill index & vary the // body condition // - for cattle, fix the chill index & vary the body condition if ((CohortsInfo.iDaysLact > 0) && (CohortsInfo.fOffspring > 0.0)) { bLactationDone = false; fCondition = 1.0; fChillIndex = 0; iMateDOY = 1 + (iDOY - CohortsInfo.iDaysLact - mainGenotype.Gestation + 729) % 365; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { AgeInfo[iCohort].iAgeAtMating = AgeInfo[iCohort].iAgeDays - CohortsInfo.iDaysLact - mainGenotype.Gestation; AgeInfo[iCohort].fSizeAtMating = GrowthCurve(AgeInfo[iCohort].iAgeAtMating, CohortsInfo.ReproClass, mainGenotype) / mainGenotype.fSexStdRefWt(CohortsInfo.ReproClass); } if (mainGenotype.Animal == GrazType.AnimalType.Sheep) { // binary search for the chill index at birth that yields the desired proportion of lambs fLowChill = 500.0; fLowOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, 1.0, fLowChill); fHighChill = 2500.0; fHighOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, 1.0, fHighChill); // this is a monotonically decreasing function... if ((fHighOffspring < CohortsInfo.fOffspring) && (fLowOffspring > CohortsInfo.fOffspring)) { do { fChillIndex = 0.5 * (fLowChill + fHighChill); fTrialOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, 1.0, fChillIndex); if (fTrialOffspring > CohortsInfo.fOffspring) fLowChill = fChillIndex; else fHighChill = fChillIndex; } while (Math.Abs(fTrialOffspring - CohortsInfo.fOffspring) >= 1.0E-5); //until (Abs(fTrialOffspring-CohortsInfo.fOffspring) < 1.0E-5); bLactationDone = true; } } // fitting lactation rate to a chill index if (!bLactationDone) { fChillIndex = 800.0; // binary search for the body condition at mating that yields the desired proportion of lambs or calves fLowCondition = 0.60; fLowOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fLowCondition, fChillIndex); fHighCondition = 1.40; fHighOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fHighCondition, fChillIndex); if (fLowOffspring > CohortsInfo.fOffspring) fCondition = fLowCondition; else if (fHighOffspring < CohortsInfo.fOffspring) fCondition = fHighCondition; else { do { fCondition = 0.5 * (fLowCondition + fHighCondition); fTrialOffspring = getReproRate(CohortsInfo, mainGenotype, AgeInfo, fLatitude, iMateDOY, fCondition, fChillIndex); if (fTrialOffspring < CohortsInfo.fOffspring) fLowCondition = fCondition; else fHighCondition = fCondition; } while (Math.Abs(fTrialOffspring - CohortsInfo.fOffspring) >= 1.0E-5); //until (Abs(fTrialOffspring-CohortsInfo.fOffspring) < 1.0E-5); } } // fitting lactation rate to a condition // Compute final offspring rates and numbers for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fLactRate = getOffspringRates(mainGenotype, fLatitude, iMateDOY, AgeInfo[iCohort].iAgeAtMating, AgeInfo[iCohort].fSizeAtMating, fCondition, fChillIndex); for (iPreg = 0; iPreg <= 3; iPreg++) { for (iLact = 1; iLact <= 3; iLact++) iShiftNumber[iLact] = Convert.ToInt32(Math.Round(fLactRate[iLact] * AgeInfo[iCohort].iNumbers[iPreg, 0])); for (iLact = 1; iLact <= 3; iLact++) { AgeInfo[iCohort].iNumbers[iPreg, iLact] += iShiftNumber[iLact]; AgeInfo[iCohort].iNumbers[iPreg, 0] -= iShiftNumber[iLact]; } } } } //_ lactating animals _ } //_ female animals // Construct the animal groups from the numbers and cohort-specific information AnimalInits.sGenotype = CohortsInfo.sGenotype; AnimalInits.sMatedTo = CohortsInfo.sMatedTo; AnimalInits.Sex = CohortsInfo.ReproClass; AnimalInits.Birth_CS = StdMath.DMISSING; AnimalInits.Paddock = ""; AnimalInits.Tag = 0; AnimalInits.Priority = 0; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { for (iPreg = 0; iPreg <= 3; iPreg++) { for (iLact = 0; iLact <= 3; iLact++) { if (AgeInfo[iCohort].iNumbers[iPreg, iLact] > 0) { AnimalInits.Number = AgeInfo[iCohort].iNumbers[iPreg, iLact]; AnimalInits.AgeDays = AgeInfo[iCohort].iAgeDays; AnimalInits.Weight = AgeInfo[iCohort].fBaseWeight + AgeInfo[iCohort].fFleeceWt; AnimalInits.MaxPrevWt = StdMath.DMISSING; // compute from cond_score AnimalInits.Fleece_Wt = AgeInfo[iCohort].fFleeceWt; AnimalInits.Fibre_Diam = TAnimalParamSet.fDefaultMicron(mainGenotype, AnimalInits.AgeDays, AnimalInits.Sex, iDaysSinceShearing, AnimalInits.Fleece_Wt); if (iPreg > 0) { AnimalInits.Pregnant = CohortsInfo.iDaysPreg; AnimalInits.No_Foetuses = iPreg; } else { AnimalInits.Pregnant = 0; AnimalInits.No_Foetuses = 0; } if ((iLact > 0) || ((mainGenotype.Animal == GrazType.AnimalType.Cattle) && (CohortsInfo.iDaysLact > 0) && (CohortsInfo.fOffspring == 0.0))) { AnimalInits.Lactating = CohortsInfo.iDaysLact; AnimalInits.No_Suckling = iLact; AnimalInits.Young_GFW = CohortsInfo.fLambGFW; AnimalInits.Young_Wt = CohortsInfo.fOffspringWt; } else { AnimalInits.Lactating = 0; AnimalInits.No_Suckling = 0; AnimalInits.Young_GFW = 0.0; AnimalInits.Young_Wt = 0.0; } groupIndex = Add(AnimalInits); if (newGroups != null) { newGroups.Add(groupIndex); } } } } } } // if CohortsInfo.iNumber > 0 }
/// <summary> /// Manage the initialisation of the animal groups for the enterprise. /// Called at the end of evtINITSTEP /// </summary> /// <param name="currentDay"></param> /// <param name="curEnt"></param> /// <param name="latitude"></param> protected void manageInitialiseStock(int currentDay, TEnterpriseInfo curEnt, double latitude) { double area; int numToBuy; TCohortsInfo CohortsInfo = new TCohortsInfo(); int birthDay; int replaceAge; int ageOffset; int yngYrs = 0, oldYrs = 0; int i; TAnimalParamSet genoprms; int iBuyYears; int dtBuy; List<int> newGroups; int groupIdx; TEnterpriseInfo.TStockEnterprise stockEnt; double survivalRate; area = calcStockArea(curEnt); if (area > 0) { newGroups = new List<int>(); numToBuy = Convert.ToInt32(Math.Truncate(curEnt.StockRateFemale * area)); stockEnt = curEnt.EntTypeFromName(curEnt.EntClass); //calc the birth date based on age at replacement replaceAge = Convert.ToInt32(Math.Truncate(MONTH2DAY * curEnt.ReplaceAge + 0.5)); ageOffset = (replaceAge + DaysFromDOY(curEnt.ReplacementDay, currentDay)) % 366; //get age range - from calc'd birth to CFA age GetAgeRange(curEnt.ReplacementDay, replaceAge, curEnt.getFirstSaleYears(1), curEnt.getFirstSaleDay(1), currentDay, ref yngYrs, ref oldYrs); genoprms = getGenotype(curEnt.BaseGenoType); if (curEnt.getPurchase(1)) { iBuyYears = curEnt.ReplaceAge / 12; dtBuy = StdDate.DateVal(StdDate.DayOf(curEnt.ReplacementDay), StdDate.MonthOf(curEnt.ReplacementDay), 1900 + (iBuyYears + 1)); birthDay = StdDate.DateShift(dtBuy, 0, -curEnt.ReplaceAge, 0) & 0xFFFF; } else birthDay = 1 + (curEnt.MateDay + 12 + genoprms.Gestation) % 365; survivalRate = Math.Min(1.0 - genoprms.AnnualDeaths(false), 0.999999); CohortsInfo.sGenotype = curEnt.BaseGenoType; CohortsInfo.iNumber = Convert.ToInt32(Math.Truncate(numToBuy * Math.Pow(survivalRate, ((currentDay - curEnt.ReplacementDay + 365) % 365) / 365))); CohortsInfo.iMinYears = yngYrs; CohortsInfo.iMaxYears = oldYrs; CohortsInfo.iAgeOffsetDays = StdDate.Interval(birthDay, currentDay); CohortsInfo.fMeanLiveWt = curEnt.ReplaceWeight; CohortsInfo.fCondScore = curEnt.ReplaceCond; switch (stockEnt) { case TEnterpriseInfo.TStockEnterprise.entEweWether: //setup cohorts for the females CohortsInfo.ReproClass = GrazType.ReproType.Empty; // or preg CohortsInfo.fMeanGFW = genoprms.PotentialGFW * DaysFromDOY(curEnt.ShearingDate, currentDay) / 365.0; CohortsInfo.iFleeceDays = DaysFromDOY365(curEnt.ShearingDate, currentDay); if (curEnt.ManageReproduction) CohortsInfo.sMatedTo = curEnt.MateWith; else CohortsInfo.sMatedTo = curEnt.BaseGenoType; // CohortsInfo.iDaysPreg = /* CohortsInfo.fFoetuses = eventData.member("foetuses").asDouble(); CohortsInfo.iDaysLact = eventData.member("lactating").asInteger(); CohortsInfo.fOffspring = eventData.member("offspring").asDouble(); CohortsInfo.fOffspringWt = eventData.member("young_wt").asDouble(); CohortsInfo.fOffspringCS = eventData.member("young_cond_score").asDouble(); CohortsInfo.fLambGFW = eventData.member("young_fleece_wt").asDouble(); */ if (CohortsInfo.iNumber > 0) AddCohorts(CohortsInfo, 1 + DaysFromDOY365(1, currentDay), latitude, null); //tag the groups for (i = 0; i <= newGroups.Count - 1; i++) { groupIdx = newGroups[i]; TagGroup(curEnt, groupIdx, 1); //tag the group } DraftToOpenPaddocks(curEnt, area); //move the groups to paddocks //setup wether cohorts break; case TEnterpriseInfo.TStockEnterprise.entLamb: case TEnterpriseInfo.TStockEnterprise.entWether: case TEnterpriseInfo.TStockEnterprise.entSteer: CohortsInfo.ReproClass = GrazType.ReproType.Castrated; //birthday offset from the current date CohortsInfo.fMeanGFW = 0; CohortsInfo.iFleeceDays = 0; CohortsInfo.sMatedTo = ""; CohortsInfo.iDaysPreg = 0; CohortsInfo.fFoetuses = 0; CohortsInfo.iDaysLact = 0; CohortsInfo.fOffspring = 0; CohortsInfo.fOffspringWt = 0; CohortsInfo.fOffspringCS = 0; CohortsInfo.fLambGFW = 0; if ((stockEnt == TEnterpriseInfo.TStockEnterprise.entWether) || (stockEnt == TEnterpriseInfo.TStockEnterprise.entLamb)) { CohortsInfo.fMeanGFW = genoprms.PotentialGFW * DaysFromDOY(curEnt.ShearingDate, currentDay) / 365.0; } if (CohortsInfo.iNumber > 0) AddCohorts(CohortsInfo, currentDay, latitude, newGroups); //tag the groups for (i = 0; i <= newGroups.Count - 1; i++) { groupIdx = newGroups[i]; TagGroup(curEnt, groupIdx, 1); //tag the group } DraftToOpenPaddocks(curEnt, area); //move the groups to paddocks break; case TEnterpriseInfo.TStockEnterprise.entBeefCow: break; default: break; } newGroups = null; } }
/// <summary> /// /// </summary> /// <param name="CohortsInfo"></param> /// <param name="mainGenotype"></param> /// <param name="AgeInfo"></param> /// <param name="fLatitude"></param> /// <param name="iMateDOY"></param> /// <param name="fCondition"></param> /// <param name="fChill"></param> /// <returns></returns> private double getReproRate(TCohortsInfo CohortsInfo, TAnimalParamSet mainGenotype, TAgeInfo[] AgeInfo, double fLatitude, int iMateDOY, double fCondition, double fChill) { double Result = 0.0; double[] fPregRate = new double[4]; int iCohort; int N; for (iCohort = CohortsInfo.iMinYears; iCohort <= CohortsInfo.iMaxYears; iCohort++) { fPregRate = getOffspringRates(mainGenotype, fLatitude, iMateDOY, AgeInfo[iCohort].iAgeAtMating, AgeInfo[iCohort].fSizeAtMating, fCondition, fChill); for (N = 1; N <= 3; N++) Result = Result + AgeInfo[iCohort].fPropn * fPregRate[N]; } return Result; }
/// <summary> /// The main stock management function that handles a number of events. /// </summary> /// <param name="Model"></param> /// <param name="stockEvent">The event parameters</param> /// <param name="dtToday"></param> /// <param name="fLatitude"></param> public void doStockManagement(TStockList Model, IStockEvent stockEvent, int dtToday = 0, double fLatitude = -35.0) { TCohortsInfo CohortsInfo = new TCohortsInfo(); TPurchaseInfo PurchaseInfo = new TPurchaseInfo(); List<string> sClosed; string sParam; int iParam1; int iParam3; double fValue; int iTag; int iGroups; if (stockEvent != null) { if (stockEvent.GetType() == typeof(TStockAdd)) // add_animals { TStockAdd stockInfo = (TStockAdd)stockEvent; CohortsInfo.sGenotype = stockInfo.genotype; CohortsInfo.iNumber = Math.Max(0, stockInfo.number); if (!ParseRepro(stockInfo.sex, ref CohortsInfo.ReproClass)) throw new Exception("Event ADD does not support sex='" + stockInfo.sex + "'"); if (dtToday > 0) CohortsInfo.iAgeOffsetDays = DaysFromDOY365(stockInfo.birth_day, dtToday); else CohortsInfo.iAgeOffsetDays = 0; CohortsInfo.iMinYears = stockInfo.min_years; CohortsInfo.iMaxYears = stockInfo.max_years; CohortsInfo.fMeanLiveWt = stockInfo.mean_weight; CohortsInfo.fCondScore = stockInfo.cond_score; CohortsInfo.fMeanGFW = stockInfo.mean_fleece_wt; if (dtToday > 0) CohortsInfo.iFleeceDays = DaysFromDOY365(stockInfo.shear_day, dtToday); else CohortsInfo.iFleeceDays = 0; CohortsInfo.sMatedTo = stockInfo.mated_to; CohortsInfo.iDaysPreg = stockInfo.pregnant; CohortsInfo.fFoetuses = stockInfo.foetuses; CohortsInfo.iDaysLact = stockInfo.lactating; CohortsInfo.fOffspring = stockInfo.offspring; CohortsInfo.fOffspringWt = stockInfo.young_wt; CohortsInfo.fOffspringCS = stockInfo.young_cond_score; CohortsInfo.fLambGFW = stockInfo.young_fleece_wt; if (CohortsInfo.iNumber > 0) Model.AddCohorts(CohortsInfo, 1 + DaysFromDOY365(1, dtToday), fLatitude, null); } else if (stockEvent.GetType() == typeof(TStockBuy)) { TStockBuy stockInfo = (TStockBuy)stockEvent; PurchaseInfo.sGenotype = stockInfo.genotype; PurchaseInfo.Number = Math.Max(0, stockInfo.number); if (!ParseRepro(stockInfo.sex, ref PurchaseInfo.Repro)) throw new Exception("Event BUY does not support sex='" + stockInfo.sex + "'"); PurchaseInfo.AgeDays = Convert.ToInt32(Math.Round(MONTH2DAY * stockInfo.age)); // Age in months PurchaseInfo.LiveWt = stockInfo.weight; PurchaseInfo.GFW = stockInfo.fleece_wt; PurchaseInfo.fCondScore = stockInfo.cond_score; PurchaseInfo.sMatedTo = stockInfo.mated_to; PurchaseInfo.Preg = stockInfo.pregnant; PurchaseInfo.Lact = stockInfo.lactating; PurchaseInfo.NYoung = stockInfo.no_young; if ((PurchaseInfo.Preg > 0) || (PurchaseInfo.Lact > 0)) PurchaseInfo.NYoung = Math.Max(1, PurchaseInfo.NYoung); PurchaseInfo.YoungWt = stockInfo.young_wt; if ((PurchaseInfo.Lact == 0) || (PurchaseInfo.YoungWt == 0.0)) // Can't use MISSING as default owing PurchaseInfo.YoungWt = StdMath.DMISSING; // to double-to-single conversion PurchaseInfo.YoungGFW = stockInfo.young_fleece_wt; iTag = stockInfo.usetag; if (PurchaseInfo.Number > 0) { Model.Buy(PurchaseInfo); if (iTag > 0) Model.setTag(Model.Count(), iTag); } } //_ buy _ //sell a number from a group of animals else if (stockEvent.GetType() == typeof(TStockSell)) { TStockSell stockInfo = (TStockSell)stockEvent; Model.Sell(stockInfo.group, stockInfo.number); } //sell a number of animals tagged with a specific tag else if (stockEvent.GetType() == typeof(TStockSellTag)) { TStockSellTag stockInfo = (TStockSellTag)stockEvent; Model.SellTag(stockInfo.tag, stockInfo.number); } else if (stockEvent.GetType() == typeof(TStockShear)) { TStockShear stockInfo = (TStockShear)stockEvent; sParam = stockInfo.sub_group.ToLower(); Model.Shear(stockInfo.group, ((sParam == "adults") || (sParam == "both") || (sParam == "")), ((sParam == "lambs") || (sParam == "both"))); } else if (stockEvent.GetType() == typeof(TStockMove)) { TStockMove stockInfo = (TStockMove)stockEvent; iParam1 = stockInfo.group; if ((iParam1 >= 1) && (iParam1 <= Model.Count())) Model.setInPadd(iParam1, stockInfo.paddock); else throw new Exception("Invalid group number in MOVE event"); } else if (stockEvent.GetType() == typeof(TStockJoin)) { TStockJoin stockInfo = (TStockJoin)stockEvent; Model.Join(stockInfo.group, stockInfo.mate_to, stockInfo.mate_days); } else if (stockEvent.GetType() == typeof(TStockCastrate)) { TStockCastrate stockInfo = (TStockCastrate)stockEvent; Model.Castrate(stockInfo.group, stockInfo.number); } else if (stockEvent.GetType() == typeof(TStockWean)) { TStockWean stockInfo = (TStockWean)stockEvent; iParam1 = stockInfo.group; sParam = stockInfo.sex.ToLower(); iParam3 = stockInfo.number; if (sParam == "males") Model.Wean(iParam1, iParam3, false, true); else if (sParam == "females") Model.Wean(iParam1, iParam3, true, false); else if ((sParam == "all") || (sParam == "")) Model.Wean(iParam1, iParam3, true, true); else throw new Exception("Invalid offspring type \"" + sParam + "\" in WEAN event"); } else if (stockEvent.GetType() == typeof(TStockDryoff)) { TStockDryoff stockInfo = (TStockDryoff)stockEvent; Model.DryOff(stockInfo.group, stockInfo.number); } //split off the requested animals from all groups else if (stockEvent.GetType() == typeof(TStockSplitAll)) { TStockSplitAll stockInfo = (TStockSplitAll)stockEvent; iGroups = Model.Count(); //get pre-split count of groups for (iParam1 = 1; iParam1 <= iGroups; iParam1++) { sParam = stockInfo.type.ToLower(); fValue = stockInfo.value; iTag = stockInfo.othertag; if (sParam == "age") Model.SplitAge(iParam1, Convert.ToInt32(Math.Round(fValue))); else if (sParam == "weight") Model.SplitWeight(iParam1, fValue); else if (sParam == "young") Model.SplitYoung(iParam1); else if (sParam == "number") Model.Split(iParam1, Convert.ToInt32(Math.Round(fValue))); else throw new Exception("Stock: invalid keyword (" + sParam + ") in \"split\" event"); if ((iTag > 0) && (Model.Count() > iGroups)) //if a tag for any new group is given Model.setTag(Model.Count(), iTag); } } //split off the requested animals from one group else if (stockEvent.GetType() == typeof(TStockSplit)) { TStockSplit stockInfo = (TStockSplit)stockEvent; iGroups = Model.Count(); //get pre-split count of groups iParam1 = stockInfo.group; sParam = stockInfo.type.ToLower(); fValue = stockInfo.value; iTag = stockInfo.othertag; if ((iParam1 < 1) && (iParam1 > Model.Count())) throw new Exception("Invalid group number in SPLIT event"); else if (sParam == "age") Model.SplitAge(iParam1, Convert.ToInt32(Math.Round(fValue))); else if (sParam == "weight") Model.SplitWeight(iParam1, fValue); else if (sParam == "young") Model.SplitYoung(iParam1); else if (sParam == "number") Model.Split(iParam1, Convert.ToInt32(Math.Round(fValue))); else throw new Exception("Stock: invalid keyword (" + sParam + ") in \"split\" event"); if ((iTag > 0) && (Model.Count() > iGroups)) //if a tag for the new group is given Model.setTag(Model.Count(), iTag); } else if (stockEvent.GetType() == typeof(TStockTag)) { TStockTag stockInfo = (TStockTag)stockEvent; iParam1 = stockInfo.group; if ((iParam1 >= 1) && (iParam1 <= Model.Count())) Model.setTag(iParam1, stockInfo.value); else throw new Exception("Invalid group number in TAG event"); } else if (stockEvent.GetType() == typeof(TStockSort)) { Model.Sort(); } else if (stockEvent.GetType() == typeof(TStockPrioritise)) { TStockPrioritise stockInfo = (TStockPrioritise)stockEvent; iParam1 = stockInfo.group; if ((iParam1 >= 1) && (iParam1 <= Model.Count())) Model.setPriority(iParam1, stockInfo.value); else throw new Exception("Invalid group number in PRIORITISE event"); } else if (stockEvent.GetType() == typeof(TStockDraft)) { TStockDraft stockInfo = (TStockDraft)stockEvent; sClosed = new List<string>(stockInfo.closed); Model.Draft(sClosed); } else throw new Exception("Event not recognised in STOCK"); } }