barunsaha commited on
Commit
eda1694
1 Parent(s): 71518f2

Add a new template (with user-edited master slides); get slide placeholders and index properly for this new template

Browse files
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.pptx filter=lfs diff=lfs merge=lfs -text
 
 
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.pptx filter=lfs diff=lfs merge=lfs -text
37
+ pptx_templates/Minimalist_sales_pitch.pptx filter=lfs diff=lfs merge=lfs -text
global_config.py CHANGED
@@ -38,16 +38,20 @@ class GlobalConfig:
38
  PPTX_TEMPLATE_FILES = {
39
  'Basic': {
40
  'file': 'pptx_templates/Blank.pptx',
41
- 'caption': 'A good start (Uses [photos](https://unsplash.com/photos/AFZ-qBPEceA) by [cetteup](https://unsplash.com/@cetteup?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash) on [Unsplash](https://unsplash.com/photos/a-foggy-forest-filled-with-lots-of-trees-d3ci37Gcgxg?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash))'
 
 
 
 
42
  },
43
  'Ion Boardroom': {
44
  'file': 'pptx_templates/Ion_Boardroom.pptx',
45
- 'caption': 'Make some bold decisions'
46
  },
47
  'Urban Monochrome': {
48
  'file': 'pptx_templates/Urban_monochrome.pptx',
49
- 'caption': 'Marvel in a monochrome dream'
50
- }
51
  }
52
 
53
  # This is a long text, so not incorporated as a string in `strings.json`
 
38
  PPTX_TEMPLATE_FILES = {
39
  'Basic': {
40
  'file': 'pptx_templates/Blank.pptx',
41
+ 'caption': '🟠 A good start (Uses [photos](https://unsplash.com/photos/AFZ-qBPEceA) by [cetteup](https://unsplash.com/@cetteup?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash) on [Unsplash](https://unsplash.com/photos/a-foggy-forest-filled-with-lots-of-trees-d3ci37Gcgxg?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash))'
42
+ },
43
+ 'Minimalist Sales Pitch': {
44
+ 'file': 'pptx_templates/Minimalist_sales_pitch.pptx',
45
+ 'caption': '⚫ In high contrast'
46
  },
47
  'Ion Boardroom': {
48
  'file': 'pptx_templates/Ion_Boardroom.pptx',
49
+ 'caption': '🔴 Make some bold decisions'
50
  },
51
  'Urban Monochrome': {
52
  'file': 'pptx_templates/Urban_monochrome.pptx',
53
+ 'caption': 'Marvel in a monochrome dream'
54
+ },
55
  }
56
 
57
  # This is a long text, so not incorporated as a string in `strings.json`
