Skip to content

Commit

Permalink
feat: adds support for grabbing current operations (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
garrett-griffin authored May 23, 2024
1 parent 700ae01 commit 05af269
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 65 deletions.
31 changes: 31 additions & 0 deletions examples/calculate_ideal_labour_from_recipes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
import asyncio
from dotenv import load_dotenv

from pymerc.client import Client

# Load the API_USER and API_TOKEN from the environment
load_dotenv()


async def calculate_ideal_labor_for_player_buildings():
client = Client(os.environ["API_USER"], os.environ["API_TOKEN"])
player = await client.player()

total_labor = 0.0

for building in player.buildings:
# Ensure we're using the Building class from pymerc.game
building = await client.building(building.id)
if building.production:
labor_required = await building.calculate_current_labor_need()
print(
f"Building ID: {building.id}, Type: {building.type}, Recipe: {building.production.recipe.value}, Labor Required: {labor_required}")
total_labor += labor_required

print(f"Total labor required for all buildings: {total_labor}")

await client.close()

if __name__ == "__main__":
asyncio.run(calculate_ideal_labor_for_player_buildings())
4 changes: 2 additions & 2 deletions examples/fix_labour.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async def main():
player = await client.player()

manager = player.storehouse.inventory.managers.get(Item.Labour)
flow = player.storehouse.inventory.previous_flows.get(Item.Labour)
flow = player.storehouse.total_flow.get(Item.Labour)

consumed = flow.consumption - flow.production

Expand All @@ -45,4 +45,4 @@ async def main():


if __name__ == "__main__":
asyncio.run(main())
asyncio.run(main())
65 changes: 38 additions & 27 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions pymerc/api/buildings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ async def get(self, id: int) -> buildings.Building:
response = await self.client.get(f"{BASE_URL}{id}")
return buildings.Building.model_validate(response.json())

async def get_operations(self, id: int) -> buildings.BuildingOperation:
"""Get the operations for a building.
Args:
id (int): The ID of the building.
Returns:
BuildingOperation: The building operation information.
"""
response = await self.client.get(f"{BASE_URL}{id}/operations")
return buildings.BuildingOperation.model_validate(response.json())

async def set_manager(self, id: int, item: common.Item, manager: common.InventoryManager) -> bool:
"""Set the manager for an item in a building.
Expand Down
13 changes: 6 additions & 7 deletions pymerc/api/models/buildings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Building(BaseModel):

capacity: Optional[int] = None
construction: Optional[BuildingConstruction] = None
delivery_cost: BuildingDeliveryCost
delivery_cost: common.DeliveryCost
id: int
land: Optional[list[common.Location]] = None
name: str
Expand All @@ -37,15 +37,14 @@ class BuildingConstruction(BaseModel):
upgrade_type: Optional[common.BuildingUpgradeType] = None


class BuildingDeliveryCost(BaseModel):
"""Represents the delivery cost of a building."""

land_distance: float


class BuildingStorage(BaseModel):
"""Represents the storage of a building."""

inventory: common.Inventory
operations: list[str]
reference: str


class BuildingOperation(BaseModel):
total_flow: Optional[dict[common.Item, common.InventoryFlow]] = None
operations: Optional[list[common.Operation]] = None
8 changes: 4 additions & 4 deletions pymerc/api/models/businesses.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations
from typing import Optional

from pydantic import BaseModel
from pydantic import BaseModel, Field

from pymerc.api.models import common

Expand All @@ -10,10 +10,10 @@ class Business(BaseModel):
"""A business in the game."""

account: BusinessAccount
account_id: int
account_id: str
building_ids: list[int]
buildings: list[Building]
contract_ids: list[str]
contract_ids: Optional[list[str]] = Field(default=None)
id: int
name: str
owner_id: int
Expand All @@ -23,7 +23,7 @@ class Business(BaseModel):
class BusinessAccount(BaseModel):
"""The account of a business."""

id: int
id: str
name: str
owner_id: int
assets: dict[common.Asset, BusinessAccountAsset]
Expand Down
32 changes: 27 additions & 5 deletions pymerc/api/models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ class Recipe(Enum):
Carting2 = "carting 2"
ChurnButter1 = "churn butter 1"
ChurnButter2 = "churn butter 2"
CogOperations = "cog operations"
CraftArms1 = "craft arms 1"
CraftBelts1 = "craft belts 1"
CraftBelts2 = "craft belts 2"
Expand Down Expand Up @@ -374,6 +375,7 @@ class Recipe(Enum):
GrowHerbs1 = "grow herbs 1"
GrowHerbs2 = "grow herbs 2"
HammerNails1 = "hammer nails 1"
HandcartOperations = "handcart operations"
HarnessOx1 = "harness ox 1"
HarnessOx2a = "harness ox 2a"
HarnessOx2b = "harness ox 2b"
Expand Down Expand Up @@ -521,6 +523,7 @@ class Recipe(Enum):
SmokingHam2 = "smoking ham 2"
SmokingMeat1 = "smoking meat 1"
SmokingMeat2 = "smoking meat 2"
SnekkjaOperations = "snekkja operations"
SpinThread1 = "spin thread 1"
SpinThread2 = "spin thread 2"
SpinYarn1 = "spin yarn 1"
Expand All @@ -529,6 +532,7 @@ class Recipe(Enum):
SplitTimber2 = "split timber 2"
TanHides1 = "tan hides 1"
TanHides2 = "tan hides 2"
TumbrelOperations = "tumbrel operations"
WeaveCloth1 = "weave cloth 1"
WeaveCloth2a = "weave cloth 2a"
WeaveCloth2b = "weave cloth 2b"
Expand Down Expand Up @@ -607,7 +611,7 @@ class InventoryAccount(BaseModel):
master_id: Optional[str] = None
name: Optional[str] = None
owner_id: int
sponsor_id: Optional[int] = None
sponsor_id: Optional[str] = None


class InventoryAccountAsset(BaseModel):
Expand Down Expand Up @@ -689,13 +693,31 @@ class InventoryFlow(BaseModel):
production: Optional[float] = None
production_cost: Optional[float] = None
purchase: Optional[int] = None
purchase_cost: Optional[float] = None
resident: Optional[float] = None
sale: Optional[int] = None
sale_value: Optional[float] = None


class DeliveryCost(BaseModel):
"""Represents the delivery cost of a building."""
land_distance: float
ferry_fee: Optional[float] = None


class Operation(BaseModel):
"""Represents an operation."""
target: float
production: float
provision: float
target: float = None
production: Optional[float] = None
provision: Optional[float] = None
reference: Optional[str] = None
recipe: Optional[Recipe] = None
volume: Optional[float] = None
tax_rate: Optional[float] = None
tax: Optional[float] = None
delivery_cost: Optional[DeliveryCost] = None
flows: Optional[dict[Item, InventoryFlow]] = None


@property
def surplus(self) -> float:
Expand All @@ -722,4 +744,4 @@ class Producer(BaseModel):
provider_id: Optional[int] = None
recipe: Recipe
reference: str
target: Optional[float] = None
target: Optional[float] = None
7 changes: 6 additions & 1 deletion pymerc/api/static.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import re
from typing import Any
from async_lru import alru_cache

from pydantic import TypeAdapter

Expand All @@ -14,6 +15,7 @@
class StaticAPI(BaseAPI):
"""A class for interacting with the static data from the game."""

@alru_cache(maxsize=1)
async def get_buildings(self) -> list[static.Building]:
"""Get the buildings from the game.
Expand All @@ -25,6 +27,7 @@ async def get_buildings(self) -> list[static.Building]:
type_adapter = TypeAdapter(list[static.Building])
return type_adapter.validate_python(data["Gm"])

@alru_cache(maxsize=1)
async def get_items(self) -> list[static.Item]:
"""Get the items from the game.
Expand All @@ -36,17 +39,18 @@ async def get_items(self) -> list[static.Item]:
type_adapter = TypeAdapter(list[static.Item])
return type_adapter.validate_python(data["RB"])

@alru_cache(maxsize=1)
async def get_recipes(self) -> list[static.Recipe]:
"""Get the recipes from the game.
Returns:
list[static.Recipe]: The recipes from the game.
"""
data = await self._get()

type_adapter = TypeAdapter(list[static.Recipe])
return type_adapter.validate_python(data["F_"])

@alru_cache(maxsize=1)
async def get_transport(self) -> list[static.Transport]:
"""Get the transport from the game.
Expand All @@ -58,6 +62,7 @@ async def get_transport(self) -> list[static.Transport]:
type_adapter = TypeAdapter(list[static.Transport])
return type_adapter.validate_python(data["g$"])

@alru_cache(maxsize=1)
async def _get(self) -> Any:
"""Get the static data from the game.
Expand Down
Loading

0 comments on commit 05af269

Please sign in to comment.