from pathlib import Path
import csv
import json
import html
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill, Alignment
from openpyxl.comments import Comment

ROOT = Path(__file__).resolve().parent
DATE = '2026-10-23'

sources = [
 ['S01','市场竞争格局 Skill 更新了 | 盒盒行研技能包','youdao-note:DF5E79EEE65D4075AFA2953AC2E7A947','C','方法文章','CLI完整读取；2094字符','企业列表、同口径份额、定位图、共同矩阵','不是智慧食堂市场事实'],
 ['S02','乐牛公司及产品介绍','https://www.lnvipsoft.com/about/','C','企业官网','网页正文回读','软硬一体、采购库存、食安、营养显示','规模、精度和服务承诺未独立验证'],
 ['S03','雄伟全场景方案','https://sovell.com/index.html','C','企业官网','网页正文回读','前后场平台、集团补贴、AI营养师入口','不能证明所有模块已在同一项目验收'],
 ['S04','满客宝智慧食堂','https://www.mankebao.com/','C','企业官网','网页正文回读','订餐、补贴、集团、食安和营养方案','客户量不是独立去重的市场份额'],
 ['S05','满客宝产品能力','https://www.mankebao.com/html/product/','C','企业官网','网页正文回读','营养查询、结算、集团与食安','不证明健康改善或持续付费'],
 ['S06','优信无限公司介绍','https://www.iyouxin.com/html/about_26.html','C','企业官网','网页正文回读','iFood前厅、iGroup后厨、营养功能入口','案例、覆盖和人员数为企业自述'],
 ['S07','新开普2026年半年度报告','https://disc.static.szse.cn/download/disc/disk03/finalpage/2026-08-25/c3bced27-b693-4d6c-bec7-5fd8b06639a1.PDF','A','正式公司披露','官方披露PDF搜索文本回读','AI餐饮、结算、身份与后勤、食安与营养测算','产品自述不等于独立性能测试；未作餐饮份额推算'],
 ['S08','快膳通产品与方案','https://www.ai-quickest.com/','C','企业官网','网页正文回读','称重视觉、库存、食安、多食堂、营养方案','伟邦整体财务不能等于食堂分部财务'],
 ['S09','永愉创高AI营养健康专家系统','https://www.shyycg.com/home/newsinfo.html?id=3becdf2f-a322-4af2-6226-3a1afaec329d','C','企业官网','网页正文回读','体检信息关联、菜肴数据、营养配餐表达','医疗效果、活跃与收费未核验；发布日期未确认'],
 ['S10','康比特AI智慧营养超级食堂','https://www.cptpro.cn/','C','企业官网','网页正文回读','营养结算、采购、食安、营养师及工程师服务表达','自家官网同样不作为独立验收或效果证明'],
 ['S11','徐汇龙南家园AI健康餐测试报道','https://www.xuhui.gov.cn/xwzx_bmlf/20261013/576933.html','B','地方政府场景报道','网页正文回读；来源日期2026-10-13','膳博康入口、称量配餐及测试场景存在','非临床研究；标题首家声明未采用；法律主体未独立核'],
 ['S12','海康开放平台','https://open.hikvision.com/osp','C','企业平台','公开搜索文本回读','身份、食堂消费、设备接口等开放能力','开放范围和费用需按项目确认'],
 ['S13','餐餐安校园食安方案','https://www.cancanan.cn/Solution/WiseCampus','C','企业官网','网页正文回读','多级监管、视频AI、台账和溯源方案','历史政策背景未当作当前合规标准'],
 ['S14','观麦供应链方案','https://www.guanmai.cn/','C','企业官网','公开搜索文本回读','食材配送、央厨、供应链产品边界','服务客户数和营销收益不用于份额或ROI结论'],
 ['S15','德保官网','https://www.debo-cn.com/','C','企业官网','Exa索引文本回读；直接正文抓取超时','团餐驻场、央厨、热链盒饭等运营范围','只确认角色，未采用第三方规模或财务数字'],
 ['S16','南京地铁智慧食堂中标候选公示','https://njggzy.nanjing.gov.cn/njweb/gchw/070003/20241101/b5cbf419-d1d5-48cb-93ac-1161cd26280b.html','A/B','公共资源交易公示','网页正文回读；来源日期2024-11-01','小牛、雄伟、集成商同场；小牛第一候选；列有银行买方业绩','候选不是最终合同或验收；业绩属候选人披露；历史样本非全国'],
 ['S17','中大五院智慧食堂硬件单一来源公示','https://www.sysu5.cn/hospital-announcement/3641','A/B','采购人官网','网页正文回读；来源日期2021-08-27','已有满客宝软件影响拟采购硬件来源','历史拟采购理由；非普遍排他或技术不可替换证明'],
 ['S18','中国农大中心与数智食堂揭牌','https://fvp.cau.edu.cn/art/2025/12/23/art_54196_1095185.html','B','项目参与高校','公开搜索文本回读；来源日期2025-12-23','科研营养资源与食堂场景协作','不是健康效果、规模经营或投资收益证明'],
 ['S19','新开普智慧餐饮方案','https://www.newcapec.com.cn/zhihuiqiyeyikatong/6244.html','C','企业官网','Exa正文回读；web工具直读不可用','原料管控、膳食分析、员工餐饮全流程','不是完整部署与验收记录'],
 ['S20','海康合作伙伴食安方案入口','https://partners.hikvision.com/solution?detailId=EAC208DAFD636DA7E053AB0B010A2818&id=158488636&parentId=499888632942542848&source=1&type=solutionTypeList','C','企业伙伴平台','公开搜索文本回读','存在学校食堂食品安全方案入口','只确认方案类别，不证明全面业务平台或营养服务'],
]

