public CalculationResult Calculate(decimal DesignKindergarten, decimal DesignElementary, decimal DesignSecondary, int LowestGrade, int HighestGrade) { tracingService.Trace("{0}", "Starting OperatingCapacity.Calculate"); tracingService.Trace("K:{0}, E: {1}, S: {2}", DesignKindergarten, DesignElementary, DesignSecondary); tracingService.Trace("Grade Low:{0}, High: {1}", LowestGrade, HighestGrade); CalculationResult result = new CalculationResult(); //Calculate Kindergarten Capacity if (DesignKindergarten != 0) { result.KindergartenCapacity = Math.Round(DesignKindergarten / Capacity.DesignKindergarten * Capacity.OperatingKindergarten, 0, MidpointRounding.AwayFromZero); } //Calculate Secondary Capacity if (DesignSecondary != 0) { result.SecondaryCapacity = Math.Round(DesignSecondary / Capacity.DesignSecondary * Capacity.OperatingSecondary, 0, MidpointRounding.AwayFromZero); } //Calculate Elementary Capacity //Get Grade Range int lowGrade = LowestGrade - 100000000; int highGrade = HighestGrade - 100000000; int lowECount = 0; int highECount = 0; if (lowGrade < 8 && highGrade > 0) { //we need to calculate elementary //get number of low and high elementary grades for (int x = 1; x <= 7; x++) { if (x >= lowGrade && x <= highGrade) { if (x <= 3) { lowECount++; } else { highECount++; } } } if (lowECount == 0) { // all high E result.ElementaryCapacity = Math.Round(DesignElementary / Capacity.DesignElementary * Capacity.OperatingHighElementary, 0, MidpointRounding.AwayFromZero); } else if (highECount == 0) { result.ElementaryCapacity = Math.Round(DesignElementary / Capacity.DesignElementary * Capacity.OperatingLowElementary, 0, MidpointRounding.AwayFromZero); } else { var calcOperatingCapacity = ((lowECount * Capacity.OperatingLowElementary) + (highECount * Capacity.OperatingHighElementary)) / (lowECount + highECount); result.ElementaryCapacity = Math.Round(DesignElementary / Capacity.DesignElementary * calcOperatingCapacity, 0, MidpointRounding.AwayFromZero); } } return(result); }
/// <summary> /// Function to calculate schedule b total /// </summary> /// <returns>Schedule B Total</returns> internal CalculationResult Calculate() { CalculationResult result = new CalculationResult(); tracingService.Trace("{0}", "Starting ScheduleB.Calculate"); //variables decimal constructionNewReplacement = 0; decimal spaceAllocationExisting = 0; decimal constructionRenovations = 0; decimal constructionSiteDevelopmentAllowance = 0; decimal softCostContingencyRenovations = 0; decimal softCostContingencySeismic = 0; decimal softCostEquipmentAllowance = 0; decimal constructionTotalConstructionBudget = 0; decimal spaceAllocationNewReplacement = 0; decimal softCostWrapUpLiabilityInsurance = 0; decimal softCostDesignFees = 0; decimal softCostContingencyNewReplacement = 0; decimal NLCAmount = 0; //Default some numbers to 0, cased on Budget Calculation type //if partial seismic, set NLC to 0 //if (BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic) //{ // NLC = 0; //} if (BudgetCalculationType == (int)caps_BudgetCalculationType.New || BudgetCalculationType == (int)caps_BudgetCalculationType.Replacement || BudgetCalculationType == (int)caps_BudgetCalculationType.Addition || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialReplacement) { //default seismic fields to 0 ConstructionSeismicUpgrade = 0; //ConstructionSPIRAdjustment = 0; //ConstructionNonStructuralSeismicUpgrade = 0; } //Get School Type var schoolTypeRecord = GetSchoolType(SchoolType); #region 2. Space Allocations for Capital Budget -- DONE tracingService.Trace("{0}", "Section 2"); spaceAllocationNewReplacement = CalculateSpaceAllocation(ApprovedDesignCapacity, SchoolType, schoolTypeRecord.caps_Name); //Get existing space allocation for addition and partial replacement less any reductions if (BudgetCalculationType == (int)caps_BudgetCalculationType.Addition || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialReplacement || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic) { spaceAllocationExisting = CalculateSpaceAllocation(ExistingAndDecreaseDesignCapacity, SchoolType, schoolTypeRecord.caps_Name); spaceAllocationNewReplacement = spaceAllocationNewReplacement - spaceAllocationExisting; } tracingService.Trace("Space Allocation - New/Replacement: {0}", spaceAllocationNewReplacement); result.SpaceAllocationNewReplacement = spaceAllocationNewReplacement; //add extra space allocation spaceAllocationNewReplacement += ExtraSpaceAllocation.GetValueOrDefault(0); //Get total square meterage decimal spaceAllocationTotalNewReplacement = spaceAllocationNewReplacement; tracingService.Trace("Space Allocation - Total New/Replacement: {0}", spaceAllocationTotalNewReplacement); //DB: Total space allocation doesn't seem to be needed //decimal spaceAllocationTotal = spaceAllocationExisting + spaceAllocationTotalNewReplacement; #endregion #region 3. Construction Unit Rate -- DONE tracingService.Trace("{0}", "Section 3"); //Get Base Budget Rate based on School Type decimal constructionBaseBudgetRate = schoolTypeRecord.caps_BaseBudgetRate.Value; result.BaseBudgetRate = constructionBaseBudgetRate; tracingService.Trace("Base Budget Rate: {0}", constructionBaseBudgetRate); //Get Project Size Factor based on square meterage and school type decimal constructionProjectSizeFactor = CalculateProjectSizeFactor(SchoolType, schoolTypeRecord.caps_Name, spaceAllocationNewReplacement); tracingService.Trace("Project Size Factor: {0}", constructionProjectSizeFactor); tracingService.Trace("Project Location Factor: {0}", ProjectLocationFactor); result.ProjectSizeFactor = constructionProjectSizeFactor; result.ProjectLocationFactor = ProjectLocationFactor; //Set Unit Rate = Base Budget Rate * Project Size Factor * Project Location Factor decimal constructionUnitRate = constructionBaseBudgetRate * constructionProjectSizeFactor * ProjectLocationFactor; tracingService.Trace("Unit Rate: {0}", constructionUnitRate); result.UnitRate = constructionUnitRate; #endregion #region 4. Construction Items -- DONE tracingService.Trace("{0}", "Section 4"); //Set Construction: New/Replacement = total space allocation * unit rate if (BudgetCalculationType != (int)caps_BudgetCalculationType.SeismicUpgrade) { constructionNewReplacement = spaceAllocationTotalNewReplacement * constructionUnitRate; } tracingService.Trace("Construction - New/Replacement: {0}", constructionNewReplacement); result.ConstructionNewReplacement = constructionNewReplacement; //Only for Addition/Partial Replacement & Partial Seismic (4.2) if (BudgetCalculationType == (int)caps_BudgetCalculationType.Addition || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialReplacement || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic) { constructionRenovations = CalculateConstructionRenovationFactor(SchoolType, schoolTypeRecord.caps_Name, spaceAllocationNewReplacement) * constructionNewReplacement; } tracingService.Trace("Construction - Renovations: {0}", constructionRenovations); result.ConstructionRenovation = constructionRenovations; //Get Site Development Allowance based on Project Type, School Type and Square meterage (4.3) if (BudgetCalculationType == (int)caps_BudgetCalculationType.New) { if (ApprovedDesignCapacity.Total() >= 1500) { constructionSiteDevelopmentAllowance = schoolTypeRecord.caps_NewSchoolGreaterThan1500.Value; } else { constructionSiteDevelopmentAllowance = schoolTypeRecord.caps_NewSchoolLessThan1500.Value; } } else if (BudgetCalculationType == (int)caps_BudgetCalculationType.Replacement || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialReplacement) { constructionSiteDevelopmentAllowance = schoolTypeRecord.caps_Replacement.Value; } else if (BudgetCalculationType == (int)caps_BudgetCalculationType.Addition || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic) { if (spaceAllocationNewReplacement > 2000) { constructionSiteDevelopmentAllowance = schoolTypeRecord.caps_Additionfor2000m2.Value; } else if (spaceAllocationNewReplacement > 1000) { constructionSiteDevelopmentAllowance = schoolTypeRecord.caps_Additionfor1000m2.Value; } else if (spaceAllocationNewReplacement > 500) { constructionSiteDevelopmentAllowance = schoolTypeRecord.caps_Additionfor500m2.Value; } } tracingService.Trace("Site Development Allowance: {0}", constructionSiteDevelopmentAllowance); result.SiteDevelopmentAllowance = constructionSiteDevelopmentAllowance; //Set Site Development Location Allowance = (Project Location Factor -1) * Site Development Allowance (4.4) decimal constructionSiteDevelopmentLocationAllowance = (ProjectLocationFactor - 1) * constructionSiteDevelopmentAllowance; tracingService.Trace("Site Development Location Allowance: {0}", constructionSiteDevelopmentLocationAllowance); result.SiteDevelopmentLocationAllowance = constructionSiteDevelopmentLocationAllowance; //Set Total Construction Budget = All fields in region if (BudgetCalculationType == (int)caps_BudgetCalculationType.SeismicUpgrade) { constructionTotalConstructionBudget = ConstructionSeismicUpgrade.GetValueOrDefault(0); } else { constructionTotalConstructionBudget = constructionNewReplacement + constructionRenovations + constructionSiteDevelopmentAllowance + constructionSiteDevelopmentLocationAllowance + ConstructionSeismicUpgrade.GetValueOrDefault(0); } tracingService.Trace("Total Construction Budget: {0}", constructionTotalConstructionBudget); #endregion #region 5. Owner's Cost Items tracingService.Trace("{0}", "Section 5"); //Set Design Fees = Reports and Studies Allowance % * Total Construction Budget + Base Reports and Studies Allowance (5.1a) if (BudgetCalculationType == (int)caps_BudgetCalculationType.SeismicUpgrade) { softCostDesignFees = (schoolTypeRecord.caps_SeismicReportsandStudiesDesignFees.GetValueOrDefault(0) * constructionTotalConstructionBudget) + GetBudgetCalculationValue("Reports and Studies Allowance"); } else { softCostDesignFees = (schoolTypeRecord.caps_ReportsandStudiesDesignFees.GetValueOrDefault(0) * constructionTotalConstructionBudget) + GetBudgetCalculationValue("Reports and Studies Allowance"); } tracingService.Trace("Design Fees: {0}", softCostDesignFees); result.DesignFees = softCostDesignFees; //Set Post-Contract Contingency = Construction % * Total Construction Budget (5.2) if (BudgetCalculationType == (int)caps_BudgetCalculationType.New || BudgetCalculationType == (int)caps_BudgetCalculationType.Replacement) { softCostContingencyNewReplacement = GetBudgetCalculationValue("Post Contract Contingency New/Replacement Space") * constructionTotalConstructionBudget; } else if (BudgetCalculationType == (int)caps_BudgetCalculationType.Addition || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialReplacement || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic ) { softCostContingencyNewReplacement = GetBudgetCalculationValue("Post Contract Contingency New/Replacement Space") * (constructionNewReplacement + constructionSiteDevelopmentAllowance + constructionSiteDevelopmentLocationAllowance); } tracingService.Trace("Post-Contract Contingency - New/Replacement: {0}", softCostContingencyNewReplacement); result.PostContractNewReplacement = softCostContingencyNewReplacement; //Set Post-Contract Contingency - Renovations (5.3) if (BudgetCalculationType == (int)caps_BudgetCalculationType.Addition || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialReplacement || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic) { softCostContingencyRenovations = GetBudgetCalculationValue("Post Contract Contingency Renovations") * constructionRenovations; } //Set Post-Contract Contingency - Seismic (5.3a) if (BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic || BudgetCalculationType == (int)caps_BudgetCalculationType.SeismicUpgrade) { softCostContingencySeismic = GetBudgetCalculationValue("Post Contract Contingency Seismic") * (ConstructionSeismicUpgrade.GetValueOrDefault(0)); } tracingService.Trace("Post-Contract Contingency - Renovations: {0}", softCostContingencyRenovations); tracingService.Trace("Post-Contract Contingency - Seismic: {0}", softCostContingencySeismic); result.PostContractRenovation = softCostContingencyRenovations; result.PostContractSeismic = softCostContingencySeismic; //**Get Equipment Allowance Percentage //**Get School District Location Freight Percentage //Set Equipment Allowance - New Space (5.5) if (BudgetCalculationType == (int)caps_BudgetCalculationType.New || BudgetCalculationType == (int)caps_BudgetCalculationType.Addition) { softCostEquipmentAllowance = (constructionBaseBudgetRate * spaceAllocationNewReplacement * schoolTypeRecord.caps_EquipmentAllowanceNewSpace.Value) + (constructionBaseBudgetRate * spaceAllocationNewReplacement * schoolTypeRecord.caps_EquipmentAllowanceNewSpace.Value * FreightRateAllowance); result.EquipmentNew = softCostEquipmentAllowance; } else if (BudgetCalculationType == (int)caps_BudgetCalculationType.Replacement || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialReplacement || BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic) { softCostEquipmentAllowance = (constructionBaseBudgetRate * spaceAllocationNewReplacement * schoolTypeRecord.caps_EquipmentAllowanceReplacementSpace.Value) + (constructionBaseBudgetRate * spaceAllocationNewReplacement * schoolTypeRecord.caps_EquipmentAllowanceNewSpace.Value * FreightRateAllowance); result.EquipmentReplacement = softCostEquipmentAllowance; } tracingService.Trace("Equipment Allowance: {0}", softCostEquipmentAllowance); //Wrap-Up Liability Insurance (5.8) if (BudgetCalculationType == (int)caps_BudgetCalculationType.PartialSeismic || BudgetCalculationType == (int)caps_BudgetCalculationType.SeismicUpgrade) { softCostWrapUpLiabilityInsurance = constructionTotalConstructionBudget / 1000 * GetBudgetCalculationValue("Wrap Up Liability Insurance Renovations or Seismic"); } else { softCostWrapUpLiabilityInsurance = constructionTotalConstructionBudget / 1000 * GetBudgetCalculationValue("Wrap Up Liability Insurance New or Replacement"); } tracingService.Trace("Liability Insurance: {0}", softCostWrapUpLiabilityInsurance); result.LiabilityInsurance = softCostWrapUpLiabilityInsurance; decimal softCostPayableTaxes = (constructionTotalConstructionBudget + softCostDesignFees + softCostContingencyNewReplacement + softCostContingencyRenovations + softCostContingencySeismic + softCostEquipmentAllowance) * GetBudgetCalculationValue("Payable Taxes"); tracingService.Trace("Payable Taxes: {0}", softCostPayableTaxes); result.PayableTaxes = softCostPayableTaxes; decimal totalOwnersCost = softCostDesignFees + softCostContingencyNewReplacement + softCostContingencyRenovations + softCostContingencySeismic + MunicipalFees + softCostEquipmentAllowance + softCostWrapUpLiabilityInsurance + softCostPayableTaxes; tracingService.Trace("Total Owners Costs: {0}", totalOwnersCost); var projectManagementFee = CalculateProjectManagementFeeAllowance(totalOwnersCost + constructionTotalConstructionBudget); result.ProjectManagement = projectManagementFee; tracingService.Trace("Project Management Fee: {0}", projectManagementFee); #endregion decimal supplementalCosts = Demolition + AbnormalTopography + TempAccommodation + OtherSupplemental; //UPDATE: Add NLC to supplemental if ((BudgetCalculationType == (int)caps_BudgetCalculationType.New || BudgetCalculationType == (int)caps_BudgetCalculationType.Replacement) && IncludeNLC) { //get ProjectLocationFactor and NLC Amount NLCAmount = CalculateNLCAmount(ApprovedDesignCapacity, SchoolType, schoolTypeRecord.caps_Name); NLCAmount = NLCAmount * ProjectLocationFactor; } result.NLCBudgetAmount = NLCAmount; tracingService.Trace("Supplemental Costs: {0}", supplementalCosts); var subTotal = totalOwnersCost + constructionTotalConstructionBudget + projectManagementFee + supplementalCosts + NLCAmount; var riskReservePercent = GetBudgetCalculationValue("Risk Reserve and Escalation"); var riskReserve = subTotal * riskReservePercent; result.RiskReserve = riskReserve; result.RiskReservePercent = riskReservePercent * 100; result.Total = subTotal + riskReserve; return(result); }