188 lines
8.7 KiB
Python
188 lines
8.7 KiB
Python
from __future__ import annotations
|
|
|
|
import uuid
|
|
from datetime import datetime, timezone
|
|
|
|
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, Numeric, String, Text, Uuid
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.extensions import db
|
|
|
|
|
|
def utcnow() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
class TimestampMixin:
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), default=utcnow, nullable=False
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), default=utcnow, onupdate=utcnow, nullable=False
|
|
)
|
|
|
|
|
|
class EngineFamily(TimestampMixin, db.Model):
|
|
__tablename__ = "engine_families"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
engine_name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True)
|
|
part_name: Mapped[str | None] = mapped_column(String(255))
|
|
cycle: Mapped[str | None] = mapped_column(String(120))
|
|
size_m: Mapped[float | None] = mapped_column(Numeric(8, 3))
|
|
entry_cost: Mapped[int | None] = mapped_column(Integer)
|
|
|
|
variants: Mapped[list["EngineVariant"]] = relationship(
|
|
back_populates="family",
|
|
cascade="all, delete-orphan",
|
|
lazy="selectin",
|
|
order_by="EngineVariant.source_sheet_row",
|
|
)
|
|
|
|
|
|
class EngineVariant(TimestampMixin, db.Model):
|
|
__tablename__ = "engine_variants"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
family_id: Mapped[uuid.UUID] = mapped_column(
|
|
Uuid, ForeignKey("engine_families.id", ondelete="CASCADE"), nullable=False, index=True
|
|
)
|
|
fuel_type: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
work_env: Mapped[str | None] = mapped_column(String(32))
|
|
sl_isp: Mapped[float | None] = mapped_column(Numeric(10, 3))
|
|
vac_isp: Mapped[float | None] = mapped_column(Numeric(10, 3))
|
|
min_thrust_kn: Mapped[float | None] = mapped_column(Numeric(12, 3))
|
|
max_thrust_kn: Mapped[float | None] = mapped_column(Numeric(12, 3))
|
|
mass_t: Mapped[float | None] = mapped_column(Numeric(10, 4))
|
|
twr: Mapped[float | None] = mapped_column(Numeric(12, 4))
|
|
throttle_ratio: Mapped[float | None] = mapped_column(Numeric(8, 4))
|
|
tvc_deg: Mapped[float | None] = mapped_column(Numeric(8, 3))
|
|
price_kd: Mapped[int | None] = mapped_column(Integer)
|
|
ignitions: Mapped[int | None] = mapped_column(Integer)
|
|
has_unlimited_ignitions: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
|
mod_source: Mapped[str | None] = mapped_column(String(120))
|
|
engine_note: Mapped[str | None] = mapped_column(Text)
|
|
config_name: Mapped[str | None] = mapped_column(String(255), index=True)
|
|
tech_required: Mapped[str | None] = mapped_column(String(120))
|
|
config_note: Mapped[str | None] = mapped_column(Text)
|
|
source_sheet_row: Mapped[int | None] = mapped_column(Integer)
|
|
|
|
family: Mapped[EngineFamily] = relationship(back_populates="variants")
|
|
|
|
|
|
class CommunicationPart(TimestampMixin, db.Model):
|
|
__tablename__ = "communication_parts"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
part_name: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
|
|
display_name: Mapped[str | None] = mapped_column(String(255))
|
|
mass_t: Mapped[float | None] = mapped_column(Numeric(10, 4))
|
|
is_active: Mapped[bool | None] = mapped_column(Boolean)
|
|
is_deployable: Mapped[bool | None] = mapped_column(Boolean)
|
|
antenna_type: Mapped[str | None] = mapped_column(String(120))
|
|
deployed_diameter_m: Mapped[float | None] = mapped_column(Numeric(10, 3))
|
|
range_raw: Mapped[float | None] = mapped_column(Numeric(24, 3))
|
|
range_km: Mapped[float | None] = mapped_column(Numeric(24, 3))
|
|
range_au: Mapped[float | None] = mapped_column(Numeric(18, 6))
|
|
range_light_year: Mapped[float | None] = mapped_column(Numeric(18, 6))
|
|
angle_deg: Mapped[float | None] = mapped_column(Numeric(10, 3))
|
|
speed: Mapped[float | None] = mapped_column(Numeric(10, 3))
|
|
idle_power_watt: Mapped[float | None] = mapped_column(Numeric(12, 4))
|
|
idle_power_text: Mapped[str | None] = mapped_column(String(64))
|
|
transmitting_power_watt: Mapped[float | None] = mapped_column(Numeric(12, 4))
|
|
transmitting_power_text: Mapped[str | None] = mapped_column(String(64))
|
|
source: Mapped[str | None] = mapped_column(String(120))
|
|
entry_cost: Mapped[int | None] = mapped_column(Integer)
|
|
cost: Mapped[int | None] = mapped_column(Integer)
|
|
description: Mapped[str | None] = mapped_column(Text)
|
|
rescale_factor: Mapped[float | None] = mapped_column(Numeric(8, 3))
|
|
tweakscale: Mapped[str | None] = mapped_column(String(64))
|
|
is_feeder: Mapped[bool | None] = mapped_column(Boolean)
|
|
tech_required: Mapped[str | None] = mapped_column(String(120))
|
|
note: Mapped[str | None] = mapped_column(Text)
|
|
|
|
|
|
class TankSpec(TimestampMixin, db.Model):
|
|
__tablename__ = "tank_specs"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
tank_name: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
|
|
fuel_type: Mapped[str | None] = mapped_column(String(120))
|
|
dry_mass_t: Mapped[float | None] = mapped_column(Numeric(10, 4))
|
|
fuel_mass_t: Mapped[float | None] = mapped_column(Numeric(10, 4))
|
|
wet_mass_t: Mapped[float | None] = mapped_column(Numeric(10, 4))
|
|
tank_volume_l: Mapped[float | None] = mapped_column(Numeric(12, 3))
|
|
mass_ratio: Mapped[float | None] = mapped_column(Numeric(12, 4))
|
|
kiloliters_per_ton: Mapped[float | None] = mapped_column(Numeric(12, 4))
|
|
vehicle_name: Mapped[str | None] = mapped_column(String(120))
|
|
source: Mapped[str | None] = mapped_column(String(120))
|
|
note: Mapped[str | None] = mapped_column(Text)
|
|
|
|
|
|
class VehicleCost(TimestampMixin, db.Model):
|
|
__tablename__ = "vehicle_costs"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
vehicle_name: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
|
|
launch_price: Mapped[int | None] = mapped_column(Integer)
|
|
source: Mapped[str | None] = mapped_column(String(120))
|
|
|
|
|
|
class Asset(TimestampMixin, db.Model):
|
|
__tablename__ = "assets"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True, index=True)
|
|
asset_type: Mapped[str] = mapped_column(String(120), nullable=False, index=True)
|
|
is_retired: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
|
program: Mapped[str | None] = mapped_column(String(255))
|
|
home_region: Mapped[str | None] = mapped_column(String(120))
|
|
note: Mapped[str | None] = mapped_column(Text)
|
|
|
|
log_entries: Mapped[list["AssetLogEntry"]] = relationship(
|
|
back_populates="asset",
|
|
cascade="all, delete-orphan",
|
|
lazy="selectin",
|
|
order_by="AssetLogEntry.start_at",
|
|
)
|
|
|
|
|
|
class AssetLogEntry(TimestampMixin, db.Model):
|
|
__tablename__ = "asset_log_entries"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
asset_id: Mapped[uuid.UUID] = mapped_column(
|
|
Uuid, ForeignKey("assets.id", ondelete="CASCADE"), nullable=False, index=True
|
|
)
|
|
entry_kind: Mapped[str] = mapped_column(String(16), nullable=False)
|
|
title: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
state_label: Mapped[str | None] = mapped_column(String(120))
|
|
mission_label: Mapped[str | None] = mapped_column(String(255))
|
|
location: Mapped[str | None] = mapped_column(String(255))
|
|
start_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True)
|
|
end_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
|
summary: Mapped[str | None] = mapped_column(Text)
|
|
note: Mapped[str | None] = mapped_column(Text)
|
|
|
|
asset: Mapped[Asset] = relationship(back_populates="log_entries")
|
|
state_nodes: Mapped[list["AssetStateNode"]] = relationship(
|
|
back_populates="entry",
|
|
cascade="all, delete-orphan",
|
|
lazy="selectin",
|
|
order_by="AssetStateNode.at_time",
|
|
)
|
|
|
|
|
|
class AssetStateNode(TimestampMixin, db.Model):
|
|
__tablename__ = "asset_state_nodes"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
|
|
entry_id: Mapped[uuid.UUID] = mapped_column(
|
|
Uuid, ForeignKey("asset_log_entries.id", ondelete="CASCADE"), nullable=False, index=True
|
|
)
|
|
title: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
detail: Mapped[str | None] = mapped_column(Text)
|
|
at_time: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True)
|
|
|
|
entry: Mapped[AssetLogEntry] = relationship(back_populates="state_nodes")
|