Skip to content

Commit

Permalink
Merge pull request #78 from theopensystemslab/oz/refactor-lifetime
Browse files Browse the repository at this point in the history
feat: refactor `lifetime` type
  • Loading branch information
zz-hh-aa authored Sep 3, 2024
2 parents 98913f3 + 18e1fd1 commit 6907c0f
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 405 deletions.
16 changes: 4 additions & 12 deletions app/components/graphs/LifetimeFairholdLandPurchaseWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,15 @@ const LifetimeFairholdLandPurchaseWrapper: React.FC<Props> = ({

// Process and format the data for the chart
const chartData =
(household.tenure.fairholdLandPurchase?.lifetime || []).map(
(household.lifetime.lifetimeData).map(
(item, index) => {
// Access and store household.lifetime array
// TODO remove defensive code after types tightened upstream
const incomeThreshold =
household.lifetime && household.lifetime[index]
? household.lifetime[index].affordabilityThresholdIncome
: 0;

// Access and store all other variables
return {
year: index.toString(),
landCost: item.landMortgagePaymentYearly,
houseCost: item.houseMortgagePaymentYearly,
incomeThreshold: item.affordabilityThresholdIncome,
landCost: item.fairholdLandMortgageYearly,
houseCost: item.depreciatedHouseMortgageYearly,
// billsCost: item.gasBillYearly,
maintenanceCost: item.maintenanceCost,
incomeThreshold: incomeThreshold,
};
}
) ?? [];
Expand Down
27 changes: 10 additions & 17 deletions app/components/graphs/LifetimeFairholdLandRentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,16 @@ const LifetimeFairholdLandRentWrapper: React.FC<Props> = ({ household }) => {

// Process and format the data for the chart
const chartData =
(household.tenure.fairholdLandRent?.lifetime || []).map((item, index) => {
// Access and store household.lifetime array
// TODO remove defensive code after types tightened upstream
const incomeThreshold =
household.lifetime && household.lifetime[index]
? household.lifetime[index].affordabilityThresholdIncome
: 0;

// Access and store all other variables
return {
year: index.toString(),
landCost: item.fairholdRentLand,
houseCost: item.houseMortgagePaymentYearly,
maintenanceCost: item.maintenanceCost,
// billsCost: item.gasBillYearly,
incomeThreshold: incomeThreshold,
};
(household.lifetime.lifetimeData).map(
(item, index) => {
return {
year: index.toString(),
incomeThreshold: item.affordabilityThresholdIncome,
landCost: item.fairholdLandRentYearly,
houseCost: item.depreciatedHouseMortgageYearly,
maintenanceCost: item.maintenanceCost,
// billsCost: item.gasBillYearly,
};
}) ?? [];

return (
Expand Down
27 changes: 10 additions & 17 deletions app/components/graphs/LifetimeMarketPurchaseWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,16 @@ const LifetimeMarketPurchaseWrapper: React.FC<Props> = ({ household }) => {

// Process and format the data for the chart
const chartData =
(household.tenure.marketPurchase?.lifetime || []).map((item, index) => {
// Access and store household.lifetime array
// TODO remove defensive code after types tightened upstream
const incomeThreshold =
household.lifetime && household.lifetime[index]
? household.lifetime[index].affordabilityThresholdIncome
: 0;

// Access and store all other variables
return {
year: index.toString(), // or just `year: index` if you want it as a number
landCost: item.landMortgagePaymentYearly,
houseCost: item.houseMortgagePaymentYearly,
maintenanceCost: item.maintenanceCost,
// billsCost: item.gasBillYearly,
incomeThreshold: incomeThreshold,
};
(household.lifetime.lifetimeData).map(
(item, index) => {
return {
year: index.toString(),
incomeThreshold: item.affordabilityThresholdIncome,
landCost: item.marketLandMortgageYearly,
houseCost: item.newbuildHouseMortgageYearly,
maintenanceCost: item.maintenanceCost,
// billsCost: item.gasBillYearly,
};
}) ?? [];

return (
Expand Down
17 changes: 5 additions & 12 deletions app/components/graphs/LifetimeMarketRentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,14 @@ const LifetimeMarketRentWrapper: React.FC<Props> = ({ household }) => {

// Process and format the data for the chart
const chartData =
(household.tenure.marketRent?.lifetime || []).map((item, index) => {
// Access and store household.lifetime array
// TODO remove defensive code after types tightened upstream
const incomeThreshold =
household.lifetime && household.lifetime[index]
? household.lifetime[index].affordabilityThresholdIncome
: 0;

// Access and store all other variables
(household.lifetime.lifetimeData).map(
(item, index) => {
return {
year: index.toString(),
landCost: item.averageRentLandYearly,
houseCost: item.averageRentHouseYearly,
incomeThreshold: item.affordabilityThresholdIncome,
landCost: item.marketLandRentYearly,
houseCost: item.marketHouseRentYearly,
// billsCost: item.gasBillYearly,
incomeThreshold: incomeThreshold,
};
}) ?? [];

Expand Down
48 changes: 24 additions & 24 deletions app/components/graphs/TotalPaymentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,54 @@ import React from "react";
import ErrorBoundary from '../ErrorBoundary';
import { Household } from "@/app/models/Household";
import TotalPaymentBarChart from "./TotalPaymentBarChart";
import { LifetimeData } from "@/app/models/Lifetime";

interface TotalPaymentWrapperProps {
household: Household;
}

type LifetimeValues = {
[key: string]: number;
};

const TotalPaymentWrapper: React.FC<TotalPaymentWrapperProps> = ({
household,
}) => {
console.log("TotalPaymentWrapper household: ", household);

const sumLifetimeValues = (
lifetime: LifetimeValues[] | undefined,
keys: string[]
lifetime: LifetimeData[] | undefined,
keys: (keyof LifetimeData)[]
): number => {
if (!lifetime || !Array.isArray(lifetime)) return 0;

return lifetime.reduce((sum, entry) => {
return (
sum +
keys.reduce((entrySum, key) => {
return entrySum + (typeof entry[key] === "number" ? entry[key] : 0);
}, 0)
);
}, 0);

let totalSum = 0;

for (const entry of lifetime) {
let entrySum = 0;
for (const key of keys) {
entrySum += entry[key];
}
totalSum += entrySum;
}

return totalSum;
};

const chartData = [
{
paymentType: "Total Payments",
marketPurchase: sumLifetimeValues(
household.tenure.marketPurchase?.lifetime,
["houseMortgagePaymentYearly", "landMortgagePaymentYearly"]
household.lifetime.lifetimeData,
["newbuildHouseMortgageYearly", "marketLandMortgageYearly"]
),
marketRent: sumLifetimeValues(household.tenure.marketRent?.lifetime, [
"averageRentHouseYearly",
"averageRentLandYearly",
marketRent: sumLifetimeValues(
household.lifetime.lifetimeData,
["marketHouseRentYearly", "marketLandRentYearly",
]),
fairholdLandPurchase: sumLifetimeValues(
household.tenure.fairholdLandPurchase?.lifetime,
["houseMortgagePaymentYearly", "landMortgagePaymentYearly"]
household.lifetime.lifetimeData,
["depreciatedHouseMortgageYearly", "fairholdLandMortgageYearly"]
),
fairholdLandRent: sumLifetimeValues(
household.tenure.fairholdLandRent?.lifetime,
["fairholdRentLand", "houseMortgagePaymentYearly"]
household.lifetime.lifetimeData,
["depreciatedHouseMortgageYearly", "fairholdLandRentYearly"]
),
},
];
Expand Down
61 changes: 20 additions & 41 deletions app/models/Household.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Property } from "./Property";
import { SocialRent } from "./tenure/SocialRent";
import { ForecastParameters } from "./ForecastParameters";
import { socialRentAdjustmentTypes } from "../data/socialRentAdjustmentsRepo";
import { Lifetime, LifetimeParams } from "./Lifetime";

const HOUSE_MULTIPLIER = 2.4;

Expand All @@ -20,11 +21,6 @@ type ConstructorParams = Pick<
housePriceIndex: number;
};

type Lifetime = {
affordabilityThresholdIncome: number;
incomeYearly: number;
}[];

export class Household {
public incomePerPersonYearly: number;
public gasBillYearly: number;
Expand All @@ -47,10 +43,7 @@ export class Household {
this.forecastParameters = params.forecastParameters;
this.incomeYearly = HOUSE_MULTIPLIER * params.incomePerPersonYearly;
this.tenure = this.calculateTenures(params);
this.lifetime = this.calculateLifetime(
this.incomeYearly,
params.forecastParameters
);
this.lifetime = this.calculateLifetime(params);
}

private calculateTenures({
Expand Down Expand Up @@ -149,36 +142,22 @@ export class Household {
};
}

private calculateLifetime(
incomeYearly: number,
{
incomeGrowthPerYear,
affordabilityThresholdIncomePercentage,
yearsForecast,
}: ForecastParameters
) {
let incomeYearlyIterative = incomeYearly;
let affordabilityThresholdIncomeIterative =
incomeYearlyIterative * affordabilityThresholdIncomePercentage;

const lifetime: Lifetime = [
{
incomeYearly: incomeYearlyIterative,
affordabilityThresholdIncome: affordabilityThresholdIncomeIterative,
},
];

for (let i = 0; i < yearsForecast - 1; i++) {
incomeYearlyIterative = incomeYearlyIterative * (1 + incomeGrowthPerYear);
affordabilityThresholdIncomeIterative =
incomeYearlyIterative * affordabilityThresholdIncomePercentage;

lifetime.push({
incomeYearly: incomeYearlyIterative,
affordabilityThresholdIncome: affordabilityThresholdIncomeIterative,
});
private calculateLifetime(params: ConstructorParams): Lifetime {
const lifetimeParams: LifetimeParams = {
marketPurchase: this.tenure.marketPurchase,
marketRent: this.tenure.marketRent,
fairholdLandPurchase: this.tenure.fairholdLandPurchase,
fairholdLandRent: this.tenure.fairholdLandRent,
property: this.property,
propertyPriceGrowthPerYear: params.forecastParameters.propertyPriceGrowthPerYear,
constructionPriceGrowthPerYear: params.forecastParameters.constructionPriceGrowthPerYear,
rentGrowthPerYear: params.forecastParameters.rentGrowthPerYear,
yearsForecast: params.forecastParameters.yearsForecast,
maintenanceCostPercentage: params.forecastParameters.maintenanceCostPercentage,
incomeGrowthPerYear: params.forecastParameters.incomeGrowthPerYear,
affordabilityThresholdIncomePercentage: params.forecastParameters.affordabilityThresholdIncomePercentage,
incomeYearly: this.incomeYearly,
};
return new Lifetime(lifetimeParams);
}

return lifetime;
}
}
}
Loading

0 comments on commit 6907c0f

Please sign in to comment.