#!/usr/bin/env python3
"""Build the auditable 28-project smart-canteen case base.

The output deliberately separates observed project facts from scenario-derived
recommendations. Missing quantities remain blank and are rendered as 待补证.
"""

from __future__ import annotations

import csv
import re
from collections import defaultdict
from pathlib import Path


ROOT = Path(__file__).resolve().parents[7]
OUT = Path(__file__).resolve().parents[1] / "data"
LOCAL_MAIN = Path("/Users/jack/code/010-cpt/008-zhct/zhctprompt")
CAPABILITY = LOCAL_MAIN / "work/2026-08-04-smart-canteen-five-dimension-base/project-capability-base.csv"
EVIDENCE = ROOT / "modules/product/products/smart-canteen/product-solutions/2026-08-06-standard-product-project-model-gate/product-project-evidence.csv"
MODEL = ROOT / "modules/product/products/smart-canteen/product-solutions/2026-08-06-standard-product-project-model-gate/project-model-view.csv"


FIELDS = [
    "id", "name", "short_name", "scene", "scene_focus", "people", "pain",
    "front_flow", "kitchen_flow", "characteristic", "validated", "recommended_software",
    "suggested_hardware", "visual", "legend",
]


def p(pid, name, short, scene, focus, people, pain, front, kitchen, characteristic,
      validated, software, hardware, visual, legend):
    return dict(zip(FIELDS, [pid, name, short, scene, focus, people, pain, front, kitchen,
                             characteristic, validated, software, hardware, visual, legend]))


