Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion backend/planning/api/serializers/plan.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
from typing import Any

from api.serializer import PydanticJSONField
from django.db import transaction
from django.shortcuts import get_object_or_404
from planning.models import PlanningEmpire, PlanningEmpirePlan, PlanningPlan, PlanningShared
from django.utils import timezone
from gamedata.models import GamePlanetCOGCProgram
from gamedata.models.game_planet import GamePlanetCOGCProgramChoices
from planning.models import PlanningCOGCChoices, PlanningEmpire, PlanningEmpirePlan, PlanningPlan, PlanningShared
from planning.schemas.latest_schemas import LATEST_SCHEMA
from rest_framework import serializers

from .cx import PlanningCXDetailSerializer
from .empire import PlanningEmpireListSerializer

COGC_MAP: dict[GamePlanetCOGCProgramChoices, PlanningCOGCChoices] = {
GamePlanetCOGCProgramChoices.Agriculture: PlanningCOGCChoices.AGRICULTURE,
GamePlanetCOGCProgramChoices.Chemistry: PlanningCOGCChoices.CHEMISTRY,
GamePlanetCOGCProgramChoices.Construction: PlanningCOGCChoices.CONSTRUCTION,
GamePlanetCOGCProgramChoices.Electronics: PlanningCOGCChoices.ELECTRONICS,
GamePlanetCOGCProgramChoices.Food_Industries: PlanningCOGCChoices.FOOD_INDUSTRIES,
GamePlanetCOGCProgramChoices.Fuel_Refining: PlanningCOGCChoices.FUEL_REFINING,
GamePlanetCOGCProgramChoices.Manufacturing: PlanningCOGCChoices.MANUFACTURING,
GamePlanetCOGCProgramChoices.Metallurgy: PlanningCOGCChoices.METALLURGY,
GamePlanetCOGCProgramChoices.Resource_Extraction: PlanningCOGCChoices.RESOURCE_EXTRACTION,
GamePlanetCOGCProgramChoices.Workforce_Pioneers: PlanningCOGCChoices.PIONEERS,
GamePlanetCOGCProgramChoices.Workforce_Settlers: PlanningCOGCChoices.SETTLERS,
GamePlanetCOGCProgramChoices.Workforce_Technicians: PlanningCOGCChoices.TECHNICIANS,
GamePlanetCOGCProgramChoices.Workforce_Engineers: PlanningCOGCChoices.ENGINEERS,
GamePlanetCOGCProgramChoices.Workforce_Scientists: PlanningCOGCChoices.SCIENTISTS,
}


class PlanningPlanDetailSerializer(serializers.ModelSerializer):
empires = PlanningEmpireListSerializer(many=True, read_only=True)
Expand All @@ -18,6 +40,9 @@ class PlanningPlanDetailSerializer(serializers.ModelSerializer):

plan_data = PydanticJSONField(pydantic_model=LATEST_SCHEMA['PLANNING_DATA'])

# COGC: must allow null, if so: populate from planets running cogc
plan_cogc = serializers.ChoiceField(choices=PlanningCOGCChoices.choices, allow_null=True, required=False)

class Meta:
model = PlanningPlan
fields = [
Expand All @@ -33,6 +58,45 @@ class Meta:
'empire_uuid',
]

def validate(self, attrs: dict[str, Any]) -> dict[str, Any]:

# plan_cogc
if attrs.get('plan_cogc') is None:
# extract planet_natural_id from attrs (CREATE/PUT) or instance (PATCH) if missing
planet_id = attrs.get('planet_natural_id')
if planet_id is None and self.instance:
planet_id = self.instance.planet_natural_id

if planet_id:
attrs['plan_cogc'] = self._calculate_planet_cogc(planet_id)
else:
attrs['plan_cogc'] = PlanningCOGCChoices.NONE

return attrs

def _calculate_planet_cogc(self, planet_natural_id: str) -> str:
# look up the active cogc program for the planet or default to NONE

now_ms = int(timezone.now().timestamp() * 1000)

raw_active_program_type = (
GamePlanetCOGCProgram.objects.filter(
planet__planet_natural_id=planet_natural_id, start_epochms__lte=now_ms, end_epochms__gte=now_ms
)
.values_list('program_type', flat=True)
.first()
)

if raw_active_program_type:
mapped_value = COGC_MAP.get(raw_active_program_type)

# return found type if existing and valid
if mapped_value:
return mapped_value

# else fallback to NONE
return PlanningCOGCChoices.NONE

@transaction.atomic
def create(self, validated_data):
user = self.context['request'].user
Expand Down
Loading