-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Simplify player action payload providers
- Loading branch information
Konrad Jamrozik
committed
Jul 12, 2024
1 parent
a7c2607
commit ceb2746
Showing
3 changed files
with
98 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,100 @@ | ||
// The a bit more advanced typing done in this file was figured out with the help of ChatGPT: | ||
// https://chat.openai.com/share/af4ac2cb-c221-4c7f-a5c6-e3cac23916c0 | ||
import _ from 'lodash' | ||
import type { PlayerActionNameInTurn } from '../codesync/PlayerActionName' | ||
import type { PlayerActionPayload } from '../codesync/PlayerActionPayload' | ||
|
||
export const playerActionsPayloadsProviders: { | ||
[actionName in PlayerActionNameInTurn]: PayloadProviderMap[actionName] | ||
} = { | ||
// CODESYNC: this must match the definition of PayloadProviderMap. | ||
const actionNameToPayloadProviderFactoryMap: { | ||
[actionName in PlayerActionNameInTurn]: PayloadProviderFactory | ||
} = | ||
// prettier-ignore | ||
{ | ||
// Note: currently Cap always buys 1 capacity. See PlayerActionPayload.cs in backend. | ||
BuyTransportCapacityPlayerAction: (TargetId: number) => ({ | ||
Name: 'BuyTransportCapacityPlayerAction' as const, | ||
TargetId, | ||
}), | ||
HireAgentsPlayerAction: (TargetId: number) => ({ | ||
Name: 'HireAgentsPlayerAction' as const, | ||
TargetId, | ||
}), | ||
SackAgentsPlayerAction: (Ids: number[]) => ({ | ||
Name: 'SackAgentsPlayerAction' as const, | ||
Ids, | ||
}), | ||
SendAgentsToGenerateIncomePlayerAction: (Ids: number[]) => ({ | ||
Name: 'SendAgentsToGenerateIncomePlayerAction' as const, | ||
Ids, | ||
}), | ||
SendAgentsToGatherIntelPlayerAction: (Ids: number[]) => ({ | ||
Name: 'SendAgentsToGatherIntelPlayerAction' as const, | ||
Ids, | ||
}), | ||
SendAgentsToTrainingPlayerAction: (Ids: number[]) => ({ | ||
Name: 'SendAgentsToTrainingPlayerAction' as const, | ||
Ids, | ||
}), | ||
RecallAgentsPlayerAction: (Ids: number[]) => ({ | ||
Name: 'RecallAgentsPlayerAction' as const, | ||
Ids, | ||
}), | ||
LaunchMissionPlayerAction: (Ids: number[], TargetId: number) => ({ | ||
Name: 'LaunchMissionPlayerAction' as const, | ||
Ids, | ||
TargetId, | ||
}), | ||
InvestIntelPlayerAction: (Ids: number[], TargetId: number) => ({ | ||
Name: 'InvestIntelPlayerAction' as const, | ||
Ids, | ||
TargetId, | ||
}), | ||
BuyTransportCapacityPlayerAction : payloadFromTargetIdFactory, | ||
HireAgentsPlayerAction : payloadFromTargetIdFactory, | ||
InvestIntelPlayerAction : payloadFromIdsAndTargetIdFactory, | ||
LaunchMissionPlayerAction : payloadFromIdsAndTargetIdFactory, | ||
RecallAgentsPlayerAction : payloadFromIdsFactory, | ||
SackAgentsPlayerAction : payloadFromIdsFactory, | ||
SendAgentsToGatherIntelPlayerAction : payloadFromIdsFactory, | ||
SendAgentsToGenerateIncomePlayerAction : payloadFromIdsFactory, | ||
SendAgentsToTrainingPlayerAction : payloadFromIdsFactory, | ||
} | ||
|
||
export type PayloadProvider = | ||
| PayloadFromIds | ||
| PayloadFromTargetId | ||
| PayloadFromIdsAndTargetId | ||
// CODESYNC: this must match the definition of actionNameToPayloadProviderFactoryMap. | ||
// | ||
// Note: this block DOES NOT PROVIDE any type-safety, | ||
// as the actionNameToPayloadProviderMap const is manually asserted to be of this type. | ||
// It provides better autocomplete on the client side. | ||
// | ||
// However, even if this block would provide types-safety, it would protect only against | ||
// given payload provider for given action having too many parameters, but not not enough. | ||
// | ||
// For example, if this declares "HireAgentsPlayerAction" player action should produce payload | ||
// only from "Target" parameter,, and the actual implementation would take both "Target" and also "IDs" parameters, | ||
// then this would properly catch it. | ||
// | ||
// However, if this declares "LaunchMissionPlayerAction" player action | ||
// should produce payload from "IDs" and "TargetId" parameters, and the actual implementation | ||
// would take "IDs" parameter only, then this would not catch that. | ||
type PayloadProviderMap = | ||
// prettier-ignore | ||
{ | ||
BuyTransportCapacityPlayerAction : PayloadFromTargetId | ||
HireAgentsPlayerAction : PayloadFromTargetId | ||
InvestIntelPlayerAction : PayloadFromIdsAndTargetId | ||
LaunchMissionPlayerAction : PayloadFromIdsAndTargetId | ||
RecallAgentsPlayerAction : PayloadFromIds | ||
SackAgentsPlayerAction : PayloadFromIds | ||
SendAgentsToGatherIntelPlayerAction : PayloadFromIds | ||
SendAgentsToGenerateIncomePlayerAction : PayloadFromIds | ||
SendAgentsToTrainingPlayerAction : PayloadFromIds | ||
} | ||
|
||
export type PayloadFromIds = (Ids: number[]) => PlayerActionPayload | ||
export type PayloadFromTargetId = (TargetId: number) => PlayerActionPayload | ||
export type PayloadFromIdsAndTargetId = ( | ||
export const actionNameToPayloadProviderMap: PayloadProviderMap = _.fromPairs( | ||
_.map(actionNameToPayloadProviderFactoryMap, (factory, actionName) => { | ||
const typedActionName = actionName as PlayerActionNameInTurn | ||
return [typedActionName, factory(typedActionName)] | ||
}), | ||
) as PayloadProviderMap | ||
|
||
type PayloadProviderFactory = | ||
| ((name: PlayerActionNameInTurn) => PayloadFromIds) | ||
| ((name: PlayerActionNameInTurn) => PayloadFromIdsAndTargetId) | ||
| ((name: PlayerActionNameInTurn) => PayloadFromTargetId) | ||
|
||
type PayloadFromIds = (Ids: number[]) => PlayerActionPayload | ||
|
||
type PayloadFromTargetId = (TargetId: number) => PlayerActionPayload | ||
|
||
type PayloadFromIdsAndTargetId = ( | ||
Ids: number[], | ||
TargetId: number, | ||
) => PlayerActionPayload | ||
|
||
type PayloadProviderMap = { | ||
[key in PlayerActionNameInTurn]: PayloadProvider | ||
} & { | ||
// Note: this block provides type-safety only against a payload provider for given action | ||
// having too many parameters, but not not enough. | ||
// For example, if this declares "AdvanceTime" player action should produce payload | ||
// from no parameters, and the actual implementation would take some parameters, | ||
// then this would properly catch it. | ||
// However, if this declares "RecallAgents" should produce payload from "IDs" parameter, | ||
// and the actual implementation would take no parameters, then this would not catch that. | ||
BuyTransportCapacityPlayerAction: PayloadFromTargetId | ||
HireAgentsPlayerAction: PayloadFromTargetId | ||
InvestIntelPlayerAction: PayloadFromIdsAndTargetId | ||
LaunchMissionPlayerAction: PayloadFromIdsAndTargetId | ||
RecallAgentsPlayerAction: PayloadFromIds | ||
SackAgentsPlayerAction: PayloadFromIds | ||
SendAgentsToGatherIntelPlayerAction: PayloadFromIds | ||
SendAgentsToGenerateIncomePlayerAction: PayloadFromIds | ||
SendAgentsToTrainingPlayerAction: PayloadFromIds | ||
function payloadFromIdsFactory(name: PlayerActionNameInTurn): PayloadFromIds { | ||
return (ids: number[]) => ({ | ||
Name: name, | ||
Ids: ids, | ||
}) | ||
} | ||
|
||
function payloadFromTargetIdFactory( | ||
name: PlayerActionNameInTurn, | ||
): PayloadFromTargetId { | ||
return (targetId: number) => ({ | ||
Name: name, | ||
TargetId: targetId, | ||
}) | ||
} | ||
|
||
function payloadFromIdsAndTargetIdFactory( | ||
name: PlayerActionNameInTurn, | ||
): PayloadFromIdsAndTargetId { | ||
return (ids: number[], targetId: number) => ({ | ||
Name: name, | ||
Ids: ids, | ||
TargetId: targetId, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters