public void GetDependentEfcProfile_ZeroNumberInCollege_ZeroEfc()
        {
            DependentEfcCalculatorArguments args = new DependentEfcCalculatorArguments
            {
                NumberInCollege = 0,
                Student = new HouseholdMember()
            };

            EfcProfile result = _efcCalculator.GetDependentEfcProfile(args);
            Assert.AreEqual(0, result.ExpectedFamilyContribution);
        }
        public void GetDependentEfcProfile_NoStudent_ZeroEfc()
        {
            DependentEfcCalculatorArguments args = new DependentEfcCalculatorArguments
            {
                NumberInCollege = 3,
                Student = null,
                MonthsOfEnrollment = 9
            };

            EfcProfile result = _efcCalculator.GetDependentEfcProfile(args);
            Assert.AreEqual(0, result.ExpectedFamilyContribution);
        }
        /// <summary>
        /// Parses "raw" string values into a <see cref="DependentEfcCalculatorArguments"/> object that
        /// can be passed to the <see cref="EfcCalculator"/>. If validation errors occur while parsing the values,
        /// they are added to the <see cref="Errors"/> property of this validator
        /// </summary>
        /// <param name="args">Set of "raw" string arguments to parse</param>
        /// <returns>The parsed <see cref="DependentEfcCalculatorArguments"/> object or null if validation failed</returns>
        public DependentEfcCalculatorArguments ValidateDependentEfcCalculatorArguments(RawDependentEfcCalculatorArguments args)
        {
            if (args == null)
            {
                throw new ArgumentException("No raw arguments provided");
            }

            // Oldest Parent Age
            int oldestParentAge
                = _validator.ValidateNonZeroInteger(
                        args.OldestParentAge,
                        LabelOldestParentAge,
                        ParamOldestParentAge);

            // Marital Status
            MaritalStatus maritalStatus
                = _validator.ValidateMaritalStatus(
                        args.MaritalStatus,
                        LabelParentMaritalStatus,
                        ParamMaritalStatus);

            // Is First Parent Working?
            bool isFirstParentWorking
                = _validator.ValidateBoolean(
                        args.IsFirstParentWorking,
                        LabelIsFirstParentWorking,
                        ParamIsFirstParentWorking);

            // First Parent Work Income
            double firstParentWorkIncome
                = isFirstParentWorking
                      ? _validator.ValidatePositiveMoneyValue(
                            args.FirstParentWorkIncome,
                            LabelFirstParentWorkIncome,
                            ParamFirstParentWorkIncome)
                      : 0;

            HouseholdMember firstParent = new HouseholdMember
            {
                IsWorking = isFirstParentWorking,
                WorkIncome = firstParentWorkIncome
            };

            HouseholdMember secondParent = null;
            if (maritalStatus == MaritalStatus.MarriedRemarried)
            {
                // Is Second Parent Working?
                bool isSecondParentWorking
                    = _validator.ValidateBoolean(
                            args.IsSecondParentWorking,
                            LabelIsSecondParentWorking,
                            ParamIsSecondParentWorking);

                // Mother Work Income
                double secondParentWorkIncome
                    = isSecondParentWorking
                          ? _validator.ValidatePositiveMoneyValue(
                                args.SecondParentWorkIncome,
                                LabelSecondParentWorkIncome,
                                ParamSecondParentWorkIncome)
                          : 0;

                secondParent = new HouseholdMember
                {
                    IsWorking = isSecondParentWorking,
                    WorkIncome = secondParentWorkIncome
                };
            }

            // Is Student Working?
            bool isStudentWorking
                = _validator.ValidateBoolean(
                        args.IsStudentWorking,
                        LabelIsStudentWorking,
                        ParamIsStudentWorking);

            // Student Work Income
            double studentWorkIncome
                = isStudentWorking
                      ? _validator.ValidatePositiveMoneyValue(
                            args.StudentWorkIncome,
                            LabelStudentWorkIncome,
                            ParamStudentWorkIncome)
                      : 0;

            HouseholdMember student = new HouseholdMember
            {
                IsWorking = isStudentWorking,
                WorkIncome = studentWorkIncome
            };

            // Parent AGI
            double parentAgi
                = _validator.ValidateMoneyValue(
                        args.ParentAgi,
                        LabelParentAgi,
                        ParamParentAgi);

            // Are Parents Tax Filers?
            bool areParentsTaxFilers
                = _validator.ValidateBoolean(
                        args.AreParentsTaxFilers,
                        LabelAreParentsTaxFilers,
                        ParamAreParentsTaxFilers);

            // Parent Income Tax Paid
            double parentIncomeTaxPaid
                = _validator.ValidateMoneyValue(
                        args.ParentIncomeTax,
                        LabelParentIncomeTax,
                        ParamParentIncomeTax);

            // Parent Untaxed Income and Benefits
            double parentUntaxedIncomeAndBenefits
                = _validator.ValidatePositiveMoneyValue(
                        args.ParentUntaxedIncomeAndBenefits,
                        LabelParentUntaxedIncomeAndBenefits,
                        ParamParentUntaxedIncomeAndBenefits);

            // Parent Additional Financial Info
            double parentAdditionalFinancialInfo
                = _validator.ValidatePositiveMoneyValue(
                        args.ParentAdditionalFinancialInfo,
                        LabelParentAdditionalFinancialInfo,
                        ParamParentAdditionalFinancialInfo);

            // Student AGI
            double studentAgi
                = _validator.ValidateMoneyValue(
                        args.StudentAgi,
                        LabelStudentAgi,
                        ParamStudentAgi);

            // Is Student Tax Filer?
            bool isStudentTaxFiler
                = _validator.ValidateBoolean(
                        args.IsStudentTaxFiler,
                        LabelIsStudentTaxFiler,
                        ParamIsStudentTaxFiler);

            // Student Income Tax Paid
            double studentIncomeTaxPaid
                = _validator.ValidateMoneyValue(
                        args.StudentIncomeTax,
                        LabelStudentIncomeTax,
                        ParamStudentIncomeTax);

            // Student Untaxed Income and Benefits
            double studentUntaxedIncomeAndBenefits
                = _validator.ValidatePositiveMoneyValue(
                        args.StudentUntaxedIncomeAndBenefits,
                        LabelStudentUntaxedIncomeAndBenefits,
                        ParamStudentUntaxedIncomeAndBenefits);

            // Student Additional Financial Information
            double studentAdditionalFinancialInfo
                = _validator.ValidatePositiveMoneyValue(
                        args.StudentAdditionalFinancialInfo,
                        LabelStudentAdditionalFinancialInfo,
                        ParamStudentAdditionalFinancialInfo);

            // Parent Cash, Savings, Checking
            double parentCashSavingsChecking
                = _validator.ValidatePositiveMoneyValue(
                        args.ParentCashSavingsChecking,
                        LabelParentCashSavingsChecking,
                        ParamParentCashSavingsChecking);

            // Parent Investment Net Worth
            double parentInvestmentNetWorth
                = _validator.ValidateMoneyValue(
                        args.ParentInvestmentNetWorth,
                        LabelParentInvestmentNetWorth,
                        ParamParentInvestmentNetWorth);

            // Parent Business Farm Net Worth
            double parentBusinessFarmNetWorth
                = _validator.ValidateMoneyValue(
                        args.ParentBusinessFarmNetWorth,
                        LabelParentBusinessFarmNetWorth,
                        ParamParentBusinessFarmNetWorth);

            // Student Cash, Savings, Checkings
            double studentCashSavingsCheckings
                = _validator.ValidatePositiveMoneyValue(
                        args.StudentCashSavingsChecking,
                        LabelStudentCashSavingsChecking,
                        ParamStudentCashSavingsChecking);

            // Student Investment Net Worth
            double studentInvestmentNetWorth
                = _validator.ValidateMoneyValue(
                        args.StudentInvestmentNetWorth,
                        LabelStudentInvestmentNetWorth,
                        ParamStudentInvestmentNetWorth);

            // Student Business Farm Net Worth
            double studentBusinessFarmNetWorth
                = _validator.ValidateMoneyValue(
                    args.StudentBusinessFarmNetWorth,
                    LabelStudentBusinessFarmNetWorth,
                    ParamStudentBusinessFarmNetWorth);

            // State of Residency
            UnitedStatesStateOrTerritory stateOfResidency
                = _validator.ValidateUnitedStatesStateOrTerritory(
                    args.StateOfResidency,
                    LabelStateOfResidency,
                    ParamStateOfResidency);

            // Number in Household
            int numberInHousehold
                = _validator.ValidateNonZeroInteger(
                    args.NumberInHousehold,
                    LabelNumInHousehold,
                    ParamNumInHousehold);

            // Number in College
            int numberInCollege
                = _validator.ValidateNonZeroInteger(
                    args.NumberInCollege,
                    LabelNumInCollege,
                    ParamNumInCollege);

            // CHECK: If Married, Number in Household must be greater than 3
            if (numberInHousehold > 0
                && maritalStatus == MaritalStatus.MarriedRemarried
                && numberInHousehold < 3)
            {
                _validator.Errors.Add(new ValidationError(ParamNumInHousehold,
                    String.Format(@"{0} was ""Married/Remarried"", but {1} was less than three",
                    LabelParentMaritalStatus, LabelNumInHousehold)));
            }
            // CHECK: Number in household must be greater than two
            else if (numberInHousehold > 0 && numberInHousehold < 2)
            {
                _validator.Errors.Add(new ValidationError(ParamNumInHousehold,
                    String.Format(@"{0} must equal at least two",
                    LabelNumInHousehold)));
            }

            // CHECK: Number in Household must be greater than or equal to Number in College
            if (numberInCollege > numberInHousehold)
            {
                _validator.Errors.Add(new ValidationError(ParamNumInCollege,
                    String.Format(@"{0} must be less than or equal to {1}",
                    LabelNumInCollege, LabelNumInHousehold)));
            }

            // Is Qualified For Simplified?
            bool isQualifiedForSimplified
                = _validator.ValidateBoolean(
                    args.IsQualifiedForSimplified,
                    LabelIsQualifiedForSimplified,
                    ParamIsQualifiedForSimplified);

            // Months of Enrollment
            int monthsOfEnrollment
                = _validator.ValidateNonZeroInteger(
                    args.MonthsOfEnrollment,
                    LabelMonthsOfEnrollment,
                    ParamMonthsOfEnrollment);

            if (_validator.Errors.Any())
            {
                return null;
            }

            // Build calculation arguments
            DependentEfcCalculatorArguments parsedArgs = new DependentEfcCalculatorArguments
                {
                    FirstParent = firstParent,
                    SecondParent = secondParent,
                    Student = student,
                    ParentAdjustedGrossIncome = parentAgi,
                    AreParentsTaxFilers = areParentsTaxFilers,
                    ParentIncomeTaxPaid = parentIncomeTaxPaid,
                    ParentUntaxedIncomeAndBenefits = parentUntaxedIncomeAndBenefits,
                    ParentAdditionalFinancialInfo = parentAdditionalFinancialInfo,
                    StudentAdjustedGrossIncome = studentAgi,
                    IsStudentTaxFiler = isStudentTaxFiler,
                    StudentIncomeTaxPaid = studentIncomeTaxPaid,
                    StudentUntaxedIncomeAndBenefits = studentUntaxedIncomeAndBenefits,
                    StudentAdditionalFinancialInfo = studentAdditionalFinancialInfo,
                    ParentCashSavingsChecking = parentCashSavingsChecking,
                    ParentInvestmentNetWorth = parentInvestmentNetWorth,
                    ParentBusinessFarmNetWorth = parentBusinessFarmNetWorth,
                    StudentCashSavingsChecking = studentCashSavingsCheckings,
                    StudentInvestmentNetWorth = studentInvestmentNetWorth,
                    StudentBusinessFarmNetWorth = studentBusinessFarmNetWorth,
                    MaritalStatus = maritalStatus,
                    StateOfResidency = stateOfResidency,
                    NumberInHousehold = numberInHousehold,
                    NumberInCollege = numberInCollege,
                    OldestParentAge = oldestParentAge,
                    IsQualifiedForSimplified = isQualifiedForSimplified,
                    MonthsOfEnrollment = monthsOfEnrollment
                };

            return parsedArgs;
        }
        public DependentEfcCalculatorArguments ValidateSimpleDependentEfcCalculatorArguments(RawSimpleDependentEfcCalculatorArguments args)
        {
            if (args == null)
            {
                throw new ArgumentException("No raw arguments provided");
            }

            // Marital Status
            MaritalStatus maritalStatus = 
                _validator.ValidateMaritalStatus(
                    args.MaritalStatus,
                    LabelParentMaritalStatus,
                    ParamMaritalStatus);

            // Parent Income
            double parentIncome =
                _validator.ValidatePositiveMoneyValue(
                        args.ParentIncome,
                        LabelParentIncome,
                        ParamParentIncome);

            // Parent Other Income
            double parentOtherIncome =
                _validator.ValidatePositiveMoneyValue(
                        args.ParentOtherIncome,
                        LabelParentOtherIncome,
                        ParamParentOtherIncome);

            // Parent Income Earned By
            IncomeEarnedBy incomeEarnedBy =
                _validator.ValidateIncomeEarnedBy(
                    args.ParentIncomeEarnedBy,
                    LabelParentIncomeEarnedBy,
                    ParamParentIncomeEarnedBy);

            // CHECK: If Single/Separated/Divorced, "Parent Income Earned By" can not be "Both"
            if (maritalStatus == MaritalStatus.SingleSeparatedDivorced && incomeEarnedBy == IncomeEarnedBy.Both)
            {
                _validator.Errors.Add(new ValidationError(ParamParentIncomeEarnedBy,
                    String.Format(@"{0} was ""Single/Separated/Divorced"", but {1} was marked as earned by both parents",
                    LabelParentMaritalStatus, LabelParentIncomeEarnedBy)));
            }

            // CHECK: If "Parent Income Earned By" is "None", then "Parent Income" must be 0
            if (incomeEarnedBy == IncomeEarnedBy.None && parentIncome > 0)
            {
                _validator.Errors.Add(new ValidationError(ParamParentIncome,
                    String.Format(@"{0} was marked as earned by neither parents, but {1} was greater than 0",
                        LabelParentIncomeEarnedBy, LabelParentIncome)));
            }

            // Parent Income Tax Paid
            double parentIncomeTaxPaid =
                _validator.ValidatePositiveMoneyValue(
                    args.ParentIncomeTax,
                    LabelParentIncomeTax,
                    ParamParentIncomeTax);

            // Parent Assets
            double parentAssets =
                _validator.ValidatePositiveMoneyValue(
                    args.ParentAssets,
                    LabelParentAssets,
                    ParamParentAssets);

            // Student Income
            double studentIncome =
                _validator.ValidatePositiveMoneyValue(
                    args.StudentIncome,
                    LabelStudentIncome,
                    ParamStudentIncome);

            // Student Other Income
            double studentOtherIncome =
                _validator.ValidatePositiveMoneyValue(
                    args.StudentOtherIncome,
                    LabelStudentOtherIncome,
                    ParamStudentOtherIncome);

            // Student Income Tax Paid
            double studentIncomeTaxPaid =
                _validator.ValidatePositiveMoneyValue(
                    args.StudentIncomeTax,
                    LabelStudentIncomeTax,
                    ParamStudentIncomeTax);

            // Student Assets
            double studentAssets =
                _validator.ValidatePositiveMoneyValue(
                    args.StudentAssets,
                    LabelStudentAssets,
                    ParamStudentAssets);

            // Number in Household
            int numberInHousehold =
                _validator.ValidateNonZeroInteger(
                    args.NumberInHousehold,
                    LabelNumInHousehold,
                    ParamNumInHousehold);

            // Number in College
            int numberInCollege =
                _validator.ValidateNonZeroInteger(
                    args.NumberInCollege,
                    LabelNumInCollege,
                    ParamNumInCollege);

            // CHECK: Number in Household must be greater than or equal to Number in College
            if (numberInCollege > numberInHousehold)
            {
                _validator.Errors.Add(new ValidationError(ParamNumInCollege,
                    String.Format(@"{0} must be less than or equal to {1}",
                    LabelNumInCollege, LabelNumInHousehold)));
            }

            // State of Residency
            UnitedStatesStateOrTerritory stateOfResidency =
                _validator.ValidateUnitedStatesStateOrTerritory(
                    args.StateOfResidency,
                    LabelStateOfResidency,
                    ParamStateOfResidency);

            if (_validator.Errors.Count > 0)
            {
                return null;
            }

            // Build a list of arguments for the full EFC calculation using assumed
            // values gleaned from the "simplified" values provided

            bool isFirstParentWorking = false;
            bool isSecondParentWorking = false;

            double firstParentWorkIncome = 0;
            double secondParentWorkIncome = 0;

            if (incomeEarnedBy == IncomeEarnedBy.One)
            {
                isFirstParentWorking = true;
                firstParentWorkIncome = parentIncome;
            }

            if (incomeEarnedBy == IncomeEarnedBy.Both)
            {
                isFirstParentWorking = isSecondParentWorking = true;
                firstParentWorkIncome = secondParentWorkIncome = (parentIncome / 2);
            }

            HouseholdMember firstParent = new HouseholdMember
            {
                IsWorking = isFirstParentWorking,
                WorkIncome = firstParentWorkIncome
            };

            HouseholdMember secondParent = null;
            if (maritalStatus == MaritalStatus.MarriedRemarried)
            {
                secondParent = new HouseholdMember
                {
                    IsWorking = isSecondParentWorking,
                    WorkIncome = secondParentWorkIncome
                };
            }

            // ASSUME: Student is working
            HouseholdMember student = new HouseholdMember
            {
                IsWorking = true,
                WorkIncome = studentIncome
            };

            // Build calculation arguments
            DependentEfcCalculatorArguments parsedArgs = new DependentEfcCalculatorArguments
            {
                FirstParent = firstParent,
                SecondParent = secondParent,
                Student = student,

                // ASSUME: "Age of Oldest Parent" is 45
                OldestParentAge = 45,

                // ASSUME: "Parent's AGI" == "Parent's Income"
                ParentAdjustedGrossIncome = parentIncome,

                // ASSUME: Parents are tax filers
                AreParentsTaxFilers = true,

                ParentIncomeTaxPaid = parentIncomeTaxPaid,

                // ASSUME: "Parent's Untaxed Income and Benefits" == "Parent's Other Income"
                ParentUntaxedIncomeAndBenefits = parentOtherIncome,

                // ASSUME: "Parent's Additional Financial Information" is zero
                ParentAdditionalFinancialInfo = 0,

                // ASSUME: "Student's AGI" == "Student's Income"
                StudentAdjustedGrossIncome = studentIncome,

                // ASSUME: Student is a tax filer
                IsStudentTaxFiler = true,

                StudentIncomeTaxPaid = studentIncomeTaxPaid,

                // ASSUME: "Student's Untaxed Income and Benefits" == "Student's Other Income"
                StudentUntaxedIncomeAndBenefits = studentOtherIncome,

                // ASSUME: "Student's Additional Financial Information" is zero
                StudentAdditionalFinancialInfo = 0,

                // ASSUME: "Parent's Cash, Savings, and Checking" == "Parent's Assets"
                ParentCashSavingsChecking = parentAssets,

                // ASSUME: "Parent's Net Worth of Investments" is zero
                ParentInvestmentNetWorth = 0,

                // ASSUME: "Parent's Net Worth of Business and/or Investment Farm" is zero
                ParentBusinessFarmNetWorth = 0,

                // ASSUME: "Student's Cash, Savings, and Checking" == "Student's Assets"
                StudentCashSavingsChecking = studentAssets,

                // ASSUME: "Student's Net Worth of Investments" is zero
                StudentInvestmentNetWorth = 0,

                // ASSUME: "Student's Net Worth of Business and/or Investment Farm" is zero
                StudentBusinessFarmNetWorth = 0,

                MaritalStatus = maritalStatus,
                StateOfResidency = stateOfResidency,
                NumberInHousehold = numberInHousehold,
                NumberInCollege = numberInCollege,

                // ASSUME: Student is NOT qualified for simplified formula
                IsQualifiedForSimplified = false,

                // ASSUME: Nine months of enrollment
                MonthsOfEnrollment = 9
            };

            return parsedArgs;
        }
        public void GetDependentEfcProfile_TwelveMonthsEnrollment_Calculated()
        {
            DependentEfcCalculatorArguments args = new DependentEfcCalculatorArguments
            {
                FirstParent = null,
                SecondParent = new HouseholdMember
                {
                    IsWorking = true,
                    WorkIncome = 60000
                },
                Student = new HouseholdMember
                {
                    IsWorking = true,
                    WorkIncome = 10000
                },
                ParentAdjustedGrossIncome = 60000,
                AreParentsTaxFilers = true,
                ParentIncomeTaxPaid = 6000,
                ParentUntaxedIncomeAndBenefits = 1000,
                ParentAdditionalFinancialInfo = 200,
                StudentAdjustedGrossIncome = 10000,
                IsStudentTaxFiler = true,
                StudentIncomeTaxPaid = 1000,
                StudentUntaxedIncomeAndBenefits = 0,
                StudentAdditionalFinancialInfo = 0,
                ParentCashSavingsChecking = 80000,
                ParentInvestmentNetWorth = 5000,
                ParentBusinessFarmNetWorth = 0,
                StudentCashSavingsChecking = 3000,
                StudentInvestmentNetWorth = 0,
                MaritalStatus = MaritalStatus.SingleSeparatedDivorced,
                StateOfResidency = UnitedStatesStateOrTerritory.California,
                NumberInHousehold = 3,
                NumberInCollege = 1,
                OldestParentAge = 45,
                MonthsOfEnrollment = 12
            };

            EfcProfile profile = _efcCalculator.GetDependentEfcProfile(args);
            Assert.AreEqual(8409, profile.ParentContribution);
            Assert.AreEqual(1403, profile.StudentContribution);
        }
        public void GetDependentEfcProfile_LowValues_Calculated()
        {
            DependentEfcCalculatorArguments args = new DependentEfcCalculatorArguments
            {
                FirstParent = new HouseholdMember
                {
                    IsWorking = false,
                    WorkIncome = 0
                },
                SecondParent = new HouseholdMember
                {
                    IsWorking = false,
                    WorkIncome = 0
                },
                Student = new HouseholdMember
                {
                    IsWorking = false,
                    WorkIncome = 0
                },
                ParentAdjustedGrossIncome = 0,
                AreParentsTaxFilers = false,
                ParentIncomeTaxPaid = 0,
                ParentUntaxedIncomeAndBenefits = 10000,
                ParentAdditionalFinancialInfo = 0,
                StudentAdjustedGrossIncome = 0,
                IsStudentTaxFiler = false,
                StudentIncomeTaxPaid = 0,
                StudentUntaxedIncomeAndBenefits = 0,
                StudentAdditionalFinancialInfo = 0,
                ParentCashSavingsChecking = 0,
                ParentInvestmentNetWorth = 0,
                ParentBusinessFarmNetWorth = 0,
                StudentCashSavingsChecking = 0,
                StudentInvestmentNetWorth = 0,
                MaritalStatus = MaritalStatus.MarriedRemarried,
                StateOfResidency = UnitedStatesStateOrTerritory.California,
                NumberInHousehold = 3,
                NumberInCollege = 1,
                OldestParentAge = 30,
                MonthsOfEnrollment = 9
            };

            EfcProfile profile = _efcCalculator.GetDependentEfcProfile(args);
            Assert.AreEqual(0, profile.ExpectedFamilyContribution);
        }
        /// <summary>
        /// Calculates parent contribution (PC), student contribution (SC), and expected family contribution (EFC) for
        /// a dependent student
        /// </summary>
        /// <param name="args">Parameters for the calculation</param>
        /// <returns>Parent contribution (PC), student contribution (SC), and expected family contribution (EFC) for
        /// a dependent student</returns>
        public EfcProfile GetDependentEfcProfile(DependentEfcCalculatorArguments args)
        {
            if (args.NumberInCollege <= 0
                || args.MonthsOfEnrollment <= 0
                || args.Student == null)
            {
                return new EfcProfile(0, 0, 0, 0);
            }

            double workIncome = 0;
            List<HouseholdMember> parents = new List<HouseholdMember>();

            if (args.FirstParent != null)
            {
                if (args.FirstParent.IsWorking)
                {
                    workIncome += args.FirstParent.WorkIncome;
                }

                parents.Add(args.FirstParent);
            }

            if (args.SecondParent != null)
            {
                if (args.SecondParent.IsWorking)
                {
                    workIncome += args.SecondParent.WorkIncome;
                }

                parents.Add(args.SecondParent);
            }

            double simpleIncome = (args.AreParentsTaxFilers) ? args.ParentAdjustedGrossIncome : workIncome;

            // Determine Auto Zero EFC eligibility
            if (args.IsQualifiedForSimplified && simpleIncome <= _constants.AutoZeroEfcMax)
            {
                return new EfcProfile(0, 0, 0, 0);
            }

            // Parent's Total Income
            double parentTotalIncome = _incomeCalculator.CalculateTotalIncome(
                                            args.ParentAdjustedGrossIncome,
                                            workIncome,
                                            args.AreParentsTaxFilers,
                                            args.ParentUntaxedIncomeAndBenefits,
                                            args.ParentAdditionalFinancialInfo);

            // Parent's Total Allowances
            double parentTotalAllowances = _allowanceCalculator.CalculateTotalAllowances(
                                            EfcCalculationRole.Parent,
                                            args.MaritalStatus,
                                            args.StateOfResidency,
                                            args.NumberInCollege,
                                            args.NumberInHousehold,
                                            parents,
                                            parentTotalIncome,
                                            args.ParentIncomeTaxPaid);

            // Parent's Available Income
            double parentAvailableIncome
                = _incomeCalculator.CalculateAvailableIncome(EfcCalculationRole.Parent, parentTotalIncome,
                                                                parentTotalAllowances);

            // Determine Simplified EFC Equation Eligibility
            bool useSimplified = (args.IsQualifiedForSimplified && simpleIncome <= _constants.SimplifiedEfcMax);

            // Parent's Contribution From Assets
            double parentAssetContribution = 0;

            if (!useSimplified)
            {
                parentAssetContribution = _assetContributionCalculator.CalculateContributionFromAssets(
                    EfcCalculationRole.Parent,
                    args.MaritalStatus,
                    args.OldestParentAge,
                    args.ParentCashSavingsChecking,
                    args.ParentInvestmentNetWorth,
                    args.ParentBusinessFarmNetWorth);
            }

            // Parent's Adjusted Available Income
            double parentAdjustedAvailableIncome = parentAvailableIncome + parentAssetContribution;

            // Parent's Contribution from AAI
            double parentContributionFromAai =
                _aaiContributionCalculator.CalculateContributionFromAai(EfcCalculationRole.Parent,
                                                                            parentAdjustedAvailableIncome);

            // Parent Contribution
            double parentContribution = Math.Round(parentContributionFromAai / args.NumberInCollege,
                MidpointRounding.AwayFromZero);

            // Modify Parent Contribution based on months of enrollment
            if (args.MonthsOfEnrollment < DefaultMonthsOfEnrollment)
            {
                // LESS than default months of enrollment
                double parentMonthlyContribution
                    = Math.Round(parentContribution / DefaultMonthsOfEnrollment, MidpointRounding.AwayFromZero);

                parentContribution
                    = Math.Round(parentMonthlyContribution * args.MonthsOfEnrollment, MidpointRounding.AwayFromZero);
            }
            else if (args.MonthsOfEnrollment > DefaultMonthsOfEnrollment)
            {
                // MORE than default months of enrollment
                double parentAltAai
                    = parentAdjustedAvailableIncome + _constants.AltEnrollmentIncomeProtectionAllowance;

                double parentAltContributionFromAai
                    = _aaiContributionCalculator.CalculateContributionFromAai(EfcCalculationRole.Parent, parentAltAai);

                double parentAltContribution
                    = Math.Round(parentAltContributionFromAai / args.NumberInCollege, MidpointRounding.AwayFromZero);

                double parentContributionDiff
                    = (parentAltContribution - parentContribution);

                double parentMonthlyContribution
                    = Math.Round(parentContributionDiff / AnnualMonthsOfEnrollment, MidpointRounding.AwayFromZero);

                double parentContributionAdjustment
                    = Math.Round(parentMonthlyContribution * (args.MonthsOfEnrollment - DefaultMonthsOfEnrollment),
                                    MidpointRounding.AwayFromZero);

                parentContribution += parentContributionAdjustment;
            }

            // Student's Total Income
            double studentTotalIncome = _incomeCalculator.CalculateTotalIncome(
                                            args.StudentAdjustedGrossIncome,
                                            args.Student.WorkIncome,
                                            args.IsStudentTaxFiler,
                                            args.StudentUntaxedIncomeAndBenefits,
                                            args.StudentAdditionalFinancialInfo);

            // Student's Total Allowances
            double studentTotalAllowances = _allowanceCalculator.CalculateTotalAllowances(
                                            EfcCalculationRole.DependentStudent,
                                            MaritalStatus.SingleSeparatedDivorced,
                                            args.StateOfResidency,
                                            args.NumberInCollege,
                                            args.NumberInHousehold,
                                            new List<HouseholdMember> { args.Student },
                                            studentTotalIncome,
                                            args.StudentIncomeTaxPaid);

            // If parent has a negative AAI, add it to the student's Total Allowances
            if (parentAdjustedAvailableIncome < 0)
            {
                studentTotalAllowances -= parentAdjustedAvailableIncome;
            }

            // Student's Available Income (Contribution From Available Income)
            double studentAvailableIncome =
                _incomeCalculator.CalculateAvailableIncome(EfcCalculationRole.DependentStudent, studentTotalIncome,
                                                           studentTotalAllowances);

            // Modify Student's Available Income based on months of enrollment
            if (args.MonthsOfEnrollment < DefaultMonthsOfEnrollment)
            {
                // LESS than default months of enrollment
                double studentMonthlyContribution = Math.Round(studentAvailableIncome / DefaultMonthsOfEnrollment,
                                                               MidpointRounding.AwayFromZero);
                studentAvailableIncome = Math.Round(studentMonthlyContribution * args.MonthsOfEnrollment,
                                                    MidpointRounding.AwayFromZero);
            }

            // For MORE than default months of enrollment, the standard Available Income is used

            // Student's Contribution From Assets
            double studentAssetContribution = 0;

            if (!useSimplified)
            {
                studentAssetContribution = _assetContributionCalculator.CalculateContributionFromAssets(
                    EfcCalculationRole.DependentStudent,
                    MaritalStatus.SingleSeparatedDivorced,
                    0,
                    args.StudentCashSavingsChecking,
                    args.StudentInvestmentNetWorth,
                    args.StudentBusinessFarmNetWorth);
            }

            // Student Contribution
            double studentContribution = studentAvailableIncome + studentAssetContribution;

            EfcProfile profile = new EfcProfile(
                parentContribution + studentContribution,
                parentContribution,
                studentContribution,
                parentTotalIncome);

            return profile;
        }