ドラゴン桜であった数学100問を自動生成するプログラムをPythonで作ってみた件

はじめまして、暇だったり忙しかったりする大学生のjunです。
ドラゴン桜見ましたか？ドラゴン桜面白かった、、
私が気になったは数学100問（足し算引き算掛け算割り算）を解くというものこれを続けると基礎計算能力があがるのだとか、ただドラマだと全部手書き、、、（めんどくさそう）
ということで、問題100問自動生成するプログラムを作れないかと思いつくりはや7ヶ月（時間かかりすぎw）ある程度形になったので投稿しようと思った次第。

使ったimportは以下
主にpython-docxとwxをpip installしておいてください
その他インストールしていないpip があればインストールをお願いします。

```python:pip一覧
import os
import wx
import random
import datetime
import math
from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Pt, Inches, RGBColor 
from docx.enum.style import WD_STYLE_TYPE
from docx.api import Document
from docx.opc.oxml import qn
```
それでは、私が作ったプログラムをお見せします。
コードの書き方は独学なのでオススメの書き方などがあればお願いします。

```python:all
import os
import wx
import random
import datetime
import math
from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Pt, Inches, RGBColor 
from docx.enum.style import WD_STYLE_TYPE
from docx.api import Document
from docx.opc.oxml import qn

Name_Text = '＃__    名前_____________'  #一行目の設定
MathL = ''#問題を入れる文字型
MathL_Ansewr = ''#答えを入れる文字型


class Configuration():
    #確率のメソッド
    def probability(self, percent):
        coin = random.random()
        if coin * 100 < percent: #%で確率調整
            return True 
        else:
            return False
    #現在時間の生成と成型
    def nowtime(self):
        Dt_Now = datetime.datetime.now()
        Dt_Name = str(Dt_Now.strftime('%Y.%m%d-%M%S'))
        return Dt_Name
    #現在のファイルpathを生成
    def MyPath(self):
        cwd = os.path.dirname(__file__)
        cwd += '/'
        print(cwd)
        return cwd


class ThreeButtonEvent(wx.PyCommandEvent):
    def __init__(self, evtType, id):
        wx.PyCommandEvent.__init__(self, evtType, id)

    def SetSelectedIndex(self, index):
        self.index = index

    def GetSelectedIndex(self):
        return self.index

myEVT_THREE_BUTTON = wx.NewEventType()
EVT_THREE_BUTTON = wx.PyEventBinder(myEVT_THREE_BUTTON, 1)

class ThreeButtonPanel(wx.Panel):
    def __init__(self, parent, id=-1):
        wx.Panel.__init__(self, parent, id)
        # Create widgets.
        self.button1 = wx.ToggleButton(self, label='生成')
        self.button2 = wx.ToggleButton(self, label='2')
        self.button3 = wx.ToggleButton(self, label='出力')
        self.button1.index = 0
        self.button2.index = 1
        self.button3.index = 2
        # Set event handlers.
        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleButton)
        # Set sizer.
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.button1)
        sizer.Add(self.button2)
        sizer.Add(self.button3)
        self.SetSizer(sizer)

    def OnToggleButton(self, evt):
        button = evt.GetEventObject()
        index = button.index
        if button.GetValue():
            if button != self.button1:
                self.button1.SetValue(False)
            if button != self.button2:
                self.button2.SetValue(False)
            if button != self.button3:
                self.button3.SetValue(False)
        else:
            index = -1
        # Raise event.
        evt = ThreeButtonEvent(myEVT_THREE_BUTTON, self.GetId())
        evt.SetSelectedIndex(index)
        self.GetEventHandler().ProcessEvent(evt)

class AutMath():
    #問題docx生成のメソッド
    def AddDocx(self, name):
        global MathL
        
        doc = Document()#docxの生成

        styles = doc.styles
        style = styles.add_style('Original-Style', WD_STYLE_TYPE.PARAGRAPH)
        font = style.font
        font.size = Pt(15)#文字の大きさの設定
        font.name = 'BIZ UDゴシック'#フォントの設定
        paragraph_format=style.paragraph_format

        p = doc.add_paragraph(MathL, style = style)
        
        p.alignment = WD_ALIGN_PARAGRAPH.LEFT
        
        doc.save(name)#保存

    #答えdocx生成のメソッド
    def AddDocx_ansewr(self, name):
        global MathL_Ansewr
        
        doc_ansewr = Document()

        styles = doc_ansewr.styles
        style = styles.add_style('Original-Style', WD_STYLE_TYPE.PARAGRAPH)
        font = style.font
        font.size = Pt(15)
        font.name = 'BIZ UDゴシック'
        paragraph_format=style.paragraph_format

        p_ansewr = doc_ansewr.add_paragraph(MathL_Ansewr,style=style)
        
        p_ansewr.alignment = WD_ALIGN_PARAGRAPH.LEFT
        
        doc_ansewr.save(name)

    #足し算のメソッド
    def addition(self):
        ad1 = random.randint(1, 99)
        ad2 = random.randint(1, 99)
        coin = Configuration()
        if (coin.probability(30) == True):
            ad1 *= 10
        if (coin.probability(30) == True):
            ad2 *= 10
        
        Sadd = (str(ad1) + '+' + str(ad2) + '=  \t')
        ad3 = ad1 + ad2
        Sadd_ansewr = ('=' + str(ad3) + '\t'+ '\t')
        return Sadd, Sadd_ansewr
    
    #引き算のメソッド
    def subtraction(self):
        su1 = random.randint(1, 99)
        su2 = random.randint(1, 99)
        coin = Configuration()
        if (coin.probability(30) == True):
            su1 *= 10
        if (coin.probability(30) == True):
            su2 *= 10

        Ssub = (str(su1) + '-' + str(su2) + '=  \t')
        su3 = su1 - su2
        Ssub_ansewr = ('=' + str(su3) + '\t'+ '\t')
        return Ssub, Ssub_ansewr

    #掛け算のメソッド
    def multiplication(self):
        mu1 = random.randint(1, 9)
        mu2 = random.randint(1, 9)
 
        Smul = (str(mu1) + '×' + str(mu2) + '=  \t')
        Smul_ansewr = ('=' + str(mu1 * mu2) + '\t'+ '\t')
        return Smul, Smul_ansewr
    
    #割り算のメソッド
    def division(self):
        di2 = random.randint(2, 9)
        di1 = di2 * random.randint(2, 10)
        coin = Configuration()
        if (coin.probability(30)):
            di1 *= random.randint(1,10)
            if (coin.probability(30) == True):
                di2 *= random.randint(1,10)
 
        Sdiv = (str(di1) + '÷' + str(di2) + '=')
        Sdiv_ansewr = ('=' + str(math.floor(di1 / di2)))
        return Sdiv, Sdiv_ansewr

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Title", size=(300,300))
        panel = ThreeButtonPanel(self)
        panel.Bind(EVT_THREE_BUTTON, self.OnThreeButton)

    def OnThreeButton(self, evt):
        global Name_Text
        global MathL
        global MathL_Ansewr
        
        if (evt.GetSelectedIndex() == 0):
            Max = 25
            MathL += Name_Text + '\n'
            MathL_Ansewr += Name_Text + '\n'
            for i in range(Max):
                
                Math = AutMath()
                Add_Math = Math.addition()
                
                MathL += '(' + str( 1 + i).zfill(2) + ')' + Add_Math[0]
                MathL_Ansewr += '(' + str( 1 + i).zfill(2) + ')' + Add_Math[1]
                
                Math = AutMath()
                Sub_Math = Math.subtraction()
                MathL += '(' + str(26 + i) + ')' + Sub_Math[0]
                MathL_Ansewr += '(' + str(26 + i) + ')' + Sub_Math[1]
                
                Math = AutMath()
                Mul_Math = Math.multiplication()
                MathL += '(' + str(51 + i) + ')' + Mul_Math[0]
                MathL_Ansewr += '(' + str(51 + i) + ')' + Mul_Math[1]
                
                Math = AutMath()
                Div_Math = Math.division()
                MathL += '(' + str(76 + i) + ')' + Div_Math[0]
                MathL_Ansewr += '(' + str(76 + i) + ')' + Div_Math[1]
                
                MathL += '\n'
                MathL_Ansewr += '\n'
        
        if (evt.GetSelectedIndex() == 2):
            File_Data = Configuration()
            Math = AutMath()
            
            #問題のファイル名設定
            File_Name = File_Data.MyPath()
            File_Name += File_Data.nowtime()
            File_Name += "_Q.docx"
            
            #答えのファイル名設定
            File_Name_ansewr = File_Data.MyPath()
            File_Name_ansewr += File_Data.nowtime()
            File_Name_ansewr += "_A.docx"
            
            #問題のdocxの生成
            Math.AddDocx(File_Name)
            #答えのdocxの生成
            Math.AddDocx_ansewr(File_Name_ansewr)
            #内容のリセット
            MathL = ''
            MathL_Ansewr = ''


        print('Selected index =', evt.GetSelectedIndex())

if __name__ == '__main__':
    app = wx.PySimpleApp()
    MyFrame().Show()
    app.MainLoop()
```

実行してみましょう。
![スクリーンショット (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1653601/a77a29e8-aab9-c01e-981c-2ee03a3854ae.png)

「生成」をクリックし「出力」をクリックすると
![スクリーンショット (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1653601/7911f899-8d3f-ee11-b9f1-723afeec4091.png)

ファイルができているのがわかると思います。
開いてみると
![スクリーンショット (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1653601/61cf76a6-dbde-4a42-6c53-024d8bec0bc9.png)

どちらもきちんと生成できていますね。

ちなみに、「生成」と「出力」の間のボタンはプレビューボタンにしようと思っていますので、現在は使用できません。（ボタンは消せます。消しても大丈夫です。消してください）
UIがゴミクソなのも許して下さい。

いかがでしたか？
これで私も計算能力を高められます！

これからの課題はプレビューを表示することですね。

参考資料はこちらです。
https://www.shibutan-bloomers.com/python_library_python-docx-3/2409/
ありがとうございました。