{
  "schema": "aspen-flowsim-stream-xml-guide/v1",
  "version": "1.2.0",
  "language": "zh-CN",
  "purpose": "从 Aspen XML Results File 读取物料流结果，保留 XML 单位，并按固定 CAD 物料表槽位生成项目级写入模型。",
  "human_documentation_url": "/stream-api/",
  "schema_url": "/api/v1/stream-schema.json",
  "empty_project_template_url": "/api/v1/stream-template.json",
  "cad_vector_template_url": "/api/v1/stream-table-template.json",
  "web_discovery": {
    "pages": [
      "/stream-info/",
      "/stream-api/"
    ],
    "html_head_relations": {
      "service-desc": "/api/v1/stream-xml-guide.json",
      "describedby": "/api/v1/stream-schema.json",
      "alternate_empty_project_template": "/api/v1/stream-template.json",
      "alternate_cad_vector_template": "/api/v1/stream-table-template.json"
    },
    "json_ld_type": "TechArticle",
    "rule": "抓取任一流股页面的 HTML head，即可发现读取指南、Schema、空项目模板和 CAD 矢量模板；无需解析可见页面文案。"
  },
  "reader_implementation": "cad_aspen_agent/scripts/xml_to_stream_table.py",
  "accepted_input": {
    "root_local_name": "Plant",
    "component_selector": "Plant/ComponentsMain/COMPID/Value",
    "stream_selector": "Plant/StreamMaterial",
    "stream_id_selector": "StreamMaterial@name",
    "value_selector": "StreamMaterial/{FIELD}/Value",
    "unit_selector": "StreamMaterial/{FIELD}@unit",
    "domain_selector": "StreamMaterial/{FIELD}@domain",
    "reject_when": [
      "根节点不是 Plant",
      "缺少 ComponentsMain/COMPID",
      "没有 StreamMaterial",
      "StreamMaterial@name 为空或重复",
      "MASSFLOW、MASSFRAC 或 MOLEFRAC 的向量长度与 COMPID 数量不一致"
    ]
  },
  "field_mapping": [
    {
      "xml": "StreamMaterial@name",
      "output": "streams[].aspen_stream_id",
      "type": "string",
      "unit": null
    },
    {
      "xml": "SOURCE/Value",
      "output": "streams[].topology.source",
      "type": "string",
      "unit": null
    },
    {
      "xml": "DESTINATION/Value",
      "output": "streams[].topology.target",
      "type": "string",
      "unit": null
    },
    {
      "xml": "COMPTYPE/Value",
      "output": "streams[].state.phase",
      "type": "string",
      "unit": null
    },
    {
      "xml": "TEMP_OUT/Value",
      "output": "streams[].state.temperature",
      "type": "quantity",
      "unit": "TEMP_OUT@unit"
    },
    {
      "xml": "PRES_OUT/Value",
      "output": "streams[].state.pressure",
      "type": "quantity",
      "unit": "PRES_OUT@unit"
    },
    {
      "xml": "VFRAC_OUT,LFRAC,SFRAC",
      "output": "streams[].phase_fractions.molar",
      "type": "fraction",
      "unit": "fraction"
    },
    {
      "xml": "MASSVFRA,MASSSFRA",
      "output": "streams[].phase_fractions.mass",
      "type": "fraction",
      "unit": "fraction",
      "note": "质量液相分率仅在汽相与固相均存在时按 1-vapor-solid 派生。"
    },
    {
      "xml": "MASSFLMX/Value",
      "output": "streams[].flows.mass_flow",
      "type": "quantity",
      "unit": "MASSFLMX@unit"
    },
    {
      "xml": "VOLFLMX/Value",
      "output": "streams[].flows.volumetric_flow",
      "type": "quantity",
      "unit": "VOLFLMX@unit"
    },
    {
      "xml": "HMX,HMX_MASS,SMX,SMX_MASS,RHOMX,RHOMX_MASS,HMX_FLOW,MWMX",
      "output": "streams[].thermodynamics",
      "type": "quantity",
      "unit": "对应 XML 字段 @unit；缺失时为 null 并进入校验警告"
    },
    {
      "xml": "MASSFLOW[n]",
      "output": "streams[].components[n].mass_flow",
      "type": "quantity",
      "unit": "MASSFLOW@unit"
    },
    {
      "xml": "MASSFRAC[n]",
      "output": "streams[].components[n].mass_fraction",
      "type": "fraction",
      "unit": "fraction"
    },
    {
      "xml": "MOLEFRAC[n]",
      "output": "streams[].components[n].mole_fraction",
      "type": "fraction",
      "unit": "fraction"
    }
  ],
  "unit_rules": {
    "quantity_shape": {
      "value": "number|null",
      "unit": "string|null"
    },
    "as_exported": "每个 quantity 的 unit 逐字段复制当前 XML 元素 @unit，不使用全局固定单位，也不自动换算。",
    "fraction": "相分率、质量分率和摩尔分率固定使用语义单位 fraction，数值保持 0..1，不转成百分数。",
    "missing": "字段缺失、Value 为空或 * 写 value:null。量纲字段有数值但无 @unit 时保留 unit:null，并记录 validation.units.missing_unit_counts。",
    "mixed_units": "stream_table 行若存在多个单位，输出 units_by_stream；写入只有一个单位列的 CAD 表之前，必须先换算成一个经项目确认的统一单位。",
    "observed_in_reference_xml": {
      "note": "以下仅是 2_丁二烯终.xml 的读取证据，不是接口默认单位。",
      "TEMP_OUT": "C",
      "PRES_OUT": "BAR",
      "MASSFLMX": "KG/HR",
      "MASSFLOW": "KG/HR",
      "VOLFLMX": "L/MIN",
      "HMX": "CAL/MOL",
      "HMX_MASS": "CAL/GM",
      "SMX": "CAL/MOL-K",
      "SMX_MASS": "CAL/GM-K",
      "RHOMX": "MOL/CC",
      "RHOMX_MASS": "GM/CC",
      "HMX_FLOW": "CAL/SEC"
    }
  },
  "cad_template": {
    "geometry": "固定使用 stream-table-template.json 的 82 条 CAD LINE，不以 HTML 边框重画。",
    "column_count": 20,
    "row_count": 60,
    "field_label_column": 1,
    "unit_column": 2,
    "stream_value_columns": {
      "first": 3,
      "last": 20,
      "capacity": 18
    },
    "row_slots": {
      "stream_header": 1,
      "fixed_properties": [
        2,
        26
      ],
      "component_mass_flow": [
        27,
        42
      ],
      "mass_fraction_heading": 43,
      "component_mass_fraction": [
        44,
        59
      ],
      "volumetric_flow": 60
    },
    "component_capacity_per_section": 16,
    "unused_slots": "留空；不得移动、合并、均分或重编号源模板格线。",
    "pagination": "streams 每 18 条一页，components 每 16 个一页；最终续表为 stream_pages × component_pages 的笛卡尔积。"
  },
  "write_algorithm": [
    "读取 COMPID，保持其顺序作为所有组分向量的唯一索引。",
    "读取每个 StreamMaterial，生成 stream_results.json；项目级 PFD 编号可用 --pfd-map 覆盖。",
    "为每个量纲数值保存 value/unit，为分率保存 value/fraction；null 单元格留空。",
    "生成 stream_table.json：每行携带 cad_template_slot，每列携带 PFD 流股号。",
    "按 18 条流股和 16 个组分分页，未使用槽位保持空白。",
    "CAD 写入时，第 1 列写 row.label，第 2 列写统一 row.unit，第 3..20 列写对应 values。",
    "文字锚点取所选行列边界的几何中心，并继承源模板文字图层、字高和样式。",
    "写入项目目录 projects/{project_id}/；不得把项目数值、单位、流股或组分写回全局 database 模板。"
  ],
  "outputs": {
    "stream_results.json": "完整项目流股记录，供拓扑、布图和后续计算。",
    "stream_table.json": "按固定 CAD 模板组织的行、列、单位、槽位与分页计划。",
    "stream_table.csv": "UTF-8 BOM 人工审阅表。"
  },
  "write_service": {
    "status": "contract_only",
    "future_route": "PUT /api/v1/projects/{project_id}/streams",
    "merge_key": "aspen_stream_id",
    "current_behavior": "公共站点只发布规则和空模板，不接受项目 XML 或项目数据上传。"
  },
  "command": "python cad_aspen_agent/scripts/xml_to_stream_table.py --xml <results.xml> --project-id <project_id> --out-dir projects/<project_id> [--pfd-map stream_map.json]"
}