competitors = [
 ['E01','南京小牛智能科技有限公司','乐牛','软硬一体','政企、学校、医院等','餐线、结算、食安、供应链','设备＋软件＋项目实施；收费结构待核','S02,S16','直接竞争／条件合作','同项目验收、服务质量、持续营养服务'],
 ['E02','杭州雄伟科技开发股份有限公司','智盘／雄伟','软硬一体','学校、机关、医院、企业','餐台、经营平台、采购、营养入口','设备＋平台＋服务；具体报价待核','S03,S16','直接竞争／条件合作','营养师服务、续费及各模块实用深度'],
 ['E03','正奇晟业（北京）科技有限公司','满客宝','软硬一体／集团平台','机构、集团、医院等','订餐结算、补贴、多食堂、营养、食安','软件＋硬件＋实施服务；许可模式待核','S04,S05,S17','直接竞争／接口合作','现版本能力、迁移责任、完整TCO'],
 ['E04','广东优信无限网络股份有限公司','iFood／iGroup','软硬一体','政企、校园、医院、园区等','前厅经营与后厨管理','软硬件＋服务；项目收费待核','S06','直接竞争／渠道合作','本地服务能力与特定项目实施成本'],
 ['E05','新开普电子股份有限公司','新开普','账户／后勤平台','校园与政企','身份账户、餐饮、智慧后勤和终端','平台＋终端＋运维；餐饮收入未拆分','S07,S19','存量入口竞争／系统合作','接口授权、迁移和多供应商责任'],
 ['E06','广东伟邦科技股份有限公司','快膳通','设备＋平台','政企、学校、医院等','称重视觉、库存、食安、多食堂','制造供货＋软件＋实施；具体边界待核','S08','直接竞争／供货合作','自研和集成责任、授权、渠道售后'],
 ['E07','上海永愉创高企业管理咨询有限公司','永愉创高','营养＋数字食堂','职工、学校、医院等','配餐、体检信息关联、菜肴数据、订餐','软件／营养方案；收费结构未知','S09','营养方向竞争','效果研究、真实使用及营养师服务'],
 ['E08','北京康比特体育科技股份有限公司','康比特数字体育科技','营养＋数字食堂','机构食堂与运动营养场景','营养结算、采购、食安、人员服务','建设＋产品＋服务为待核收入拆分','S10','分析标的','差异化赢单、服务成本、续费和主业协同'],
 ['E09','杭州海康威视数字技术股份有限公司及伙伴','海康生态','物联／食安','学校、园区等','视频、设备接入、消费和食安方案入口','设备／平台／伙伴集成；按合同核','S12,S20','局部竞争／物联合作','完整食安流程、伙伴权责、平台费用'],
 ['E10','主体待工商核验','餐餐安','食安监管','学校与区域监管','多级平台、视频AI、台账和溯源','平台＋物联＋实施；合同角色待核','S13','监管竞争／接口合作','当前主体、地区案例、付费与验收'],
 ['E11','深圳市观麦网络科技有限公司（待主体登记复核）','观麦','供应链软件','配送企业、央厨及团餐相关客户','采购、分拣、仓配与央厨','SaaS及相关服务；具体套餐待核','S14','局部竞争／后厨合作','与食堂终端边界、接口和授权'],
 ['E12','深圳市德保膳食管理有限公司','德保','团餐运营','学校、工厂、企业、医院等','驻场供餐、央厨和综合服务','团餐运营合同；不能与软件收入混算','S15','买方／渠道／替代方案','对外采购、软件权属、数据及营养责任'],
 ['E13','法律主体待独立核验','膳博康／龙南家园测试场景','营养新场景','社区供餐；其他场景待验证','小程序、个人推荐、称量配餐','试点商业模式和收费未确认','S11','新进入路线观察','付费、复制、主体及长期效果'],
 ['E14','中国农业大学相关研究中心及场景合作方','精准营养研究中心／数智食堂','科研协作路线','社区及公共就餐场景','营养研究与食堂技术、运营协同','不视作单一可采购厂商；合作模式待核','S18','潜在合作／替代专业能力','实际运营方、交付权责、服务定价'],
]

