Skip to content

Commit

Permalink
feat: adds example for generating inventory report
Browse files Browse the repository at this point in the history
  • Loading branch information
jmgilman committed May 23, 2024
1 parent 1fd5a26 commit 700ae01
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 17 deletions.
94 changes: 94 additions & 0 deletions examples/inventory_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""
This example demonstrates how to generate a report of the financial status of a storehouse in a table format.
"""
from __future__ import annotations

from dataclasses import dataclass
import math
import os
import asyncio
from dotenv import load_dotenv
from pymerc.api.models.common import Item, Transport
from pymerc.client import Client
from pymerc.game.player import Player
from tabulate import tabulate

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

@dataclass
class ItemReport:
balance: float = 0
item: Item = None
imported: float = 0
production: float = 0
purchase: float = 0
consumption: float = 0
export: float = 0
sale: float = 0

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

table = []
headers = ["Item", "Imported", "Production", "Purchase", "Consumption", "Export", "Sale", "Balance"]

for item in player.storehouse.items:
if item.value in Transport:
continue

report = generate_report(player, item)
table.append([
item.name,
report.imported,
report.production,
report.purchase,
report.consumption,
report.export,
report.sale,
report.balance
])

print(tabulate(table, headers, floatfmt=".2f"))

def generate_report(player: Player, target_item: Item) -> ItemReport:
report = ItemReport(target_item)
report.item = target_item
item = player.storehouse.items[target_item]

input = 0
output = 0

if item.imported:
input += item.import_cost_flowed
report.imported = -item.import_cost_flowed
if item.produced:
input += item.production_cost
report.production = -item.production_cost
if item.purchased:
input += item.purchased_cost
report.purchase = -item.purchased_cost
if item.consumed:
consumption = 0
if target_item in player.sustenance_items:
consumed = item.consumed - player.sustenance_item_consumption(target_item)
consumption = consumed * item.average_cost
else:
consumption = item.consumption_cost

input -= consumption
report.consumption = consumption

if item.exported:
output += item.export_value_flowed
report.export = item.export_value_flowed
if item.sold:
output += item.sale_value
report.sale = item.sale_value

report.balance = round(output - input, 2)
return report

if __name__ == "__main__":
asyncio.run(main())
16 changes: 15 additions & 1 deletion poetry.lock

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

2 changes: 1 addition & 1 deletion pymerc/api/models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ class Producer(BaseModel):
limited: bool
manager: str
previous_operation: Operation
provider_id: int
provider_id: Optional[int] = None
recipe: Recipe
reference: str
target: Optional[float] = None
10 changes: 6 additions & 4 deletions pymerc/game/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ def sustenance_cost(self) -> float:
"""The cost of the player's sustenance."""
total_cost = 0
for item in self.sustenance_items:
volume = self.sustenance_item_consumption(item)
cost = self.storehouse.items[item].average_cost
total_cost += volume * cost
total_cost += self.sustenance_item_cost(item)

return total_cost

Expand All @@ -95,4 +93,8 @@ def sustenance_items(self) -> list[common.Item]:

def sustenance_item_consumption(self, item: common.Item) -> float:
"""The amount of an item consumed by the player's sustenance."""
return self.data.household.sustenance.inventory.previous_flows[item].consumption
return self.data.household.sustenance.inventory.previous_flows[item].consumption

def sustenance_item_cost(self, item: common.Item) -> float:
"""The cost of an item consumed by the player's sustenance."""
return self.sustenance_item_consumption(item) * self.storehouse.items[item].average_cost
49 changes: 38 additions & 11 deletions pymerc/game/storehouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,22 @@ def average_cost(self) -> float:
if self.produced:
costs.append(self.production_cost / self.produced)
if self.imported:
costs.append(self.import_cost / self.imported)
costs.append(self.import_cost_flowed / self.imported)
if self.purchased:
costs.append(self.purchased_cost / self.purchased)

return sum(costs) / len(costs)
if costs:
return sum(costs) / len(costs)
else:
return 0

@property
def consumed(self) -> float:
"""The amount of the item consumed."""
return self.flow.consumption
if self.flow:
return self.flow.consumption
else:
return 0.0

@property
def consumption_cost(self) -> float:
Expand All @@ -76,7 +82,10 @@ def consumption_cost(self) -> float:
@property
def exported(self) -> int:
"""The amount of the item exported."""
return self.flow.export or 0
if self.flow:
return self.flow.export or 0
else:
return 0

@property
def export_value(self) -> float:
Expand All @@ -91,7 +100,10 @@ def export_value_flowed(self) -> float:
@property
def imported(self) -> int:
"""The amount of the item imported."""
return self.flow.imported or 0
if self.flow:
return self.flow.imported or 0
else:
return 0

@property
def import_cost(self) -> float:
Expand All @@ -106,7 +118,10 @@ def import_cost_flowed(self) -> float:
@property
def sold(self) -> int:
"""The amount of the item sold."""
return self.flow.sale or 0
if self.flow:
return self.flow.sale or 0
else:
return 0

@property
def sale_value(self) -> float:
Expand All @@ -119,22 +134,34 @@ def sale_value(self) -> float:
@property
def produced(self) -> float:
"""The amount of the item produced."""
return self.flow.production
if self.flow:
return self.flow.production
else:
return 0.0

@property
def production_cost(self) -> float:
"""The cost of producing the item."""
return self.flow.production_cost or 0
if self.flow:
return self.flow.production_cost or 0
else:
return 0.0

@property
def purchased(self) -> int:
"""The amount of the item purchased."""
return self.flow.purchase or 0
if self.flow:
return self.flow.purchase or 0
else:
return 0

@property
def purchased_cost(self) -> float:
"""The cost of purchasing the item."""
if self.flow.purchase:
return self.asset.purchase * self.asset.purchase_price
if self.flow:
if self.flow.purchase:
return self.asset.purchase * self.asset.purchase_price
else:
return 0
else:
return 0
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pytest-asyncio = "^0.23.6"
python-dotenv = "^1.0.1"
pytest-subtests = "^0.12.1"
ruff = "^0.4.4"
tabulate = "^0.9.0"

[build-system]
requires = ["poetry-core"]
Expand Down

0 comments on commit 700ae01

Please sign in to comment.