@ww_nero/skills 3.0.2 → 3.0.4

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
@@ -201,8 +201,7 @@ const GUIDES = {
201
201
  - **不要使用\`BeautifulSoup\`这种通用的解析元素的方式,而是逐个元素从svg代码转化为python创建元素的代码**
202
202
  - 转换过程中,需要把图片占位元素替换成前面准备的图片素材
203
203
 
204
- 4. **保留工作文件**:
205
- - 完成后**需要保留**规划文档、html页面文件和python转化脚本,方便进一步根据反馈进行修改`
204
+ **注意**:完成后**需要保留**规划文档、html页面文件和python转化脚本,方便进一步根据反馈进行修改`
206
205
  }
207
206
  };
208
207
 
@@ -284,7 +283,7 @@ const listTools = () => ({
284
283
  ]
285
284
  });
286
285
 
287
- const server = new Server({ name: 'skills', version: '3.0.2' }, { capabilities: { tools: {} } });
286
+ const server = new Server({ name: 'skills', version: '3.0.4' }, { capabilities: { tools: {} } });
288
287
 
289
288
  server.setRequestHandler(ListToolsRequestSchema, async () => listTools());
290
289
 
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.4",
4
4
  "description": "MCP server that returns Python reference snippets and skill guides",
5
5
  "main": "index.js",
6
6
  "bin": {