Skip to content

Commit

Permalink
Add ability to pause facilities; closes #116
Browse files Browse the repository at this point in the history
  • Loading branch information
toddmedema committed Apr 30, 2024
1 parent 525a90f commit 3043aa9
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/Types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export interface GeneratorOperatingType
currentW: number;
yearsToBuildLeft: number;
minuteCreated: number; // That the user clicked buy, not construction complete
paused: boolean;
}

export interface StorageOperatingType extends StorageShoppingType, LoanInfo {
Expand Down
41 changes: 36 additions & 5 deletions src/components/views/Facilities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
Toolbar,
Typography,
} from "@mui/material";
import PauseIcon from "@mui/icons-material/Pause";
import PlayIcon from "@mui/icons-material/PlayArrow";
import CancelIcon from "@mui/icons-material/Cancel";
import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
import DragIndicatorIcon from "@mui/icons-material/DragIndicator";
Expand All @@ -35,6 +37,7 @@ interface FacilityListItemProps {
facility: FacilityOperatingType;
spotInList: number;
listLength: number;
onTogglePause: DispatchProps["onTogglePause"];
onSell: DispatchProps["onSell"];
onReprioritize: DispatchProps["onReprioritize"];
}
Expand All @@ -52,7 +55,7 @@ function FacilityListItem(props: FacilityListItemProps): JSX.Element {
setOpen(!open);
};

