Skill: geming416684729-svg/flowchart-exam-generator (version 1.0.0)

--- name: flowchart-exam-generator description: 根据流程图图片自动生成应知应会考试题（单选题、多选题）。当用户要求"根据流程图出考试题"、"根据流程图生成题目"、"根据流程图出应知应会"时使用。 --- # 流程图考试题生成器 根据上传的流程图图片，自动分析流程内容并生成标准格式的应知应会考试题Excel文件。 ## 工作流程 ### 1. 分析流程图 使用 `images_understand` 工具分析流程图，提取： - 流程名称和主题 - 所有步骤和环节 - 每个步骤的具体内容、操作人员、输入输出文件 - 判断条件和分支 - 涉及的部门或岗位 - 特殊情况或注意事项 ### 2. 生成考试题 根据分析结果生成考试题，默认配置： - **单选题**：5道（可自定义数量） - **多选题**：5道（可自定义数量） ### 3. 输出格式要求 **题目格式规范：** 1. 出处放在题干前面，用逗号分隔 ``` 流程名称，题目内容（） ``` 2. 用`（）`代替提问部分 3. 每道题4个选项（A/B/C/D） 4. 答案格式：`A=1, B=2, C=3, D=4` 5. 多选题答案用逗号隔开（如：`1,2,3`） ### 4. Excel输出结构 | 列 | 内容 | |----|------| | 题型 | 单选题/多选题 | | 题目 | 带出处的完整题目 | | 选项1 | A选项 | | 选项2 | B选项 | | 选项3 | C选项 | | 选项4 | D选项 | | 正确答案 | 数字格式（1/2/3/4，多选用逗号） | | 解析 | 答案解析 | | 出处 | 流程名称 | ## 执行示例 ``` 用户：请根据这个流程图出5道单选和5道多选 1. 分析流程图内容 2. 生成符合格式的考试题 3. 保存为Excel文件 4. 提供下载链接 ``` ## 注意事项 - 确保流程图清晰可读 - 涉及部门、岗位、文件名称都要提取 - 特殊情况（如判断条件、分支处理）要单独出题 - 解析部分要准确说明答案原因

path: _meta.json
content: id: 1038
version: 1.0.0
slug: flowchart-exam-generator

path: scripts/generate_exam.py
content: #!/usr/bin/env python3
"""
流程图考试题生成脚本
根据流程图分析结果生成标准格式的应知应会考试题Excel
"""

import sys
import json
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side

# 答案格式：A=1, B=2, C=3, D=4
ANSWER_MAP = {'A': '1', 'B': '2', 'C': '3', 'D': '4'}

def create_excel(exam_questions, output_path='考试题.xlsx'):
    """
    创建考试题Excel文件

    Args:
        exam_questions: 考试题列表，每道题为dict，包含题型、题目、选项、正确答案、解析、出处
        output_path: 输出文件路径
    """
    wb = Workbook()
    ws = wb.active
    ws.title = "考试题库"

    # 设置列宽
    ws.column_dimensions['A'].width = 12
    ws.column_dimensions['B'].width = 80
    ws.column_dimensions['C'].width = 20
    ws.column_dimensions['D'].width = 20
    ws.column_dimensions['E'].width = 20
    ws.column_dimensions['F'].width = 20
    ws.column_dimensions['G'].width = 12
    ws.column_dimensions['H'].width = 60
    ws.column_dimensions['I'].width = 15

    # 标题样式
    header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
    header_font = Font(bold=True, color="FFFFFF", size=11)
    thin_border = Border(
        left=Side(style='thin'),
        right=Side(style='thin'),
        top=Side(style='thin'),
        bottom=Side(style='thin')
    )

    # 写入表头
    headers = ['题型', '题目', '选项1', '选项2', '选项3', '选项4', '正确答案', '解析', '出处']
    for col, header in enumerate(headers, 1):
        cell = ws.cell(row=1, column=col, value=header)
        cell.fill = header_fill
        cell.font = header_font
        cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        cell.border = thin_border

    # 写入数据
    for row, question in enumerate(exam_questions, 2):
        ws.cell(row=row, column=1, value=question.get('题型', '')).border = thin_border
        ws.cell(row=row, column=2, value=question.get('题目', '')).border = thin_border
        ws.cell(row=row, column=3, value=question.get('选项1', '')).border = thin_border
        ws.cell(row=row, column=4, value=question.get('选项2', '')).border = thin_border
        ws.cell(row=row, column=5, value=question.get('选项3', '')).border = thin_border
        ws.cell(row=row, column=6, value=question.get('选项4', '')).border = thin_border
        ws.cell(row=row, column=7, value=question.get('正确答案', '')).border = thin_border
        ws.cell(row=row, column=8, value=question.get('解析', '')).border = thin_border
        ws.cell(row=row, column=9, value=question.get('出处', '')).border = thin_border

        # 设置对齐方式
        for col in range(1, 10):
            ws.cell(row=row, column=col).alignment = Alignment(
                horizontal='center', vertical='center', wrap_text=True
            )

    # 保存文件
    wb.save(output_path)
    print(f"考试题已生成并保存至: {output_path}")

    # 统计
    single_count = sum(1 for q in exam_questions if q.get('题型') == '单选题')
    multi_count = sum(1 for q in exam_questions if q.get('题型') == '多选题')
    print(f"共计 {len(exam_questions)} 道题目")
    print(f"- 单选题: {single_count} 道")
    print(f"- 多选题: {multi_count} 道")
    print("\n答案格式说明：")
    print("- A=1, B=2, C=3, D=4")
    print("- 多选题答案示例: 1,3,4 表示选A、C、D")


