feat: PinMAP转PinList v1.2.0 - 新增PinList转PinMAP反向转换功能
This commit is contained in:
@@ -101,3 +101,88 @@ def validate_pinmap(pinmap: PinMAP) -> ValidationResult:
|
||||
result.is_valid = False
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def validate_pinlist_for_map(
|
||||
entries: list,
|
||||
rows: int,
|
||||
cols: int,
|
||||
) -> ValidationResult:
|
||||
"""验证 PinList 数据是否适合转换为 PinMAP。
|
||||
|
||||
Checks performed
|
||||
----------------
|
||||
1. **Continuity** — pin numbers must start from 1 with no gaps.
|
||||
2. **Uniqueness** — no duplicate pin numbers.
|
||||
3. **Perimeter match** — total pin count must equal
|
||||
2×rows + 2×cols − 4 (the grid perimeter).
|
||||
4. **Non-multiple-of-4** — if pin count is not a multiple of 4,
|
||||
a warning is issued (but conversion is not blocked).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
entries : list[PinListEntry]
|
||||
PinList entries, each with ``number`` and ``name`` attributes.
|
||||
rows : int
|
||||
Target PinMAP row count.
|
||||
cols : int
|
||||
Target PinMAP column count.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ValidationResult
|
||||
"""
|
||||
result = ValidationResult(is_valid=True, errors=[], warnings=[])
|
||||
|
||||
numbers = [e.number for e in entries]
|
||||
|
||||
# ── 1. Continuity (1..N, no gaps) ────────────────────────────
|
||||
expected_numbers = list(range(1, len(numbers) + 1))
|
||||
if numbers != expected_numbers:
|
||||
missing = set(expected_numbers) - set(numbers)
|
||||
if missing:
|
||||
result.errors.append(ValidationError(
|
||||
level="error",
|
||||
message="Pin序号不连续",
|
||||
details=f"缺失的序号: {sorted(missing)}",
|
||||
))
|
||||
|
||||
# ── 2. Uniqueness ────────────────────────────────────────────
|
||||
if len(numbers) != len(set(numbers)):
|
||||
counts = Counter(numbers)
|
||||
duplicates = sorted(n for n, c in counts.items() if c > 1)
|
||||
result.errors.append(ValidationError(
|
||||
level="error",
|
||||
message="Pin序号存在重复",
|
||||
details=f"重复的序号: {duplicates}",
|
||||
))
|
||||
|
||||
# ── 3. Perimeter match ───────────────────────────────────────
|
||||
expected_total = 2 * rows + 2 * cols - 4
|
||||
actual_total = len(entries)
|
||||
if actual_total != expected_total:
|
||||
result.errors.append(ValidationError(
|
||||
level="error",
|
||||
message="Pin数量与网格周长不匹配",
|
||||
details=(
|
||||
f"网格 {rows}×{cols} 需要 {expected_total} 个引脚,"
|
||||
f"但 PinList 有 {actual_total} 个"
|
||||
),
|
||||
))
|
||||
|
||||
# ── 4. Non-multiple-of-4 warning ─────────────────────────────
|
||||
if actual_total % 4 != 0:
|
||||
result.warnings.append(ValidationError(
|
||||
level="warning",
|
||||
message="Pin数量不是4的倍数",
|
||||
details=(
|
||||
f"Pin数量 ({actual_total}) 不是 4 的倍数,"
|
||||
f"四条边将不均匀分布"
|
||||
),
|
||||
))
|
||||
|
||||
# ── Final verdict ────────────────────────────────────────────
|
||||
if result.errors:
|
||||
result.is_valid = False
|
||||
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user