const { facility } = props;
const { facility, onTogglePause } = props;
const underConstruction = facility.yearsToBuildLeft > 0;
let secondaryText = "";
if (underConstruction) {
Expand Down Expand Up @@ -131,8 +134,6 @@ function FacilityListItem(props: FacilityListItemProps): JSX.Element {
? ` and the rest will go towards paying off the remaining loan balance of ${formatMoneyConcise(facility.loanAmountLeft)}`
: ""}
.
{!underConstruction &&
` You will be selling your facility to a competitor.`}
</DialogContentText>
</DialogContent>
<DialogActions>
Expand All @@ -153,6 +154,28 @@ function FacilityListItem(props: FacilityListItemProps): JSX.Element {
</DialogActions>
</Dialog>
<ListItemSecondaryAction>
{!underConstruction &&
props.listLength > 1 &&
!facility.paused && (
<IconButton
onClick={() => onTogglePause(facility.id)}
edge="end"
color="primary"
size="large"
>
<PauseIcon />
</IconButton>
)}
{facility.paused && (
<IconButton
onClick={() => onTogglePause(facility.id)}
edge="end"
color="primary"
size="large"
>
<PlayIcon />
</IconButton>
)}
{!underConstruction && props.listLength > 1 && (
<IconButton
onClick={toggleDialog}
Expand Down Expand Up @@ -188,6 +211,7 @@ export interface StateProps {
export interface DispatchProps {
onGeneratorBuild: () => void;
onSell: (id: FacilityOperatingType["id"]) => void;
onTogglePause: (id: FacilityOperatingType["id"]) => void;
onReprioritize: (spotInList: number, delta: number) => void;
onStorageBuild: () => void;
}
Expand Down Expand Up @@ -223,8 +247,14 @@ export default class Facilities extends React.Component<Props, {}> {
}

public render() {
const { game, onGeneratorBuild, onSell, onReprioritize, onStorageBuild } =
this.props;
const {
game,
onGeneratorBuild,
onSell,
onTogglePause,
onReprioritize,
onStorageBuild,
} = this.props;
const facilitiesCount = game.facilities.length;

return (
Expand Down Expand Up @@ -270,6 +300,7 @@ export default class Facilities extends React.Component<Props, {}> {
facility={g}
key={g.id}
onSell={onSell}
onTogglePause={onTogglePause}
onReprioritize={onReprioritize}
spotInList={i}
listLength={facilitiesCount}
Expand Down
11 changes: 9 additions & 2 deletions src/components/views/FacilitiesContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import Redux from "redux";
import { connect } from "react-redux";
import { navigate } from "../../reducers/Card";
import { sellFacility, reprioritizeFacility } from "../../reducers/Game";
import {
sellFacility,
togglePauseFacility,
reprioritizeFacility,
} from "../../reducers/Game";
import { AppStateType } from "../../Types";
import Facilities, { DispatchProps, StateProps } from "./Facilities";

Expand All @@ -19,6 +23,9 @@ const mapDispatchToProps = (dispatch: Redux.Dispatch<any>): DispatchProps => {
onSell: (id) => {
dispatch(sellFacility(id));
},
onTogglePause: (id) => {
dispatch(togglePauseFacility(id));
},
onReprioritize: (spotInList: number, delta: number) => {
dispatch(reprioritizeFacility({ spotInList, delta }));
},
Expand All @@ -30,7 +37,7 @@ const mapDispatchToProps = (dispatch: Redux.Dispatch<any>): DispatchProps => {

const FacilitiesContainer = connect(
mapStateToProps,
mapDispatchToProps,
mapDispatchToProps
)(Facilities);

export default FacilitiesContainer;
22 changes: 17 additions & 5 deletions src/data/Scenarios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,18 @@ export const SCENARIOS = [
content: (
<Typography variant="body1">
This chart shows forecasted supply and demand over the next year -
including any upcoming blackouts.
including any upcoming blackouts. Try pausing a generator to see how
it affects your ability to meet demand.
</Typography>
),
},
{
target: "#chartForecastSupplyByFuel",
content: (
<Typography variant="body1">
This chart shows what fuels are supplying your electricity. Try
dragging to re-order your facilities to see how it affects your fuel
consumption.
</Typography>
),
},
Expand All @@ -436,8 +447,9 @@ export const SCENARIOS = [
target: "#chartForecastWeather",
content: (
<Typography variant="body1">
This chart shows forecasted weather, which contributes to demand -
and the output of renewable generators.
This chart shows forecasted weather, which affects demand (such as
heating and air conditioning) - and the output of solar and wind
generators.
</Typography>
),
},
Expand All @@ -450,8 +462,8 @@ export const SCENARIOS = [
menu.
<br />
<br />
This tutorial will run for 1 year - see how the forecasts change
over time.
This tutorial will run for 1 year so that you can see how the
forecasts change over time.
</Typography>
),
},
Expand Down
25 changes: 24 additions & 1 deletion src/reducers/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,16 @@ export const gameSlice = createSlice({
);
state.timeline = reforecastSupply(state);
},
togglePauseFacility: (state, action: PayloadAction<number>) => {
state.facilities.forEach(
(g: GeneratorOperatingType | StorageOperatingType) => {
if (g.id === action.payload) {
g.paused = !g.paused;
}
}
);
state.timeline = reforecastSupply(state);
},
reprioritizeFacility: (
state,
action: PayloadAction<ReprioritizeFacilityAction>
Expand Down Expand Up @@ -269,6 +279,7 @@ export const {
quit,
buildFacility,
sellFacility,
togglePauseFacility,
reprioritizeFacility,
loaded,
setSpeed,
Expand Down Expand Up @@ -621,6 +632,13 @@ function updateSupplyFacilitiesFinances(
let charge = 0;
let storedWh = 0;
facilities.forEach((g: FacilityOperatingType, i: number) => {
if (g.paused) {
g.currentW = Math.max(
0,
g.currentW - (g.peakW * TICK_MINUTES) / g.spinMinutes
); // ramp down
return;
}
if (g.yearsToBuildLeft === 0) {
if (g.fuel) {
// Capable of generating electricity
Expand Down Expand Up @@ -715,7 +733,12 @@ function updateSupplyFacilitiesFinances(
let principalRepayment = 0;
facilities.forEach((g: FacilityShoppingType) => {
if (g.yearsToBuildLeft === 0) {
expensesOM += g.annualOperatingCost / TICKS_PER_YEAR;
if (g.paused) {
// paused facilities only pay half of their operating costs
expensesOM += g.annualOperatingCost / TICKS_PER_YEAR / 2;
} else {
expensesOM += g.annualOperatingCost / TICKS_PER_YEAR;
}
if (g.fuel && FUELS[g.fuel]) {
const fuelBtu =
((g.currentW * (g.btuPerWh || 0)) / TICKS_PER_HOUR) *
Expand Down

0 comments on commit 3043aa9

Please sign in to comment.