/**
  * Calculates Contribution from Adjusted Available Income (AAI)
  * @param EfcCalculationRole $role Role of the subject within the calculation
  * @param float $adjustedAvailableIncome Adjusted Available Income
  * @return float
  */
 public function CalculateContributionFromAai($role, $adjustedAvailableIncome)
 {
     if ($role == EfcCalculationRole::DependentStudent || $role == EfcCalculationRole::IndependentStudentWithoutDependents) {
         return EfcMathHelper::roundPositive($adjustedAvailableIncome);
     }
     $aaiContributionRanges = $this->_constants->aaiContributionRanges;
     $aaiContributionPercents = $this->_constants->aaiContributionPercents;
     $aaiContributionBases = $this->_constants->aaiContributionBases;
     if ($adjustedAvailableIncome < $aaiContributionRanges[0]) {
         return 0;
     }
     $baseRange = 0;
     $maxIndex = count($aaiContributionRanges) - 1;
     // Loop through AAIContributionRanges until adjustedAvailableIncome param is within range
     foreach ($aaiContributionRanges as $index => $range) {
         // If at end of ranges, set baseAmount to maximum range
         if ($index == $maxIndex) {
             $baseRange = $aaiContributionRanges[$index];
             break;
         }
         // If adjustedAvailableIncome is within range
         if ($adjustedAvailableIncome < $aaiContributionRanges[$index + 1]) {
             // If adjustedAvailableIncome is within first range, there is no baseAmount;
             // otherwise, assign standard baseAmount
             $baseRange = $index == 0 ? 0 : $range;
             break;
         }
     }
     // Contribution From AAI =
     //      (Base Amount for Range)
     //          + (((Adjusted Available Income) - (Lowest Value of Range)) * (Percent for Range))
     $contributionFromAai = $aaiContributionBases[$index] + ($adjustedAvailableIncome - $baseRange) * ($aaiContributionPercents[$index] * 0.01);
     return EfcMathHelper::roundPositive($contributionFromAai);
 }
 /**
  * Calculates Available Income
  * @param EfcCalculationRole $role Subject's role within the calculation
  * @param float $totalIncome Total income
  * @param float $totalAllowances Total allowances
  * @return float
  */
 public function calculateAvailableIncome($role, $totalIncome, $totalAllowances)
 {
     $availableIncome = EfcMathHelper::round($totalIncome - $totalAllowances);
     // The available income for Dependent Students and Independent Students Without Depends is
     // multiplied by an assessment percent
     if ($role == EfcCalculationRole::DependentStudent || $role == EfcCalculationRole::IndependentStudentWithoutDependents) {
         return $availableIncome < 0 ? 0 : EfcMathHelper::round($availableIncome * $this->_constants->aiAssessmentPercent);
     }
     return $availableIncome;
 }
 /**
  * Calculates the Adjusted Net Worth of Business/Farm contribution
  * @param EfcCalculationRole $role Subject's role within the calculation
  * @param float $businessFarmNetWorth Net worth of business and/or investment farm
  * @return float
  */
 public function calculateAdjustedBusinessFarmNetWorthContribution($role, $businessFarmNetWorth)
 {
     if ($role == EfcCalculationRole::DependentStudent) {
         return EfcMathHelper::roundPositive($businessFarmNetWorth);
     }
     $businessFarmNetWorthAdjustmentRanges = $this->_constants->businessFarmNetWorthAdjustmentRanges;
     $businessFarmNetWorthAdjustmentBases = $this->_constants->businessFarmNetWorthAdjustmentBases;
     $businessFarmNetWorthAdjustmentPercents = $this->_constants->businessFarmNetWorthAdjustmentPercents;
     $baseRange = 0;
     $maxIndex = count($businessFarmNetWorthAdjustmentRanges) - 1;
     // Loop through $businessFarmNetWorthAdjustmentContributionRanges until $businessFarmNetWorth
     // param is within range
     foreach ($businessFarmNetWorthAdjustmentRanges as $index => $range) {
         // If at end of ranges, set baseAmount to maximum range
         if ($index == $maxIndex) {
             $baseRange = $businessFarmNetWorthAdjustmentRanges[$index];
             break;
         }
         // If businessFarmNetWorth is within range
         if ($businessFarmNetWorth < $businessFarmNetWorthAdjustmentRanges[$index + 1]) {
             // If $businessFarmNetWorth is within first range, there is no baseAmount
             // Otherwise, assign standard baseAmount
             $baseRange = $index == 0 ? 0 : $range;
             break;
         }
     }
     // Contribution From AAI =
     //      (Base Amount for Range)
     //          + (((Business Farm Net Worth) - (Lowest Value of Range)) * (Percent for Range))
     $adjustedBusinessFarmNetWorth = $businessFarmNetWorthAdjustmentBases[$index] + ($businessFarmNetWorth - $baseRange) * ($businessFarmNetWorthAdjustmentPercents[$index] * 0.01);
     return EfcMathHelper::roundPositive($adjustedBusinessFarmNetWorth);
 }
 /**
  * Calculates Employmement Expense Allowance
  * @param EfcCalculationRole $role Subject's role within the calculation
  * @param MaritalStatus $maritalStatus Marital status
  * @param HouseholdMember[] $employablePersons People capable of employment. Exact definition varies depending on role. If the role is "Parent"
  * for example, this refers to the parents. If the role is "IndependentStudent", this refers to the student and spouse
  * @return float
  */
 public function calculateEmploymentExpenseAllowance($role, $maritalStatus, $employablePersons)
 {
     if ($employablePersons == null || count($employablePersons) == 0 || $role == EfcCalculationRole::DependentStudent || $role == EfcCalculationRole::IndependentStudentWithoutDependents && $maritalStatus == MaritalStatus::SingleSeparatedDivorced) {
         return 0;
     }
     // Determine if all employable persons are earning money
     foreach ($employablePersons as $person) {
         if (!$person->isWorking) {
             // Not all of the employable persons are working
             return 0;
         }
     }
     // Determine the lowest income
     $lowestIncomePerson = $employablePersons[0];
     $lowestIncome = $lowestIncomePerson->workIncome;
     foreach ($employablePersons as $person) {
         if ($person->workIncome < $lowestIncome) {
             $lowestIncome = $person->workIncome;
         }
     }
     $employmentExpensePercent = $this->_constants->employmentExpensePercent;
     $employmentExpenseMaximum = $this->_constants->employmentExpenseMaximum;
     // Use the lowest of the incomes for the calculation
     $adjustedLowestIncome = $lowestIncome * $employmentExpensePercent;
     $employmentExpenseAllowance = $adjustedLowestIncome > $employmentExpenseMaximum ? $employmentExpenseMaximum : $adjustedLowestIncome;
     return EfcMathHelper::roundPositive($employmentExpenseAllowance);
 }
 /**
  * Calculates student contribution (SC) and expected family contribution (EFC) for an independent student
  * @param IndependentEfcCalculatorArguments $args Parameters for the calculation
  * @return EfcProfile
  */
 public function getIndependentEfcProfile($args)
 {
     if ($args->numberInCollege <= 0 || $args->monthsOfEnrollment <= 0 || $args->student == null) {
         return new EfcProfile(0, 0, 0, 0);
     }
     $role = $args->hasDependents ? EfcCalculationRole::IndependentStudentWithDependents : EfcCalculationRole::IndependentStudentWithoutDependents;
     $workIncome = 0;
     $householdMembers = array($args->student);
     $workIncome += $args->student->isWorking ? $args->student->workIncome : 0;
     if ($args->spouse != null) {
         if ($args->spouse->isWorking) {
             $workIncome += $args->spouse->workIncome;
         }
         $householdMembers[] = $args->spouse;
     }
     $simpleIncome = $args->areTaxFilers ? $args->adjustedGrossIncome : $workIncome;
     // Determine Auto Zero EFC eligibility
     if ($args->isQualifiedForSimplified && $role == EfcCalculationRole::IndependentStudentWithDependents && $simpleIncome <= $this->_constants->autoZeroEfcMax) {
         return new EfcProfile(0, 0, 0, 0);
     }
     // Student's Total Income
     $totalIncome = $this->_incomeCalculator->calculateTotalIncome($args->adjustedGrossIncome, $workIncome, $args->areTaxFilers, $args->untaxedIncomeAndBenefits, $args->additionalFinancialInfo);
     // Student's Total Allowances
     $totalAllowances = $this->_allowanceCalculator->calculateTotalAllowances($role, $args->maritalStatus, $args->stateOfResidency, $args->numberInCollege, $args->numberInHousehold, $householdMembers, $totalIncome, $args->incomeTaxPaid);
     // Student's Available Income (Contribution from Available Income)
     $availableIncome = $this->_incomeCalculator->calculateAvailableIncome($role, $totalIncome, $totalAllowances);
     // Determine Simplified EFC Equation Eligibility
     $useSimplified = $args->isQualifiedForSimplified && $simpleIncome <= $this->_constants->simplifiedEfcMax;
     // Student's Contribution From Assets
     $assetContribution = 0;
     if (!$useSimplified) {
         $assetContribution = $this->_assetContributionCalculator->calculateContributionFromAssets($role, $args->maritalStatus, $args->age, $args->cashSavingsCheckings, $args->investmentNetWorth, $args->businessFarmNetWorth);
     }
     // Student's Adjusted Available Income
     $adjustedAvailableIncome = $availableIncome + $assetContribution;
     // Student Contribution From AAI
     $studentContributionFromAai = $this->_aaiContributionCalculator->calculateContributionFromAai($role, $adjustedAvailableIncome);
     // Student's Contribution
     $studentContribution = EfcMathHelper::round($studentContributionFromAai / $args->numberInCollege);
     // Modify Student's Available Income based on months of enrollment
     if ($args->monthsOfEnrollment < self::DefaultMonthsOfEnrollment) {
         // LESS than default months of enrollment
         $monthlyContribution = EfcMathHelper::round($studentContribution / self::DefaultMonthsOfEnrollment);
         $studentContribution = $monthlyContribution * $args->monthsOfEnrollment;
     }
     // For MORE than default months of enrollment, the standard contribution is used
     $profile = new EfcProfile($studentContribution, 0, $studentContribution, 0);
     return $profile;
 }