import { EconomicSystem as EconomicSystemDoc, HelpSheet, LocalizedOption, PureMessageKey, UnassembledMessages } from '@gecogvidanto/shared'; import { FormBuilder, FormData } from '../tools'; import ServerGame from './ServerGame'; /** * Definition of an economic system. Many hooks will be called during the rounds. The next table describes * all the process. * * Legend: * - **S**: step number; * - **R**: round number; * - **C**: category; either **M** for hook modifiable function (modifications in the game made by the * plugin will be saved), **X** for executable only hook (game should not be modified), or empty for API * and/or server part. Executable only hooks must be pure functions, meaning they must return the same value * if executed in same conditions, as they may be called multiple time by the client or server especially if * client page is refreshed because of user language change or a player leaves the game, etc. * * | S | R | Description | C | API / Hook | * |----|---|--------------------------------------------------------------------|---|--------------------| * | 0 | - | Create set, initialize characters | | gameSetAdd | * | 1 | 0 | Request for initial data | | gameFormCreate | * | 2 | 0 | Create initial form, if any | X | getForm | * | 3 | 0 | Send form result and terminate the round | | gameFormSend | * | 4 | 0 | Initialize game, if needed | M | execForm | * | 5 | 0 | Last hook before set start, may add NPCs | M | terminateRound | * | 6 | 1 | Request game options | | gameOptionsCreate | * | 6 | 1 | Request help sheet (may not be called) | | gameHelpSheetMoney | * | 7 | 1 | Create plugin options | X | getOptions | * | 7 | 1 | Create help sheet for money (may not be called) | X | getMoneyHelpSheet | * | 8 | 1 | Request for form between round 0 and 1 | | gameFormCreate | * | 9 | 1 | Create form between rounds, if needed | X | getForm | * | 10 | 1 | Send form result and terminate the round | | gameFormSend | * | 11 | 1 | Update data, if needed | M | execForm | * | 12 | 1 | Calculate characters total score | | | * | 13 | 1 | Terminate first round | M | terminateRound | * * Steps 6 to 13 are repeated for each round until end of set, i.e. Up to round number * {@link Game#roundsPerSet} included. * * Hooks which are not defined here to be called at round 0 **must not be called at round 0**. Plugins may * throw exception if this is not respected. * * Note that if the total score needs to be modified, the {@link #valueCost} factor must be taken into * account, as the total score manipulated by plugins is expressed in low money count, whereas the user * visible one is in low value count. */ export default abstract class EconomicSystem implements EconomicSystemDoc { readonly id: string; readonly name: PureMessageKey; readonly valueCost: number; /** * Create the economic system. * * @param id - The (internal) identifier of the economic system. * @param name - The visible name of the economic system. * @param valueCost - The cost of a value in low money. */ constructor(id: string, name: PureMessageKey, valueCost?: number); /** * This identity function is required to check the type of built unassembled message (normal type check is * disabled because the expected result is of type any). * * @param p - The unassembled message to type check. * @returns The input parameter. */ protected unassembledMessage(p: UnassembledMessages[K]): UnassembledMessages[K]; /** * This identity function is required to check the type of built localized option (normal type check is * disabled because the expected result is of type any). * * @param p - The localized option to type check. * @returns The input parameter. */ protected localizedOption(p: LocalizedOption): LocalizedOption; /** * Get the name of the non playing character. * * **Note**: This method may be called by any client at any time, even with finished game or for non * current set. * * @param id - The identifier of non player character, always negative. * @param gameId - Identifier The game for which to get the NPC name. * @param setId - Identifier of the set for which to get the NPC name. */ abstract getNonPlayerCharacterName(id: number, gameId: string, setId: number): Promise[keyof T]>; /** * Get the help sheet for money. This method **must not** modify the game or the internal state of the * plugin. * * @param game - The current game. */ abstract getMoneyHelpSheet(game: Readonly): Promise; /** * Options callable during the round. This method **must not** modify the game or the internal state of * the plugin. * * @param game - The current game. */ abstract getOptions(game: Readonly): Promise>>; /** * Get the form to display to game master at round end (for this round or next one) or option call. There * may be no field to add to builder. This method **must not** modify the game or the internal state of * the plugin. * * @param builder - The form builder to be completed (already contains server parts of form). Note that * the parameter given to builder type, which is the type of the parameter object given to the update * method, is defined by the plugin, as the server does not set an update function. * @param game - The current game. * @param optionId - The identifier of the called option or undefined for round end call. * * @returns The builder, eventually completed, or even modified. */ abstract getForm(builder: FormBuilder, game: Readonly, optionId: string | undefined): Promise>; /** * Execute actions associated to the given form. Modifications made to the game by this method * **will be saved**. * * @param data - The data filled in the form. * @param game - The current game. * @param optionId - The identifier of the called option or undefined for round end call. * * @returns The data, eventually modified. */ abstract execForm(data: FormData, game: ServerGame, optionId: string | undefined): Promise; /** * Execute actions to terminate the round. Modifications made to the game by this method * **will be saved**. * * @param game - The current game. */ abstract terminateRound(game: ServerGame): Promise; }