PROFILES = [
    p("P001", "三全智慧营养健康餐厅", "三全", "大型食品企业综合食堂", "收货验收、食品安全与多节点稳定运行",
      "企业员工|食堂员工|食品安全员|运营与IT人员", "高峰集中|原料验收留痕难|后厨视频巡检工作量大|多节点稳定性要求高",
      "员工到店→选餐→身份核验/支付→就餐→评价", "供应商到货→AI收货验收→入库→备餐→食品安全巡检→出品",
      "前厅交易与后厨食品安全同时覆盖，适合展示企业综合能力", "已形成AI收货秤和AI分析盒候选配置；多节点架构仍需以最终部署验收为准",
      "交易结算|账户与消费策略|移动服务|采购库存|食品安全|运营看板",
      "AI收货秤|AI分析盒|消费终端|电子菜牌|后厨摄像机|运营大屏",
      "大型食品企业园区，左侧前厅选餐结算，右侧透明后厨，后场独立收货验收区和AI视频巡检区",
      "01员工入口|02电子菜牌|03选餐档口|04消费终端|05AI收货秤|06AI分析盒与摄像机|07食品安全管理|08运营看板"),
    p("P002", "产业园智慧营养健康餐厅", "产业园", "产业园区多人群食堂", "多企业、多班次、多策略的园区用餐",
      "园区企业员工|访客|档口与食堂人员|园区运营人员", "企业与班次复杂|高峰拥堵|补贴口径不一|经营数据分散",
      "员工/访客入场→选餐→按身份匹配策略→多入口结算→就餐", "采购→入库→备餐→档口出品→库存与经营复盘",
      "真实生产库可核验，适合展示园区多人群和多策略运营", "已验证真实订单与活跃账户；硬件型号和签收数量待补证",
      "交易结算|账户组织|消费策略|移动服务|经营分析|接口管理",
      "消费终端|闸机|自助点餐机|电子菜牌|厨房打印机|运营大屏",
      "产业园双入口食堂，展示不同企业工牌员工和访客，从两侧入口汇入多个档口，后厨备餐和园区运营中心可见",
      "01园区入口A|02园区入口B|03身份识别|04多档口选餐|05消费终端|06访客支付|07后厨出品|08园区运营台"),
    p("P003", "人大附中", "人大附中", "中学校园电子菜牌场景", "菜单发布、营养公示与多屏统一管理",
      "学生|教师|后厨与档口人员|学校食堂管理员", "菜单更新慢|价格与营养信息不统一|多块屏幕维护困难|用餐高峰识别效率低",
      "师生进入→查看电子菜牌→选餐→结算→就餐", "管理员编排菜单→审核发布→多屏同步→档口出品→异常屏处理",
      "以电子菜牌和统一内容发布为核心，不应包装成全量智慧食堂", "已观察新屏14台、旧屏11台和PoE交换机1台；交易硬件待补证",
      "电子菜牌发布|菜单与价格管理|营养公示|多屏编组|内容审核|设备运维",
      "电子菜牌|PoE交换机|管理电脑|消费终端（待补证）",
      "中学校园食堂剖视图，前厅有一整排电子菜牌和学生教师，后台有菜单发布管理电脑与厨房出品区",
      "01学生入口|02教师入口|03电子菜牌墙|04档口选餐|05结算区|06菜单发布台|07PoE网络|08后厨出品"),
    p("P004", "四川射洪", "射洪", "区域机构综合食堂", "小规模真实运行与区域项目综合配置",
      "机构职工|食堂人员|管理人员|运维人员", "项目资料分散|设备清单不完整|日常运营缺少统一视图|复制方案难",
      "人员到店→选餐→结算→就餐→运营留痕", "采购→备餐→出品→留样/巡检→日结",
      "已有真实运行痕迹，但场景与BOM证据仍需补齐", "生产数据可见小规模活跃与订单；软硬件最终签收待补证",
      "交易结算|账户管理|菜单管理|食品安全|经营报表",
      "消费终端|电子菜牌|留样设备|管理电脑|厨房打印机",
      "县域机构食堂，紧凑型前厅与后厨，少量职工排队，管理员在侧边管理台查看运营数据",
      "01职工入口|02菜单展示|03选餐档口|04消费终端|05就餐区|06后厨出品|07留样区|08管理台"),
    p("P005", "城市副中心", "城市副中心", "机关园区政务云食堂", "政务云、安全分区和多节点稳定部署",
      "机关工作人员|访客|食堂人员|信息化与安全运维人员", "安全边界严格|内外网分区|高峰并发|数据库与应用高可用要求高",
      "人员入园→身份核验→选餐→策略结算→就餐", "菜单/采购→备餐→出品→食品安全→数据经安全区汇聚",
      "销售价值不只在终端，而在政务云和安全架构下的完整交付", "已形成9台服务器、OceanBase/OBProxy与安全分区的方案证据；最终验收待补证",
      "交易结算|组织账户|消费策略|移动服务|接口管理|食品安全|高可用运维",
      "消费终端|闸机|电子菜牌|安全网关|服务器集群|监控大屏",
      "机关园区食堂等距3D剖视，前厅身份核验和结算，后厨出品，右下角透明机房展示应用、数据库和安全区，不显示品牌",
      "01机关入口|02身份核验|03选餐档口|04消费结算|05后厨|06安全交换区|07应用数据库集群|08运维监控"),
    p("P006", "多样人群营养支持健康教育系统", "营养支持", "多样人群营养健康服务", "营养评估、个性化建议和健康教育闭环",
      "普通就餐者|慢病/特殊膳食人群|营养师|健康教育管理员", "营养需求差异大|食谱与个人目标脱节|干预效果难跟踪|健康教育触达不足",
      "建档→营养评估→获得推荐→选餐→查看反馈与教育内容", "营养师建模→食谱标注→人群分层→内容发布→效果复盘",
      "这是营养服务系统场景，不应强行补成完整食堂交付项目", "当前为规划/产品能力证据，人数、硬件和真实运行量均待补证",
      "健康档案|营养评估|人群分层|食谱推荐|健康教育|干预随访|数据看板",
      "健康评估终端|体测设备|营养展示屏|移动端|营养师工作站",
      "健康服务中心与轻食餐厅组合的3D剖视图，营养师工作站、评估终端、营养展示屏和个性化取餐区同屏",
      "01用户建档|02健康评估|03营养师工作站|04推荐菜单|05个性化选餐|06营养展示|07随访反馈|08健康教育"),
    p("P007", "山西焦煤", "山西焦煤", "大型工业企业职工食堂", "轮班职工高峰供餐与真实交易运营",
      "矿区/产业职工|轮班人员|食堂员工|企业后勤管理人员", "班次集中|短时间高峰|工种补贴差异|多点运营难统一",
      "轮班职工到店→身份识别→快速选餐→策略结算→离场", "按班次预测→备餐→档口出品→补菜→日结分析",
      "适合展示工业企业轮班、高峰和补贴策略", "已验证真实活跃账户和订单；终端型号与部署清单待补证",
      "交易结算|班次与账户|消费策略|补贴管理|经营分析|设备运维",
      "快速消费终端|闸机|电子菜牌|自选餐台|厨房看板|运营大屏",
      "大型煤炭工业园职工食堂，轮班职工从入口快速通过多条餐线，后厨按班次集中出餐，侧边有企业后勤运营台",
      "01班次入口|02身份识别|03电子菜牌|04多餐线|05快速结算|06后厨补菜|07就餐区|08后勤运营"),
    p("P008", "无锡新吴区区政府", "无锡新吴区", "区政府机关食堂", "电子价签、视觉结算与营养展示",
      "机关职工|访客|食堂人员|机关后勤管理员", "菜价频繁更新|人工结算慢|营养信息难公示|设备分散",
      "职工入场→查看电子价签→自选餐→视觉/人工复核结算→就餐", "菜单维护→价签同步→备餐出品→销售与营养复盘",
      "电子价签规模化和视觉结算组合是主要差异点", "已观察PC/手机端各1套、电子价签45台、视觉结算相关设备2台；为历史版本/非标证据",
      "交易结算|电子价签|菜单价格|营养展示|移动服务|经营报表",
      "电子价签|视觉结算台|消费终端|服务器|电子菜牌|管理电脑",
      "区政府机关食堂，前厅一排带电子价签的菜品，中央视觉结算台，后厨和管理发布台同时可见",
      "01机关入口|02电子价签|03自选餐线|04视觉结算|05人工复核|06就餐区|07后厨|08价签管理台"),
    p("P009", "机场", "机场", "机场内部员工高频食堂", "多工种、多餐线、高峰高频交易",
      "地勤人员|安保人员|机务人员|行政与食堂人员", "工种与班次复杂|窗口期短|排队压力大|交易连续性要求高",
      "员工到店→按餐线选餐→刷卡/身份结算→就餐→快速返岗", "按航班/班次备餐→多档口出品→实时补菜→异常交易处理→运营分析",
      "是高并发、高可用和多餐线销售的首选标杆", "注册账户9916、近30日活跃7123、累计有效订单895908、近30日订单148050；硬件观察为15台挂式POS、3台读写设备、500张卡",
      "交易结算|账户组织|消费策略|移动服务|接口管理|经营监控|异常补单",
      "挂式POS|读写器|员工卡|电子菜牌|多餐线设备|运营监控台",
      "机场员工食堂，窗外可见停机坪，地勤安保机务多工种人员进入多条餐线，后台运营监控和异常处理窗口可见",
      "01员工入口|02多餐线|03选餐档口|04挂式POS|05员工卡|06移动预订|07异常处理|08运营监控"),
    p("P010", "江苏国信", "江苏国信", "央企园区多策略食堂", "复杂消费策略、国产化与多系统接口",
      "企业员工|亲友/访客|招待人员|食堂、财务与IT人员", "身份场景多|消费策略复杂|一卡通与财务对账要求高|软硬件型号易货不对版",
      "人员选本人/亲友/招待场景→选餐→策略校验→结算→财务归集", "采购验收→备餐→食品安全→出品→对账与运营分析",
      "完整展示策略、接口、国产化和前后厅协同，也是产品定标的重点案例", "已观察PC/手机端、结算系统、4台POS、1台AI收货秤、1台AI分析盒；POS与分析盒存在来源冲突需定标",
      "交易结算|移动订餐|本人/亲友/招待策略|一卡通接口|财务对账|食品安全|采购库存|国产化部署",
      "双面POS|AI收货秤|AI分析盒|自助点餐机|电子菜牌|摄像机|服务器",
      "央企园区综合食堂，前厅区分本人餐、亲友餐、招待餐三条流线，后厨有AI收货、视频分析，右侧展示一卡通财务接口控制台",
      "01员工入口|02访客招待入口|03移动订餐|04双面POS|05策略校验|06AI收货|07食品安全|08财务接口台"),
    p("P011", "江西206", "江西206", "机构内部称重自选食堂", "称重自选、绑盘与食品安全组合",
      "内部就餐人员|食堂员工|食品安全员|后勤管理员", "自选计价慢|餐盘身份易错|设备数量多|食品安全留痕难",
      "身份/餐盘绑定→称重选餐→自动累计→结算→就餐", "收货→晨检→备餐→留样/检测→布菲炉补菜→日结",
      "称重自选设备密集，适合展示餐盘绑定与多秤协同", "已有POS、壁挂POS、称重台、布菲炉、绑盘、读卡、AI盒、留样柜和检测仪证据；部分数量冲突",
      "称重结算|餐盘绑定|账户管理|菜单计价|食品安全|设备管理|经营分析",
      "膳识智能台|布菲炉单秤|绑盘终端|POS|读卡器|AI分析盒|留样柜|检测仪",
      "机构内部食堂，中央长条称重自选餐线由多台智能秤与布菲炉组成，入口绑盘，后厨食品安全检测和留样区可见",
      "01绑盘终端|02智能餐盘|03称重自选台|04布菲炉|05POS结算|06AI分析盒|07留样检测|08运营台"),
    p("P012", "海开集团", "海开集团", "集团园区员工食堂", "园区餐饮运营与食品安全基础",
      "集团员工|园区访客|食堂人员|后勤运营人员", "园区经营分散|采购与出品留痕弱|食品安全设备孤立|数据难汇总",
      "员工/访客入场→选餐→扫码/账户结算→就餐", "扫码收货→备餐→打印分单→留样检测→经营复盘",
      "第三方设备较多，适合说明兼容接入和非标治理", "已观察留样柜1台、食品安全检测仪1台及扫码秤/打印机等非标批次；总历史硬件观察93件",
      "交易结算|账户管理|采购收货|食品安全|打印分单|经营报表|第三方设备接入",
      "扫码秤|厨房打印机|留样柜|食品安全检测仪|消费终端|管理电脑",
      "集团园区食堂，前厅员工扫码结算，后厨展示扫码收货、厨房打印、留样柜和食品安全检测台，管理台汇总数据",
      "01园区入口|02扫码结算|03选餐区|04厨房打印|05扫码收货|06留样柜|07食品检测|08运营台"),
    p("P013", "湖南体职院", "湖南体职院", "体育院校营养食堂", "运动人群分层营养与高校餐饮",
      "运动员|普通学生|教练与教师|营养师和食堂人员", "训练项目差异大|能量需求不同|训练餐与普通餐混行|营养执行难追踪",
      "身份识别→匹配训练/普通餐→选餐→结算→营养反馈", "营养师编制食谱→厨房按队伍备餐→分区出品→摄入与训练复盘",
      "突出运动营养，不应只按普通高校食堂销售", "已有注册账户痕迹但当前窗口无交易；软硬件BOM与队伍人数待补证",
      "运动员档案|营养评估|训练餐计划|菜单营养|交易结算|移动端|营养看板",
      "身份识别终端|称重自选台|营养展示屏|体测终端|移动端|营养师工作站",
      "体育院校食堂，运动员与普通学生分区用餐，营养师工作站、训练餐取餐区、称重自选台和营养大屏同屏",
      "01运动员入口|02普通学生入口|03身份识别|04训练餐区|05称重自选|06营养大屏|07营养师台|08后厨配餐"),
    p("P014", "滨州健康科技职业学院", "滨州健康学院", "高校多餐段智慧食堂", "大规模称重自选、一卡通与营养管理",
      "学生|教职工|食堂与档口人员|学校后勤/营养/IT人员", "就餐人群大|多餐段峰值高|称重设备多|一卡通与数据迁移复杂",
      "师生身份识别→绑盘/取盘→称重自选→POS/一卡通结算→就餐", "晨检→AI收货→备餐→布菲炉出品→留样→补菜与经营分析",
      "当前28案中设备规模最完整的高校综合案例之一", "已观察16台POS、72台布菲炉、72台膳识台、8台绑盘、2台晨检、2台留样秤、1台AI收货秤、4台PoE交换机及2000个餐盘；需关注型号冲突",
      "PC/手机端|一卡通|称重结算|餐盘绑定|营养管理|食品安全|数据迁移|运营分析",
      "POS|布菲炉|膳识智能台|绑盘终端|智能餐盘|晨检仪|留样秤|AI收货秤|PoE交换机",
      "大型高校食堂等距剖视，学生与教职工从入口绑盘后进入多条称重自选餐线，后厨有晨检、AI收货和留样，侧边一卡通运营台",
      "01师生入口|02绑盘取盘|03称重自选|04POS一卡通|05晨检|06AI收货|07留样区|08运营中心"),
    p("P015", "莱蒂森", "莱蒂森", "中学校园基础智慧食堂", "校园师生收银与基础管理",
      "学生|教师|食堂人员|学校后勤管理员", "课间高峰集中|人工收银慢|账户管理分散|设备型号需冻结",
      "师生入场→选餐→卧式POS结算→就餐", "菜单维护→备餐→档口出品→日结对账",
      "基础型校园食堂案例，适合标准小套餐销售", "已观察PC端1套、卧式POS 2台、读写设备1台；为第三方/非标写法",
      "交易结算|账户管理|菜单管理|日结报表|设备管理",
      "卧式POS|读写器|电子菜牌|管理电脑|厨房打印机",
      "中学校园紧凑食堂，学生教师排队选餐，两台卧式收银机结算，后厨备餐和学校后勤管理台可见",
      "01学生入口|02教师入口|03菜单展示|04选餐档口|05卧式POS|06读写器|07后厨|08管理台"),
    p("P016", "西康宾馆", "西康宾馆", "宾馆内部员工补贴食堂", "补贴策略与称重自选",
      "宾馆员工|管理人员|食堂厨师|财务与后勤人员", "员工补贴口径复杂|称重计价易错|人工对账费时|餐线效率不足",
      "员工身份识别→补贴校验→称重选餐→结算→就餐", "菜单定价→备餐→单/双秤出品→补菜→补贴与消费对账",
      "最适合展示补贴策略与单/双秤协同", "注册账户349、近30日活跃236、累计有效订单121920；已观察绑盘终端1台、单秤4台、双秤2台及PC/手机端",
      "交易结算|补贴管理|消费策略|称重计价|账户管理|移动服务|财务报表",
      "绑盘终端|单秤膳识台|双秤膳识台|消费终端|管理电脑|数据大屏",
      "宾馆员工食堂，员工先做补贴身份校验，再经过单秤和双秤自选餐台，后厨补菜、财务管理台与运营大屏同屏",
      "01员工入口|02补贴校验|03绑盘|04单秤餐台|05双秤餐台|06结算|07后厨补菜|08财务运营"),
    p("P017", "赛迪物业", "赛迪物业", "写字楼与产业园多入口食堂", "多入口、闸机与消费机协同",
      "写字楼租户员工|园区企业员工|访客|物业与食堂运营人员", "入口分散|客流峰值波动|访客与员工权限不同|物业难统一运营",
      "不同楼栋入口→闸机身份核验→餐线选餐→消费机结算→就餐/离场", "按客流备餐→档口出品→补菜→多入口交易汇总→物业分析",
      "物业型、多入口消费模式的首选标杆", "注册账户6596、近30日活跃1862、累计有效订单145955、近30日订单26703；消费机与闸机承担主要交易，型号/数量待补证",
      "交易结算|闸机通行|租户账户|访客策略|多入口管理|经营分析|设备监控",
      "闸机|消费机|电子菜牌|多餐线终端|访客机|物业运营大屏",
      "写字楼与产业园连接的中央食堂，两侧不同入口都有闸机，租户员工和园区员工汇入多餐线，物业运营中心可见",
      "01写字楼入口|02园区入口|03闸机核验|04多餐线|05消费机|06访客通道|07就餐区|08物业运营"),
    p("P018", "重庆环卫", "重庆环卫", "环卫职工集中供餐", "户外轮班人员、自动售卖与咖啡设备接入",
      "环卫一线职工|班组长|食堂/供应人员|后勤管理人员", "作业时间分散|非标准餐时|夜班补给难|外部售卖设备数据割裂",
      "职工刷卡/扫码→取标准餐或自动售卖→消费结算→补给", "按班组备餐→集中配送/出品→售卖机补货→库存与消费汇总",
      "说明食堂系统可延伸到自动售卖和咖啡自助场景", "已有独立部署与咖啡/售卖机接口方案证据；人数、交易和设备数量待补证",
      "交易结算|班组账户|补贴策略|自动售卖接入|咖啡机接入|补货库存|运营报表",
      "消费终端|自动售卖柜|咖啡机|补货手持终端|厨房打印机|运营台",
      "环卫服务站与集中食堂组合，轮班职工在非标准餐时使用自动售卖柜和咖啡机，后侧集中配餐与补货区可见",
      "01班组入口|02标准餐取餐|03消费终端|04自动售卖柜|05咖啡机|06集中配餐|07补货作业|08后勤运营"),
    p("P019", "金斯瑞", "金斯瑞", "企业食堂完整前厅", "线上订餐、现场选餐、取餐柜与复杂硬件协同",
      "企业员工|访客|食堂员工|运营/食品安全/IT人员", "高峰排队|线上线下订单并行|取餐错拿|多类设备协同难",
      "移动订餐/到店→现场选餐或到柜取餐→身份结算→就餐→评价", "订单汇总→厨房分单打印→备餐→留样→装柜→取餐核销→运营复盘",
      "前厅最全、线上线下融合最完整的企业食堂标杆", "注册账户7782、近30日活跃6459、累计有效订单874171、近30日订单259201；观察厨房打印机15台、留样柜2台、取餐柜1台、NVR 2台及PC/手机端",
      "移动订餐|交易结算|消费策略|取餐核销|厨房分单|食品安全|视频管理|经营分析",
      "自助点餐机|消费终端|厨房打印机|智能取餐柜|留样柜|NVR摄像系统|管理电脑",
      "企业食堂完整前厅与透明后厨，员工从移动订餐或现场选餐进入，厨房打印分单，右侧智能取餐柜核销，后台运营分析",
      "01自助点餐|02移动订餐|03现场选餐|04消费终端|05厨房打印|06留样柜|07取餐柜|08运营分析"),
    p("P020", "首通智城", "首通智城", "园区写字楼员工食堂", "小规模园区运营与邮储支付接口",
      "园区员工|访客|食堂人员|园区财务与运营人员", "园区规模小但支付渠道复杂|访客结算|对账分散|设备利用率需优化",
      "员工/访客入场→选餐→账户或邮储支付→结算→就餐", "备餐→出品→交易归集→支付对账→运营复盘",
      "适合展示轻量化园区套餐和银行支付接口", "注册账户263、近30日活跃37、累计有效订单2618；观察前厅设备4台和邮储支付接口证据",
      "交易结算|账户管理|访客支付|银行支付接口|对账报表|设备管理",
      "消费终端|访客支付机|电子菜牌|管理电脑|支付对账台",
      "小型园区写字楼食堂，员工和访客在同一前厅用不同支付方式结算，后厨紧凑，右侧展示银行支付对账台",
      "01员工入口|02访客入口|03电子菜单|04选餐|05账户结算|06银行支付|07后厨|08对账运营"),
    p("P021", "国康项目", "国康", "医院职工与多角色就餐", "医院职工餐、访客与售货柜接入",
      "医护人员|行政后勤|患者陪护/访客|食堂与设备运营人员", "医护班次不规律|非餐时需求|角色权限不同|售货柜与食堂账户割裂",
      "医护/访客身份识别→食堂选餐或售货柜取货→结算→记录归集", "按班次备餐→出品→售货柜补货→库存与交易统一",
      "医院多角色与非标准餐时的组合场景", "已有售货柜对接和系统模块切换方案证据；人数、订单、型号数量待补证",
      "交易结算|医护账户|访客策略|班次餐|售货柜接入|库存补货|运营分析",
      "消费终端|售货柜|身份识别终端|厨房打印机|补货手持机|运营台",
      "医院职工食堂与24小时售货区的3D剖视，医护、行政和访客分流，后厨按班次出餐，售货柜补货和运营台可见",
      "01医护入口|02访客入口|03身份识别|04职工餐线|05售货柜|06厨房分单|07补货区|08运营台"),
    p("P022", "四方达项目", "四方达", "制造企业职工食堂", "AI识别结算与双服务器部署",
      "制造企业员工|轮班人员|食堂人员|企业IT与后勤人员", "午餐高峰|人工识别菜品慢|结算差错|部署稳定性要求",
      "员工选餐→AI识别菜品→人工复核/支付→就餐", "备餐→档口出品→菜品模型维护→销售复盘",
      "小而完整的AI识别结算标准案例", "已观察AI识别结算台1台、双面POS 3台及应用/数据库双服务器方案",
      "AI识别结算|交易结算|菜品管理|账户管理|经营分析|设备运维",
      "AI识别结算台|双面POS|电子菜牌|应用服务器|数据库服务器|管理电脑",
      "制造企业食堂，员工端着餐盘经过AI识别结算台，旁边三条人工复核收银位，后厨出品与透明双服务器机柜可见",
      "01员工入口|02选餐档口|03AI识别台|04人工POS|05就餐区|06后厨|07应用服务器|08数据库运维"),
    p("P023", "网信办项目", "网信办", "机关食品安全与安全部署", "食品安全全链路、视频AI与内网安全",
      "机关职工|后厨人员|食品安全员|信息安全与后勤人员", "食品安全监管要求高|视频点位多|内网部署严格|设备型号一致性要求高",
      "职工入场→选餐→身份结算→就餐", "晨检→双摄AI收货→备餐→视频AI巡检→检测/留样→电子墨水屏公示",
      "后厨食品安全硬件最集中，适合食品安全专项销售", "已观察双摄收货秤2台、AI盒4台、晨检2台、检测仪2台、摄像机20台、PoE交换机2台、NVR 2台、留样秤2台、电子墨水屏50台和大屏2台；存在型号冲突",
      "食品安全监管|AI视频巡检|晨检|收货验收|留样检测|电子公示|内网部署|交易基础",
      "双摄AI收货秤|AI分析盒|晨检仪|检测仪|摄像机|PoE交换机|NVR|留样秤|电子墨水屏|大屏",
      "机关食堂剖视，前厅电子墨水屏公示，后厨按晨检、双摄收货、视频AI、检测、留样形成连续区域，右侧内网运维台",
      "01机关入口|02电子公示|03晨检|04双摄收货|05视频AI|06食品检测|07留样区|08内网运维"),
    p("P024", "大兴项目", "大兴", "多校区收货验收场景", "三校区AI收货和集中监管",
      "学校师生|三校区收货人员|食堂管理人员|教育后勤监管人员", "校区分散|收货标准不一|供应商验收留痕难|集中监管困难",
      "师生在各校区选餐→结算→就餐", "供应商到三校区→AI收货验收→入库→备餐→集中监管",
      "核心不是前厅，而是多校区收货标准化", "已观察AI收货秤3台，按三校区组合推定为分点配置；其他软硬件待补证",
      "收货验收|供应商管理|采购库存|食品安全|多校区监管|交易基础",
      "AI收货秤|管理电脑|供应商手持终端|监控摄像机|前厅消费终端",
      "三所学校以三个小型3D剖视单元并列，共享中央监管大屏；每个后场收货口有一台AI收货秤，前厅只做简洁示意",
      "01校区A|02校区B|03校区C|04供应商到货|05AI收货秤|06入库|07师生前厅|08集中监管"),
    p("P025", "安徽部队项目", "安徽部队", "部队集中就餐", "编制化人群、集中供餐与安全管理",
      "官兵|值勤/轮班人员|炊事人员|后勤保障与信息化人员", "就餐时间集中|编制与餐标严格|离线/内网要求|食品安全与物资保障要求高",
      "分队入场→身份/编制核验→快速取餐→就餐→离场", "物资验收→入库→按分队备餐→留样检测→集中出品→保障复盘",
      "适合讲集中供餐、内网部署和后勤保障，但项目事实仍待补齐", "当前只有项目登记，人数、订单、软件、硬件和验收均待补证",
      "编制账户|餐标策略|集中供餐|离线/内网交易|食品安全|物资库存|保障看板",
      "身份核验终端|快速消费终端|电子菜牌|AI收货秤|留样柜|内网服务器|保障大屏",
      "部队营区集中食堂，官兵按分队有序入场，多条快速餐线，后厨物资验收、留样和内网保障中心同屏，无军徽无敏感标识",
      "01分队入口|02身份核验|03快速餐线|04消费终端|05物资收货|06留样检测|07内网服务器|08保障看板"),
    p("P026", "中煤", "中煤", "大型煤炭企业职工食堂", "营养管理、收银和视频基础能力",
      "煤炭企业职工|轮班人员|食堂员工|后勤与安全管理人员", "轮班高峰|工种营养需求不同|交易与视频系统割裂|多点监管难",
      "职工入场→选餐→收银结算→就餐", "按班次备餐→出品→视频巡检→营养与经营复盘",
      "适合以‘交易+营养+视频’轻量组合切入大型工业企业", "已有项目定位证据；人数、订单、设备型号和数量待补证",
      "交易结算|账户班次|营养管理|视频巡检|经营分析|设备运维",
      "消费终端|电子菜牌|视频摄像机|NVR/AI盒|营养大屏|管理电脑",
      "大型煤炭企业职工食堂，轮班职工经过多档口和收银，后厨视频巡检点位与营养运营大屏可见",
      "01班次入口|02电子菜牌|03多档口|04收银结算|05就餐区|06后厨|07视频巡检|08营养运营"),
    p("P027", "保康三中", "保康三中", "中学校园综合智慧食堂", "师生高峰、校园账户与营养公示",
      "学生|教师|食堂人员|学校后勤与家校管理人员", "课间高峰集中|学生账户管理|营养信息触达|家校与后勤缺少数据",
      "学生/教师入场→看菜单营养→选餐→账户结算→就餐", "菜单编排→备餐→出品→留样→日结与营养公示",
      "校园综合场景可作为标准学校套餐参照，但现有证据不足", "当前只有项目定位证据；人数、订单、软件和硬件数量待补证",
      "校园账户|交易结算|菜单营养|电子菜牌|食品安全|家校/后勤报表",
      "消费终端|电子菜牌|营养展示屏|留样柜|管理电脑|厨房打印机",
      "中学校园食堂，学生教师分流进入，电子菜牌显示菜品营养，后厨留样和学校后勤管理台可见",
      "01学生入口|02教师入口|03电子菜牌|04选餐档口|05账户结算|06就餐区|07留样后厨|08学校管理"),
    p("P028", "C08", "C08", "项目特定大规模称重自选", "免绑盘称重、余量看板与大屏运营",
      "项目内部就餐人员|食堂员工|运营管理员|设备运维人员", "餐线设备密集|绑盘流程影响效率|菜品余量不可见|多设备运维复杂",
      "人员取餐→免绑盘称重自选→自动累计/结算→查看余量→就餐", "备餐→布菲炉出品→实时余量采集→补菜→大屏运营",
      "免绑盘称重台规模化、余量看板和大屏协同是主要特点", "已观察免绑盘膳识台56台、布菲炉56台、余量看板1台、餐盘2000个、PoE交换机5台和75寸大屏2台；膳识台存在历史别名",
      "免绑盘称重|交易结算|菜品余量|设备监控|大屏运营|账户管理",
      "免绑盘膳识台|布菲炉|余量看板|智能餐盘|PoE交换机|数据大屏",
      "大型称重自选食堂，中央两条超长免绑盘餐线，布菲炉与膳识台成组，前方余量看板，侧边大屏和设备运维台",
      "01人员入口|02免绑盘取餐|03膳识台|04布菲炉|05自动结算|06余量看板|07数据大屏|08设备运维"),
]


