feat: PinMAP转PinList v1.2.0 - 新增PinList转PinMAP反向转换功能

This commit is contained in:
2026-05-28 01:53:51 +08:00
parent 853f10a73b
commit 3228c1a2e6
18 changed files with 3781 additions and 977 deletions

View File

@@ -0,0 +1,112 @@
"""PinList validator — checks pin data integrity.
Validates a PinList for:
1. Pin numbers starting from 1 with no gaps
2. No duplicate pin numbers
3. Total pin count matches grid perimeter (2×rows + 2×cols 4)
4. Missing PinName defaults to NC (warning)
5. Pin count not a multiple of 4 (info)
"""
from models import PinListEntry, ValidationResult, ValidationError
def validate_pinlist(
entries: list[PinListEntry],
rows: int,
cols: int,
) -> ValidationResult:
"""
验证 PinList 数据。
检查项:
1. Pin 序号从 1 开始连续无缺失
2. Pin 序号无重复
3. Pin 总数 = 2×rows + 2×cols 4周长匹配
4. Pin 缺少 PinName 时默认为 NCwarning
5. Pin 数量不是 4 的倍数时提示info
Parameters
----------
entries : list[PinListEntry]
已按序号排序的引脚列表
rows : int
用户输入的 PinMAP 行数
cols : int
用户输入的 PinMAP 列数
Returns
-------
ValidationResult
"""
errors: list[ValidationError] = []
warnings: list[ValidationError] = []
infos: list[ValidationError] = []
numbers = [e.number for e in entries]
# ── 1. 连续性检查 ────────────────────────────────────────────
expected_numbers = list(range(1, len(numbers) + 1))
if numbers != expected_numbers:
missing = set(expected_numbers) - set(numbers)
if missing:
errors.append(ValidationError(
level="error",
message="Pin序号不连续",
details=f"缺失的序号: {sorted(missing)}",
))
# ── 2. 唯一性检查 ────────────────────────────────────────────
if len(numbers) != len(set(numbers)):
from collections import Counter
counts = Counter(numbers)
duplicates = sorted(n for n, c in counts.items() if c > 1)
errors.append(ValidationError(
level="error",
message="Pin序号存在重复",
details=f"重复的序号: {duplicates}",
))
# ── 3. 周长匹配 ──────────────────────────────────────────────
expected_total = 2 * rows + 2 * cols - 4
actual_total = len(entries)
if actual_total != expected_total:
errors.append(ValidationError(
level="error",
message="Pin数量与网格周长不匹配",
details=(
f"网格 {rows}×{cols} 需要 {expected_total} 个引脚,"
f"但 PinList 有 {actual_total}"
),
))
# ── 4. 缺失 PinNamewarning────────────────────────────────
missing_names = [e for e in entries if not e.name or not e.name.strip()]
if missing_names:
warnings.append(ValidationError(
level="warning",
message=f"检测到 {len(missing_names)} 个引脚缺少 PinName",
details=(
f"缺失引脚序号: {[e.number for e in missing_names]}"
f"将默认为 NC"
),
))
# ── 5. 非 4 倍数提示info──────────────────────────────────
if actual_total % 4 != 0:
infos.append(ValidationError(
level="info",
message="Pin数量不是4的倍数",
details=(
f"Pin数量 ({actual_total}) 不是 4 的倍数,"
f"四条边将不均匀分布"
),
))
is_valid = len(errors) == 0
return ValidationResult(
is_valid=is_valid,
errors=errors,
warnings=warnings,
)