@ww_nero/skills 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,7 @@
1
- #!/usr/bin/env python3
2
1
  # -*- coding: utf-8 -*-
3
- """
4
- 将HTML文件中的SVG转换为PPTX
5
-
6
- 注意事项:
7
- - 对于 icon 元素(如带有 id="icon-*" 的 <g> 元素),
8
- 会先将其独立保存为小的 PNG 图片,然后再插入到 PPTX 中。
9
- 这样可以保证矢量图标在 PowerPoint 中正确显示。
10
- """
11
2
  import os
12
3
  import re
4
+ import math
13
5
  import tempfile
14
6
  from pptx import Presentation
15
7
  from pptx.util import Pt, Emu
@@ -522,6 +514,106 @@ def add_circular_image(slide, image_path, cx, cy, r):
522
514
  shape = slide.shapes.add_picture(buffer, px(cx - r), px(cy - r), px(diameter), px(diameter))
523
515
  return shape
524
516
 
517
+ def add_pie_chart(slide, cx, cy, r, data, colors, labels=None, start_angle=-90, stroke_color=None, stroke_width=0, opacity=1.0, has_shadow=False):
518
+ total = sum(data)
519
+ if total == 0:
520
+ return []
521
+
522
+ shapes = []
523
+ current_angle = start_angle
524
+
525
+ for i, value in enumerate(data):
526
+ if value <= 0:
527
+ continue
528
+
529
+ percentage = value / total
530
+ sweep_angle = percentage * 360
531
+
532
+ color = colors[i % len(colors)]
533
+ shape = _add_pie_slice(slide, cx, cy, r, current_angle, sweep_angle,
534
+ color, stroke_color, stroke_width, opacity, has_shadow)
535
+ if shape:
536
+ shapes.append(shape)
537
+
538
+ current_angle += sweep_angle
539
+
540
+ return shapes
541
+
542
+ def _add_pie_slice(slide, cx, cy, r, start_angle, sweep_angle, fill_color, stroke_color=None, stroke_width=0, opacity=1.0, has_shadow=False):
543
+ if sweep_angle >= 360:
544
+ sweep_angle = 359.99
545
+
546
+ start_rad = math.radians(start_angle)
547
+ end_rad = math.radians(start_angle + sweep_angle)
548
+
549
+ points = [(cx, cy)]
550
+
551
+ num_segments = max(int(sweep_angle / 5), 2)
552
+ for i in range(num_segments + 1):
553
+ angle = start_rad + (end_rad - start_rad) * i / num_segments
554
+ x = cx + r * math.cos(angle)
555
+ y = cy + r * math.sin(angle)
556
+ points.append((x, y))
557
+
558
+ points.append((cx, cy))
559
+
560
+ shape = add_freeform_path(slide, points, fill_color=fill_color,
561
+ stroke_color=stroke_color, stroke_width=stroke_width,
562
+ opacity=opacity, closed=True, has_shadow=has_shadow)
563
+ return shape
564
+
565
+ def add_donut_chart(slide, cx, cy, outer_r, inner_r, data, colors, labels=None, start_angle=-90, stroke_color=None, stroke_width=0, opacity=1.0, has_shadow=False):
566
+ total = sum(data)
567
+ if total == 0:
568
+ return []
569
+
570
+ shapes = []
571
+ current_angle = start_angle
572
+
573
+ for i, value in enumerate(data):
574
+ if value <= 0:
575
+ continue
576
+
577
+ percentage = value / total
578
+ sweep_angle = percentage * 360
579
+
580
+ color = colors[i % len(colors)]
581
+ shape = _add_donut_slice(slide, cx, cy, outer_r, inner_r, current_angle, sweep_angle,
582
+ color, stroke_color, stroke_width, opacity, has_shadow)
583
+ if shape:
584
+ shapes.append(shape)
585
+
586
+ current_angle += sweep_angle
587
+
588
+ return shapes
589
+
590
+ def _add_donut_slice(slide, cx, cy, outer_r, inner_r, start_angle, sweep_angle, fill_color, stroke_color=None, stroke_width=0, opacity=1.0, has_shadow=False):
591
+ if sweep_angle >= 360:
592
+ sweep_angle = 359.99
593
+
594
+ start_rad = math.radians(start_angle)
595
+ end_rad = math.radians(start_angle + sweep_angle)
596
+
597
+ points = []
598
+
599
+ num_segments = max(int(sweep_angle / 5), 2)
600
+ for i in range(num_segments + 1):
601
+ angle = start_rad + (end_rad - start_rad) * i / num_segments
602
+ x = cx + outer_r * math.cos(angle)
603
+ y = cy + outer_r * math.sin(angle)
604
+ points.append((x, y))
605
+
606
+ for i in range(num_segments, -1, -1):
607
+ angle = start_rad + (end_rad - start_rad) * i / num_segments
608
+ x = cx + inner_r * math.cos(angle)
609
+ y = cy + inner_r * math.sin(angle)
610
+ points.append((x, y))
611
+
612
+ shape = add_freeform_path(slide, points, fill_color=fill_color,
613
+ stroke_color=stroke_color, stroke_width=stroke_width,
614
+ opacity=opacity, closed=True, has_shadow=has_shadow)
615
+ return shape
616
+
525
617
  def create_slide(prs):