matrix = [
 ['乐牛','公','公','公','公','待','公','待','S02'],
 ['雄伟／智盘','公','公','公','公','公','公','待','S03'],
 ['满客宝','公','公','公','公','公','公','待','S04,S05'],
 ['优信无限','公','公','公','公','待','公','待','S06'],
 ['新开普','披','披','公','披','披','披','待','S07,S19'],
 ['快膳通','公','公','公','公','公','公','待','S08'],
 ['永愉创高','待','公','待','待','待','公','待','S09'],
 ['康比特','公','待','公','公','待','公','公','S10'],
]

actions = [
 ['V01','同类输赢单','销售／售前（建议）','近一年按同场景记录竞争者、预算、评分与输赢原因','A/B','验证直接对手和客户购买标准','未指派、未执行'],
 ['V02','同配置报价','售前／采购（建议）','对齐BOM、许可、接口、税费、部署、服务和付款','A/B','解释价格差，不生成无口径均价','未指派、未执行'],
 ['V03','营养持续付费','客户成功／营养负责人（建议）','恢复服务内容、付款方、活跃、续费和服务成本','A/B','判断是否能形成可持续服务收入','未指派、未执行'],
 ['V04','存量接入','产品／交付（建议）','核接口、授权、数据出口、升级及故障责任','A/B','选择接入、替换、合作或拒绝重定制','未指派、未执行'],
 ['V05','采购样本','市场／销售运营（建议）','先冻结一个区域12个月窗口再去重成交包','A/B','只能形成该样本份额与集中度','未指派、未执行'],
]

budget = [
 ['政企改造＋员工健康','后勤／信息化；健康预算另核','综合厂商、集成商、既有系统','基础运营可靠＋营养可选服务','付款人、增量付费与交付成本','D'],
 ['高校存量一卡通','后勤／信息中心；部分银行参与','新开普、食堂厂商、区域生态','兼容接入或有边界替换','账户迁移、设备协议与责任','D；S16提供历史银行路径线索'],
 ['区域校园食安监管','教育／学校／监管；资金待核','餐餐安、物联生态、区域集成','食安数据与营养模块协同','现平台、数据标准、验收与授权','D'],
 ['团餐多点经营','团餐运营、采购和财务','ERP、内部平台、全栈厂商','营养模块或联营合作','成本价值、数据归属、持续付费','D'],
 ['体育基地营养','基地、训练及营养保障','科研自建、营养服务、集成商','专业营养与真实供餐闭环','复用、服务工时、场景迁移','D'],
 ['医院／社区营养供餐','后勤／运营方／专业部门；付款待核','医院订餐、社区运营与新营养方案','按人群区分服务包','责任与流程、付费、效果边界','D；S11提供测试场景'],
]

