Compare commits

..

4 Commits

Author SHA1 Message Date
j 5b97b4b219 invoking comment added to gamestate initalizer 2024-03-31 23:25:11 -04:00
j 94cb64f37a status update logic added 2024-03-31 23:24:38 -04:00
j 78c36d1b77 addtl enum value 2024-03-31 23:23:58 -04:00
j b0e7d1051c cleanup 2024-03-31 23:23:43 -04:00
4 changed files with 79 additions and 26 deletions

View File

@ -1,5 +1,6 @@
import GameState, { PHASE_ENUM } from './gameState'; import GameState, { PHASE_ENUM } from './gameState';
import { MessageService, MessageFileName } from '../utils/MessageService' import { MessageService, MessageFileName } from '../utils/MessageService'
import { CommentPoster } from '../rdrama/services/CommentPoster';
class GameFlow { class GameFlow {
gameState: GameState; gameState: GameState;
@ -52,7 +53,56 @@ class GameFlow {
} }
} }
private async handleSetupPhase(userInput?: string): Promise<string> { formatDate(date: Date): string {
return date.toLocaleDateString("en-US", {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
}).toUpperCase();
}
async statusUpdate(message: string): Promise<void> {
const placeholders: { [key: string]: string } = {
playerName: this.gameState.authorName,
message: message,
date: this.gameState.currentDate,
money: this.gameState.cashLeftAfterInitialPurchases.toString(),
totalMileage: this.gameState.totalMileageWholeTrip.toString(),
oxen: this.describeOxenQuality(),
food: this.gameState.amountSpentOnFood.toString(),
ammo: this.gameState.amountSpentOnAmmunition.toString(),
clothing: this.gameState.amountSpentOnClothing.toString(),
supplies: this.gameState.amountSpentOnMiscellaneousSupplies.toString(),
};
const parsedMessage = `${MessageService.getRandomMessage(MessageFileName.Oregon_Template, placeholders)}`
await CommentPoster.postComment(`c_${this.gameState.comment.id}`, parsedMessage)
}
describeOxenQuality(): string {
const spent = this.gameState.amountSpentOnAnimals;
const qualityLevels = [
{ max: 220, description: 'Basic Quality' },
{ max: 240, description: 'Moderate Quality' },
{ max: 260, description: 'Good Quality' },
{ max: 280, description: 'High Quality' },
{ max: 300, description: 'Exceptional Quality' }
];
for (const level of qualityLevels) {
if (spent <= level.max) {
return level.description;
}
}
// Default to the lowest quality if for some reason the amount doesn't fit the expected range
return 'Unknown Quality';
}
private async handleSetupPhase(userInput?: string): Promise<void> {
let responseMessage = ""; let responseMessage = "";
// Logic to handle initial setup // Logic to handle initial setup
switch (this.gameState.subPhase) { switch (this.gameState.subPhase) {
@ -71,7 +121,6 @@ class GameFlow {
if (purchaseResult.success) { if (purchaseResult.success) {
// If the purchase was successful, advance to the next subphase and recursively call handleSetupPhase without userInput to get the next set of instructions // If the purchase was successful, advance to the next subphase and recursively call handleSetupPhase without userInput to get the next set of instructions
this.gameState.subPhase++; this.gameState.subPhase++;
//TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player
return this.handleSetupPhase(); return this.handleSetupPhase();
} else { } else {
// If there was an error, include the error message in responseMessage // If there was an error, include the error message in responseMessage
@ -91,7 +140,6 @@ class GameFlow {
const purchaseResult = this.handleGenericPurchase(PurchaseOption.OXEN, userInput, 200, 300); const purchaseResult = this.handleGenericPurchase(PurchaseOption.OXEN, userInput, 200, 300);
if (purchaseResult.success) { if (purchaseResult.success) {
this.gameState.subPhase++; this.gameState.subPhase++;
//TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player
return this.handleSetupPhase(); // Call setup phase again for next subphase return this.handleSetupPhase(); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
@ -109,7 +157,6 @@ class GameFlow {
const purchaseResult = this.handleGenericPurchase(PurchaseOption.FOOD, userInput); const purchaseResult = this.handleGenericPurchase(PurchaseOption.FOOD, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
this.gameState.subPhase++; this.gameState.subPhase++;
//TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player
return this.handleSetupPhase(); // Call setup phase again for next subphase return this.handleSetupPhase(); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
@ -127,7 +174,6 @@ class GameFlow {
const purchaseResult = this.handleGenericPurchase(PurchaseOption.AMMO, userInput); const purchaseResult = this.handleGenericPurchase(PurchaseOption.AMMO, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
this.gameState.subPhase++; this.gameState.subPhase++;
//TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player
return this.handleSetupPhase(); // Call setup phase again for next subphase return this.handleSetupPhase(); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
@ -145,7 +191,6 @@ class GameFlow {
const purchaseResult = this.handleGenericPurchase(PurchaseOption.CLOTHING, userInput); const purchaseResult = this.handleGenericPurchase(PurchaseOption.CLOTHING, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
this.gameState.subPhase++; this.gameState.subPhase++;
//TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player
return this.handleSetupPhase(); // Call setup phase again for next subphase return this.handleSetupPhase(); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
@ -163,7 +208,6 @@ class GameFlow {
const purchaseResult = this.handleGenericPurchase(PurchaseOption.MISC, userInput); const purchaseResult = this.handleGenericPurchase(PurchaseOption.MISC, userInput);
if (purchaseResult.success) { if (purchaseResult.success) {
this.gameState.subPhase++; this.gameState.subPhase++;
//TODO next we will need to add a wrapper methood that will dump the game object and the message back to the player
return this.handleSetupPhase(); // Call setup phase again for next subphase return this.handleSetupPhase(); // Call setup phase again for next subphase
} else { } else {
responseMessage = purchaseResult.errorMessage || ''; responseMessage = purchaseResult.errorMessage || '';
@ -174,7 +218,9 @@ class GameFlow {
//Advance Phase //Advance Phase
break; break;
} }
return responseMessage;
await this.statusUpdate(responseMessage)
return;
} }
handleWeaponPurchase(userInput: string): { success: boolean; errorMessage?: string } { handleWeaponPurchase(userInput: string): { success: boolean; errorMessage?: string } {

View File

@ -1,4 +1,5 @@
import { DatabaseService } from "../db/services/Database"; import { DatabaseService } from "../db/services/Database";
import { Comment } from "../rdrama/models/Comment";
/** /**
* Represents the state of a game session for an Oregon Trail-style game. * Represents the state of a game session for an Oregon Trail-style game.
@ -6,7 +7,9 @@ import { DatabaseService } from "../db/services/Database";
* to load from and save to a database. * to load from and save to a database.
*/ */
class GameState { class GameState {
authorId: number = 0; comment: Comment;
authorId: number;
authorName: string;
amountSpentOnAnimals: number = 0; amountSpentOnAnimals: number = 0;
amountSpentOnAmmunition: number = 0; amountSpentOnAmmunition: number = 0;
actualResponseTimeForBang: number = 0; actualResponseTimeForBang: number = 0;
@ -16,7 +19,7 @@ class GameState {
yesNoResponseToQuestions: string = ''; yesNoResponseToQuestions: string = '';
eventCounter: number = 0; eventCounter: number = 0;
turnNumberForSettingDate: number = 0; turnNumberForSettingDate: number = 0;
currentDate: string = ''; currentDate: string = 'MONDAY MARCH 29 1847';
shootingExpertiseLevelChoice: number = 0; shootingExpertiseLevelChoice: number = 0;
eatingChoice: number = 0; eatingChoice: number = 0;
amountSpentOnFood: number = 0; amountSpentOnFood: number = 0;
@ -43,8 +46,10 @@ class GameState {
phase: PHASE_ENUM = PHASE_ENUM.SETUP; phase: PHASE_ENUM = PHASE_ENUM.SETUP;
subPhase: number = 0; subPhase: number = 0;
private constructor(authorId: number, state?: Partial<GameState>) { private constructor(comment: Comment, state?: Partial<GameState>) {
this.authorId = authorId; this.comment = comment
this.authorId = comment.author_id;
this.authorName = comment.author_name;
Object.assign(this, state); // Initialize with loaded state or undefined Object.assign(this, state); // Initialize with loaded state or undefined
} }
@ -57,20 +62,21 @@ class GameState {
/** /**
* Loads an existing game state from the database or creates a new one if it doesn't exist. * Loads an existing game state from the database or creates a new one if it doesn't exist.
* @param {number} authorId - The ID of the author/player. * @param {Comment} comment - The invoking comment of the author/player.
* @returns {Promise<GameState>} - The loaded or newly created game state. * @returns {Promise<GameState>} - The loaded or newly created game state.
*/ */
public static async load(authorId: number): Promise<GameState> { public static async load(comment: Comment): Promise<GameState> {
const loadedState = await DatabaseService.loadGameState(authorId); const loadedState = await DatabaseService.loadGameState(comment.author_id);
if (loadedState) { if (loadedState) {
return new GameState(authorId, loadedState); return new GameState(comment, loadedState);
} else { } else {
// Create a new GameState with default values // Create a new GameState with default values
const newState = new GameState(authorId); const newState = new GameState(comment);
await newState.save(); // Optionally save the new state to the database await newState.save(); // Optionally save the new state to the database
return newState; return newState;
} }
} }
} }
export default GameState export default GameState

View File

@ -9,22 +9,22 @@
<details> <details>
<summary>πŸ›’ Current Supplies</summary> <summary>πŸ›’ Current Supplies</summary>
- **Oxen:** {oxen} teams (Essential for travel speed) - **Oxen:** {oxen} (Essential for travel speed; higher quality means faster travel)
- **Food:** {food} lbs (Vital for health) - **Food:** {food} lbs (Vital for sustaining health and energy)
- **Ammunition:** {ammo} boxes (Needed for hunting) - **Ammunition:** {ammo} bullets (Critical for hunting and defense against threats)
- **Clothing:** {clothing} set(s) (Important for health in bad weather) - **Clothing Supplies:** {clothing} (Important for protection against the elements)
- **Misc. Supplies:** {supplies} items (Useful for various challenges along the way) - **Misc. Supplies:** {supplies} lbs (Useful for various challenges along the way)
</details> </details>
<details> <details>
<summary>✨ Actions Available</summary> <summary>✨ Actions Available</summary>
- **Start Over:** Begin a new game. - **Restart:** Begin a new game.
- **Status:** Get the current game state. - **Status:** Get the current game state.
- **Help:** Show game instructions and tips. - **Help:** Show game instructions and tips.
- **Buy Supplies:** Make purchases at the current location (Available at forts). - **Fort:** Make purchases at the current location (Available at forts).
- **Continue on Trail:** Move forward with your journey. - **Continue:** Move forward with your journey.
- **Hunt:** Spend a day hunting for food. - **Hunt:** Spend a day hunting for food.
- **Rest:** Rest for a day to improve health. - **Rest:** Rest for a day to improve health.
@ -33,7 +33,7 @@
### πŸ”„ To Make a Choice ### πŸ”„ To Make a Choice
Please reply with **!!Oregon** followed by one of the actions above. For example: Please reply with **!!Oregon** followed by one of the actions above. For example:
``` ```
!!Oregon Buy Supplies !!Oregon Fort
``` ```
Remember, wise choices and preparation are key to a successful journey on the Oregon Trail. Good luck, traveler! πŸš—πŸ’¨ Remember, wise choices and preparation are key to a successful journey on the Oregon Trail. Good luck, traveler! πŸš—πŸ’¨

View File

@ -9,6 +9,7 @@ export enum MessageFileName {
Oregon_AmmoPurchase = 'oregon_AmmoPurchase.txt', Oregon_AmmoPurchase = 'oregon_AmmoPurchase.txt',
Oregon_ClothingPurchase = 'oregon_ClothingPurchase.txt', Oregon_ClothingPurchase = 'oregon_ClothingPurchase.txt',
Oregon_MiscSuppliesPurchase = 'oregon_MiscSuppliesPurchase.txt', Oregon_MiscSuppliesPurchase = 'oregon_MiscSuppliesPurchase.txt',
Oregon_Template = 'oregon_Template.txt',
} }
export class MessageService { export class MessageService {