sde_types_market & rework infra

This commit is contained in:
Tom Villette
2023-10-03 18:03:41 +02:00
parent b90e7028b7
commit d8aa735a55
10 changed files with 251 additions and 126 deletions

16
.env.template Normal file
View File

@@ -0,0 +1,16 @@
ESI_CLIENT_ID=
ESI_SECRET_KEY=
ESI_CALLBACK_URL=
ESI_USER_AGENT=
REDIS_URL=
REDIS_PORT=
REDIS_USER=
REDIS_PASSWORD=
REDIS_SSL=
SQLITE_DB_PATH=
POSTGRES_PASSWORD=
POSTGRES_USER=
POSTGRES_DB=

View File

@@ -1,24 +0,0 @@
FROM python:3.11-slim as sde_import
WORKDIR /app
COPY requirements.txt .
RUN python -m pip install --no-cache-dir --upgrade -r requirements.txt
COPY --chown=appuser:appuser eveal /app/eveal
COPY --chown=appuser:appuser static_eve /app/static_eve
COPY --chown=appuser:appuser import_sde.py /app/import_sde.py
RUN python import_sde.py
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
RUN adduser -u 5678 --disabled-password --gecos "" appuser
WORKDIR /app
COPY --from=sde_import --chown=appuser:appuser /app/sde.db /app/sde.db
COPY requirements.txt .
RUN python -m pip install --no-cache-dir --upgrade -r requirements.txt
COPY --chown=appuser:appuser eveal /app/eveal
USER appuser
CMD ["uvicorn", "eveal.main:app", "--host", "0.0.0.0", "--port", "8000"]

62
docker-compose.dev.yml Normal file
View File