MODULE_LABELS = {
    "交易结算": "交易结算", "移动端": "移动服务", "营养管理": "营养管理",
    "接口集成": "接口集成", "消费策略": "消费策略", "食品安全": "食品安全",
    "采购库存": "采购库存", "线上订餐": "移动订餐", "取餐柜": "取餐核销",
}


def read_csv(path):
    with path.open(encoding="utf-8-sig", newline="") as f:
        return list(csv.DictReader(f))


def write_csv(name, rows, fieldnames):
    OUT.mkdir(parents=True, exist_ok=True)
    with (OUT / name).open("w", encoding="utf-8-sig", newline="") as f:
        w = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")
        w.writeheader(); w.writerows(rows)


def clean_num(v):
    if v is None or str(v).strip() == "": return ""
    try:
        n = float(v)
        return int(n) if n.is_integer() else round(n, 2)
    except ValueError:
        return v


def qty_values(text):
    nums = [float(x) for x in re.findall(r"\d+(?:\.\d+)?", text or "")]
    if not nums: return "", ""
    return min(nums), max(nums)


def hardware_category(name):
    for key, cat in [
        ("收货秤", "后厨-收货验收"), ("晨检", "后厨-食品安全"), ("留样", "后厨-食品安全"),
        ("检测仪", "后厨-食品安全"), ("摄像机", "后厨-视频AI"), ("分析盒", "后厨-视频AI"),
        ("NVR", "后厨-视频AI"), ("打印机", "后厨-分单出品"), ("取餐柜", "前厅-取餐"),
        ("收银机", "前厅-结算"), ("POS", "前厅-结算"), ("结算台", "前厅-结算"),
        ("膳识", "前厅-称重自选"), ("布菲炉", "前厅-称重自选"), ("绑盘", "前厅-餐盘绑定"),
        ("读卡器", "前厅-身份介质"), ("电视机", "前厅-信息展示"), ("电子墨水屏", "前厅-信息展示"),
        ("菜品余量", "前厅-信息展示"), ("数据大屏", "运营-数据展示"), ("交换机", "基础设施-网络"),
        ("餐盘", "耗材/载体"), ("M1卡", "耗材/载体"),
    ]:
        if key.lower() in (name or "").lower(): return cat
    return "其他/非标"


