fix: BUG-007 列偏移修复 — 上边从 col 2 开始,右边在 cols+2/+3
1. 上边/下边列偏移从 [1, cols] → [2, cols+1](预留左边 Name 列后空一列) 2. 右边列偏移 cols+1/+2 → cols+2/+3(对齐上边偏移) 3. 更新 test_f012/test_f016 中的列引用 4. 更新 context.md 为修复后状态 验收测试全通过(10/10)。
This commit is contained in:
@@ -111,9 +111,9 @@ def calculate_layout(
|
|||||||
# 从第 3 行开始是左/下/右边引脚
|
# 从第 3 行开始是左/下/右边引脚
|
||||||
#
|
#
|
||||||
# 左边: Number (r, 0) r ∈ [3, rows+2] Name (r, 1)
|
# 左边: Number (r, 0) r ∈ [3, rows+2] Name (r, 1)
|
||||||
# 下边: Number (rows+4, c) c ∈ [1, cols] Name (rows+3, c)
|
# 下边: Number (rows+4, c) c ∈ [2, cols+1] Name (rows+3, c)
|
||||||
# 右边: Number (r, cols+1) r ∈ [rows+2, 3] Name (r, cols) 逆序
|
# 右边: Number (r, cols+3) r ∈ [rows+2, 3] Name (r, cols+2) 逆序
|
||||||
# 上边: Number (1, c) c ∈ [cols, 1] Name (2, c) 逆序
|
# 上边: Number (1, c) c ∈ [cols+1, 2] Name (2, c) 逆序
|
||||||
#
|
#
|
||||||
# Pin1: Number (3,0) = A4, Name (3,1) = B4 — 左上角
|
# Pin1: Number (3,0) = A4, Name (3,1) = B4 — 左上角
|
||||||
|
|
||||||
@@ -121,13 +121,13 @@ def calculate_layout(
|
|||||||
left_cells = [(r, 0) for r in range(3, rows + 3)]
|
left_cells = [(r, 0) for r in range(3, rows + 3)]
|
||||||
|
|
||||||
# 下边:从左到右 (cols 个),Number 在最底行 rows+4
|
# 下边:从左到右 (cols 个),Number 在最底行 rows+4
|
||||||
bottom_cells = [(rows + 4, c) for c in range(1, cols + 1)]
|
bottom_cells = [(rows + 4, c) for c in range(2, cols + 2)]
|
||||||
|
|
||||||
# 右边:从下到上 (rows 个),Number 在 cols+1 列(右扩一列)
|
# 右边:从下到上 (rows 个),Number 在 cols+3 列(右扩三列:上边偏移1 + 间距1)
|
||||||
right_cells = [(r, cols + 1) for r in range(rows + 2, 2, -1)]
|
right_cells = [(r, cols + 3) for r in range(rows + 2, 2, -1)]
|
||||||
|
|
||||||
# 上边:从右到左 (cols 个)
|
# 上边:从右到左 (cols 个),从 col 2 开始(预留左边 Name 列 + 空列)
|
||||||
top_cells = [(1, c) for c in range(cols, 0, -1)]
|
top_cells = [(1, c) for c in range(cols + 1, 1, -1)]
|
||||||
|
|
||||||
# ── 构建 EdgePins ─────────────────────────────────────────────
|
# ── 构建 EdgePins ─────────────────────────────────────────────
|
||||||
def _make_edge(edge_name: str, pin_list: list[PinListEntry],
|
def _make_edge(edge_name: str, pin_list: list[PinListEntry],
|
||||||
|
|||||||
@@ -261,15 +261,15 @@ def test_f012_pinname_position():
|
|||||||
output_path=None,
|
output_path=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
# ── 3. 检查单元格位置 (BUG-007 fixed) ─────────────────────
|
# ── 3. 检查单元格位置 (BUG-007 final) ──────────────────
|
||||||
# 5×5: rows=5, cols=5, 20 pins
|
# 5×5: rows=5, cols=5, 20 pins
|
||||||
# 上边: Number (1, 5..1), Name (2, 1..5)
|
# 上边: Number (1, 6..2), Name (2, 6..2)
|
||||||
# 左边: Number (3..7, 0), Name (3..7, 1)
|
# 左边: Number (3..7, 0), Name (3..7, 1)
|
||||||
# 下边: Name (8, 1..5), Number (9, 1..5)
|
# 下边: Name (8, 2..6), Number (9, 2..6)
|
||||||
# 右边: Number (7..3, 6), Name (7..3, 5)
|
# 右边: Number (7..3, 8), Name (7..3, 7)
|
||||||
|
|
||||||
# ── 3a. 验证上边 Name 位置 (2, 1..cols) ─────────────────
|
# ── 3a. 验证上边 Name 位置 (2, 2..cols+1) ──────────────
|
||||||
for c in range(1, cols + 1):
|
for c in range(2, cols + 2):
|
||||||
num_ref = rc_to_cell_ref(1, c) # Number at row 1
|
num_ref = rc_to_cell_ref(1, c) # Number at row 1
|
||||||
name_ref = rc_to_cell_ref(2, c) # Name at row 2
|
name_ref = rc_to_cell_ref(2, c) # Name at row 2
|
||||||
assert num_ref in data, f"上边 Number {num_ref} 缺失"
|
assert num_ref in data, f"上边 Number {num_ref} 缺失"
|
||||||
@@ -277,8 +277,8 @@ def test_f012_pinname_position():
|
|||||||
f"上边 Name 应在 {name_ref} (row 2), 但未找到。Number 在 {num_ref}"
|
f"上边 Name 应在 {name_ref} (row 2), 但未找到。Number 在 {num_ref}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# ── 3b. 验证下边 Name 位置 (rows+3=8, 1..cols) ──────────
|
# ── 3b. 验证下边 Name 位置 (rows+3=8, 2..cols+1) ─────
|
||||||
for c in range(1, cols + 1):
|
for c in range(2, cols + 2):
|
||||||
num_ref = rc_to_cell_ref(rows + 4, c) # Number at row 9
|
num_ref = rc_to_cell_ref(rows + 4, c) # Number at row 9
|
||||||
name_ref = rc_to_cell_ref(rows + 3, c) # Name at row 8
|
name_ref = rc_to_cell_ref(rows + 3, c) # Name at row 8
|
||||||
assert num_ref in data, f"下边 Number {num_ref} 缺失"
|
assert num_ref in data, f"下边 Number {num_ref} 缺失"
|
||||||
@@ -293,10 +293,10 @@ def test_f012_pinname_position():
|
|||||||
assert num_ref in data, f"左边 Number {num_ref} 缺失"
|
assert num_ref in data, f"左边 Number {num_ref} 缺失"
|
||||||
assert name_ref in data, f"左边 Name {name_ref} 缺失"
|
assert name_ref in data, f"左边 Name {name_ref} 缺失"
|
||||||
|
|
||||||
# ── 3d. 验证右边 Name 位置 (7..3, 5) ────────────────────
|
# ── 3d. 验证右边 Name 位置 (7..3, 7) ────────────────────
|
||||||
for r in range(rows + 2, 2, -1):
|
for r in range(rows + 2, 2, -1):
|
||||||
num_ref = rc_to_cell_ref(r, cols + 1)
|
num_ref = rc_to_cell_ref(r, cols + 3)
|
||||||
name_ref = rc_to_cell_ref(r, cols)
|
name_ref = rc_to_cell_ref(r, cols + 2)
|
||||||
assert num_ref in data, f"右边 Number {num_ref} 缺失"
|
assert num_ref in data, f"右边 Number {num_ref} 缺失"
|
||||||
assert name_ref in data, f"右边 Name {name_ref} 缺失"
|
assert name_ref in data, f"右边 Name {name_ref} 缺失"
|
||||||
|
|
||||||
@@ -777,22 +777,22 @@ def test_f016_qfn60_list_to_map():
|
|||||||
f"Number 单元格应覆盖 1..60\n缺失: {sorted(set(range(1,61)) - all_numbers)}"
|
f"Number 单元格应覆盖 1..60\n缺失: {sorted(set(range(1,61)) - all_numbers)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# ── 验证四边布局(BUG-007 fixed layout)──────────────
|
# ── 验证四边布局(BUG-007 final layout)──────────────
|
||||||
# BUG-007 修复布局:
|
# BUG-007 最终布局:
|
||||||
# Title: A1 (row 0 only)
|
# Title: A1 (row 0 only)
|
||||||
# Top Numbers: (1, 1..15)
|
# Top Numbers: (1, 2..16)
|
||||||
# Top Names: (2, 1..15)
|
# Top Names: (2, 2..16)
|
||||||
# Left: Number (3..17, 0), Name (3..17, 1)
|
# Left: Number (3..17, 0), Name (3..17, 1)
|
||||||
# Bottom: Name (18, 1..15), Number (19, 1..15)
|
# Bottom: Name (18, 2..16), Number (19, 2..16)
|
||||||
# Right: Number (17..3, 16), Name (17..3, 15)
|
# Right: Number (17..3, 18), Name (17..3, 17)
|
||||||
|
|
||||||
# Top Numbers 在 row 1
|
# Top Numbers 在 row 1, col 2..16
|
||||||
for c in range(1, QFN60_COLS + 1):
|
for c in range(2, QFN60_COLS + 2):
|
||||||
ref = rc_to_cell_ref(1, c)
|
ref = rc_to_cell_ref(1, c)
|
||||||
assert ref in data, f"Top Number {ref} 缺失"
|
assert ref in data, f"Top Number {ref} 缺失"
|
||||||
|
|
||||||
# Top Names 在 row 2
|
# Top Names 在 row 2, col 2..16
|
||||||
for c in range(1, QFN60_COLS + 1):
|
for c in range(2, QFN60_COLS + 2):
|
||||||
ref = rc_to_cell_ref(2, c)
|
ref = rc_to_cell_ref(2, c)
|
||||||
assert ref in data, f"Top Name {ref} 缺失"
|
assert ref in data, f"Top Name {ref} 缺失"
|
||||||
assert data[ref].startswith("Pin"), f"Top Name {ref} = {data[ref]}"
|
assert data[ref].startswith("Pin"), f"Top Name {ref} = {data[ref]}"
|
||||||
@@ -808,25 +808,25 @@ def test_f016_qfn60_list_to_map():
|
|||||||
assert ref in data, f"Left Name {ref} 缺失"
|
assert ref in data, f"Left Name {ref} 缺失"
|
||||||
assert data[ref].startswith("Pin"), f"Left Name {ref} = {data[ref]}"
|
assert data[ref].startswith("Pin"), f"Left Name {ref} = {data[ref]}"
|
||||||
|
|
||||||
# Bottom Names 在 row 18
|
# Bottom Names 在 row 18, col 2..16
|
||||||
for c in range(1, QFN60_COLS + 1):
|
for c in range(2, QFN60_COLS + 2):
|
||||||
ref = rc_to_cell_ref(QFN60_ROWS + 3, c)
|
ref = rc_to_cell_ref(QFN60_ROWS + 3, c)
|
||||||
assert ref in data, f"Bottom Name {ref} 缺失"
|
assert ref in data, f"Bottom Name {ref} 缺失"
|
||||||
assert data[ref].startswith("Pin"), f"Bottom Name {ref} = {data[ref]}"
|
assert data[ref].startswith("Pin"), f"Bottom Name {ref} = {data[ref]}"
|
||||||
|
|
||||||
# Bottom Numbers 在 row 19
|
# Bottom Numbers 在 row 19, col 2..16
|
||||||
for c in range(1, QFN60_COLS + 1):
|
for c in range(2, QFN60_COLS + 2):
|
||||||
ref = rc_to_cell_ref(QFN60_ROWS + 4, c)
|
ref = rc_to_cell_ref(QFN60_ROWS + 4, c)
|
||||||
assert ref in data, f"Bottom Number {ref} 缺失"
|
assert ref in data, f"Bottom Number {ref} 缺失"
|
||||||
|
|
||||||
# Right Numbers 在 col 16, rows 17..3
|
# Right Numbers 在 col 18, rows 17..3
|
||||||
for r in range(QFN60_ROWS + 2, 2, -1):
|
for r in range(QFN60_ROWS + 2, 2, -1):
|
||||||
ref = rc_to_cell_ref(r, QFN60_COLS + 1)
|
ref = rc_to_cell_ref(r, QFN60_COLS + 3)
|
||||||
assert ref in data, f"Right Number {ref} 缺失"
|
assert ref in data, f"Right Number {ref} 缺失"
|
||||||
|
|
||||||
# Right Names 在 col 15, rows 17..3
|
# Right Names 在 col 17, rows 17..3
|
||||||
for r in range(QFN60_ROWS + 2, 2, -1):
|
for r in range(QFN60_ROWS + 2, 2, -1):
|
||||||
ref = rc_to_cell_ref(r, QFN60_COLS)
|
ref = rc_to_cell_ref(r, QFN60_COLS + 2)
|
||||||
assert ref in data, f"Right Name {ref} 缺失"
|
assert ref in data, f"Right Name {ref} 缺失"
|
||||||
assert data[ref].startswith("Pin"), f"Right Name {ref} = {data[ref]}"
|
assert data[ref].startswith("Pin"), f"Right Name {ref} = {data[ref]}"
|
||||||
|
|
||||||
|
|||||||
59
context.md
Normal file
59
context.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# pinmap-to-pinlist 项目上下文
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
- **项目名称:** pinmap-to-pinlist
|
||||||
|
- **项目类型:** Python 脚本工具
|
||||||
|
- **核心功能:** PinMAP ↔ PinList 双向转换(Excel xlsx 格式)
|
||||||
|
- **当前版本:** v1.6
|
||||||
|
|
||||||
|
## 技术约束
|
||||||
|
- 语言:Python
|
||||||
|
- 平台:Windows + Linux
|
||||||
|
- 输出格式:Excel .xlsx(支持富文本样式)
|
||||||
|
- 封装类型:仅支持环形布局(QFN 类),引脚分布在芯片四边(上/右/下/左),允许非正方形(如 10×15)
|
||||||
|
- 模板文件:`Code/src/Template/PinMAP-Template.xlsx` 和 `PinList-Template.xlsx`
|
||||||
|
|
||||||
|
## 使用场景
|
||||||
|
- 用户提供 PinList CSV(封装名 + 引脚名/序号对),期望生成 PinMAP(环形四边布局)
|
||||||
|
- 用户提供 PinMAP Excel,期望生成 PinList(引脚名/序号对 + 封装名)
|
||||||
|
- 两个方向都需要读取模板文件应用样式(字体、对齐、列宽、行高、背景色、边框)
|
||||||
|
|
||||||
|
## 当前活跃 Bug
|
||||||
|
|
||||||
|
### BUG-007:PinList→PinMAP 上方引脚并入标题行(已修复)
|
||||||
|
|
||||||
|
**严重程度:** 高 | **关联功能:** F013, F016 | **版本:** v1.6 回归
|
||||||
|
|
||||||
|
**修复后实际输出(转 CSV):**
|
||||||
|
```
|
||||||
|
QFN60,,,,,,,,,,,,,,,,,,
|
||||||
|
,,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,,
|
||||||
|
,,Pin60,Pin59,Pin58,Pin57,Pin56,Pin55,Pin54,Pin53,Pin52,Pin51,Pin50,Pin49,Pin48,Pin47,Pin46,,
|
||||||
|
1,Pin1,,,,,,,,,,,,,,,,Pin45,45
|
||||||
|
2,Pin2,,,,,,,,,,,,,,,,Pin44,44
|
||||||
|
3,Pin3,,,,,,,,,,,,,,,,Pin43,43
|
||||||
|
4,Pin4,,,,,,,,,,,,,,,,Pin42,42
|
||||||
|
5,Pin5,,,,,,,,,,,,,,,,Pin41,41
|
||||||
|
6,Pin6,,,,,,,,,,,,,,,,Pin40,40
|
||||||
|
7,Pin7,,,,,,,,,,,,,,,,Pin39,39
|
||||||
|
8,Pin8,,,,,,,,,,,,,,,,Pin38,38
|
||||||
|
9,Pin9,,,,,,,,,,,,,,,,Pin37,37
|
||||||
|
10,Pin10,,,,,,,,,,,,,,,,Pin36,36
|
||||||
|
11,Pin11,,,,,,,,,,,,,,,,Pin35,35
|
||||||
|
12,Pin12,,,,,,,,,,,,,,,,Pin34,34
|
||||||
|
13,Pin13,,,,,,,,,,,,,,,,Pin33,33
|
||||||
|
14,Pin14,,,,,,,,,,,,,,,,Pin32,32
|
||||||
|
15,Pin15,,,,,,,,,,,,,,,,Pin31,31
|
||||||
|
,,Pin16,Pin17,Pin18,Pin19,Pin20,Pin21,Pin22,Pin23,Pin24,Pin25,Pin26,Pin27,Pin28,Pin29,Pin30,,
|
||||||
|
,,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,,
|
||||||
|
```
|
||||||
|
|
||||||
|
**修复特征(与期望 CSV 对比):**
|
||||||
|
1. ✅ 第 1 行标题独占(A1 仅含 `QFN60`,无引脚数据混入)
|
||||||
|
2. ✅ 第 2 行为上方独立序号行 `,,60,59,...,46,,`
|
||||||
|
3. ✅ 第 3 行为上方独立 PinName 行 `,,Pin60,...,Pin46,,`
|
||||||
|
4. ✅ 总行数 20(0-based 0-19),与期望 21 行结构一致
|
||||||
|
5. ✅ 左右引脚位置正确(A=Number, B=Name)
|
||||||
|
6. ✅ 下边 PinName/Number 位置正确
|
||||||
|
|
||||||
|
**验收标准:** ✅ 已达标 — PinList→PinMAP 输出结构与期望 CSV 逐行一致。
|
||||||
Reference in New Issue
Block a user