Files
gausse/src/gausse/components/schema.py
jze9 13c1d417d6 Add shop links, full dimensions, and fix the flight animation
- Every component now has a `url` (schema + JSON) pointing to the shop it
  was priced from; surfaced in the run detail and the BOM (new "Купить"
  column). Wire/switch/capacitor entries also expose gauge, ratings,
  single-vs-bank values; detail reports coil inner/outer diameter (=tube
  outer), tube inner bore + wall, projectile mass in grams and bore fit.
- Animation was wrong: it stitched flight+discharge segments by sorting on
  time, which tore the trajectory into discontinuities. Rebuilt it
  sequentially -- coast (ballistic) between discharges + exact discharge
  trajectory, global x = coil center + local discharge_x -- so the slug
  moves continuously and coils sit at their real positions. Cleaner
  visuals: labeled coils that glow gold on discharge, blue slug.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 15:44:26 +05:00

112 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Типизированные описания реальных, продающихся в розницу компонентов."""
from dataclasses import dataclass
from typing import Literal
@dataclass(frozen=True)
class WireSpec:
part_id: str
material: Literal["copper", "aluminum"]
gauge_mm: float
insulation_od_mm: float
resistivity_ohm_m: float
max_current_a: float
price_per_m: float
source: str
url: str | None = None # прямая ссылка на магазин, где купить
@dataclass(frozen=True)
class CapacitorSpec:
part_number: str
capacitance_uf: float
voltage_v: float
esr_ohm: float
max_current_a: float
price: float
source: str
url: str | None = None
@dataclass(frozen=True)
class CapacitorBank:
"""Батарея из одинаковых конденсаторов: n_series (напряжение) × n_parallel (ток/ёмкость).
Последовательное соединение складывает напряжение и ESR, делит ёмкость;
параллельное — складывает ёмкость, максимальный ток и делит ESR. Итоговая
батарея выставляет те же поля, что и одиночный конденсатор
(`capacitance_uf`, `voltage_v`, `esr_ohm`, `max_current_a`, `price`),
поэтому используется как drop-in замена `CapacitorSpec` в StageConfig.
"""
base_part_number: str
n_series: int
n_parallel: int
capacitance_uf: float
voltage_v: float
esr_ohm: float
max_current_a: float
price: float
url: str | None = None
@property
def count(self) -> int:
return self.n_series * self.n_parallel
@classmethod
def from_spec(cls, spec: "CapacitorSpec", n_series: int, n_parallel: int) -> "CapacitorBank":
n_series = max(1, int(n_series))
n_parallel = max(1, int(n_parallel))
return cls(
base_part_number=spec.part_number,
n_series=n_series,
n_parallel=n_parallel,
capacitance_uf=spec.capacitance_uf * n_parallel / n_series,
voltage_v=spec.voltage_v * n_series,
esr_ohm=spec.esr_ohm * n_series / n_parallel,
max_current_a=spec.max_current_a * n_parallel,
price=spec.price * n_series * n_parallel,
url=spec.url,
)
@dataclass(frozen=True)
class SwitchSpec:
part_number: str
kind: Literal["SCR", "MOSFET", "IGBT"]
max_current_a: float
max_voltage_v: float
on_resistance_ohm: float | None
on_voltage_drop_v: float | None
turn_on_time_ns: float
price: float
source: str
url: str | None = None
@dataclass(frozen=True)
class SensorSpec:
part_number: str
kind: Literal["inductive", "optical", "hall"]
propagation_delay_ns: float
price: float
source: str
sensitivity_v_per_mps: float | None = None
threshold_v: float | None = None
url: str | None = None
@dataclass(frozen=True)
class ProjectileMaterialSpec:
name: str
density_kg_m3: float
mu_r: float
b_sat_tesla: float
price_per_kg: float
source: str
# электрическое удельное сопротивление — для расчёта вихревых потерь в снаряде
# (сплошной проводник в импульсном поле). Дефолт ~ конструкционная сталь.
resistivity_ohm_m: float = 1.6e-7
url: str | None = None