@@ -0,0 +1,62 @@
version: '3'
services:
eveal:
image: eveal:latest
build:
context: .
dockerfile: Dockerfile
env_file:
- .env
ports:
- 8000:8000
volumes:
- ./eveal:/app/eveal
- ./eveal.db:/app/eveal.db
command: ["uvicorn", "eveal.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
depends_on:
redis:
condition: service_healthy
# db:
# condition: service_healthy
# elasticsearch:
# condition: service_healthy
redis:
image: redis:latest
ports:
- 6379:6379
healthcheck:
test: redis-cli ping
interval: 3s
# db:
# image: postgres:13-alpine
# ports:
# - 5432:5432
# volumes:
# - ./dump_sde.sql:/docker-entrypoint-initdb.d/init_sde.sql
# - mabras_dbdata:/var/lib/postgresql/data
# environment:
# - POSTGRES_PASSWORD
# - POSTGRES_USER
# - POSTGRES_DB
# healthcheck:
# test: pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
# interval: 10s
# timeout: 3s
# retries: 3
# elasticsearch:
# image: elasticsearch:latest
# ports:
# - 9200:9200
# environment:
# - discovery.type=single-node
# - cluster.name=elasticsearch
# - bootstrap.memory_lock=true
# - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
# healthcheck:
# test: curl -s http://elasticsearch:9200 >/dev/null || exit 1
# interval: 10s
# timeout: 3s
# retries: 3

View File

@@ -1,12 +1,13 @@
import os
from sqlmodel import create_engine, Session from sqlmodel import create_engine, Session
from eveal import models_sde from eveal import models_sde
sqlite_sde_file_name = "sde.db" sqlite_file_name = os.getenv("SQLITE_DB_PATH", "eveal.db")
sde_engine = create_engine(f"sqlite:///{sqlite_sde_file_name}", echo=True, future=True, connect_args={"check_same_thread": False}) engine = create_engine(f"sqlite:///{sqlite_file_name}", echo=True, future=True, connect_args={"check_same_thread": False})
def get_sde_session(): def get_session():
db = Session(sde_engine) db = Session(engine)
try: try:
yield db yield db
finally: finally:

32
eveal/esi.py Normal file
View File

@@ -0,0 +1,32 @@
import datetime
import os
import redis
import pickle
from esy.client import ESIClient
from esy.auth import ESIAuthenticator
class ESICache(object):
def __init__(self, redis_url: str, redis_port: int, db: str):
self._r = redis.Redis(host=redis_url, port=redis_port, db=db)
# self._r = redis.StrictRedis(host=redis_url, port=redis_port, db=db)
def get(self, key):
# return pickle.loads(self._r[key])
return pickle.loads(self._r.get(key))
def set(self, key, data, cached_until: datetime.datetime):
self._r.set(key, pickle.dumps(data), ex=cached_until - datetime.datetime.now(datetime.timezone.utc))
def __contains__(self, item):
# return item in self._r
return self._r.exists(item)
esi_client_id = os.getenv('ESI_CLIENT_ID')
esi_secret_key = os.getenv('ESI_SECRET_KEY')
esi_cache = ESICache(redis_url=os.getenv("REDIS_URL"), redis_port=int(os.getenv("REDIS_PORT")), db="0")
esi_client = ESIClient.get_client(user_agent=os.getenv('ESI_USER_AGENT'), cache=esi_cache)
esi_auth = ESIAuthenticator()

View File

@@ -6,10 +6,10 @@ from typing import List, Annotated, Tuple, Literal
from sqlmodel import SQLModel, Session, select from sqlmodel import SQLModel, Session, select
from eveal.schemas import Evepraisal, PriceReprocess from eveal.schemas import Evepraisal, PriceReprocess
from eveal.database import sde_engine, get_sde_session from eveal.database import engine, get_session
from eveal import models_sde from eveal import models_sde, esi
SQLModel.metadata.create_all(sde_engine) # remove? db should be created by import_sde.py SQLModel.metadata.create_all(engine) # use alembic?
app = FastAPI() app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"]) app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
@@ -21,13 +21,13 @@ async def root():
@app.post("/reprocess/") @app.post("/reprocess/")
async def reprocess(ep_items: Evepraisal, ep_mat: Evepraisal, efficiency: float = .55, sde: Session = Depends(get_sde_session)) -> List[PriceReprocess]: async def reprocess(ep_items: Evepraisal, ep_mat: Evepraisal, efficiency: float = .55, db: Session = Depends(get_session)) -> List[PriceReprocess]:
matprices = {item.typeID: {'sell': item.prices.sell.min, 'buy': item.prices.buy.max} for item in ep_mat.items} matprices = {item.typeID: {'sell': item.prices.sell.min, 'buy': item.prices.buy.max} for item in ep_mat.items}
item_reprocess: List[PriceReprocess] = [] item_reprocess: List[PriceReprocess] = []
for rawitem in ep_items.items: for rawitem in ep_items.items:
# item = sde.exec(select(models_sde.Type).where(models_sde.Type.id == rawitem.typeID)).one() # item = sde.exec(select(models_sde.Type).where(models_sde.Type.id == rawitem.typeID)).one()
item = sde.get(models_sde.Type, rawitem.typeID) item = db.get(models_sde.SDEType, rawitem.typeID)
buy_reprocess = sell_reprocess = 0.0 buy_reprocess = sell_reprocess = 0.0
for mat in item.materials.all(): for mat in item.materials.all():
buy_reprocess += matprices[mat.type.id]['buy'] * mat.quantity * efficiency buy_reprocess += matprices[mat.type.id]['buy'] * mat.quantity * efficiency
@@ -43,17 +43,29 @@ async def reprocess(ep_items: Evepraisal, ep_mat: Evepraisal, efficiency: float
@app.get("/sde/types/{sde_type}/") @app.get("/sde/types/{sde_type}/")
async def sde_types(sde_type: int | str, sde: Session = Depends(get_sde_session)) -> models_sde.Type: async def sde_types(sde_type: int | str, db: Session = Depends(get_session)) -> models_sde.SDEType:
try: try:
item = sde.get(models_sde.Type, int(sde_type)) item = db.get(models_sde.SDEType, int(sde_type))
except ValueError: except ValueError:
item = sde.exec(select(models_sde.Type).where(models_sde.Type.name == sde_type)).one() item = db.exec(select(models_sde.SDEType).where(models_sde.SDEType.name == sde_type)).one()
return item return item
@app.post("/sde/types/search") @app.post("/sde/types/search")
async def sde_types_search(query: List[Tuple[Literal["id", "name"], int | str]], sde: Session = Depends(get_sde_session)) -> List[models_sde.Type]: async def sde_types_search(query: List[Tuple[Literal["id", "name"], int | str]], db: Session = Depends(get_session)) -> List[models_sde.SDEType]:
items = [] items = []
for key, val in query: for key, val in query:
items.extend(sde.exec(select(models_sde.Type).where(getattr(models_sde.Type, key) == val)).all()) items.extend(db.exec(select(models_sde.SDEType).where(getattr(models_sde.SDEType, key) == val)).all())
return items return items
@app.get("/esi/types/{sde_type}/market/{region_id}/")
async def sde_types_market(sde_type: int | str, region_id: int | str, db: Session = Depends(get_session)):
"""Get market orders for a type in a region. example: /esi/types/22291/market/10000002/"""
"""TODO: use ESIMarketOrder"""
return list(esi.esi_client.Market.get_markets_region_id_orders(order_type="all", type_id=sde_type, region_id=region_id))
if __name__ == "__main__":
import uvicorn
uvicorn.run("eveal.main:app", host="0.0.0.0", port=8000, reload=True)

24
eveal/models_esi.py Normal file
View File

@@ -0,0 +1,24 @@
from datetime import datetime
from typing import Optional, List
from sqlmodel import SQLModel, Field, Relationship
class ESIMarketOrder(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
timestamp: datetime = Field(default_factory=datetime.utcnow, nullable=False)
region_id: int
type_id: int # TODO: link to SDE
location_id: int # TODO: link to SDE
volume_total: int
volume_remain: int
min_volume: int
order_id: int # TODO: use this as PK ? (will lose volume_remain history)
price: float
is_buy_order: bool
duration: int
issued: datetime
range: str # TODO: enum?
system_id: int # TODO: link to SDE

View File

@@ -2,107 +2,107 @@ from typing import Optional, List
from sqlmodel import SQLModel, Field, Relationship from sqlmodel import SQLModel, Field, Relationship
class Icon(SQLModel, table=True): class SDEIcon(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
description: Optional[str] = None description: Optional[str] = None
iconFile: str iconFile: str
categories: List['Category'] = Relationship(back_populates="icon") categories: List['SDECategory'] = Relationship(back_populates="icon")
groups: List['Group'] = Relationship(back_populates="icon") groups: List['SDEGroup'] = Relationship(back_populates="icon")
marketgroups: List['MarketGroup'] = Relationship(back_populates="icon") marketgroups: List['SDEMarketGroup'] = Relationship(back_populates="icon")
types: List['Type'] = Relationship(back_populates="icon") types: List['SDEType'] = Relationship(back_populates="icon")
class Category(SQLModel, table=True): class SDECategory(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
icon_id: Optional[int] = Field(default=None, foreign_key="icon.id") icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
icon: Optional[Icon] = Relationship(back_populates="categories") icon: Optional[SDEIcon] = Relationship(back_populates="categories")
name: str name: str
published: bool published: bool
groups: List['Group'] = Relationship(back_populates="category") groups: List['SDEGroup'] = Relationship(back_populates="category")
class Group(SQLModel, table=True): class SDEGroup(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
anchorable: bool anchorable: bool
anchored: bool anchored: bool
category_id: Optional[int] = Field(default=None, foreign_key="category.id") category_id: Optional[int] = Field(default=None, foreign_key="sdecategory.id")
category: Optional[Category] = Relationship(back_populates="groups") category: Optional[SDECategory] = Relationship(back_populates="groups")
fittableNonSingletion: bool fittableNonSingletion: bool
icon_id: Optional[int] = Field(default=None, foreign_key="icon.id") icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
icon: Optional[Icon] = Relationship(back_populates="groups") icon: Optional[SDEIcon] = Relationship(back_populates="groups")
name: str name: str
published: bool published: bool
useBasePrice: bool useBasePrice: bool
types: List['Type'] = Relationship(back_populates="group") types: List['SDEType'] = Relationship(back_populates="group")
class MarketGroup(SQLModel, table=True): class SDEMarketGroup(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
description: Optional[str] = None description: Optional[str] = None
hasTypes: bool hasTypes: bool
icon_id: Optional[int] = Field(default=None, foreign_key="icon.id") icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
icon: Optional[Icon] = Relationship(back_populates="marketgroups") icon: Optional[SDEIcon] = Relationship(back_populates="marketgroups")
name: str name: str
parent_marketgroup_id: Optional[int] = Field(default=None, foreign_key="marketgroup.id") parent_marketgroup_id: Optional[int] = Field(default=None, foreign_key="sdemarketgroup.id")
parent_marketgroup: Optional['MarketGroup'] = Relationship(back_populates="children_marketgroups", parent_marketgroup: Optional['SDEMarketGroup'] = Relationship(back_populates="children_marketgroups",
sa_relationship_kwargs={"remote_side": 'MarketGroup.id'}) # workaround for self reference: https://github.com/tiangolo/sqlmodel/issues/127#issuecomment-1224135123 sa_relationship_kwargs={"remote_side": 'SDEMarketGroup.id'}) # workaround for self reference: https://github.com/tiangolo/sqlmodel/issues/127#issuecomment-1224135123
children_marketgroups: List['MarketGroup'] = Relationship(back_populates="parent_marketgroup") children_marketgroups: List['SDEMarketGroup'] = Relationship(back_populates="parent_marketgroup")
types: List['Type'] = Relationship(back_populates="marketgroup") types: List['SDEType'] = Relationship(back_populates="marketgroup")
class Type(SQLModel, table=True): class SDEType(SQLModel, table=True):
id: int = Field(primary_key=True) id: int = Field(primary_key=True)
group_id: Optional[int] = Field(default=None, foreign_key="group.id") group_id: Optional[int] = Field(default=None, foreign_key="sdegroup.id")
group: Optional[Group] = Relationship(back_populates="types") group: Optional[SDEGroup] = Relationship(back_populates="types")
marketgroup_id: Optional[int] = Field(default=None, foreign_key="marketgroup.id") marketgroup_id: Optional[int] = Field(default=None, foreign_key="sdemarketgroup.id")
marketgroup: Optional[MarketGroup] = Relationship(back_populates="types") marketgroup: Optional[SDEMarketGroup] = Relationship(back_populates="types")
name: str name: str
published: bool = False published: bool = False
description: Optional[str] = None description: Optional[str] = None
basePrice: Optional[float] = None basePrice: Optional[float] = None
icon_id: Optional[int] = Field(default=None, foreign_key="icon.id") icon_id: Optional[int] = Field(default=None, foreign_key="sdeicon.id")
icon: Optional[Icon] = Relationship(back_populates="types") icon: Optional[SDEIcon] = Relationship(back_populates="types")
volume: Optional[float] = None volume: Optional[float] = None
portionSize: int portionSize: int
materials: List['TypeMaterial'] = Relationship(back_populates="type", materials: List['SDETypeMaterial'] = Relationship(back_populates="type",
sa_relationship_kwargs={"foreign_keys": '[TypeMaterial.type_id]'}) # https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1537445078 sa_relationship_kwargs={"foreign_keys": '[SDETypeMaterial.type_id]'}) # https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1537445078
material_of: List['TypeMaterial'] = Relationship(back_populates="material_type", material_of: List['SDETypeMaterial'] = Relationship(back_populates="material_type",
sa_relationship_kwargs={"foreign_keys": '[TypeMaterial.material_type_id]'}) # https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1537445078 sa_relationship_kwargs={"foreign_keys": '[SDETypeMaterial.material_type_id]'}) # https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1537445078
class TypeMaterial(SQLModel, table=True): class SDETypeMaterial(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
type_id: Optional[int] = Field(default=None, foreign_key="type.id") type_id: Optional[int] = Field(default=None, foreign_key="sdetype.id")
type: Optional[Type] = Relationship(back_populates="materials", type: Optional[SDEType] = Relationship(back_populates="materials",
sa_relationship_kwargs={"primaryjoin": 'TypeMaterial.type_id==Type.id', sa_relationship_kwargs={"primaryjoin": 'SDETypeMaterial.type_id==SDEType.id',
'lazy': 'joined'}) # workaround: https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1002835506 'lazy': 'joined'}) # workaround: https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1002835506
material_type_id: Optional[int] = Field(default=None, foreign_key="type.id") material_type_id: Optional[int] = Field(default=None, foreign_key="sdetype.id")
material_type: Optional[Type] = Relationship(back_populates="material_of", material_type: Optional[SDEType] = Relationship(back_populates="material_of",
sa_relationship_kwargs={"primaryjoin": 'TypeMaterial.material_type_id==Type.id', sa_relationship_kwargs={"primaryjoin": 'SDETypeMaterial.material_type_id==SDEType.id',
'lazy': 'joined'}) # workaround: https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1002835506 'lazy': 'joined'}) # workaround: https://github.com/tiangolo/sqlmodel/issues/10#issuecomment-1002835506
quantity: int quantity: int

View File

@@ -1,14 +1,14 @@
import yaml import yaml
from eveal.database import sde_engine, sqlite_sde_file_name from eveal.database import engine, sqlite_file_name
from sqlmodel import Session, SQLModel from sqlmodel import Session, SQLModel
from eveal import models_sde from eveal import models_sde
import os import os
try: try:
os.remove(sqlite_sde_file_name) os.remove(sqlite_file_name)
except: except:
pass pass
SQLModel.metadata.create_all(sde_engine) SQLModel.metadata.create_all(engine)
print("Importing SDE data...") print("Importing SDE data...")
@@ -16,9 +16,9 @@ print("Importing icons...")
with open("static_eve/sde/fsd/iconIDs.yaml", "r", encoding="utf-8") as f: with open("static_eve/sde/fsd/iconIDs.yaml", "r", encoding="utf-8") as f:
icons = yaml.safe_load(f) icons = yaml.safe_load(f)
with Session(sde_engine) as db: with Session(engine) as db:
for id, icon in icons.items(): for id, icon in icons.items():
db.add(models_sde.Icon(id=id, **icon)) db.add(models_sde.SDEIcon(id=id, **icon))
db.commit() db.commit()
@@ -26,14 +26,14 @@ print("Importing categories...")
with open("static_eve/sde/fsd/categoryIDs.yaml", "r", encoding="utf-8") as f: with open("static_eve/sde/fsd/categoryIDs.yaml", "r", encoding="utf-8") as f:
categories = yaml.safe_load(f) categories = yaml.safe_load(f)
with Session(sde_engine) as db: with Session(engine) as db:
for id, category in categories.items(): for id, category in categories.items():
if category["published"] == False: if category["published"] == False:
continue continue
db.add(models_sde.Category(id=id, db.add(models_sde.SDECategory(id=id,
icon_id=category['iconID'] if 'iconID' in category else None, icon_id=category['iconID'] if 'iconID' in category else None,
name=category['name']['en'], name=category['name']['en'],
published=category['published'])) published=category['published']))
db.commit() db.commit()
@@ -41,20 +41,20 @@ print("Importing groups...")
with open("static_eve/sde/fsd/groupIDs.yaml", "r", encoding="utf-8") as f: with open("static_eve/sde/fsd/groupIDs.yaml", "r", encoding="utf-8") as f:
groups = yaml.safe_load(f) groups = yaml.safe_load(f)
with Session(sde_engine) as db: with Session(engine) as db:
for id, group in groups.items(): for id, group in groups.items():
if group["published"] == False: if group["published"] == False:
continue continue
db.add(models_sde.Group(id=id, db.add(models_sde.SDEGroup(id=id,
anchorable=group['anchorable'], anchorable=group['anchorable'],
anchored=group['anchored'], anchored=group['anchored'],
category_id=group['categoryID'], category_id=group['categoryID'],
fittableNonSingletion=group['fittableNonSingleton'], fittableNonSingletion=group['fittableNonSingleton'],
icon_id=group['iconID'] if 'iconID' in group else None, icon_id=group['iconID'] if 'iconID' in group else None,
name=group['name']['en'], name=group['name']['en'],
published=group['published'], published=group['published'],
useBasePrice=group['useBasePrice'] useBasePrice=group['useBasePrice']
)) ))
db.commit() db.commit()
@@ -62,15 +62,15 @@ print("Importing marketgroups...")
with open("static_eve/sde/fsd/marketGroups.yaml", "r", encoding="utf-8") as f: with open("static_eve/sde/fsd/marketGroups.yaml", "r", encoding="utf-8") as f:
marketgroups = yaml.safe_load(f) marketgroups = yaml.safe_load(f)
with Session(sde_engine) as db: with Session(engine) as db:
for id, marketgroup in marketgroups.items(): for id, marketgroup in marketgroups.items():
db.add(models_sde.MarketGroup(id=id, db.add(models_sde.SDEMarketGroup(id=id,
description=marketgroup['descriptionID']['en'] if 'descriptionID' in marketgroup else None, description=marketgroup['descriptionID']['en'] if 'descriptionID' in marketgroup else None,
hasTypes=marketgroup['hasTypes'], hasTypes=marketgroup['hasTypes'],
icon_id=marketgroup['iconID'] if 'iconID' in marketgroup else None, icon_id=marketgroup['iconID'] if 'iconID' in marketgroup else None,
name=marketgroup['nameID']['en'], name=marketgroup['nameID']['en'],
parent_marketgroup_id=marketgroup['parentGroupID'] if 'parentGroupID' in marketgroup else None, parent_marketgroup_id=marketgroup['parentGroupID'] if 'parentGroupID' in marketgroup else None,
)) ))
db.commit() db.commit()
@@ -78,21 +78,21 @@ print("Importing types...")
with open("static_eve/sde/fsd/typeIDs.yaml", "r", encoding="utf-8") as f: with open("static_eve/sde/fsd/typeIDs.yaml", "r", encoding="utf-8") as f:
types = yaml.safe_load(f) types = yaml.safe_load(f)
with Session(sde_engine) as db: with Session(engine) as db:
for id, type in types.items(): for id, type in types.items():
if type["published"] == False: if type["published"] == False:
continue continue
db.add(models_sde.Type(id=id, db.add(models_sde.SDEType(id=id,
group_id=type['groupID'], group_id=type['groupID'],
marketgroup_id=type['marketGroupID'] if 'marketGroupID' in type else None, marketgroup_id=type['marketGroupID'] if 'marketGroupID' in type else None,
name=type['name']['en'], name=type['name']['en'],
published=type['published'], published=type['published'],
basePrice=type['basePrice'] if 'basePrice' in type else None, basePrice=type['basePrice'] if 'basePrice' in type else None,
description=type['description']['en'] if 'description' in type else None, description=type['description']['en'] if 'description' in type else None,
icon_id=type['iconID'] if 'iconID' in type else None, icon_id=type['iconID'] if 'iconID' in type else None,
portionSize=type['portionSize'], portionSize=type['portionSize'],
volume=type['volume'] if 'volume' in type else None, volume=type['volume'] if 'volume' in type else None,
)) ))
db.commit() db.commit()
@@ -100,13 +100,13 @@ print("Importing materials...")
with open("static_eve/sde/fsd/typeMaterials.yaml", "r", encoding="utf-8") as f: with open("static_eve/sde/fsd/typeMaterials.yaml", "r", encoding="utf-8") as f:
materials = yaml.safe_load(f) materials = yaml.safe_load(f)
with Session(sde_engine) as db: with Session(engine) as db:
for id, material in materials.items(): for id, material in materials.items():
for mat in material['materials']: for mat in material['materials']:
db.add(models_sde.TypeMaterial(type_id=id, db.add(models_sde.SDETypeMaterial(type_id=id,
material_id=mat['materialTypeID'], material_id=mat['materialTypeID'],
quantity=mat['quantity'] quantity=mat['quantity']
)) ))
db.commit() db.commit()

View File

@@ -1,4 +1,6 @@
fastapi fastapi
httpx httpx
uvicorn[standard] uvicorn[standard]
sqlmodel sqlmodel
esy
redis