Install
openclaw skills install @flyboat403/score-analyzer-skillAnalyze student score data from Excel files and generate professional analysis reports. Use when the user provides an Excel score sheet (.xlsx), asks to analyze student scores, test results, exam data, or grade data. The Agent performs all analysis directly using Python scripts (pandas, matplotlib) and its own intelligence for report writing—no external LLM API needed during execution. Supports data cleaning, statistical analysis, chart generation (score distribution, class comparison, radar, trends, boxplot, heatmap, deviation, top-bottom), narrative report writing, and ZIP package output. Triggers: "analyze scores", "score report", "exam analysis", "成绩分析", "成绩报告", "学生成绩", "score sheet", "upload excel for analysis", "analyze test results", "成绩统计", "前10名", "成绩对比", "班级成绩".
openclaw skills install @flyboat403/score-analyzer-skillAgent analyzes student Excel score sheets and produces professional reports. No external LLM API needed.
python3 scripts/extract_data.py --input <file> --output reports/data.csv
extract_data.py. Agent must manually process and output reports/data.csv in strict Long Format:
student_id,student_name,student_class,subject,value
001,张三,一班,语文分数,85.0
001,张三,一班,数学分数,92.0
002,李四,一班,语文分数,88.0
student_id, student_name, subject, valuevalue MUST be numeric floatdf = pd.read_excel(file, header=n) # n = header row index (try 0, 1, 2)
df.rename(columns={'学号': 'student_id', '姓名': 'student_name'}, inplace=True)
id_cols = ['student_id', 'student_name']
if 'student_class' in df.columns:
id_cols.append('student_class')
df_long = df.melt(id_vars=id_cols, var_name='subject', value_name='value')
df_long = df_long.dropna(subset=['value'])
df_long['value'] = pd.to_numeric(df_long['value'], errors='coerce')
df_long.to_csv('reports/data.csv', index=False)
python3 scripts/data_cleaner.py --input reports/data.csv --output reports/data.csvpython3 scripts/tagger.py --input reports/data.csv --output reports/students_tags.csv (Generates "偏科预警" etc.)python3 scripts/individual_reports.py --input reports/data.csv --output reports/individual_reportspython3 scripts/dynamic_thresholds.py --input reports/data.csv --output reports/dynamic_thresholds.jsonreports/data.csv (or cleaned_data.csv) file present?value column has no NaN/null entries?students_tags.csv generated?reports/dynamic_thresholds.json generated?reports/dynamic_thresholds.json for percentile-based metrics.references/analysis_prompt.md for guidelines.. NEVER use tables or appendix formats. The assemble script only recognizes inline placeholders.python3 scripts/generate_charts.py --input reports/data.csv --output reports/charts/python3 scripts/assemble_reports.py --data reports/data.csv --charts reports/charts/ --report "REPORT.md" --output reports/ls reports/charts/*.png | wc -l equals 12 (or 9 if no grouping)?ls -la reports/charts/*.png | awk '$5 < 10000 {print "TOO SMALL: "$0}'reports/report.html contains valid base64 charts?
grep -c 'data:image/png;base64' reports/report.html ≥ 12?report.docx?
python3 -c "from docx import Document; print(len(Document('reports/report.docx').element.xpath('.//a:blip')))" ≥ 12?PLOT:XXX remains?
grep -c 'PLOT:' reports/report.html = 0?grep -c '!\[.*\](PLOT:' reports/report_content.md → must be ≥ 12 before running assemble_reports.py. If result is 0, the report has placeholders in wrong format (e.g. table).ls reports/individual_reports/*.html | wc -l equals student count?reports/report.zipFor the full report structure and analysis guidelines, READ: references/analysis_prompt.md
Mandatory Chart Placeholders (include all that apply — match count to generated charts):
| Category | Placeholder | Chart |
|---|---|---|
| Overview | PLOT:DISTRIBUTION | Score distribution histogram |
PLOT:CDF | Cumulative distribution function | |
PLOT:NORMAL | Normal distribution Q-Q plot | |
| Comparison | PLOT:TREND | Subject mean trends |
PLOT:HEATMAP | Class/subject heatmap | |
PLOT:BOXPLOT_SUBJ | Subject box plots | |
| Gap/Spread | PLOT:SCATTER | Total vs subject scatter |
PLOT:TOP_BOTTOM | Top vs bottom N comparison | |
PLOT:DEVIATION | Score deviation analysis | |
| Grouped* | PLOT:COMPARISON | Inter-class comparison |
PLOT:RADAR | Class radar chart | |
PLOT:BOXPLOT | Class total box plot |
*Grouped placeholders require a grouping column (class/major/school) in the data.
NEVER include chart placeholders if chart generation failed — but ALWAYS ensure the markdown text includes exactly 12 placeholders if charts were generated successfully.
NEVER write a minimal text report. Must include dynamic passing rates, fine-grained segments, and granular actionable advice.
extract_data.py backup.extract_data.py. Use Agent's pandas/LLM intelligence directly to map columns.PLOT:COMPARISON, PLOT:RADAR, and PLOT:BOXPLOT from the report.fc-list :lang=zh. If missing, install apt install fonts-noto-cjk → Re-generate charts."Test Report" to assemble_reports.py.
Why: The script embeds EXACTLY what you pass. If the report content is short, the final docx/html will appear "empty". You MUST generate a full markdown analysis with statistics tables and narrative text.generate_charts.py skips charts 7-9 if grouping is missing. Assembly will leave raw placeholder text in the document.extract_data.py for complex Excel files (e.g., merged headers, sub-headers).
Why: It fails on IndexError when detecting headers on complex layouts (we learned this the hard way!). Use pandas + Agent intelligence instead.report.zip in the zip archive.
Why: Recursive self-inclusion creates massive 3GB+ files. The script has been patched to skip this, but verify create_zip_package logic if modifying code.