ledger = [
 ['F01','S16','2024-11-01','小牛、雄伟、江苏移动集成等出现在同一项目评审；小牛第一候选','A/B','证明该项目竞争结构','全国份额、最终履约与当年整体竞争力'],
 ['F02','S17','2021-08-27','采购人因满客宝软件一致性提出同源硬件拟采购','A/B','证明历史增购路径','所有项目排他或无法技术替代'],
 ['F03','S07','2026-08-25','正式半年报描述餐饮、身份后勤协同与营养测算','A','证明正式披露产品路线','独立性能与餐饮单独收入'],
 ['F04','S04,S05,S06,S08','抓取2026-10-23','多家官网公开提供营养相关功能或方案','C','否定营养功能独占假设','效果一致、客户已付费或全部验收'],
 ['F05','S09','日期未确认；抓取2026-10-23','永愉创高公开体检信息关联及个性配餐方案','C','证明方案表达存在','医疗效果、规模和收入'],
 ['F06','S10','抓取2026-10-23','康比特公开营养师／工程师现场和远程服务表达','C','提出服务差异化验证方向','独占性、成本可控、所有合同都有此服务'],
 ['F07','S11','2026-10-13','徐汇报道龙南家园使用膳博康开展健康餐测试','B','证明测试场景与用户流程','全国首家、临床效果、商业成熟'],
 ['F08','S18','2025-12-23','参与高校报道精准营养研究中心与数智食堂同步揭牌','B','证明科研与场景协作路线','经营成效与统一厂商主体'],
 ['I01','F01,F02,F03','2026-10-23','存量账户、接口和交付关系可能影响采购','D','商机前置核验','未经逐商机核实不得作绝对规律'],
 ['I02','F04,F05,F06,F07','2026-10-23','营养服务需以数据、人员与付费闭环验证差异化','D','产品与经营验证建议','不代表康比特现已形成优势或利润'],
]

def write_csv(name, heads, rows):
    with (ROOT/name).open('w', encoding='utf-8-sig', newline='') as f:
        w=csv.writer(f); w.writerow(heads); w.writerows(rows)

tables = [
 ('企业列表','competitor-list.csv',['ID','主体','品牌','群组','客户','产品','商业模式／边界','来源','关系判断D','缺口'],competitors),
 ('能力矩阵','capability-matrix.csv',['企业','智能结算','订餐／补贴','采购／库存','食安管理','多组织／集团','营养分析或配餐','专业人员服务表达','来源'],matrix),
 ('预算竞争','competitive-budget-map.csv',['购买情境','潜在预算方','竞争／替代','康比特验证方向','缺口','等级'],budget),
 ('来源索引','source-index.csv',['ID','标题','来源定位','等级','类型','获取状态','支持事实','不能证明'],sources),
 ('证据账本','evidence-ledger.csv',['ID','来源ID','日期','事实／判断','等级','允许使用','不能证明'],ledger),
 ('补证动作','validation-backlog.csv',['ID','主题','建议角色','动作','需要证据','决策用途','状态'],actions),
]
wb=Workbook(); ws=wb.active; ws.title='使用说明'
for row in [
 ['智慧食堂市场竞争格局',DATE],
 ['状态','公开证据研究稿；非全国份额榜单'],
 ['方法','有道CLI读取指定文章：企业列表→同口径份额门禁→定位图→共同矩阵→策略'],
 ['公','企业公开产品或方案（C）；不是验收'],
 ['披','正式报告披露（A）；不是独立性能测试'],
 ['待','本轮证据不足；不是没有能力'],
 ['关系与预算','属于D级分析，按具体项目重新核验'],
 ['财务／份额','未建立统一分母；不披露CRn、HHI、全国份额或市场均价'],
 ['角色','补证负责人仅建议角色，未实际指派或配置催办'],
 ['来源日期','DATE为检索日期；网页原始日期未知者保持未知'],
 ]: ws.append(row)
