feat: named case-result load combinations with full GUI support
Snapshots the current development tree, headlined by proper load combinations (user request): a reusable LoadCombination entity of weighted completed static-case results (e.g. 1.2xDead + 1.6xLive). - core: LoadCombination/LoadCombinationItem entities, Project integration (lookup, unique ids, reference validation) - services: combinations.py (linear superposition + envelope), exported via services __init__ - commands: undoable Add/Delete/Update for combinations - GUI: Load Combinations manager dialog, Run-dialog evaluation, envelope display in Results panel, Combinations tab in Table dock - tests: unit coverage (validation, math, error paths) + integration superposition check vs a single factored run
This commit is contained in:
commit
f361fee969
560 changed files with 178701 additions and 0 deletions
74
tools/gidopensees_import/schema_model.py
Normal file
74
tools/gidopensees_import/schema_model.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
"""
|
||||
Pydantic v2 intermediate representation for GiD schema files (.mat / .cnd).
|
||||
|
||||
Each parsed MATERIAL or CONDITION block becomes an EntrySpec. Fields within a
|
||||
block become FieldSpec objects. DEPENDENCIES lines are normalised into
|
||||
DependencyRule / DependencyAction objects. The final output is a CatalogSpec
|
||||
(serialisable to JSON via model_dump_json()).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class DependencyAction(BaseModel):
|
||||
"""One action inside a DEPENDENCIES rule: RESTORE, HIDE, or SET a field."""
|
||||
|
||||
action: Literal["RESTORE", "HIDE", "SET"]
|
||||
field: str
|
||||
target: str # "#CURRENT#" or a literal value
|
||||
|
||||
|
||||
class DependencyRule(BaseModel):
|
||||
"""A complete DEPENDENCIES clause: when trigger matches, apply actions."""
|
||||
|
||||
trigger: str
|
||||
actions: list[DependencyAction]
|
||||
|
||||
|
||||
class FieldSpec(BaseModel):
|
||||
"""One QUESTION block inside a MATERIAL or CONDITION entry."""
|
||||
|
||||
name: str
|
||||
widget_type: Literal["CB", "UNITS", "MAT", "SCALAR", "TUPLE"]
|
||||
options: list[str] = Field(default_factory=list)
|
||||
default: str = ""
|
||||
width_hint: int | None = None
|
||||
help_text: str = ""
|
||||
image: str = ""
|
||||
state: str | None = None # "HIDDEN" | "DISABLED" | None
|
||||
tkwidgets: list[str] = Field(default_factory=list)
|
||||
dependencies: list[DependencyRule] = Field(default_factory=list)
|
||||
section_title: str | None = None # enclosing TITLE: context
|
||||
|
||||
|
||||
class EntrySpec(BaseModel):
|
||||
"""One MATERIAL or CONDITION block."""
|
||||
|
||||
name: str
|
||||
book: str
|
||||
source_type: Literal["MATERIAL", "CONDITION"]
|
||||
comment: str = ""
|
||||
image: str = ""
|
||||
tkwidgets: list[str] = Field(default_factory=list)
|
||||
fields: list[FieldSpec] = Field(default_factory=list)
|
||||
condtype: str = "" # CONDITION-only: CONDTYPE value
|
||||
condmeshtype: str = "" # CONDITION-only: CONDMESHTYPE value
|
||||
|
||||
|
||||
class BookSpec(BaseModel):
|
||||
"""A BOOK section grouping related entries."""
|
||||
|
||||
name: str
|
||||
source: Literal["mat", "cnd"]
|
||||
entries: list[EntrySpec] = Field(default_factory=list)
|
||||
|
||||
|
||||
class CatalogSpec(BaseModel):
|
||||
"""Top-level output: all books from the .mat and .cnd files."""
|
||||
|
||||
mat_books: list[BookSpec] = Field(default_factory=list)
|
||||
cnd_books: list[BookSpec] = Field(default_factory=list)
|
||||
Loading…
Reference in a new issue