Compare commits

...
Author SHA1 Message Date
adminandClaude Opus 4.5 ad974357f4 Update deproto plan: add DiplomacyOfferStatus and next candidates
- Document completed DiplomacyOfferStatus enum migration (PR #5093)
- Add Enum Type Migrations section tracking proto enum conversions
- Add Next Candidates section with priority items for future work

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 05:36:47 -08:00
adminandClaude Opus 4.5 d9dfb5cbb2 Deproto: Use Scala Status in EligibleDiplomacyStatuses
Convert EligibleDiplomacyStatuses to use Scala Status types internally,
with conversion to proto at the call sites where needed for building
AvailableCommand proto messages.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 21:40:31 -08:00
8 changed files with 57 additions and 27 deletions
+32 -1
View File
@@ -231,6 +231,21 @@ All action files have been migrated to use Scala types:
-`CommandChoiceHelpers` migrated to Scala types
-`ResolveBattleAction` refactored to use Scala GameState and ActionResultApplier (PR #5048)
### Enum Type Migrations
Proto enums are being converted to Scala sealed traits with converters at boundaries:
| Enum | Scala Type | Status | Notes |
|------|------------|--------|-------|
| `DiplomacyOfferStatus` | `Status` sealed trait | ✅ **Complete** | PR #5093 - `EligibleDiplomacyStatuses` uses Scala types internally |
| `RoundPhase` | `RoundPhase` sealed trait | Partial | Some usages converted |
| `BattalionType` | `BattalionType` sealed trait | Partial | Some usages converted |
**DiplomacyOfferStatus Migration (PR #5093):**
- `EligibleDiplomacyStatuses.scala` now returns `Vector[Status]` instead of `Vector[DiplomacyOfferStatus]`
- Call sites in `AvailableResolve*CommandFactory` files convert to proto via `StatusConverter.toProto` at the boundary
- This pattern should be applied to other proto enums
### CommandChoiceHelpers Migration Status
Several command selectors have already been converted to use Scala types:
@@ -257,7 +272,23 @@ Several command selectors have already been converted to use Scala types:
|--------|-------|
| Action files fully protoless | 52 / 52 (100%) ✅ |
| Proto usages in remaining actions | 0 |
| Next target | History APIs (InMemoryHistory, PersistedHistory) |
| Next target | See "Next Candidates" section below |
### Next Candidates
Priority candidates for further deproto work:
1. **More Enum Migrations** - Apply the `DiplomacyOfferStatus` pattern to other proto enums:
- Files importing `net.eagle0.eagle.common.round_phase.RoundPhase` (proto) could use Scala `RoundPhase`
- Files importing `net.eagle0.eagle.common.battalion_type.BattalionType` (proto) could use Scala `BattalionType`
2. **AvailableCommandsFactory Files** - Many still use proto `GameState` internally:
- These files build proto `AvailableCommand` messages but could use Scala types for internal logic
- Convert to accept Scala `GameState`, only convert fields to proto when building the response
3. **History APIs** - `InMemoryHistory` and `PersistedHistory`:
- Change to vend Scala `GameState` and `ActionResultT` instead of proto versions
- `PersistedHistory` converts to proto internally for disk persistence
### Validation
- [x] `ActionResultApplier` created and tested
@@ -42,7 +42,7 @@ object AvailableResolveAllianceOfferCommandFactory {
actingFactionId = factionId,
provinces = gameState.provinces.values
)
.toVector).toVector,
.toVector).map(StatusConverter.toProto),
offerTextId = allianceOffer.offerTextId
)
}
@@ -96,11 +96,11 @@ object AvailableResolveAllianceOfferCommandFactory {
messengerHeroId = messengerHeroId,
messengerOriginProvinceId = messengerOriginProvinceId,
status = status,
eligibleStatuses = EligibleDiplomacyStatuses.acceptRejectStatuses ++ EligibleDiplomacyStatuses
eligibleStatuses = (EligibleDiplomacyStatuses.acceptRejectStatuses ++ EligibleDiplomacyStatuses
.maybeImprisonStatus(
actingFactionId = factionId,
gameState = gameState
),
)).map(StatusConverter.toProto),
offerTextId = offerTextId
)
}
@@ -46,6 +46,7 @@ object AvailableResolveBreakAllianceCommandFactory {
actingFactionId = factionId,
provinces = gameState.provinces.values
)
.map(StatusConverter.toProto)
.toVector).toVector,
offerTextId = breakAlliance.offerTextId
)
@@ -102,10 +103,12 @@ object AvailableResolveBreakAllianceCommandFactory {
status = status,
eligibleStatuses = Vector(
DIPLOMACY_OFFER_STATUS_ACCEPTED
) ++ EligibleDiplomacyStatuses.maybeImprisonStatus(
actingFactionId = factionId,
gameState = gameState
),
) ++ EligibleDiplomacyStatuses
.maybeImprisonStatus(
actingFactionId = factionId,
gameState = gameState
)
.map(StatusConverter.toProto),
offerTextId = offerTextId
)
}
@@ -64,7 +64,7 @@ object AvailableResolveInvitationCommandFactory {
actingFactionId = factionId,
provinces = gameState.provinces.values
)
.toVector).toVector,
.toVector).map(StatusConverter.toProto),
offerTextId = invitation.offerTextId
)
}.toVector
@@ -138,11 +138,11 @@ object AvailableResolveInvitationCommandFactory {
ResolveInvitationAvailableCommand(
invitations = actionableInvitations.map {
_.withEligibleStatuses(
EligibleDiplomacyStatuses.acceptRejectStatuses ++ EligibleDiplomacyStatuses
(EligibleDiplomacyStatuses.acceptRejectStatuses ++ EligibleDiplomacyStatuses
.maybeImprisonStatus(
actingFactionId = factionId,
gameState = gameState
)
)).map(StatusConverter.toProto)
)
}
)
@@ -111,7 +111,7 @@ object AvailableResolveRansomOfferCommandFactory {
messengerHeroId = ransomOffer.messengerHeroId,
messengerOriginProvinceId = ransomOffer.messengerOriginProvinceId,
status = StatusConverter.toProto(ransomOffer.status),
eligibleStatuses = EligibleDiplomacyStatuses.acceptRejectStatuses,
eligibleStatuses = EligibleDiplomacyStatuses.acceptRejectStatuses.map(StatusConverter.toProto),
offerTextId = ransomOffer.offerTextId
)
}.toVector
@@ -195,7 +195,7 @@ object AvailableResolveRansomOfferCommandFactory {
ResolveRansomOfferAvailableCommand(
offers = offers.map {
_.withEligibleStatuses(
EligibleDiplomacyStatuses.acceptRejectStatuses
EligibleDiplomacyStatuses.acceptRejectStatuses.map(StatusConverter.toProto)
)
}
)
@@ -48,7 +48,7 @@ object AvailableResolveTruceOfferCommandFactory {
actingFactionId = factionId,
provinces = gameState.provinces.values
)
.toVector).toVector,
.toVector).map(StatusConverter.toProto),
offerTextId = truceOffer.offerTextId
)
}
@@ -111,7 +111,7 @@ object AvailableResolveTruceOfferCommandFactory {
actingFactionId = factionId,
gameState = gameState
)
.toVector).toVector,
.toVector).map(StatusConverter.toProto),
offerTextId = offerTextId
)
}.toVector
@@ -874,11 +874,11 @@ scala_library(
],
deps = [
":pkg",
"//src/main/protobuf/net/eagle0/eagle/common:diplomacy_offer_status_scala_proto",
"//src/main/protobuf/net/eagle0/eagle/internal:game_state_scala_proto",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils:legacy_faction_utils",
"//src/main/scala/net/eagle0/eagle/model/state/diplomacy_offer/status",
"//src/main/scala/net/eagle0/eagle/model/state/province",
],
)
@@ -1,31 +1,27 @@
package net.eagle0.eagle.library.actions.availability
import net.eagle0.eagle.common.diplomacy_offer_status.DiplomacyOfferStatus
import net.eagle0.eagle.common.diplomacy_offer_status.DiplomacyOfferStatus.DIPLOMACY_OFFER_STATUS_IMPRISONED
import net.eagle0.eagle.internal.game_state.GameState
import net.eagle0.eagle.library.util.faction_utils.{FactionUtils, LegacyFactionUtils}
import net.eagle0.eagle.model.state.diplomacy_offer.status.{Accepted, Imprisoned, Rejected, Status}
import net.eagle0.eagle.model.state.province.ProvinceT
import net.eagle0.eagle.FactionId
object EligibleDiplomacyStatuses {
def acceptRejectStatuses: Vector[DiplomacyOfferStatus] =
Vector(
DiplomacyOfferStatus.DIPLOMACY_OFFER_STATUS_ACCEPTED,
DiplomacyOfferStatus.DIPLOMACY_OFFER_STATUS_REJECTED
)
def acceptRejectStatuses: Vector[Status] =
Vector(Accepted, Rejected)
/** Scala overload */
def maybeImprisonStatus(
actingFactionId: FactionId,
provinces: Iterable[ProvinceT]
): Option[DiplomacyOfferStatus] = Option.when(
): Option[Status] = Option.when(
FactionUtils.hasProvinces(actingFactionId, provinces)
)(DIPLOMACY_OFFER_STATUS_IMPRISONED)
)(Imprisoned)
def maybeImprisonStatus(
actingFactionId: FactionId,
gameState: GameState
): Option[DiplomacyOfferStatus] = Option.when(
): Option[Status] = Option.when(
LegacyFactionUtils.hasProvinces(actingFactionId, gameState)
)(DIPLOMACY_OFFER_STATUS_IMPRISONED)
)(Imprisoned)
}