Begin building trade calculations
This commit is contained in:
parent
677f122a03
commit
7cbd8e2fb7
2 changed files with 52 additions and 12 deletions
|
@ -3,6 +3,7 @@ import csv
|
|||
import dataclasses
|
||||
import enum
|
||||
import fractions
|
||||
import functools
|
||||
import importlib.resources
|
||||
import typing
|
||||
|
||||
|
@ -11,6 +12,7 @@ from elite_engineering import trade
|
|||
|
||||
@dataclasses.dataclass
|
||||
class Material:
|
||||
symbol: str
|
||||
name: str
|
||||
type_: str
|
||||
category: str
|
||||
|
@ -27,7 +29,7 @@ def _load() -> typing.Dict[str, Material]:
|
|||
lines = path.read_text().splitlines()
|
||||
reader = csv.reader(lines[1:])
|
||||
return {
|
||||
symbol.lower(): Material(name, type_, category, int(grade))
|
||||
symbol.lower(): Material(symbol.lower(), name, type_, category, int(grade))
|
||||
for fdevid, symbol, grade, type_, category, name in reader
|
||||
}
|
||||
|
||||
|
@ -66,10 +68,22 @@ class Inventory(collections.UserDict):
|
|||
return all([self[name] >= quantity for name, quantity in items.items()])
|
||||
|
||||
def __add__(self, other: "Inventory") -> "Inventory":
|
||||
return Inventory({name: self[name] + qty for name, qty in other.items()})
|
||||
return Inventory({name: self[name] + other[name] for name in materials})
|
||||
|
||||
def __sub__(self, other: "Inventory") -> "Inventory":
|
||||
return Inventory({name: self[name] - qty for name, qty in other.items()})
|
||||
return Inventory({name: self[name] - other[name] for name in materials})
|
||||
|
||||
def trades(self, symbol: str, quantity: int) -> "Materials":
|
||||
if self.has(Materials({symbol: quantity})):
|
||||
return Materials({})
|
||||
raise ValueError
|
||||
|
||||
def trade_for(self, other: "Inventory") -> "Inventory":
|
||||
def accumulate(inv: "Inventory", mat: typing.Tuple[str, int]) -> "Inventory":
|
||||
symbol, quantity = mat
|
||||
return inv - inv.trades(symbol, quantity)
|
||||
|
||||
return functools.reduce(accumulate, other.items(), self)
|
||||
|
||||
@classmethod
|
||||
def from_event(
|
||||
|
|
|
@ -25,8 +25,12 @@ class TradeCalculationTests(unittest.TestCase):
|
|||
actual = [
|
||||
[
|
||||
self.format_ratio(
|
||||
materials.Material("name", "raw", "category", grade_in).trade_ratio(
|
||||
materials.Material("name", "raw", "category", grade_out)
|
||||
materials.Material(
|
||||
"symbol", "name", "raw", "category", grade_in
|
||||
).trade_ratio(
|
||||
materials.Material(
|
||||
"symbol", "name", "raw", "category", grade_out
|
||||
)
|
||||
)
|
||||
)
|
||||
for grade_in in [1, 2, 3, 4, 5]
|
||||
|
@ -47,8 +51,10 @@ class TradeCalculationTests(unittest.TestCase):
|
|||
actual = [
|
||||
[
|
||||
self.format_ratio(
|
||||
materials.Material("name", "raw", "category", grade_in).trade_ratio(
|
||||
materials.Material("name", "raw", "other", grade_out)
|
||||
materials.Material(
|
||||
"symbol", "name", "raw", "category", grade_in
|
||||
).trade_ratio(
|
||||
materials.Material("symbol", "name", "raw", "other", grade_out)
|
||||
)
|
||||
)
|
||||
for grade_in in [1, 2, 3, 4, 5]
|
||||
|
@ -70,8 +76,12 @@ class TradeCalculationTests(unittest.TestCase):
|
|||
actual = [
|
||||
[
|
||||
self.format_ratio(
|
||||
materials.Material("name", "raw", "category", grade_in).trade_ratio(
|
||||
materials.Material("name", "encoded", "other", grade_out)
|
||||
materials.Material(
|
||||
"symbol", "name", "raw", "category", grade_in
|
||||
).trade_ratio(
|
||||
materials.Material(
|
||||
"symbol", "name", "encoded", "other", grade_out
|
||||
)
|
||||
)
|
||||
)
|
||||
for grade_in in [1, 2, 3, 4, 5]
|
||||
|
@ -146,9 +156,6 @@ class InventoryTests(unittest.TestCase):
|
|||
self.assertEqual(exc.exception.args, (-1,))
|
||||
|
||||
def test_load_from_materials_event(self) -> None:
|
||||
event = json.loads(
|
||||
pathlib.Path(__file__).parent.joinpath("events/materials.json").read_text()
|
||||
)
|
||||
event = {
|
||||
"timestamp": "2022-01-23T02:58:12Z",
|
||||
"event": "Materials",
|
||||
|
@ -222,6 +229,25 @@ class InventoryTests(unittest.TestCase):
|
|||
self.from_event(event)
|
||||
self.assertEqual(exc.exception.args, ("Not a 'Materials' event",))
|
||||
|
||||
def test_trade_unnecessary(self) -> None:
|
||||
inventory = self.make({"carbon": 3, "niobium": 1})
|
||||
recipe = materials.Materials({"carbon": 3})
|
||||
self.assertEqual(inventory, inventory.trade_for(recipe))
|
||||
|
||||
def test_trade_impossible(self) -> None:
|
||||
inventory = self.make()
|
||||
recipe = materials.Materials({"carbon": 3})
|
||||
with self.assertRaises(ValueError):
|
||||
inventory.trade_for(recipe)
|
||||
|
||||
@unittest.skip("Not implemented")
|
||||
def test_trade_grade_2_for_grade_1(self) -> None:
|
||||
inventory = self.make({"vanadium": 1, "niobium": 1})
|
||||
recipe = materials.Materials({"carbon": 3})
|
||||
self.assertEqual(
|
||||
self.make({"carbon": 3, "niobium": 1}), inventory.trade_for(recipe)
|
||||
)
|
||||
|
||||
|
||||
class MaterialsTests(InventoryTests):
|
||||
def make(
|
||||
|
|
Loading…
Reference in a new issue