Skip to content

Commit

Permalink
Merge pull request #39 from microsoft/won
Browse files Browse the repository at this point in the history
Post-game prompt and result screen content
  • Loading branch information
WonSong committed Sep 18, 2024
2 parents 1390fc7 + 67d38ab commit 2484868
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 31 deletions.
3 changes: 3 additions & 0 deletions Client/src/context/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export function AppContextProvider(
props: React.PropsWithChildren<{}>,
): React.ReactElement {
const [userName, setUserName] = React.useState<string>("");
const [finalMessage, setFinalMessage] = React.useState<string>("");
const [numberOfRounds, setNumberOfRounds] = React.useState<number>(5);
const [gameRounds, setGameRounds] = React.useState<GameRound[]>([]);
const [selectedRound, setSelectedRound] = React.useState<number>(0);
Expand Down Expand Up @@ -53,6 +54,8 @@ export function AppContextProvider(
return (
<AppContext.Provider
value={{
finalMessage,
setFinalMessage,
userName,
setUserName,
gameId,
Expand Down
52 changes: 39 additions & 13 deletions Client/src/hooks/useCareerGame.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from "react";
import { AppContext } from "../context/AppContext";
import { GameResponse } from "../models/GameResponse";
import { GameResponse, GameResultResponse } from "../models/GameResponse";
import { IAppContext } from "../models/IAppContext";
import { Http } from "../services/Http";

export function useCareerGame() {
const { addRound, setGameId } = React.useContext<IAppContext>(AppContext);
const { addRound, setGameId, setFinalMessage } =
React.useContext<IAppContext>(AppContext);
const [isLoading, setLoading] = React.useState<boolean>(false);

const startGame = async (career: string): Promise<void> => {
Expand All @@ -22,28 +23,31 @@ export function useCareerGame() {
if (response.data.round?.options?.length === 0)
throw new Error("InvalidCareerChoice");

setGameId(response.data.conversationId)
setGameId(response.data.conversationId);
addRound({
...response.data.round,
optionSelected: null,
});
}
} catch (error: any) {
throw new Error("FailedToStartGame")
throw new Error("FailedToStartGame");
} finally {
setLoading(false);
}
};

const continueGame = async (gameId: string, userResponse: string): Promise<void> => {
const continueGame = async (
gameId: string,
userResponse: string,
): Promise<void> => {
try {
setLoading(true);
const response = await Http.getInstance().post<GameResponse>(
"/api/career-game/continue",
{
conversationId: gameId,
response: userResponse,
},
"/api/career-game/continue",
{
conversationId: gameId,
response: userResponse,
},
);

if (response.ok && response.data) {
Expand All @@ -53,18 +57,40 @@ export function useCareerGame() {
});
}
} catch (error: any) {
console.log(error)
console.log(error);
} finally {
setLoading(false);
}
};

const completeGame = async (response: string): Promise<void> => {};
const completeGame = async (
gameId: string,
userResponse: string,
): Promise<void> => {
try {
setLoading(true);
const response = await Http.getInstance().post<GameResultResponse>(
"/api/career-game/complete",
{
conversationId: gameId,
response: userResponse,
},
);

if (response.ok && response.data) {
setFinalMessage(response.data.round.outcome);
}
} catch (error: any) {
console.log(error);
} finally {
setLoading(false);
}
};

return {
startGame,
continueGame,
completeGame,
isLoading,
}
};
}
1 change: 1 addition & 0 deletions Client/src/hooks/usePrompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export function usePrompts(): [
const [prompts, setPrompts] = React.useState<GamePrompts>({
preGamePrompt: null,
userResponsePrompt: null,
postGamePrompt: null,
});

const loadGamePrompts = () => {
Expand Down
1 change: 1 addition & 0 deletions Client/src/models/GamePrompts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type GamePrompts = {
preGamePrompt: string | null;
userResponsePrompt: string | null;
postGamePrompt: string | null;
};
7 changes: 7 additions & 0 deletions Client/src/models/GameResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ export type GameResponse = {
conversationId: string;
round: GameRound;
};

export type GameResultResponse = {
conversationId: string;
round: {
outcome: string;
}
}
3 changes: 3 additions & 0 deletions Client/src/models/IAppContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ export interface IAppContext {
userName: string;
setUserName: React.Dispatch<React.SetStateAction<string>>;

finalMessage: string;
setFinalMessage: React.Dispatch<React.SetStateAction<string>>;

gameId: string | null;

setGameId(gameId: string | null): void;
Expand Down
8 changes: 8 additions & 0 deletions Client/src/screens/AdminScreen/AdminScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ export function AdminScreen(): React.ReactElement {
value={prompt.userResponsePrompt || ""}
/>

<TextField
label="Post game prompt"
multiline
name="postGamePrompt"
onChange={handlePromptUpdated}
value={prompt.postGamePrompt || ""}
/>

<ButtonBar>
<PrimaryButton
title="Save prompts"
Expand Down
8 changes: 4 additions & 4 deletions Client/src/screens/GameScreen/GameScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function GameScreen(): React.ReactElement {
usePageTracking("GameScreen");

const navigate = useNavigate();
const { continueGame, isLoading } = useCareerGame();
const { continueGame, completeGame, isLoading } = useCareerGame();
const {
rounds,
selectRound,
Expand All @@ -46,7 +46,7 @@ export function GameScreen(): React.ReactElement {
const cleanedOption = cleanOption(option);

if (optionIndex !== -1) {
await completeRound(selectedRound, optionIndex);
completeRound(selectedRound, optionIndex);
await continueGame(gameId!, cleanedOption);
if (selectedRound < numberOfRounds - 1) {
selectRound(selectedRound + 1);
Expand All @@ -69,8 +69,8 @@ export function GameScreen(): React.ReactElement {
const handleCompleteGameButtonClicked = async () => {
const firstOption = round.options[0];
const cleanedOption = cleanOption(firstOption);
await completeRound(selectedRound, 0);
await continueGame(gameId!, cleanedOption);
completeRound(selectedRound, 0);
await completeGame(gameId!, cleanedOption);
navigate("/career-game/results");
};

Expand Down
9 changes: 7 additions & 2 deletions Client/src/screens/ResultScreen/ResultScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import React from "react";
import { H1 } from "../../components/Typography";
import { AppContext } from "../../context/AppContext";
import { usePageTracking } from "../../hooks/usePageTracking";
import { IAppContext } from "../../models/IAppContext";

export function ResultScreen(): React.ReactElement {
usePageTracking("ResultScreen");
const { finalMessage, userName } = React.useContext<IAppContext>(AppContext);

return (
<div>
<h1>Result Screen</h1>
<p>This is the result screen</p>
<H1>Great work, {userName}!</H1>

{finalMessage}
</div>
);
}
1 change: 1 addition & 0 deletions Server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def build_game(app, telemetry):
game_prompts = {
"preGamePrompt": app.config["preGamePrompt"],
"userResponsePrompt": app.config["userResponsePrompt"],
"postGamePrompt": app.config["postGamePrompt"],
}

return CareerGame(game_prompts=game_prompts, message_history=message_history, open_ai=open_ai, telemetry=telemetry, logger=app.logger)
Expand Down
35 changes: 27 additions & 8 deletions Server/configs/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ def start_career_game():
}), 400

try:
resposne = career_game.start_game(career_choice)
response = career_game.start_game(career_choice)

return jsonify(resposne), 200
return jsonify(response), 200
except Exception as e:
return jsonify({
"error": "GameError",
Expand Down Expand Up @@ -98,10 +98,25 @@ def continue_career_game():

@app.route('/api/career-game/complete', methods=['POST'])
def complete_career_game():
return jsonify({
"error": "GameError",
"message": "Game could not be completed"
}), 500
request_body = request.json
conversation_id = request_body.get('conversationId', "")
user_response = request_body.get('response', "")
if conversation_id == "" or user_response == "":
return jsonify({
"error": "BadRequest",
"message": "conversationId and response are required"
}), 400

try:
response = career_game.complete_game(
conversation_id, user_response)

return jsonify(response), 200
except Exception as e:
return jsonify({
"error": "GameError",
"message": "Game could not be completed"
}), 500

@app.route('/api/career-game/admin/prompts', methods=['GET'])
def get_career_game_prompts():
Expand All @@ -112,21 +127,25 @@ def update_career_game_prompts():
request_body = request.json
preGamePrompt = request_body.get('preGamePrompt', "")
userResponsePrompt = request_body.get('userResponsePrompt', "")
postGamePrompt = request_body.get('postGamePrompt', "")

if preGamePrompt == "" or userResponsePrompt == "":
if preGamePrompt == "" or userResponsePrompt == "" or postGamePrompt == "":
return jsonify({
"error": "BadRequest",
"message": "preGamePrompt and userResponsePrompt are required"
"message": "All prompts are required"
}), 400

try:
Config.update_configs(app, "preGamePrompt", preGamePrompt)
Config.update_configs(
app, "userResponsePrompt", userResponsePrompt)
Config.update_configs(
app, "postGamePrompt", postGamePrompt)

game_prompts = {
"preGamePrompt": app.config["preGamePrompt"],
"userResponsePrompt": app.config["userResponsePrompt"],
"postGamePrompt": app.config["postGamePrompt"],
}
career_game.update_prompts(game_prompts)
except:
Expand Down
9 changes: 5 additions & 4 deletions Server/modules/career_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,18 @@ def start_game(self, career_choice):
return self.__process_game__(conversation_id)

def continue_game(self, conversation_id, user_choice):
print(conversation_id, user_choice)

# self.logger.debug(
# "Continuing game with user choice: {}".format(user_choice))
self.message_history.append_user_message(
conversation_id, self.game_prompts["userResponsePrompt"].format(user_choice))

return self.__process_game__(conversation_id)

def end_game(self, conversation_id):
raise NotImplementedError
def complete_game(self, conversation_id, user_choice):
self.message_history.append_user_message(
conversation_id, self.game_prompts["postGamePrompt"].format(user_choice))

return self.__process_game__(conversation_id)

def __process_game__(self, conversation_id):
messages = self.message_history.get_messages(conversation_id)
Expand Down

0 comments on commit 2484868

Please sign in to comment.