helpers/pptx_helper.py CHANGED
@@ -73,11 +73,6 @@ def generate_powerpoint_presentation(
73
 
74
  # The structured "JSON" might contain trailing commas, so using json5
75
  parsed_data = json5.loads(structured_data)
76
-
77
- logger.debug(
78
- '*** Using PPTX template: %s',
79
- GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file']
80
- )
81
  presentation = pptx.Presentation(GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file'])
82
  slide_width_inch, slide_height_inch = _get_slide_width_height_inches(presentation)
83
 
@@ -88,14 +83,17 @@ def generate_powerpoint_presentation(
88
  subtitle = slide.placeholders[1]
89
  title.text = parsed_data['title']
90
  logger.info(
91
- 'PPT title: %s | #slides: %d',
92
- title.text, len(parsed_data['slides'])
 
93
  )
94
  subtitle.text = 'by Myself and SlideDeck AI :)'
95
  all_headers = [title.text, ]
96
 
97
  # Add content in a loop
98
  for a_slide in parsed_data['slides']:
 
 
99
  is_processing_done = _handle_double_col_layout(
100
  presentation=presentation,
101
  slide_json=a_slide,
@@ -151,6 +149,47 @@ def get_flat_list_of_contents(items: list, level: int) -> List[Tuple]:
151
  return flat_list
152
 
153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  def _handle_default_display(
155
  presentation: pptx.Presentation,
156
  slide_json: dict,
@@ -193,7 +232,13 @@ def _handle_default_display(
193
 
194
  shapes = slide.shapes
195
  title_shape = shapes.title
196
- body_shape = shapes.placeholders[1]
 
 
 
 
 
 
197
  title_shape.text = remove_slide_number_from_heading(slide_json['heading'])
198
  text_frame = body_shape.text_frame
199
 
@@ -238,12 +283,31 @@ def _handle_display_image__in_foreground(
238
  img_keywords = slide_json['img_keywords'].strip()
239
  slide = presentation.slide_layouts[8] # Picture with Caption
240
  slide = presentation.slides.add_slide(slide)
 
241
 
242
  title_placeholder = slide.shapes.title
243
  title_placeholder.text = remove_slide_number_from_heading(slide_json['heading'])
244
 
245
- pic_col: PicturePlaceholder = slide.shapes.placeholders[1]
246
- text_col: SlidePlaceholder = slide.shapes.placeholders[2]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  flat_items_list = get_flat_list_of_contents(slide_json['bullet_points'], level=0)
248
 
249
  for idx, an_item in enumerate(flat_items_list):
@@ -305,9 +369,15 @@ def _handle_display_image__in_background(
305
 
306
  # Add a photo in the background, text in the foreground
307
  slide = presentation.slides.add_slide(presentation.slide_layouts[1])
308
-
309
  title_shape = slide.shapes.title
310
- body_shape = slide.shapes.placeholders[1]
 
 
 
 
 
 
 
311
  title_shape.text = remove_slide_number_from_heading(slide_json['heading'])
312
 
313
  flat_items_list = get_flat_list_of_contents(slide_json['bullet_points'], level=0)
@@ -418,39 +488,73 @@ def _handle_double_col_layout(
418
  ) and isinstance(double_col_content[0], dict) and isinstance(double_col_content[1], dict):
419
  slide = presentation.slide_layouts[4]
420
  slide = presentation.slides.add_slide(slide)
 
421
 
422
  shapes = slide.shapes
423
  title_placeholder = shapes.title
424
  title_placeholder.text = remove_slide_number_from_heading(slide_json['heading'])
425
 
426
- left_heading, right_heading = shapes.placeholders[1], shapes.placeholders[3]
427
- left_col, right_col = shapes.placeholders[2], shapes.placeholders[4]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  left_col_frame, right_col_frame = left_col.text_frame, right_col.text_frame
429
 
430
- if 'heading' in double_col_content[0]:
431
  left_heading.text = double_col_content[0]['heading']
432
  if 'bullet_points' in double_col_content[0]:
433
  flat_items_list = get_flat_list_of_contents(
434
  double_col_content[0]['bullet_points'], level=0
435
  )
436
 
 
 
 
437
  for idx, an_item in enumerate(flat_items_list):
438
- if idx == 0:
439
  left_col_frame.text = an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER)
440
  else:
441
  paragraph = left_col_frame.add_paragraph()
442
  paragraph.text = an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER)
443
  paragraph.level = an_item[1]
444
 
445
- if 'heading' in double_col_content[1]:
446
  right_heading.text = double_col_content[1]['heading']
447
  if 'bullet_points' in double_col_content[1]:
448
  flat_items_list = get_flat_list_of_contents(
449
  double_col_content[1]['bullet_points'], level=0
450
  )
451
 
 
 
 
452
  for idx, an_item in enumerate(flat_items_list):
453
- if idx == 0:
454
  right_col_frame.text = an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER)
455
  else:
456
  paragraph = right_col_frame.add_paragraph()
@@ -614,153 +718,160 @@ def _get_slide_width_height_inches(presentation: pptx.Presentation) -> Tuple[flo
614
  return slide_width_inch, slide_height_inch
615
 
616
 
617
- def print_placeholder_names(slide: pptx.slide.Slide):
618
- """
619
- Display the placeholder details of a given slide.
620
-
621
- :param slide: The slide.
622
- """
623
-
624
- for shape in slide.placeholders:
625
- print(f'{shape.placeholder_format.idx=}, {shape.name=}')
626
-
627
-
628
  if __name__ == '__main__':
629
  _JSON_DATA = '''
630
  {
631
- "title": "Mastering PowerPoint Shapes",
632
  "slides": [
633
  {
634
- "heading": "Introduction to PowerPoint Shapes",
635
  "bullet_points": [
636
- "Shapes are fundamental elements in PowerPoint",
637
- "Used to create diagrams, flowcharts, and visuals",
638
- "Available in various types: lines, rectangles, circles, etc."
 
 
 
639
  ],
640
- "key_message": "",
641
- "img_keywords": "PowerPoint shapes, basic shapes"
642
  },
643
  {
644
- "heading": "Types of Shapes in PowerPoint",
645
  "bullet_points": [
646
- "Lines: Connect two points",
647
- "Rectangles: Four-sided figures with right angles",
648
- [
649
- "Squares: Special type of rectangle with equal sides",
650
- "Rounded Rectangles: Rectangles with rounded corners"
651
- ],
652
- "Circles: Round shapes with no corners",
653
- "Ovals: Elliptical shapes"
654
  ],
655
- "key_message": "",
656
- "img_keywords": "PowerPoint shapes, types of shapes"
657
  },
658
  {
659
- "heading": "Creating and Manipulating Shapes",
660
  "bullet_points": [
661
- ">> Select the 'Home' tab and click on 'Shapes'",
662
- ">> Choose the desired shape",
663
- ">> Click and drag to create the shape",
664
- ">> Resize, move, or rotate shapes using handles",
665
- ">> Change shape color, fill, and outline"
 
 
 
666
  ],
667
- "key_message": "Demonstrates the process of creating and manipulating shapes",
668
- "img_keywords": "PowerPoint shapes, creating shapes, manipulating shapes"
669
  },
670
  {
671
- "heading": "Advanced Shape Manipulation",
672
  "bullet_points": [
673
  {
674
- "heading": "Adding Text to Shapes",
675
  "bullet_points": [
676
- "Right-click on the shape and select 'Add Text'",
677
- "Type or paste the desired text"
678
  ]
679
  },
680
  {
681
- "heading": "Grouping and Ungrouping Shapes",
682
  "bullet_points": [
683
- "Select multiple shapes and press 'Ctrl + G' to group",
684
- "Right-click and select 'Ungroup' to separate"
685
  ]
686
  }
687
  ],
688
- "key_message": "Explores advanced techniques for working with shapes",
689
- "img_keywords": "PowerPoint shapes, advanced manipulation, grouping, text in shapes"
690
  },
691
  {
692
- "heading": "Using the 'Format' Tab for Shapes",
693
  "bullet_points": [
694
- "Access advanced shape formatting options",
695
- "Change shape fill, outline, and effects",
696
- "Adjust shape size and position"
697
  ],
698
- "key_message": "",
699
- "img_keywords": "PowerPoint shapes, format tab, advanced formatting"
700
  },
701
  {
702
- "heading": "Example: Creating a Simple Diagram",
703
  "bullet_points": [
704
- "Use rectangles to represent blocks",
705
- "Use lines to connect blocks",
706
- "Add text to shapes to label elements"
 
 
707
  ],
708
- "key_message": "Illustrates the use of shapes to create a simple diagram",
709
- "img_keywords": "PowerPoint shapes, diagram example, simple diagram"
710
  },
711
  {
712
- "heading": "Example: Creating a Flowchart",
713
  "bullet_points": [
714
- "Use different shapes to represent steps, decisions, and inputs/outputs",
715
- "Use connectors to link shapes",
716
- "Add text to shapes to describe each step"
 
717
  ],
718
- "key_message": "Demonstrates the use of shapes to create a flowchart",
719
- "img_keywords": "PowerPoint shapes, flowchart example, creating flowchart"
720
  },
721
  {
722
- "heading": "Double Column Layout: Shapes in Older vs. Newer PowerPoint Versions",
723
  "bullet_points": [
724
  {
725
- "heading": "Older PowerPoint Versions",
726
  "bullet_points": [
727
- "Limited shape types and formatting options",
728
- "Less intuitive shape creation and manipulation"
 
729
  ]
730
  },
731
  {
732
- "heading": "Newer PowerPoint Versions",
733
  "bullet_points": [
734
- "Expanded shape library with more types and styles",
735
- "Improved shape formatting and manipulation tools"
 
736
  ]
737
  }
738
  ],
739
- "key_message": "Compares the use of shapes in older and newer PowerPoint versions",
740
- "img_keywords": "PowerPoint shapes, older versions, newer versions, comparison"
741
  },
742
  {
743
- "heading": "Tips for Effective Use of Shapes",
744
  "bullet_points": [
745
- "Keep shapes simple and uncluttered",
746
- "Use consistent colors and styles",
747
- "Avoid overusing shapes, maintain balance with text and other elements"
 
 
 
 
 
 
 
 
 
 
 
748
  ],
749
- "key_message": "Provides best practices for using shapes in presentations",
750
- "img_keywords": "PowerPoint shapes, best practices, effective use"
751
  },
752
  {
753
  "heading": "Conclusion",
754
  "bullet_points": [
755
- "Shapes are versatile tools in PowerPoint",
756
- "Mastering shapes enhances presentation visuals",
757
- "Practice and experimentation are key to improving shape usage"
758
  ],
759
- "key_message": "Summarizes the importance of shapes in PowerPoint and encourages practice",
760
- "img_keywords": "PowerPoint shapes, conclusion, importance"
761
  }
762
  ]
763
- }'''
 
764
 
765
  temp = tempfile.NamedTemporaryFile(delete=False, suffix='.pptx')
766
  path = pathlib.Path(temp.name)
@@ -768,7 +879,7 @@ if __name__ == '__main__':
768
  generate_powerpoint_presentation(
769
  json5.loads(_JSON_DATA),
770
  output_file_path=path,
771
- slides_template='Basic'
772
  )
773
  print(f'File path: {path}')
774
 
 
73
 
74
  # The structured "JSON" might contain trailing commas, so using json5
75
  parsed_data = json5.loads(structured_data)
 
 
 
 
 
76
  presentation = pptx.Presentation(GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file'])
77
  slide_width_inch, slide_height_inch = _get_slide_width_height_inches(presentation)
78
 
 
83
  subtitle = slide.placeholders[1]
84
  title.text = parsed_data['title']
85
  logger.info(
86
+ 'PPT title: %s | #slides: %d | template: %s',
87
+ title.text, len(parsed_data['slides']),
88
+ GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file']
89
  )
90
  subtitle.text = 'by Myself and SlideDeck AI :)'
91
  all_headers = [title.text, ]
92
 
93
  # Add content in a loop
94
  for a_slide in parsed_data['slides']:
95
+ # The loop has a bug:
96
+ # if any of this functions fail (i.e., returns False), an empty slide would still exist
97
  is_processing_done = _handle_double_col_layout(
98
  presentation=presentation,
99
  slide_json=a_slide,
 
149
  return flat_list
150
 
151
 
152
+ def get_slide_placeholders(
153
+ slide: pptx.slide.Slide,
154
+ layout_number: int,
155
+ is_debug: bool = False
156
+ ) -> List[Tuple[int, str]]:
157
+ """
158
+ Return the index and name (lower case) of all placeholders present in a slide, except
159
+ the title placeholder.
160
+
161
+ A placeholder in a slide is a place to add content. Each placeholder has a name and an index.
162
+ This index is NOT a list index, rather a set of keys used to look up a dict. So, `idx` is
163
+ non-contiguous. Also, the title placeholder of a slide always has index 0. User-added
164
+ placeholder get indices assigned starting from 10.
165
+
166
+ With user-edited or added placeholders, their index may be difficult to track. This function
167
+ returns the placeholders name as well, which could be useful to distinguish between the
168
+ different placeholder.
169
+
170
+ :param slide: The slide.
171
+ :param layout_number: The layout number used by the slide.
172
+ :param is_debug: Whether to print debugging statements.
173
+ :return: A list containing placeholders (idx, name) tuples, except the title placeholder.
174
+ """
175
+
176
+ if is_debug:
177
+ print(
178
+ f'Slide layout #{layout_number}:'
179
+ f' # of placeholders: {len(slide.shapes.placeholders)} (including the title)'
180
+ )
181
+
182
+ placeholders = [
183
+ (shape.placeholder_format.idx, shape.name.lower()) for shape in slide.shapes.placeholders
184
+ ]
185
+ placeholders.pop(0) # Remove the title placeholder
186
+
187
+ if is_debug:
188
+ print(placeholders)
189
+
190
+ return placeholders
191
+
192
+
193
  def _handle_default_display(
194
  presentation: pptx.Presentation,
195
  slide_json: dict,
 
232
 
233
  shapes = slide.shapes
234
  title_shape = shapes.title
235
+
236
+ try:
237
+ body_shape = shapes.placeholders[1]
238
+ except KeyError:
239
+ placeholders = get_slide_placeholders(slide, layout_number=1)
240
+ body_shape = shapes.placeholders[placeholders[0][0]]
241
+
242
  title_shape.text = remove_slide_number_from_heading(slide_json['heading'])
243
  text_frame = body_shape.text_frame
244
 
 
283
  img_keywords = slide_json['img_keywords'].strip()
284
  slide = presentation.slide_layouts[8] # Picture with Caption
285
  slide = presentation.slides.add_slide(slide)
286
+ placeholders = None
287
 
288
  title_placeholder = slide.shapes.title
289
  title_placeholder.text = remove_slide_number_from_heading(slide_json['heading'])
290
 
291
+ try:
292
+ pic_col: PicturePlaceholder = slide.shapes.placeholders[1]
293
+ except KeyError:
294
+ placeholders = get_slide_placeholders(slide, layout_number=8)
295
+ pic_col = None
296
+ for idx, name in placeholders:
297
+ if 'picture' in name:
298
+ pic_col: PicturePlaceholder = slide.shapes.placeholders[idx]
299
+
300
+ try:
301
+ text_col: SlidePlaceholder = slide.shapes.placeholders[2]
302
+ except KeyError:
303
+ text_col = None
304
+ if not placeholders:
305
+ placeholders = get_slide_placeholders(slide, layout_number=8)
306
+
307
+ for idx, name in placeholders:
308
+ if 'content' in name:
309
+ text_col: SlidePlaceholder = slide.shapes.placeholders[idx]
310
+
311
  flat_items_list = get_flat_list_of_contents(slide_json['bullet_points'], level=0)
312
 
313
  for idx, an_item in enumerate(flat_items_list):
 
369
 
370
  # Add a photo in the background, text in the foreground
371
  slide = presentation.slides.add_slide(presentation.slide_layouts[1])
 
372
  title_shape = slide.shapes.title
373
+
374
+ try:
375
+ body_shape = slide.shapes.placeholders[1]
376
+ except KeyError:
377
+ placeholders = get_slide_placeholders(slide, layout_number=1)
378
+ # Layout 1 usually has two placeholders, including the title
379
+ body_shape = slide.shapes.placeholders[placeholders[0][0]]
380
+
381
  title_shape.text = remove_slide_number_from_heading(slide_json['heading'])
382
 
383
  flat_items_list = get_flat_list_of_contents(slide_json['bullet_points'], level=0)
 
488
  ) and isinstance(double_col_content[0], dict) and isinstance(double_col_content[1], dict):
489
  slide = presentation.slide_layouts[4]
490
  slide = presentation.slides.add_slide(slide)
491
+ placeholders = None
492
 
493
  shapes = slide.shapes
494
  title_placeholder = shapes.title
495
  title_placeholder.text = remove_slide_number_from_heading(slide_json['heading'])
496
 
497
+ try:
498
+ left_heading, right_heading = shapes.placeholders[1], shapes.placeholders[3]
499
+ except KeyError:
500
+ # For manually edited/added master slides, the placeholder idx numbers in the dict
501
+ # will be different (>= 10)
502
+ left_heading, right_heading = None, None
503
+ placeholders = get_slide_placeholders(slide, layout_number=4)
504
+
505
+ for idx, name in placeholders:
506
+ if 'text placeholder' in name:
507
+ if not left_heading:
508
+ left_heading = shapes.placeholders[idx]
509
+ elif not right_heading:
510
+ right_heading = shapes.placeholders[idx]
511
+
512
+ try:
513
+ left_col, right_col = shapes.placeholders[2], shapes.placeholders[4]
514
+ except KeyError:
515
+ left_col, right_col = None, None
516
+ if not placeholders:
517
+ placeholders = get_slide_placeholders(slide, layout_number=4)
518
+
519
+ for idx, name in placeholders:
520
+ if 'content placeholder' in name:
521
+ if not left_col:
522
+ left_col = shapes.placeholders[idx]
523
+ elif not right_col:
524
+ right_col = shapes.placeholders[idx]
525
+
526
  left_col_frame, right_col_frame = left_col.text_frame, right_col.text_frame
527
 
528
+ if 'heading' in double_col_content[0] and left_heading:
529
  left_heading.text = double_col_content[0]['heading']
530
  if 'bullet_points' in double_col_content[0]:
531
  flat_items_list = get_flat_list_of_contents(
532
  double_col_content[0]['bullet_points'], level=0
533
  )
534
 
535
+ if not left_heading:
536
+ left_col_frame.text = double_col_content[0]['heading']
537
+
538
  for idx, an_item in enumerate(flat_items_list):
539
+ if left_heading and idx == 0:
540
  left_col_frame.text = an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER)
541
  else:
542
  paragraph = left_col_frame.add_paragraph()
543
  paragraph.text = an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER)
544
  paragraph.level = an_item[1]
545
 
546
+ if 'heading' in double_col_content[1] and right_heading:
547
  right_heading.text = double_col_content[1]['heading']
548
  if 'bullet_points' in double_col_content[1]:
549
  flat_items_list = get_flat_list_of_contents(
550
  double_col_content[1]['bullet_points'], level=0
551
  )
552
 
553
+ if not right_heading:
554
+ right_col_frame.text = double_col_content[1]['heading']
555
+
556
  for idx, an_item in enumerate(flat_items_list):
557
+ if right_col_frame and idx == 0:
558
  right_col_frame.text = an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER)
559
  else:
560
  paragraph = right_col_frame.add_paragraph()
 
718
  return slide_width_inch, slide_height_inch
719
 
720
 
 
 
 
 
 
 
 
 
 
 
 
721
  if __name__ == '__main__':
722
  _JSON_DATA = '''
723
  {
724
+ "title": "The Fascinating World of Chess",
725
  "slides": [
726
  {
727
+ "heading": "Introduction to Chess",
728
  "bullet_points": [
729
+ "Chess is a strategic board game played between two players.",
730
+ [
731
+ "Each player begins the game with 16 pieces: one king, one queen, two rooks, two knights, two bishops, and eight pawns.",
732
+ "The goal of the game is to checkmate your opponent's king. This means the king is in a position to be captured (in 'check') but has no move to escape (mate)."
733
+ ],
734
+ "Chess is believed to have originated in northern India in the 6th century AD."
735
  ],
736
+ "key_message": "Understanding the basics of chess is crucial before delving into strategies.",
737
+ "img_keywords": "chessboard, chess pieces, king, queen, rook, knight, bishop, pawn"
738
  },
739
  {
740
+ "heading": "The Chessboard",
741
  "bullet_points": [
742
+ "The chessboard is made up of 64 squares in an 8x8 grid.",
743
+ "Each player starts with their pieces on their home rank (row).",
744
+ "The board is divided into two camps: one for each player."
 
 
 
 
 
745
  ],
746
+ "key_message": "Knowing the layout of the chessboard is essential for understanding piece movement.",
747
+ "img_keywords": "chessboard layout, 8x8 grid, home rank, player camps"
748
  },
749
  {
750
+ "heading": "Movement of Pieces",
751
  "bullet_points": [
752
+ ">> Each piece moves differently. Learning these movements is key to playing chess.",
753
+ ">> The king moves one square in any direction.",
754
+ ">> The queen combines the moves of the rook and bishop.",
755
+ ">> The rook moves horizontally or vertically along a rank or file.",
756
+ ">> The bishop moves diagonally.",
757
+ ">> The knight moves in an L-shape: two squares in a horizontal or vertical direction, then one square perpendicular to that.",
758
+ ">> The pawn moves forward one square, but captures diagonally.",
759
+ ">> Pawns have the initial option of moving two squares forward on their first move."
760
  ],
761
+ "key_message": "Understanding how each piece moves is fundamental to playing chess.",
762
+ "img_keywords": "chess piece movements, king, queen, rook, bishop, knight, pawn"
763
  },
764
  {
765
+ "heading": "Special Moves",
766
  "bullet_points": [
767
  {
768
+ "heading": "Castling",
769
  "bullet_points": [
770
+ "Castling is a unique move involving the king and a rook.",
771
+ "It involves moving the king two squares towards a rook, then moving that rook to the square the king skipped over."
772
  ]
773
  },
774
  {
775
+ "heading": "En Passant",
776
  "bullet_points": [
777
+ "En passant is a special pawn capture move.",
778
+ "It occurs when a pawn moves two squares forward from its starting position and lands beside an opponent's pawn, which could have captured it if the first pawn had only moved one square forward."
779
  ]
780
  }
781
  ],
782
+ "key_message": "Understanding these special moves can add depth to your chess strategy.",
783
+ "img_keywords": "castling, en passant, special chess moves"
784
  },
785
  {
786
+ "heading": "Chess Notation",
787
  "bullet_points": [
788
+ "Chess notation is a system used to record and communicate chess games.",
789
+ "It uses algebraic notation, where each square on the board is identified by a letter and a number.",
790
+ "Pieces are identified by their initial letters: K for king, Q for queen, R for rook, B for bishop, N for knight, and P for pawn."
791
  ],
792
+ "key_message": "Learning chess notation is helpful for recording, analyzing, and discussing games.",
793
+ "img_keywords": "chess notation, algebraic notation, chess symbols"
794
  },
795
  {
796
+ "heading": "Chess Strategies",
797
  "bullet_points": [
798
+ "Develop your pieces quickly and efficiently.",
799
+ "Control the center of the board.",
800
+ "Castle early to protect your king.",
801
+ "Keep your king safe.",
802
+ "Think ahead and plan your moves."
803
  ],
804
+ "key_message": "Following these strategies can help improve your chess skills.",
805
+ "img_keywords": "chess strategies, piece development, center control, king safety, planning ahead"
806
  },
807
  {
808
+ "heading": "Chess Tactics",
809
  "bullet_points": [
810
+ "Fork: attacking two enemy pieces with the same move.",
811
+ "Pin: restricting the movement of an enemy piece.",
812
+ "Skewer: forcing an enemy piece to move away from a threatened piece.",
813
+ "Discovered attack: moving a piece to reveal an attack by another piece behind it."
814
  ],
815
+ "key_message": "Mastering these tactics can help you gain an advantage in games.",
816
+ "img_keywords": "chess tactics, fork, pin, skewer, discovered attack"
817
  },
818
  {
819
+ "heading": "Chess Openings",
820
  "bullet_points": [
821
  {
822
+ "heading": "Italian Game",
823
  "bullet_points": [
824
+ "1. e4 e5",
825
+ "2. Nf3 Nc6",
826
+ "3. Bc4 Bc5"
827
  ]
828
  },
829
  {
830
+ "heading": "Ruy Lopez",
831
  "bullet_points": [
832
+ "1. e4 e5",
833
+ "2. Nf3 Nc6",
834
+ "3. Bb5"
835
  ]
836
  }
837
  ],
838
+ "key_message": "Learning popular chess openings can help you start games effectively.",
839
+ "img_keywords": "chess openings, Italian Game, Ruy Lopez"
840
  },
841
  {
842
+ "heading": "Chess Endgames",
843
  "bullet_points": [
844
+ {
845
+ "heading": "King and Pawn Endgame",
846
+ "bullet_points": [
847
+ "This endgame involves a king and one or more pawns against a lone king.",
848
+ "The goal is to promote a pawn to a new queen."
849
+ ]
850
+ },
851
+ {
852
+ "heading": "Rook Endgame",
853
+ "bullet_points": [
854
+ "This endgame involves a rook against a lone king.",
855
+ "The goal is to checkmate the opponent's king using the rook."
856
+ ]
857
+ }
858
  ],
859
+ "key_message": "Understanding common chess endgames can help you win games.",
860
+ "img_keywords": "chess endgames, king and pawn endgame, rook endgame"
861
  },
862
  {
863
  "heading": "Conclusion",
864
  "bullet_points": [
865
+ "Chess is a complex game that requires strategy, tactics, and planning.",
866
+ "Understanding the rules, piece movements, and common strategies can help improve your chess skills.",
867
+ "Practice regularly to improve your game."
868
  ],
869
+ "key_message": "To excel at chess, one must understand its fundamentals and practice regularly.",
870
+ "img_keywords": "chess fundamentals, chess improvement, regular practice"
871
  }
872
  ]
873
+ }
874
+ '''
875
 
876
  temp = tempfile.NamedTemporaryFile(delete=False, suffix='.pptx')
877
  path = pathlib.Path(temp.name)
 
879
  generate_powerpoint_presentation(
880
  json5.loads(_JSON_DATA),
881
  output_file_path=path,
882
+ slides_template='Minimalist Sales Pitch'
883
  )
884
  print(f'File path: {path}')
885
 
pptx_templates/Minimalist_sales_pitch.pptx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2a6da48abf9a44bde11fa8337519435d51fe5f161e605d8f5ab00d4a914fc964
3
+ size 1298028