def convert_answer(answer_str):
    """
    将字母格式的答案转换为数字格式
    例如: 'ABCD' -> '1,2,3,4', 'AC' -> '1,3'
    """
    result = []
    for char in answer_str.upper():
        if char in ANSWER_MAP:
            result.append(ANSWER_MAP[char])
    return ','.join(result)


if __name__ == '__main__':
    # 示例数据
    sample_questions = [
        {
            '题型': '单选题',
            '题目': '测试流程，流程从（）部门开始。',
            '选项1': 'A部门',
            '选项2': 'B部门',
            '选项3': 'C部门',
            '选项4': 'D部门',
            '正确答案': '2',
            '解析': '根据流程图，流程从B部门开始。',
            '出处': '测试流程'
        }
    ]

    if len(sys.argv) > 1:
        # 从命令行参数读取题目数据(JSON格式)
        try:
            questions = json.loads(sys.argv[1])
            output = sys.argv[2] if len(sys.argv) > 2 else '考试题.xlsx'
            create_excel(questions, output)
        except json.JSONDecodeError as e:
            print(f"JSON解析错误: {e}")
            sys.exit(1)
    else:
        create_excel(sample_questions)


path: scripts/quick_validate.py
content: #!/usr/bin/env python3
"""
技能结构验证脚本
验证SKILL.md和_meta.json的格式是否正确
"""

import os
import re
import json
import sys

def validate_skill(skill_path):
    """
    验证技能结构

    Returns:
        tuple: (is_valid, errors)
    """
    errors = []

    # 检查SKILL.md是否存在
    skill_md_path = os.path.join(skill_path, 'SKILL.md')
    if not os.path.exists(skill_md_path):
        errors.append("SKILL.md 文件不存在")
        return False, errors

    # 读取SKILL.md内容
    with open(skill_md_path, 'r', encoding='utf-8') as f:
        content = f.read()

    # 检查frontmatter格式
    if not content.startswith('---'):
        errors.append("SKILL.md 必须以 YAML frontmatter (---) 开头")

    # 提取frontmatter
    frontmatter_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
    if not frontmatter_match:
        errors.append("无法解析 YAML frontmatter")
    else:
        frontmatter = frontmatter_match.group(1)

        # 检查必填字段
        if 'name:' not in frontmatter:
            errors.append("frontmatter 必须包含 name 字段")
        if 'description:' not in frontmatter:
            errors.append("frontmatter 必须包含 description 字段")

    # 检查_meta.json
    meta_path = os.path.join(skill_path, '_meta.json')
    if not os.path.exists(meta_path):
        errors.append("_meta.json 文件不存在")
    else:
        try:
            with open(meta_path, 'r', encoding='utf-8') as f:
                meta = json.load(f)

            # 检查必填字段
            if 'id' not in meta:
                errors.append("_meta.json 必须包含 id 字段")
            if 'version' not in meta:
                errors.append("_meta.json 必须包含 version 字段")

            # 检查id类型
            if 'id' in meta and not isinstance(meta['id'], int):
                errors.append("_meta.json 的 id 必须是整数")
        except json.JSONDecodeError as e:
            errors.append(f"_meta.json JSON格式错误: {e}")

    return len(errors) == 0, errors


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("用法: python quick_validate.py <skill_path>")
        sys.exit(1)

    skill_path = sys.argv[1]
    is_valid, errors = validate_skill(skill_path)

    if is_valid:
        print("✓ 验证通过")
        sys.exit(0)
    else:
        print("✗ 验证失败:")
        for error in errors:
            print(f"  - {error}")
        sys.exit(1)


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)