import "./QuestProgress.css";
import classnames from "classnames";
import React, { useState } from "react";
import { GameState, Quest, ResourceType } from "../data/GameState";
import { UpdaterGeneratorType2 } from "../lib/util/updaterGenerator";
import { Grade, remapEfficiencyGradeToNumber } from "../game/EfficiencyCalculator";
type Props = {
spSpentThisQuest: number | undefined;
createQuestCb: () => void;
activeQuest: Quest | undefined;
playerResourceAmounts?: { [k in ResourceType]: number };
updaters: UpdaterGeneratorType2<GameState, GameState>["playerSave"];
efficiencyGrade: Grade;
score: GameState["playerSave"]["score"];
questInitialAmount: number;
};
type QuestScoreReward = {
total: number;
scoreComponents: ScoreComponent[];
};
type ScoreComponent = {
// inputAmount: number | string;
// inputTitle: string;
// outputScore: number;
// outputDescription: string;
scoreAmount: number;
scoreReason: string;
};
export default React.memo(QuestProgressComponent);
function calculateQuestScoreReward(grade: Grade): QuestScoreReward {
const scoreComponents = [
{
scoreReason: 'Quest completed',
scoreAmount: 50,
},
{
scoreReason: `Efficiency: "${grade}"`,
scoreAmount: remapEfficiencyGradeToNumber(grade) * 25,
}
];
const total = scoreComponents.reduce((pv, cv) => pv + cv.scoreAmount, 0);
return {
total,
scoreComponents,
};
}
function QuestProgressComponent({
activeQuest,
spSpentThisQuest,
createQuestCb,
playerResourceAmounts,
updaters,
efficiencyGrade,
// score,
questInitialAmount,
}: Props) {
/**
* activeQuest === undefined => no active quest, need to start quest
* isQuestComplete => can finish the quest to generate rewards
* rewards ready => can accept rewards to increment score; cannot generate a new quest
*/
const isQuestComplete =
activeQuest &&
(playerResourceAmounts?.[activeQuest.resourceType] || 0) >= activeQuest.resourceAmount;
const [didAcceptRewards, setDidAcceptRewards] = useState(true);
const [scoreReward, setScoreReward] = useState<QuestScoreReward | undefined>();
const handleStartQuest = () => {
createQuestCb();
};
const doFinishQuest = () => {
updaters.activeQuest.enqueueUpdate(() => {
return undefined;
});
setScoreReward(calculateQuestScoreReward(efficiencyGrade));
setDidAcceptRewards(false);
};
const doClaimRewards = () => {
if (scoreReward) {
updaters.score.enqueueUpdate((prev) => {
return prev + scoreReward.total;
});
setDidAcceptRewards(true);
}
};
return (
<>
{<Score doClaimRewards={doClaimRewards} scoreReward={scoreReward} didAcceptRewards={didAcceptRewards}/>}
{activeQuest === undefined ? (
<>
<h2>No active quest
</h2>
<br></br>
<button className="button" onClick={handleStartQuest} disabled={!didAcceptRewards}>
{didAcceptRewards ? 'Start a quest' : 'Claim rewards first!'}
</button>
<br></br>
<br></br>
<br></br>
</>
) : (
<>
<h2> Active quest: </h2>
<table className={classnames({ table: true })}>
<tr>
<td>
Initial
</td>
<td>
{questInitialAmount} {activeQuest.resourceType}
</td>
</tr>
<tr>
<td>
Current
</td>
<td>
{playerResourceAmounts?.[activeQuest.resourceType]} {activeQuest.resourceType}
</td>
</tr>
<tr>
<td>
Target
</td>
<td>
{activeQuest.resourceAmount} {activeQuest.resourceType}
</td>
</tr>
<tr>
<td>
SP spent
</td>
<td>
{spSpentThisQuest === undefined ? "" : spSpentThisQuest}
</td>
</tr>
<tr>
<td>
Efficiency
</td>
<td>
{efficiencyGrade}
</td>
</tr>
</table>
{isQuestComplete ? (
<>
<br></br>
<button className="button" onClick={doFinishQuest}>
Finish quest
</button>
</>
) : (
<></>
)}
</>
)}
</>
);
}
function Score({
scoreReward,
doClaimRewards,
didAcceptRewards,
}: {
scoreReward: QuestScoreReward | undefined;
doClaimRewards: () => void;
didAcceptRewards: boolean;
}) {
if (scoreReward === undefined) {
return (<> </>);
}
return (
<>
<h3>Quest Rewards</h3>
<div>+{scoreReward.total} to your score! </div>
<br></br>
<table className={classnames({ table: true })}>
{scoreReward.scoreComponents.map((it) => (
<tr>
<td> +{it.scoreAmount} score </td>
<td> {it.scoreReason} </td>
</tr>))
}
</table>
<br></br>
{(
didAcceptRewards ? (<> </>) :
(
<button
className="button"
onClick={() => doClaimRewards()}>
Claim rewards!
</button>
)
)}
</>
);
}
// function formatDelta(d: number): string {
// return d < 0 ? d.toString() : "+" + d.toString();
// }