深大校园寻路
这个 Skill 干什么
同学报一个建筑名、俗称或课表上的教室代码 → 在深圳大学官方校区地图(粤海 Map 1 / 丽湖 Map 2)的标注里检索 → 用红圈圈出目标建筑 + 白底红字名称气泡 + 引线,输出图片给用户。检索不到就只回一句「没有找到该建筑」。
索引覆盖 108 个地点(粤海 68 / 丽湖 40):教学楼、图书馆、体育馆/运动场、校门、食堂、宿舍区、广场、湖山、校医院、地铁站。
铁律(违反任何一条都算做错)
- 必须先检索,绝不凭记忆猜坐标。 坐标只在
data/pois.json里,不许自己编、不许"大概在这个位置"。 - 按脚本退出码分支,不许自作主张。
1未命中 → 只能输出「没有找到该建筑」;2多候选 → 本轮不出图,列候选让用户选序号;0才出图。 - 一次只圈一个建筑。 用户选了第 N 个候选,就用
--pick N,不要一次圈一堆。 - 出图后要自检。 用图片查看工具打开产物,确认红圈压在目标楼的标注上、气泡没压住关键标注。最多自检 2 轮。
- 不许改
assets/里的底图;坐标数据可以改(改完记得verified思路:小步修正 + 重新出图核对)。
环境
- Python:
C:\Users\wgpho\.workbuddy\binaries\python\versions\3.13.12\python(脚本里已处理路径,直接调用即可) - 只依赖 PyMuPDF(环境自带)。不要 pip 安装 Pillow / OCR / 任何东西。
- 不需要联网。底图在
assets/,索引在data/。
下面把 $SK 记作本 Skill 目录(即本文件所在目录,通常 C:\Users\wgpho\.workbuddy\skills\szu-campus-navigator)。
标准流程
第 1 步:检索(必做,先看有几个)
python "$SK/scripts/pin_map.py" --search "<用户原话>"
把用户的原始说法整句丢进去即可(文科楼、H2-201、S401、南区体育馆、丽湖图书馆、四方楼西座、食堂、体育馆 都支持)。
只想看候选不打图,用 --json 或 scripts/resolve.py --search "..."。
第 2 步:按退出码走
| 退出码 | 含义 | 你要做的 |
|---|---|---|
0 |
唯一命中,已出图 | 走第 4 步 |
1 |
没检索到 | 只输出「没有找到该建筑」。可以再加一句「你可能想找:A / B / C」(30–45 分的模糊项),但主句一个字都不许改 |
2 |
命中多个 | 输出候选清单(模板见下),本轮不出图,等用户说选哪个 |
3 |
参数错 | 修参数重试 |
4 |
索引坏了 | 告诉用户索引文件异常,建议重建 |
5 |
渲染失败 | 加 --no-bubble 重试一次;仍失败就把原图路径给用户并用文字描述方位 |
6 |
底图指纹不匹配 | 明确说「地图底图变了、坐标索引已失效」,绝对不要猜坐标,也不要出图 |
多候选时的回复模板(务必带序号,用户回「第 2 个」你才能接):
找到多个匹配,告诉我要哪一个(回序号即可):
1. 南区运动广场(南区体育馆)— 粤海校区·东南区·沧海校区北
2. 元平体育馆 — 粤海校区·北区·星空广场东
3. 至畅体育馆 — 丽湖校区·风雨操场西
候选上限 8 条。用户选定后用 --pick N 出图,不要重新用 --search(会二次歧义):
python "$SK/scripts/pin_map.py" --search "<原话>" --pick 2
第 3 步(可选):加指引箭头
用户明确问"从 X 门/从某处怎么走"时,先确认起点在索引里,然后:
python "$SK/scripts/pin_map.py" --poi yuehai.huiwen --arrow-from yuehai.ligongmen
--arrow-from 接受 POI id 或名字(如 立功门)。箭头是示意方向,不是精确路线(地图没有路网数据),文字里必须这么说明,别承诺"沿这条路走 300 米"。
第 4 步:自检 + 回复
脚本 stdout 是一行 JSON,关键字段:
out(图片路径)、name、campus_label、zone、radius、roomcode、arrow、bubble_geom。
- 打开
out看一眼:红圈是否压在name的标注上?气泡是否压住了别的楼名? - 明显偏了(>60px 或圈错楼)→ 改
data/pois.json里该条的x/y/r,再重跑一次。最多 2 轮。 - 把图片给用户看(用 present_files 或直接给路径),配一句方位话:
> 已在粤海校区地图上用红圈标出汇文楼(文科楼)。它在中心区、文山湖北侧;H2 教室就在本楼(H01–H07 在负一楼阶梯教室)。
方位话从 zone / note / nearby 字段取,别自己编。
教室代码怎么算(已内置,别自己推)
data/roomcode_rules.json,脚本自动先解析代码、再匹配楼名:
| 课表上的写法 | 落到哪栋楼 |
|---|---|
H1–H6、H01–H07、H2-201 |
汇文楼(文科楼),H01–H07 在负一楼阶梯教室 |
A301/B302/C303/D304(A–D 座 + 3 位房号) |
汇紫楼(教学楼) |
N 开头(N301) |
致信楼(信工楼),沧海校区 |
S 开头(S401) |
致信楼(机电楼),沧海校区 |
L1–L3 |
致理楼(理工楼) |
L4–L7 |
号段官方未公开,脚本会给「致真楼 / 致艺楼」两个候选,必须让用户选 |
汇德A302/汇德B201 |
汇德楼(原师范学院) |
汇意B/汇意C |
汇意楼(建筑与城市规划学院) |
四方楼东/南/西/北座 |
丽湖四方楼对应一座(--instance east/south/west/north) |
代码解析优先于楼名匹配,所以 H2 不会被当成「H 楼」;A301 不会被当成宿舍 A 座。
容易踩的坑
- 同名跨校区:图书馆(汇典楼北馆 / 汇晖楼南馆 / 丽湖石明楼)、体育馆、食堂、宿舍都有多处。用户没说校区时,脚本会走候选分支,别替他猜。
- 俗称:文科楼=汇文楼、师院=汇德楼、小球馆=至柔馆、理工楼=致理楼、南体=南区运动广场、信工楼/机电楼=致信楼。别名已写进索引,直接搜俗称即可。
- 课表里的怪名字:「南区体育馆XXX」指南区运动广场;「南秋馆游泳池」指南秋馆;「海边足球场/网球场」指校医院东南侧场地。
--search无结果但用户坚持说"肯定有":可以让一让,把用户说的名字原样回一句「地图标注里没有这个名称」,再给 1–2 个最接近的候选。不许临时编坐标。- 输出默认 JPG(约 650KB)。要 PNG 加
--format png(约 3.9MB,别默认用)。
常用命令速查
# 检索 + 唯一命中直接出图
python "$SK/scripts/pin_map.py" --search "文科楼"
# 多候选后按序号出图
python "$SK/scripts/pin_map.py" --search "食堂" --pick 3
# 直接用 id(最稳,适合批量/调试)
python "$SK/scripts/pin_map.py" --poi lihu.sifanglou --instance west
# 带起点箭头
python "$SK/scripts/pin_map.py" --search "元平体育馆" --arrow-from 立功门
# 只要圈不要气泡 / 加深目标突出
python "$SK/scripts/pin_map.py" --search "H1" --no-bubble --dim
# 列出全部 POI
python "$SK/scripts/pin_map.py" --list
维护(用户说"圈歪了"的时候)
python "$SK/scripts/crop_region.py" --campus yuehai --rect x0,y0,x1,y1 --zoom 3 --pin x,y --out build/check.png- 看图算出该挪多少像素,改
data/pois.json里对应条目(x/y是底图原生像素:粤海 1280×1737、丽湖 1280×1810)。 - 重跑
pin_map.py复核。 - 换底图 = 全部坐标作废:必须重跑
build_tiles.py→ 重新标点 → 更新maps[].sha256,脚本会在指纹不符时直接拒绝出图(这是故意的)。
细节规范见 references/render_spec.md,别名全表见 references/alias_cheatsheet.md,索引重建看 references/build_index_guide.md。