From 96f3c0520775742dc22a90f15c72c5f2c3b502d0 Mon Sep 17 00:00:00 2001 From: crupest Date: Mon, 12 Oct 2020 17:38:50 +0800 Subject: import(life): Add question-pptx. --- works/life/question-pptx/main.py | 95 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 works/life/question-pptx/main.py (limited to 'works/life/question-pptx/main.py') diff --git a/works/life/question-pptx/main.py b/works/life/question-pptx/main.py new file mode 100644 index 0000000..618efa6 --- /dev/null +++ b/works/life/question-pptx/main.py @@ -0,0 +1,95 @@ +import random +import pptx +from pptx.util import Pt +import re +from typing import Iterable + +# Chinese colon and English colon is different but both should be supported with love! +choice_question_regex = re.compile( + r'(?P\S*?)[\((](?P[a-dA-D])[\))](?P\S*?)\s*[aA]\s+(?P\S+?)\s+[bB]\s*(?P\S+?)\s+[cC]\s*(?P\S+?)\s+[dD]\s*(?P\S+?)\s+', re.MULTILINE) + +choice_text = open('./choose.txt', 'r', encoding='utf-8').read() + +questions = [] + +for match in choice_question_regex.finditer(choice_text): + questions.append({ + 'type': 'c', + 'problem': match.group('problem_1') + "( )" + match.group('problem_2'), + 'answer': match.group('answer').lower(), + 'choices': { + 'a': match.group('choice_a'), + 'b': match.group('choice_b'), + 'c': match.group('choice_c'), + 'd': match.group('choice_d') + } + }) + +judge_question_regex = re.compile( + r'(?P\S+?)\s*[\((](?P[a-bA-B])[\))]', re.MULTILINE) + +judge_text = open('./judge.txt', 'r', encoding='utf-8').read() + + +for match in judge_question_regex.finditer(judge_text): + questions.append({ + 'type': 'j', + 'problem': match.group('problem'), + 'answer': match.group('answer').lower() + }) + + +random.shuffle(questions) + +presentation: pptx.presentation.Presentation = pptx.Presentation() + +buttons: Iterable[pptx.shapes.autoshape.Shape] = [] + +for question in questions: + slide: pptx.slide.Slide = presentation.slides.add_slide( + presentation.slide_layouts[6]) + + title = slide.shapes.add_textbox(Pt(20), Pt(25), Pt(680), Pt(50)) + problem = slide.shapes.add_textbox(Pt(20), Pt(80), Pt(680), Pt(380)) + answer = slide.shapes.add_textbox(Pt(560), Pt(450), Pt(40), Pt(40)) + + if question['type'] == 'c': + title.text = '选择题' + problem.text = question['problem'] + '\n' + '\n'.join( + [choice.upper() + '. ' + question['choices'][choice]for choice in 'abcd']) + answer.text = question['answer'].upper() + else: + title.text = '判断题' + problem.text = question['problem'] + answer.text = '√' if question['answer'] == 'a' else '×' + + title_text_frame: pptx.text.text.TextFrame = title.text_frame + para: pptx.text.text._Paragraph + for para in title_text_frame.paragraphs: + para.font.size = Pt(42) + para.font.color.theme_color = pptx.enum.dml.MSO_THEME_COLOR.TEXT_2 + + problem_text_frame: pptx.text.text.TextFrame = problem.text_frame + problem_text_frame.margin_top = Pt(10) + para: pptx.text.text._Paragraph + for para in problem_text_frame.paragraphs: + para.space_after = Pt(6) + para.font.size = Pt(30) + problem_text_frame.word_wrap = True + + answer_text_frame: pptx.text.text.TextFrame = answer.text_frame + para: pptx.text.text._Paragraph + for para in answer_text_frame.paragraphs: + para.font.size = Pt(40) + para.font.color.rgb = pptx.dml.color.RGBColor(255, 0, 0) + + buttons.append(slide.shapes.add_shape(pptx.enum.shapes.MSO_SHAPE.OVAL, Pt( + 660), Pt(460), Pt(40), Pt(40))) + +slide: pptx.slide.Slide = presentation.slides.add_slide( + presentation.slide_layouts[6]) + +for button in buttons: + button.click_action.target_slide = slide + +presentation.save('test.pptx') -- cgit v1.2.3 From a8e4766c95e86ff2c48f0d17bf5060eccd70b249 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 13 Oct 2020 15:01:29 +0800 Subject: import(life): (question-pptx): Relayout. --- works/life/question-pptx/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'works/life/question-pptx/main.py') diff --git a/works/life/question-pptx/main.py b/works/life/question-pptx/main.py index 618efa6..b854060 100644 --- a/works/life/question-pptx/main.py +++ b/works/life/question-pptx/main.py @@ -49,8 +49,8 @@ for question in questions: slide: pptx.slide.Slide = presentation.slides.add_slide( presentation.slide_layouts[6]) - title = slide.shapes.add_textbox(Pt(20), Pt(25), Pt(680), Pt(50)) - problem = slide.shapes.add_textbox(Pt(20), Pt(80), Pt(680), Pt(380)) + title = slide.shapes.add_textbox(Pt(20), Pt(40), Pt(680), Pt(50)) + problem = slide.shapes.add_textbox(Pt(20), Pt(120), Pt(680), Pt(350)) answer = slide.shapes.add_textbox(Pt(560), Pt(450), Pt(40), Pt(40)) if question['type'] == 'c': -- cgit v1.2.3 From 277d60c91ced882e445c05a37be13e4af9f5d692 Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 25 Oct 2020 01:08:34 +0800 Subject: import(life): (question-pptx) Makes parsing regex more "general", add problem id, and add a script to generate 10 pptx. --- works/life/question-pptx/.gitignore | 4 +++ works/life/question-pptx/gen.ps1 | 4 +++ works/life/question-pptx/main.py | 49 ++++++++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 works/life/question-pptx/gen.ps1 (limited to 'works/life/question-pptx/main.py') diff --git a/works/life/question-pptx/.gitignore b/works/life/question-pptx/.gitignore index 365e45e..1400b46 100644 --- a/works/life/question-pptx/.gitignore +++ b/works/life/question-pptx/.gitignore @@ -1 +1,5 @@ test.pptx +real-choose.txt +real-judge.txt +*.pptx +question-pptx.zip diff --git a/works/life/question-pptx/gen.ps1 b/works/life/question-pptx/gen.ps1 new file mode 100644 index 0000000..e7903c9 --- /dev/null +++ b/works/life/question-pptx/gen.ps1 @@ -0,0 +1,4 @@ +foreach ($i in 1..10) { + py ./main.py + mv test.pptx "$i.pptx" +} diff --git a/works/life/question-pptx/main.py b/works/life/question-pptx/main.py index b854060..6c4e9bb 100644 --- a/works/life/question-pptx/main.py +++ b/works/life/question-pptx/main.py @@ -6,38 +6,56 @@ from typing import Iterable # Chinese colon and English colon is different but both should be supported with love! choice_question_regex = re.compile( - r'(?P\S*?)[\((](?P[a-dA-D])[\))](?P\S*?)\s*[aA]\s+(?P\S+?)\s+[bB]\s*(?P\S+?)\s+[cC]\s*(?P\S+?)\s+[dD]\s*(?P\S+?)\s+', re.MULTILINE) + r'(?P\d+)\s*[\.、.]?\s*(?P.*?)[\((]\s*(?P[a-eA-E])\s*[\))](?P.*?)\s*[aA]\s*[\.、.]?\s*(?P\S+?)\s*[bB]\s*[\.、.]?\s*(?P\S+?)\s*[cC]\s*[\.、.]?\s*(?P\S+?)\s+([dD]\s*[\.、.]?\s*(?P\S+?)\s+)?([eE]\s*[\.、.]?\s*(?P\S+?)\s+)?', re.MULTILINE) -choice_text = open('./choose.txt', 'r', encoding='utf-8').read() +choice_text = open('./real-choose.txt', 'r', encoding='utf-8').read() questions = [] for match in choice_question_regex.finditer(choice_text): - questions.append({ + q = { + 'id': int(match.group('problem_id')), 'type': 'c', 'problem': match.group('problem_1') + "( )" + match.group('problem_2'), 'answer': match.group('answer').lower(), 'choices': { 'a': match.group('choice_a'), 'b': match.group('choice_b'), - 'c': match.group('choice_c'), - 'd': match.group('choice_d') + 'c': match.group('choice_c') } - }) + } + + if match.group('choice_d') != None: + q['choices']['d'] = match.group('choice_d') + + if match.group('choice_e') != None: + q['choices']['e'] = match.group('choice_e') + + questions.append(q) + +print(len(questions)) judge_question_regex = re.compile( - r'(?P\S+?)\s*[\((](?P[a-bA-B])[\))]', re.MULTILINE) + r'(?P\d+)\s*[\.、.]?\s*(?P.+)\s*[\((]\s*(?P[✓√×xX])\s*[\))]', re.MULTILINE) -judge_text = open('./judge.txt', 'r', encoding='utf-8').read() +judge_text = open('./real-judge.txt', 'r', encoding='utf-8').read() for match in judge_question_regex.finditer(judge_text): questions.append({ + 'id': int(match.group('problem_id')), 'type': 'j', 'problem': match.group('problem'), - 'answer': match.group('answer').lower() + 'answer': '×' if match.group('answer') in '×xX' else '✓' }) +print(len(questions)) + +id_list = [q['id'] for q in questions] +id_list.sort() +for i in range(606): + if not i in id_list: + print(i) random.shuffle(questions) @@ -52,16 +70,19 @@ for question in questions: title = slide.shapes.add_textbox(Pt(20), Pt(40), Pt(680), Pt(50)) problem = slide.shapes.add_textbox(Pt(20), Pt(120), Pt(680), Pt(350)) answer = slide.shapes.add_textbox(Pt(560), Pt(450), Pt(40), Pt(40)) + id = slide.shapes.add_textbox(Pt(20), Pt(480), Pt(80), Pt(40)) if question['type'] == 'c': title.text = '选择题' problem.text = question['problem'] + '\n' + '\n'.join( - [choice.upper() + '. ' + question['choices'][choice]for choice in 'abcd']) + [choice.upper() + '. ' + question['choices'][choice]for choice in question['choices'].keys()]) answer.text = question['answer'].upper() else: title.text = '判断题' problem.text = question['problem'] - answer.text = '√' if question['answer'] == 'a' else '×' + answer.text = question['answer'] + + id.text = str(question['id']) title_text_frame: pptx.text.text.TextFrame = title.text_frame para: pptx.text.text._Paragraph @@ -83,6 +104,12 @@ for question in questions: para.font.size = Pt(40) para.font.color.rgb = pptx.dml.color.RGBColor(255, 0, 0) + id_text_frame: pptx.text.text.TextFrame = id.text_frame + para: pptx.text.text._Paragraph + for para in id_text_frame.paragraphs: + para.font.size = Pt(20) + para.font.color.rgb = pptx.dml.color.RGBColor(128, 128, 128) + buttons.append(slide.shapes.add_shape(pptx.enum.shapes.MSO_SHAPE.OVAL, Pt( 660), Pt(460), Pt(40), Pt(40))) -- cgit v1.2.3 From 9a7553406beef499f64d220131ac02465f524ee1 Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 1 Nov 2020 21:39:34 +0800 Subject: import(life): The mate has deleted the bland target slide of hyperlink in pptx and he asked me to write a script to add it back. --- works/life/question-pptx/.gitignore | 5 ++--- works/life/question-pptx/add-hyperlink.py | 24 ++++++++++++++++++++++++ works/life/question-pptx/main.py | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 works/life/question-pptx/add-hyperlink.py (limited to 'works/life/question-pptx/main.py') diff --git a/works/life/question-pptx/.gitignore b/works/life/question-pptx/.gitignore index 1400b46..8c198b1 100644 --- a/works/life/question-pptx/.gitignore +++ b/works/life/question-pptx/.gitignore @@ -1,5 +1,4 @@ -test.pptx real-choose.txt real-judge.txt -*.pptx -question-pptx.zip +**/*.pptx +**/*.zip diff --git a/works/life/question-pptx/add-hyperlink.py b/works/life/question-pptx/add-hyperlink.py new file mode 100644 index 0000000..b427bdd --- /dev/null +++ b/works/life/question-pptx/add-hyperlink.py @@ -0,0 +1,24 @@ +import pptx +import sys +import os + +fn = sys.argv[1] + +presentation: pptx.presentation.Presentation = pptx.Presentation(fn) + +target_slide = presentation.slides.add_slide(presentation.slide_layouts[6]) + +slide: pptx.slide.Slide +for slide in presentation.slides: + for shape in slide.shapes: + try: + if isinstance(shape, pptx.shapes.autoshape.Shape) and shape.auto_shape_type == pptx.enum.shapes.MSO_SHAPE.OVAL: + shape.click_action.target_slide = target_slide + except: + pass +try: + os.mkdir('output') +except: + pass + +presentation.save(os.path.join('output', os.path.basename(fn))) diff --git a/works/life/question-pptx/main.py b/works/life/question-pptx/main.py index 6c4e9bb..ee278d4 100644 --- a/works/life/question-pptx/main.py +++ b/works/life/question-pptx/main.py @@ -64,7 +64,7 @@ presentation: pptx.presentation.Presentation = pptx.Presentation() buttons: Iterable[pptx.shapes.autoshape.Shape] = [] for question in questions: - slide: pptx.slide.Slide = presentation.slides.add_slide( + slide: pptx.slide.Slide = c.add_slide( presentation.slide_layouts[6]) title = slide.shapes.add_textbox(Pt(20), Pt(40), Pt(680), Pt(50)) -- cgit v1.2.3