for sheet,name,heads,rows in tables:
    write_csv(name,heads,rows)
    ws=wb.create_sheet(sheet); ws.append(heads)
    for row in rows: ws.append(row)
    ws.auto_filter.ref=ws.dimensions; ws.freeze_panes='C2' if sheet=='企业列表' else 'B2'
    for row in ws.iter_rows(min_row=2):
        for c in row:
            if isinstance(c.value,str) and c.value.startswith('https://'):
                c.hyperlink=c.value
            if sheet=='能力矩阵' and 2<=c.column<=8:
                colors={'公':'E2EFF0','披':'E4EAF8','待':'F2F3F5'}
                c.fill=PatternFill('solid',fgColor=colors[c.value])
                c.comment=Comment('公=官网方案C；披=正式披露A；待=证据不足。均非现场验收。来源见本行最后列。','Codex')
for ws in wb:
    ws.sheet_view.showGridLines=False
    ws.freeze_panes=ws.freeze_panes or 'B2'
    for row in ws:
        for c in row:
            c.font=Font(name='微软雅黑',size=12,color='153E45')
            c.alignment=Alignment(vertical='top',wrap_text=True)
    for c in ws[1]:
        c.font=Font(name='微软雅黑',size=12,bold=True,color='FFFFFF'); c.fill=PatternFill('solid',fgColor='174D57')
    for col in ws.columns:
        letter=col[0].column_letter
        ws.column_dimensions[letter].width=18 if col[0].column<=2 else 30
    ws.row_dimensions[1].height=36
    for i in range(2,ws.max_row+1): ws.row_dimensions[i].height=96 if ws.title!='能力矩阵' else 42
    ws.print_options.horizontalCentered=True
    ws.sheet_properties.pageSetUpPr.fitToPage=True
    ws.page_setup.orientation='landscape'; ws.page_setup.paperSize=ws.PAPERSIZE_A3
    ws.page_setup.fitToWidth=1; ws.page_setup.fitToHeight=0
    ws.print_title_rows='1:1'
wb.save(ROOT/'智慧食堂竞争格局_企业与证据.xlsx')

def svg_start(w,h,title,desc):
    return [f'<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}" role="img" aria-labelledby="title desc">',f'<title id="title">{title}</title><desc id="desc">{desc}</desc>', '<style>text{font-family:"PingFang SC","Microsoft YaHei",sans-serif;fill:#173f49}.muted{fill:#5c747c}.small{font-size:17px}.body{font-size:21px}.title{font-size:34px;font-weight:700}</style>',f'<rect width="{w}" height="{h}" rx="20" fill="#f7fafb"/>']

def tx(out,x,y,s,cls='body',**attrs):
    a=' '.join(f'{k.replace("_","-")}="{v}"' for k,v in attrs.items())
    out.append(f'<text x="{x}" y="{y}" class="{cls}" {a}>{html.escape(s)}</text>')

