Skip to content

Commit

Permalink
Merge pull request #292 from ORNL-AMO/issue-180-revert
Browse files Browse the repository at this point in the history
Issue 180 - Revert display wording changes, fix current game year snafu
  • Loading branch information
rhernandez-intertech authored Mar 25, 2024
2 parents deec34a + 48a62cf commit ee2fbfa
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 54 deletions.
10 changes: 4 additions & 6 deletions GAMEPLAY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
## General

- The game is played in 1 or 2 year budget periods (intervals)
- Project info cards will always display the annual cost
- Players may move backwards a single budget period to make changes.
- Players receive additional budget at each year start:
1: 75_000,
Expand All @@ -18,7 +19,7 @@
9: 112_500,
10: 112_500

- Yearly emissions factor defaults are used to calculate emissions. For 2 year gameplay the later year is used (i.e. year 4 in 3/4)
- Yearly emissions factor defaults are used to calculate emissions. For 2 year gameplay the later year is used (i.e. year 4 in 3/4).
1: .371,
2: .358,
3: .324,
Expand Down Expand Up @@ -101,13 +102,10 @@ All normal projects are now added to `implementedFinancedProjects` and `implemen

Capital Funding pays projects in full and has it's own state object, but is also considered a financing type so that the feature can follow the app's pattern for project implementation.

#### Opportunities
#### Game Gotcha's / Quirks
**!!!!** For 2 year gameplay the later emissions factor year is used (i.e. year 4 in 3/4). This leads to slightly different emissions calculations given the same inputs

Implemented projects are being added to a number of arrays to track state between years, including implementedProjectIds, implementedFinancedProjects, implementedRenewableProjects, and so on. This was done to stay within existing app patterns. We should refactor for a single source of truth where implemented project objects have knowledge of their own state.


#### TODO
- gameYearsImplemented - renewable projects cannot be unimplemented after first year so we shouldn't need this anymore



24 changes: 18 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ export class App extends React.PureComponent<unknown, AppState> {
console.log('Game Total Spending', newYearTrackedStats.gameTotalSpending);
console.log('======== END =================');

this.setState({
let nextState = {
completedProjects: newCompletedProjects,
completedYears: completedYears,
implementedProjectsIds: [],
Expand All @@ -579,18 +579,30 @@ export class App extends React.PureComponent<unknown, AppState> {
yearRangeInitialStats: newYearRangeInitialStats,
capitalFundingState: newCapitalFundingState,
yearlyCostSavings: yearlyCostSavings
});
};

if (newYearTrackedStats.carbonSavingsPercent >= 0.5) {
this.setPage(Pages.winScreen);
} else if (newYearTrackedStats.currentGameYear === this.state.gameSettings.totalGameYears + 1) {
this.setPage(Pages.loseScreen);
const isGameWon = newYearTrackedStats.carbonSavingsPercent >= 0.5;
const isEndOfGame = newYearTrackedStats.currentGameYear === this.state.gameSettings.totalGameYears + 1

if (isGameWon) {
this.endGame(Pages.winScreen, newYearTrackedStats, nextState);
} else if (isEndOfGame) {
this.endGame(Pages.loseScreen, newYearTrackedStats, nextState);
} else {
this.setState(nextState);
this.setPage(Pages.scope1Projects);
}

}

endGame(page: symbol, newYearTrackedStats: TrackedStats, nextState) {
// Game is over - don't advance year
newYearTrackedStats.currentGameYear -= 1;
nextState.trackedStats = newYearTrackedStats;
this.setState(nextState);
this.setPage(page);
}

setNewYearStats(newYearTrackedStats: TrackedStats, newBudget: number, currentYearStats: TrackedStats) {
newYearTrackedStats.yearBudget = newBudget;
console.log('Total new year budget: ', newBudget);
Expand Down
57 changes: 21 additions & 36 deletions src/components/EndGameReport/EndGameReportPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import InfoIcon from '@mui/icons-material/Info';
export default class EndGameReportPage extends React.Component<EndGameReportPageProps> {
render() {
const yearRangeInitialStats: TrackedStats[] = [...this.props.yearRangeInitialStats];
const mutableStats: TrackedStats = { ...this.props.yearRangeInitialStats[this.props.trackedStats.currentGameYear - 1] };
const year10Stats: TrackedStats = { ...this.props.trackedStats}
let completedRenewables = [...this.props.implementedRenewableProjects].map(renewable => {
return {
completedYear: mutableStats.currentGameYear - 1,
completedYear: year10Stats.currentGameYear - 1,
gameYearsImplemented: renewable.gameYearsImplemented,
yearStarted: renewable.yearStarted,
financingOption: renewable.financingOption,
Expand All @@ -37,7 +37,7 @@ export default class EndGameReportPage extends React.Component<EndGameReportPage
implementedFinancedProjects={this.props.implementedFinancedProjects}
renewableProjects={this.props.implementedRenewableProjects}
completedProjects={completedProjects}
mutableStats={mutableStats}
year10Stats={year10Stats}
defaultTrackedStats={this.props.defaultTrackedStats}
/>
</Box>
Expand All @@ -54,36 +54,36 @@ function EndGameReport(props: ReportProps) {
let isFinanced = implementationFinancing.financingType.id !== 'budget';
let financingData: ImplementedFinancingData = {
option: implementationFinancing,
isPaidOff: isFinanced ? isProjectFullyFunded(project, props.mutableStats) : false,
isPaidOff: isFinanced ? isProjectFullyFunded(project, props.year10Stats) : false,
isFinanced: isFinanced,

}
let projectNetCost = implementedProject.getYearEndTotalSpending(financingData.option, props.mutableStats.gameYearInterval);
let projectNetCost = implementedProject.getYearEndTotalSpending(financingData.option, props.year10Stats.gameYearInterval);
let totalProjectExtraCosts = implementedProject.getHiddenCost();

projectRecapCards.push(
getProjectCard(
implementedProject,
props.mutableStats,
props.year10Stats,
projectNetCost,
totalProjectExtraCosts,
financingData,
));

});

let projectedFinancedSpending = getProjectedFinancedSpending(props.implementedFinancedProjects, props.renewableProjects, props.mutableStats);
let gameCurrentAndProjectedSpending = props.mutableStats.gameTotalSpending + projectedFinancedSpending;
setCarbonEmissionsAndSavings(props.mutableStats, props.defaultTrackedStats);

setCostPerCarbonSavings(props.mutableStats, gameCurrentAndProjectedSpending);

// * sub year to get projections
props.year10Stats.currentGameYear - 1;
let projectedFinancedSpending = getProjectedFinancedSpending(props.implementedFinancedProjects, props.renewableProjects, props.year10Stats);
let gameCurrentAndProjectedSpending = props.year10Stats.gameTotalSpending + projectedFinancedSpending;
setCarbonEmissionsAndSavings(props.year10Stats, props.defaultTrackedStats);
setCostPerCarbonSavings(props.year10Stats, gameCurrentAndProjectedSpending);
let endOfGameResults = {
carbonSavingsPercent: props.mutableStats.carbonSavingsPercent,
gameTotalSpending: props.mutableStats.gameTotalSpending,
carbonSavingsPercent: props.year10Stats.carbonSavingsPercent,
gameTotalSpending: props.year10Stats.gameTotalSpending,
projectedFinancedSpending: projectedFinancedSpending,
gameCurrentAndProjectedSpending: gameCurrentAndProjectedSpending,
costPerCarbonSavings: props.mutableStats.costPerCarbonSavings
costPerCarbonSavings: props.year10Stats.costPerCarbonSavings
}
const noDecimalsFormatter = Intl.NumberFormat('en-US', {
minimumFractionDigits: 0,
Expand All @@ -92,28 +92,13 @@ function EndGameReport(props: ReportProps) {
const carbonSavingsPercentFormatted: string = (endOfGameResults.carbonSavingsPercent * 100).toFixed(2);
const gameTotalNetCostFormatted: string = noDecimalsFormatter.format(endOfGameResults.gameTotalSpending);
const projectedFinancedSpendingFormatted: string = noDecimalsFormatter.format(endOfGameResults.projectedFinancedSpending);
const gameCurrentAndProjectedSpendingFormatted: string = noDecimalsFormatter.format(endOfGameResults.gameCurrentAndProjectedSpending);
const costPerCarbonSavingsFormatted: string = endOfGameResults.costPerCarbonSavings !== undefined ? Intl.NumberFormat('en-US', {
minimumFractionDigits: 0,
maximumFractionDigits: 2,
}).format(endOfGameResults.costPerCarbonSavings) : '0';

console.log('props.mutableStats.currentGameYear '+ props.mutableStats.currentGameYear);
console.log('props.mutableStats.gameYearInterval '+ props.mutableStats.gameYearInterval);
console.log('props.mutableStats.gameYearDisplayOffset '+ props.mutableStats.gameYearDisplayOffset);


return (
<Fragment>
{props.mutableStats.gameYearInterval == 1 &&
<Typography variant='h3'>
Looking Forward - Year {props.mutableStats.currentGameYear}
</Typography>
}
{props.mutableStats.gameYearInterval == 2 &&
<Typography variant='h3'>
Looking Forward - Years {props.mutableStats.gameYearDisplayOffset} & {props.mutableStats.gameYearDisplayOffset + 1}
</Typography>
}
<ParentSize>
{(parent) => (
<EnergyUseLineChart
Expand Down Expand Up @@ -144,7 +129,7 @@ function EndGameReport(props: ReportProps) {
<ListItemText
primary={
<Typography variant={'h5'}>
You have spent{' '}<Emphasis>${gameTotalNetCostFormatted}</Emphasis>{' '} on GHG reduction measures.
You have spent{' '}<Emphasis>${gameTotalNetCostFormatted}</Emphasis>{' '} throughout the game.
</Typography>
}
/>
Expand All @@ -169,7 +154,7 @@ function EndGameReport(props: ReportProps) {
<ListItemText
primary={
<Typography variant={'h5'}>
After this budget period, you still have {' '}<Emphasis>${gameCurrentAndProjectedSpendingFormatted}</Emphasis>{' '} on financed and renewable projects in the coming years.
You are projected to spend {' '}<Emphasis>${projectedFinancedSpendingFormatted}</Emphasis>{' '} on financed and renewed projects in future years
</Typography>
}
/>
Expand Down Expand Up @@ -207,15 +192,15 @@ function EndGameReport(props: ReportProps) {
}

interface ReportProps extends ReportPDFProps {
mutableStats: TrackedStats,
year10Stats: TrackedStats,
defaultTrackedStats: TrackedStats,
implementedFinancedProjects: ImplementedProject[],
renewableProjects: RenewableProject[]
}


function getProjectCard(implementedProject: ProjectControl,
mutableStats: TrackedStats,
year10Stats: TrackedStats,
projectNetCost: number,
totalExtraCosts: number,
financingData: ImplementedFinancingData
Expand All @@ -237,7 +222,7 @@ function getProjectCard(implementedProject: ProjectControl,

let yearMultiplier = 1;
if (implementedProject.isRenewable) {
yearMultiplier = mutableStats.gameYearInterval;
yearMultiplier = year10Stats.gameYearInterval;
}
let initialCost = implementedProject.financedAnnualCost ? implementedProject.financedAnnualCost : implementedProject.baseCost;
initialCost *= yearMultiplier;
Expand Down
13 changes: 9 additions & 4 deletions src/components/EnergyUseLineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ import React from 'react';

export default function EnergyUseLineChart(props: EnergyUseLineChartProps) {
const data = [];
let xYears: number[] = Array.from([...props.yearRangeInitialStats], statYear => statYear.currentGameYear);
const yearlyStats = [...props.yearRangeInitialStats]
// remove end of game year
yearlyStats.pop()
let xYears: number[] = Array.from(yearlyStats, statYear => {
return statYear.currentGameYear;
});
let xTicks: string[] = Array.from(xYears, year => {
return 'Budget Period ' + String(year);
return 'Year ' + String(year * props.yearRangeInitialStats[0].gameYearInterval);
});

let energyTypeYearValues = {
electricity: [],
naturalGas: [],
landfillGases: [],
}
props.yearRangeInitialStats.forEach(statYear => {
yearlyStats.forEach(statYear => {
let electricityEmissions = statYear.electricityUseKWh * getElectricityEmissionsFactor(statYear.currentGameYear, statYear.gameYearInterval, statYear.gameYearDisplayOffset);
let natGasEmissions = statYear.naturalGasMMBTU * statYear.naturalGasEmissionsPerMMBTU;
let landfillGasEmissions = statYear.hydrogenMMBTU * statYear.hydrogenEmissionsPerMMBTU;
Expand Down Expand Up @@ -65,7 +70,7 @@ export default function EnergyUseLineChart(props: EnergyUseLineChartProps) {
const layout = {
width: props.parentElement.width,
title: {
text: `GHG Reductions through Budget Period ${xYears.length}`,
text: `${xYears.length * props.yearRangeInitialStats[0].gameYearInterval} Year GHG Reduction`,
font: {
family: 'Roboto',
size: 24
Expand Down
5 changes: 3 additions & 2 deletions src/trackedStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,15 @@ export const initialTrackedStats: TrackedStats = {
initialTrackedStats.carbonEmissions = calculateEmissions(initialTrackedStats);

export function getElectricityEmissionsFactor(currentGameYear: number, gameYearInterval: number, gameYearDisplayOffset: number): number {
let isEndOfGame = gameYearInterval > 1? currentGameYear > 5 : currentGameYear > 10;
let isEndOfGame = gameYearInterval > 1? gameYearDisplayOffset >= 10 : currentGameYear > 10;
let year = currentGameYear;
if (isEndOfGame) {
year = 10;
} else if (gameYearInterval > 1) {
year = gameYearDisplayOffset + 1;
}
return ElectricityEmissionsFactors[year];
let emissionsFactor = ElectricityEmissionsFactors[year];
return emissionsFactor;
}

export function calculateEmissions(stats: TrackedStats): number {
Expand Down

0 comments on commit ee2fbfa

Please sign in to comment.