228 lines
7 KiB
Python
228 lines
7 KiB
Python
import collections
|
|
import dataclasses
|
|
import enum
|
|
import fractions
|
|
import typing
|
|
|
|
from elite_engineering import trade
|
|
|
|
|
|
class MaterialType(enum.Enum):
|
|
raw = "Raw"
|
|
manufactured = "Manufactured"
|
|
encoded = "Encoded"
|
|
|
|
|
|
categorized = {
|
|
MaterialType.raw: {
|
|
"Raw Material Category 1": ["Carbon", "Vanadium", "Niobium", "Yttrium"],
|
|
"Raw Material Category 2": [
|
|
"Phosphorus",
|
|
"Chromium",
|
|
"Molybdenum",
|
|
"Technetium",
|
|
],
|
|
"Raw Material Category 3": ["Sulphur", "Manganese", "Cadmium", "Ruthenium"],
|
|
"Raw Material Category 4": ["Iron", "Zinc", "Tin", "Selenium"],
|
|
"Raw Material Category 5": ["Nickel", "Germanium", "Tungsten", "Tellurium"],
|
|
"Raw Material Category 6": ["Rhenium", "Arsenic", "Mercury", "Polonium"],
|
|
"Raw Material Category 7": ["Lead", "Zirconium", "Boron", "Antimony"],
|
|
},
|
|
MaterialType.manufactured: {
|
|
"Chemical": [
|
|
"Chemical Storage Units",
|
|
"Chemical Processors",
|
|
"Chemical Distillery",
|
|
"Chemical Manipulators",
|
|
"Pharmaceutical Isolators",
|
|
],
|
|
"Thermic": [
|
|
"Tempered Alloys",
|
|
"Heat Resistant Ceramics",
|
|
"Precipitated Alloys",
|
|
"Thermic Alloys",
|
|
"Military Grade Alloys",
|
|
],
|
|
"Heat": [
|
|
"Heat Conduction Wiring",
|
|
"Heat Dispersion Plate",
|
|
"Heat Exchangers",
|
|
"Heat Vanes",
|
|
"Proto Heat Radiators",
|
|
],
|
|
"Conductive": [
|
|
"Basic Conductors",
|
|
"Conductive Components",
|
|
"Conductive Ceramics",
|
|
"Conductive Polymers",
|
|
"Biotech Conductors",
|
|
],
|
|
"Mechanical Components": [
|
|
"Mechanical Scrap",
|
|
"Mechanical Equipment",
|
|
"Mechanical Components",
|
|
"Configurable Components",
|
|
"Improvised Components",
|
|
],
|
|
"Capacitors": [
|
|
"Grid Resistors",
|
|
"Hybrid Capacitors",
|
|
"Electrochemical Arrays",
|
|
"Polymer Capacitors",
|
|
"Military Supercapacitors",
|
|
],
|
|
"Shielding": [
|
|
"Worn Shield Emitters",
|
|
"Shield Emitters",
|
|
"Shielding Sensors",
|
|
"Compound Shielding",
|
|
"Imperial Shielding",
|
|
],
|
|
"Composite": [
|
|
"Compact Composites",
|
|
"Filament Composites",
|
|
"High Density Composites",
|
|
"Proprietary Composites",
|
|
"Core Dynamics Composites",
|
|
],
|
|
"Crystals": [
|
|
"Crystal Shards",
|
|
"Flawed Focus Crystals",
|
|
"Focus Crystals",
|
|
"Refined Focus Crystals",
|
|
"Exquisite Focus Crystals",
|
|
],
|
|
"Alloys": [
|
|
"Salvaged Alloys",
|
|
"Galvanising Alloys",
|
|
"Phase Alloys",
|
|
"Proto Light Alloys",
|
|
"Proto Radiolic Alloys",
|
|
],
|
|
},
|
|
MaterialType.encoded: {
|
|
"Emission Data": [
|
|
"Exceptional Scrambled Emission Data",
|
|
"Irregular Emission Data",
|
|
"Unexpected Emission Data",
|
|
"Decoded Emission Data",
|
|
"Abnormal Compact Emissions Data",
|
|
],
|
|
"Wake Scans": [
|
|
"Atypical Disrupted Wake Echoes",
|
|
"Anomalous FSD Telemetry",
|
|
"Strange Wake Solutions",
|
|
"Eccentric Hyperspace Trajectories",
|
|
"Datamined Wake Exceptions",
|
|
],
|
|
"Shield Data": [
|
|
"Distorted Shield Cycle Recordings",
|
|
"Inconsistent Shield Soak Analysis",
|
|
"Untypical Shield Scans",
|
|
"Aberrant Shield Pattern Analysis",
|
|
"Peculiar Shield Frequency Data",
|
|
],
|
|
"Encryption Files": [
|
|
"Unusual Encrypted Files",
|
|
"Tagged Encryption Codes",
|
|
"Open Symmetric Keys",
|
|
"Atypical Encryption Archives",
|
|
"Adaptive Encryptors Capture",
|
|
],
|
|
"Data Archives": [
|
|
"Anomalous Bulk Scan Data",
|
|
"Unidentified Scan Archives",
|
|
"Classified Scan Databanks",
|
|
"Divergent Scan Data",
|
|
"Classified Scan Fragment",
|
|
],
|
|
"Encoded Firmware": [
|
|
"Specialised Legacy Firmware",
|
|
"Modified Consumer Firmware",
|
|
"Cracked Industrial Firmware",
|
|
"Security Firmware Patch",
|
|
"Modified Embedded Firmware",
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Material:
|
|
name: str
|
|
type_: MaterialType
|
|
category: str
|
|
grade: int
|
|
|
|
def trade_ratio(self, other: "Material") -> typing.Optional[fractions.Fraction]:
|
|
if self.type_ != other.type_:
|
|
return None
|
|
return trade.ratio(self.grade, other.grade, self.category != other.category)
|
|
|
|
|
|
materials: typing.Dict[str, Material] = {
|
|
name: Material(name, type_, category, grade)
|
|
for type_, categories in categorized.items()
|
|
for category, names in categories.items()
|
|
for grade, name in enumerate(names)
|
|
}
|
|
|
|
|
|
class Inventory(collections.UserDict):
|
|
"""A mapping of every available material with an associated quantity."""
|
|
|
|
def __init__(
|
|
self,
|
|
items: typing.Optional[typing.Union[typing.Dict[str, int], "Inventory"]] = None,
|
|
) -> None:
|
|
self.data = {name: 0 for name in materials}
|
|
if items:
|
|
self.update(items)
|
|
|
|
def __setitem__(self, key, value) -> None:
|
|
if key not in materials:
|
|
raise KeyError(key)
|
|
if value < 0:
|
|
raise ValueError(value)
|
|
super().__setitem__(key, value)
|
|
|
|
def has(self, items: typing.Union[typing.Dict[str, int], "Inventory"]) -> bool:
|
|
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()})
|
|
|
|
def __sub__(self, other: "Inventory") -> "Inventory":
|
|
return Inventory({name: self[name] - qty for name, qty in other.items()})
|
|
|
|
|
|
class Materials(Inventory):
|
|
"""Same as Inventory, but omits zeroed materials."""
|
|
|
|
def __init__(
|
|
self,
|
|
items: typing.Optional[typing.Union[typing.Dict[str, int], "Inventory"]] = None,
|
|
) -> None:
|
|
self.data: typing.Dict[str, int] = {}
|
|
if items:
|
|
self.update(items)
|
|
|
|
def __setitem__(self, key: str, value: int) -> None:
|
|
if key not in materials:
|
|
raise KeyError(key)
|
|
if value < 0:
|
|
raise ValueError(value)
|
|
if value == 0:
|
|
return
|
|
super().__setitem__(key, value)
|
|
|
|
def __getitem__(self, key: str) -> int:
|
|
if key not in materials:
|
|
raise KeyError(key)
|
|
return self.data.get(key, 0)
|
|
|
|
def __add__(self, other: "Inventory") -> "Materials":
|
|
return Materials({name: self[name] + other[name] for name in materials})
|
|
|
|
def __sub__(self, other: "Inventory") -> "Materials":
|
|
return Materials({name: self[name] - other[name] for name in materials})
|