526
618
  """深度学习的崛起(1990-2017)"""
527
619
  slide = prs.slides.add_slide(prs.slide_layouts[6])
@@ -680,6 +772,25 @@ def create_slide(prs):
680
772
  # SVG: <text x="320" y="650" font-size="32" fill="#ffffff">🧠</text>
681
773
  add_text_box(slide, "🧠", 320, 650, 50, 40, 32, "#ffffff", anchor='start', valign='top')
682
774
 
775
+ # 饼状图演示:展示各技术占比
776
+ # SVG: <g transform="translate(500, 550)">
777
+ # <!-- 饼状图: CNN 40%, RNN 25%, GAN 20%, Transformer 15% -->
778
+ # </g>
779
+ pie_data = [40, 25, 20, 15]
780
+ pie_colors = ["#ff6384", "#36a2eb", "#ffce56", "#4bc0c0"]
781
+ add_pie_chart(slide, 500, 580, 50, pie_data, pie_colors, stroke_color="#1a237e", stroke_width=1)
782
+ add_text_box(slide, "技术分布", 500, 520, 100, 20, 12, "#b3e5fc", anchor='middle', valign='top')
783
+
784
+ # 环形图演示:展示GPU使用率
785
+ # SVG: <g transform="translate(600, 550)">
786
+ # <!-- 环形图: 训练 60%, 推理 30%, 空闲 10% -->
787
+ # </g>
788
+ donut_data = [60, 30, 10]
789
+ donut_colors = ["#00e5ff", "#2979ff", "#ffffff"]
790
+ add_donut_chart(slide, 600, 580, 50, 30, donut_data, donut_colors, stroke_color="#1a237e", stroke_width=1, opacity=0.9)
791
+ add_text_box(slide, "GPU", 600, 580, 40, 20, 14, "#ffffff", bold=True, anchor='middle', valign='middle')
792
+ add_text_box(slide, "使用率", 600, 520, 100, 20, 12, "#b3e5fc", anchor='middle', valign='top')
793
+
683
794
  def main():
684
795
  prs = Presentation()
685
796
  prs.slide_width = px(1280)
package/index.js CHANGED
@@ -284,7 +284,7 @@ const listTools = () => ({
284
284
  ]
285
285
  });
286
286
 
287
- const server = new Server({ name: 'skills', version: '3.0.2' }, { capabilities: { tools: {} } });
287
+ const server = new Server({ name: 'skills', version: '3.0.3' }, { capabilities: { tools: {} } });
288
288
 
289
289
  server.setRequestHandler(ListToolsRequestSchema, async () => listTools());
290
290
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ww_nero/skills",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "description": "MCP server that returns Python reference snippets and skill guides",
5
5
  "main": "index.js",
6
6
  "bin": {