def is_software(row):
    return row.get("单位") == "套" or any(k in row.get("标准产品名称", "") for k in ["管理系统", "监督管理系统", "结算系统"])


def main():
    profiles = {x["id"]: x for x in PROFILES}
    capability = {r["项目ID"]: r for r in read_csv(CAPABILITY)}
    model = {r["项目ID"]: r for r in read_csv(MODEL)}
    evidence = read_csv(EVIDENCE)
    evidence_by = defaultdict(list)
    for r in evidence: evidence_by[r["项目ID"]].append(r)

    project_rows, people_rows, software_rows, hardware_rows, gap_rows, prompt_rows, assets = [], [], [], [], [], [], []

    for idx, profile in enumerate(PROFILES, 1):
        pid = profile["id"]
        cap = capability.get(pid, {})
        mod = model.get(pid, {})
        ev = evidence_by.get(pid, [])

        metrics = [
            ("注册账户", cap.get("注册用户数", ""), "个"),
            ("最近有单日日活", cap.get("最近有单日日活", ""), "个"),
            ("30日活跃账户", cap.get("30日活跃用户", ""), "个"),
            ("累计有效订单", cap.get("累计有效订单量", ""), "笔"),
            ("近30日订单", cap.get("近30日订单量", ""), "笔"),
            ("累计有效订单金额", cap.get("累计有效订单金额", ""), "元"),
            ("近30日订单金额", cap.get("近30日订单金额", ""), "元"),
        ]
        for metric, value, unit in metrics:
            people_rows.append({"项目ID": pid, "项目名称": profile["name"], "记录类型": "运行规模", "人群/指标": metric,
                                "数量": clean_num(value), "单位": unit, "数量状态": "已观察" if str(value).strip() else "待补证",
                                "证据等级": cap.get("综合证据等级", ""), "证据边界": cap.get("运营数据边界", "") or "未进入可核验数据库"})
        for group in profile["people"].split("|"):
            people_rows.append({"项目ID": pid, "项目名称": profile["name"], "记录类型": "场景角色", "人群/指标": group,
                                "数量": "", "单位": "人", "数量状态": "待补证", "证据等级": "D-场景推导",
                                "证据边界": "角色用于场景表达，不代表已核验人数"})

        actual_modules = []
        for token in re.split(r"[|、,，]", cap.get("软件功能模块", "") or ""):
            token = token.strip()
            if token: actual_modules.append(MODULE_LABELS.get(token, token))
        for r in ev:
            if is_software(r):
                actual_modules.append(r["标准产品名称"])
                software_rows.append({"项目ID": pid, "项目名称": profile["name"], "软件模块": r["标准产品名称"],
                                      "事实/建议": "项目证据", "数量": r["数量"], "单位": r["单位"], "版本/型号": r["项目型号/写法"],
                                      "映射状态": r["映射状态"], "证据等级": r["证据等级"], "证据路径": r["证据路径"]})
        for name in dict.fromkeys(actual_modules):
            if not any(x["软件模块"] == name and x["项目ID"] == pid for x in software_rows):
                software_rows.append({"项目ID": pid, "项目名称": profile["name"], "软件模块": name, "事实/建议": "运行/清单观察",
                                      "数量": "", "单位": "模块", "版本/型号": "待补证", "映射状态": "功能级观察",
                                      "证据等级": cap.get("综合证据等级", ""), "证据路径": "project-capability-base.csv"})
        recommended = profile["recommended_software"].split("|")
        for name in recommended:
            if name not in actual_modules:
                software_rows.append({"项目ID": pid, "项目名称": profile["name"], "软件模块": name, "事实/建议": "场景建议",
                                      "数量": "", "单位": "模块", "版本/型号": "待售前定标", "映射状态": "不作为已交付事实",
                                      "证据等级": "D-场景推导", "证据路径": "本案例场景推导"})

        hard_evidence = [r for r in ev if not is_software(r)]
        for r in hard_evidence:
            qmin, qmax = qty_values(r["数量"])
            hardware_rows.append({"项目ID": pid, "项目名称": profile["name"], "硬件类别": hardware_category(r["标准产品名称"] + r["项目型号/写法"]),
                                  "硬件名称": r["标准产品名称"], "标准型号": r["标准型号"], "项目写法/型号": r["项目型号/写法"],
                                  "数量原文": r["数量"] or "待补证", "数量下限": qmin, "数量上限": qmax, "单位": r["单位"],
                                  "事实/建议": "项目证据", "映射状态": r["映射状态"], "证据等级": r["证据等级"], "证据路径": r["证据路径"],
                                  "是否计入设备总数": "否" if hardware_category(r["标准产品名称"] + r["项目型号/写法"]) == "耗材/载体" else "是"})
        if not hard_evidence:
            for name in profile["suggested_hardware"].split("|"):
                hardware_rows.append({"项目ID": pid, "项目名称": profile["name"], "硬件类别": hardware_category(name), "硬件名称": name,
                                      "标准型号": "待售前定标", "项目写法/型号": "无项目级证据", "数量原文": "待补证", "数量下限": "", "数量上限": "", "单位": "台/套",
                                      "事实/建议": "场景建议", "映射状态": "不作为已交付事实", "证据等级": "D-场景推导", "证据路径": "本案例场景推导", "是否计入设备总数": "否"})
        hist_count = clean_num(cap.get("历史项目清单硬件观察数量", ""))
        sales_count = clean_num(cap.get("2026销售明细可计数设备数量", ""))
        observed_device_count = sales_count or hist_count or ""
        observed_basis = "2026销售明细" if sales_count != "" else ("历史项目清单" if hist_count != "" else "待补证")

        actual_software = list(dict.fromkeys(actual_modules))
        actual_hw_names = [r["标准产品名称"] for r in hard_evidence]
        project_rows.append({
            "序号": idx, "项目ID": pid, "项目名称": profile["name"], "简称": profile["short_name"], "场景类型": profile["scene"],
            "一句话场景": profile["scene_focus"], "服务人群": profile["people"].replace("|", "、"), "已观察注册账户": clean_num(cap.get("注册用户数", "")),
            "已观察日日活": clean_num(cap.get("最近有单日日活", "")), "已观察30日活跃": clean_num(cap.get("30日活跃用户", "")),
            "累计有效订单": clean_num(cap.get("累计有效订单量", "")), "近30日订单": clean_num(cap.get("近30日订单量", "")),
            "主要问题": profile["pain"].replace("|", "；"), "实际软件观察": "、".join(actual_software) if actual_software else "待补证",
            "场景建议软件": profile["recommended_software"].replace("|", "、"), "实际硬件观察": "、".join(actual_hw_names) if actual_hw_names else "待补证",
            "历史硬件观察数量": hist_count, "2026销售可计数设备数量": sales_count, "用于总览的设备观察数": observed_device_count,
            "设备观察口径": observed_basis, "前厅主流程": profile["front_flow"], "后厨主流程": profile["kitchen_flow"],
            "项目特点": profile["characteristic"], "验证能力/证据边界": profile["validated"], "项目证据等级": cap.get("综合证据等级", "") or mod.get("项目证据等级", ""),
            "定标结论": mod.get("定标结论", "") or "待补项目级证据", "主要证据缺口": cap.get("主要证据缺口", "") or "人数、软件版本、硬件BOM/SN与验收待补证",
            "3D图文件": f"assets/scenes/{pid}-{profile['short_name']}.png", "图像性质": "AI虚拟3D场景示意，不是现场照片，不证明型号或安装数量",
            "图例": profile["legend"].replace("|", "；"),
        })

        gaps = cap.get("主要证据缺口", "") or "人数、软件版本、硬件BOM/SN与验收待补证"
        for gap in re.split(r"[、，,；;]", gaps):
            if gap.strip(): gap_rows.append({"项目ID": pid, "项目名称": profile["name"], "证据缺口": gap.strip(), "影响": "不可作为合同/验收硬承诺", "建议补证": "合同BOM、出库单、SN铭牌、验收单、运行报表四证对齐"})

        prompt = (
            "Create one 16:9 high-detail isometric 3D cutaway diorama for a Chinese smart canteen case. "
            "Kangbite Digital Executive Soft-Minimal visual direction: warm ivory background, realistic architectural materials, "
            "clean enterprise presentation, soft natural light, dark green, blue and muted gold accent flows. Show front hall and back kitchen in one coherent dollhouse view. "
            f"Project scene: {profile['visual']}. People: {profile['people'].replace('|', ', ')}. "
            f"Key hardware to visualize as representative categories, not exact installed counts: {profile['suggested_hardware'].replace('|', ', ')}. "
            f"Main front flow: {profile['front_flow']}. Main kitchen flow: {profile['kitchen_flow']}. "
            "Add exactly eight circular numbered markers 01 to 08 matching key nodes, with subtle colored path arrows. "
            "Do not add project logos, brand names, military insignia, readable Chinese text, model numbers, quantities, tables or watermarks. "
            "Do not imply that every pictured device was actually installed. Image should be presentation-ready, visually clear at a glance, no collage panels."
        )
        prompt_rows.append({"项目ID": pid, "项目名称": profile["name"], "图像文件": f"{pid}-{profile['short_name']}.png", "Prompt": prompt, "图例": profile["legend"].replace("|", "；")})
        reused = {"P009": "airport-high-frequency-panorama.png", "P016": "xikang-subsidy-weighing-panorama.png", "P017": "saidi-multi-entry-panorama.png", "P019": "genscript-front-hall-panorama.png"}.get(pid, "")
        assets.append({"资产ID": f"SCENE-{pid}", "项目ID": pid, "项目名称": profile["name"], "文件名": f"{pid}-{profile['short_name']}.png", "资产类型": "单项目3D场景主图",
                       "生成/复用": "复用既有场景图" if reused else "待生成", "既有来源": reused, "最终状态": "待复制" if reused else "待生成",
                       "权利/隐私": "AI虚拟场景；无真实人物肖像；无客户敏感数据", "证据声明": "场景示意，不作为现场、型号、数量或验收证据"})

    write_csv("project-case-base.csv", project_rows, list(project_rows[0]))
    write_csv("people-detail.csv", people_rows, list(people_rows[0]))
    write_csv("software-detail.csv", software_rows, list(software_rows[0]))
    write_csv("hardware-detail.csv", hardware_rows, list(hardware_rows[0]))
    write_csv("evidence-gaps.csv", gap_rows, list(gap_rows[0]))
    write_csv("scene-prompts.csv", prompt_rows, list(prompt_rows[0]))
    write_csv("asset-map.csv", assets, list(assets[0]))
    print(f"built {len(project_rows)} projects, {len(people_rows)} people metrics, {len(software_rows)} software rows, {len(hardware_rows)} hardware rows")


if __name__ == "__main__":
    main()