def box(out,x,y,w,h,fill='#ffffff',stroke='#d8e4e7',dash=None):
    extra=f' stroke-dasharray="{dash}"' if dash else ''
    out.append(f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="12" fill="{fill}" stroke="{stroke}"{extra}/>')

out=svg_start(1400,850,'智慧食堂公开方案定位图','横轴为方案覆盖边界，纵轴为价值主张侧重。定性分组，无实力评分。')
tx(out,55,65,'智慧食堂公开方案定位图','title')
tx(out,55,100,'2026-10-23 · 定性分组，非实力评分；组内位置无优劣含义','small')
box(out,210,150,520,245,'#edf5f3'); box(out,750,150,585,245,'#e5f1ed')
box(out,210,415,520,245,'#edf1f6'); box(out,750,415,585,245,'#e7f0f5')
tx(out,60,210,'价值侧重','small'); tx(out,60,250,'个体营养'); tx(out,60,282,'健康服务')
tx(out,60,505,'经营效率'); tx(out,60,537,'与管控')
tx(out,235,185,'营养模块／专业协作机会','small')
tx(out,235,235,'此象限不放证据不足的企业')
tx(out,235,276,'未核方案边界，不推定其只做单点','small')
tx(out,235,322,'膳博康、高校场景另作观察','small')
tx(out,235,355,'S11／S18尚不足以确定横轴位置','small')
tx(out,775,185,'营养为核心主张的数字食堂','small')
tx(out,775,237,'康比特  ·  永愉创高')
tx(out,775,281,'已有专业／个体化服务表达')
tx(out,775,323,'持续付费、交付成本和效果待核','small')
tx(out,775,355,'来源 S09、S10；均为企业公开描述','small')
tx(out,235,453,'单点工具／局部系统','small')
tx(out,235,501,'海康食安／物联、观麦供应链')
tx(out,235,544,'按其食堂项目中的局部产品定位','small')
tx(out,235,588,'本图不覆盖各公司的全部业务','small')
tx(out,235,625,'来源 S12、S14、S20；营养服务待核','small')
tx(out,775,453,'跨流程经营与管控平台','small')
tx(out,775,501,'乐牛  ·  雄伟／智盘  ·  满客宝')
tx(out,775,545,'优信无限  ·  新开普  ·  快膳通')
tx(out,775,588,'这些平台也公开提供营养相关功能','small')
tx(out,775,625,'来源 S02—S08、S19','small')
tx(out,225,710,'单点工具／局部流程','small'); tx(out,920,710,'跨前后场、多角色平台','small')
tx(out,600,750,'方案覆盖边界 →','body')
tx(out,55,800,'读图边界：位置依据公开主张与方案范围；不代表验收、健康效果、市场份额或商业成熟度。','small')
out.append('</svg>'); (ROOT/'positioning-map.svg').write_text('\n'.join(out))

out=svg_start(1600,800,'智慧食堂共同能力矩阵','公为公开产品方案，披为正式报告披露，待为证据不足。标记不是性能评分。')
tx(out,45,60,'智慧食堂共同能力矩阵','title')
tx(out,45,100,'公 = 公开方案 C    披 = 正式报告披露 A    待 = 本轮证据不足；所有标记均非现场验收','small')
heads=['智能结算','订餐／补贴','采购／库存','食安管理','多组织／集团','营养／配餐','专业人员服务']
left=225; cw=183; top=180; rh=58
for j,h in enumerate(heads): tx(out,left+j*cw+cw/2,150,h,'small',text_anchor='middle')
for i,row in enumerate(matrix):
    y=top+i*rh
    tx(out,45,y+35,row[0],'body')
    for j,v in enumerate(row[1:8]):
        x=left+j*cw; fill={'公':'#d9ece9','披':'#dde6f8','待':'#edf0f2'}[v]
        box(out,x,y,cw-12,rh-10,fill,'#ffffff')
        tx(out,x+(cw-12)/2,y+33,v,'body',text_anchor='middle')
tx(out,45,700,'来源：乐牛 S02；雄伟 S03；满客宝 S04/S05；优信 S06；新开普 S07/S19；快膳通 S08；永愉 S09；康比特 S10。','small')
tx(out,45,742,'“待”不代表没有能力。此图展示公开证据覆盖，不能用颜色计数或相加得出厂商实力排名。','small')
out.append('</svg>'); (ROOT/'capability-matrix.svg').write_text('\n'.join(out))

receipt = {'date':DATE,'note_id':'DF5E79EEE65D4075AFA2953AC2E7A947','cli_version':'1.3.4','commands':['youdaonote list','youdaonote version','youdaonote search 市场竞争格局','youdaonote read DF5E79EEE65D4075AFA2953AC2E7A947'],'article_chars':2094,'article_sha256':'c661565becf303b67b0574e104d893b9a04898c44c3e3fdd7526eee69d098a6a','raw_article_committed':False,'original_article_url':'CLI正文未返回，未猜测','public_source_count':len(sources)-1,'participant_count':len(competitors),'matrix_rows':len(matrix),'matrix_dimensions':7,'share_metrics':'全国份额/CRn/HHI未计算：缺同口径分母','git':'共享主工作树未知跨任务二进制和分叉保留；本次不提交推送'}
(ROOT/'collection-receipt.json').write_text(json.dumps(receipt,ensure_ascii=False,indent=2)+'\n')

check=load_workbook(ROOT/'智慧食堂竞争格局_企业与证据.xlsx')
assert check['企业列表'].max_row == 15
assert check['能力矩阵'].max_row == 9
assert check['来源索引'].max_row == 21
assert not any(c.data_type=='f' or c.data_type=='e' for s in check for row in s for c in row)
assert len({r[0] for r in competitors})==len(competitors)
print(json.dumps({'sheets':check.sheetnames,'sources':len(sources),'participants':len(competitors),'matrix_rows':len(matrix),'formula_errors':0},ensure_ascii=False))
