import wx

from scipy.special import comb


class MainWindow(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Dices Probability Predictor", size=(550, 175), style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN)

        # ウインドウ全体のSizer
        self.__background = wx.Panel(self)
        self.__backsizer = wx.BoxSizer(wx.VERTICAL)
        self.__background.SetSizer(self.__backsizer)

        self.__sizer = wx.BoxSizer(wx.VERTICAL)
        self.__backsizer.Add(self.__sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=15)

        self.__sentence_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.__sizer.Add(self.__sentence_sizer, flag=wx.EXPAND)

        # ダイスの面数
        self.__ni_dice = wx.SpinCtrl(self.__background, min=1, initial=6)
        self.__sentence_sizer.Add(self.__ni_dice, flag=wx.ALIGN_CENTER)

        # 間の文章
        sentence_1 = wx.StaticText(self.__background, label="面ダイスを")
        self.__sentence_sizer.Add(sentence_1, flag=wx.ALIGN_CENTER)

        # ダイスの個数
        self.__ni_num = wx.SpinCtrl(self.__background, min=1, initial=1)
        self.__sentence_sizer.Add(self.__ni_num, flag=wx.ALIGN_CENTER)

        # 間の文章
        sentence_2 = wx.StaticText(self.__background, label="個振るとき、")
        self.__sentence_sizer.Add(sentence_2, flag=wx.ALIGN_CENTER)

        # 指定の出目
        self.__ni_roll = wx.SpinCtrl(self.__background, min=1, initial=1)
        self.__sentence_sizer.Add(self.__ni_roll, flag=wx.ALIGN_CENTER)

        self.__roll_radio_sizer = wx.BoxSizer(wx.VERTICAL)
        self.__sentence_sizer.Add(self.__roll_radio_sizer, flag=wx.ALIGN_CENTER)
        self.__roll_radio_or_more = wx.RadioButton(self.__background, wx.ID_ANY, "以上", style=wx.RB_GROUP)
        self.__roll_radio_or_less = wx.RadioButton(self.__background, wx.ID_ANY, "以下")
        self.__roll_radio_sizer.Add(self.__roll_radio_or_more, flag=wx.ALIGN_CENTER)
        self.__roll_radio_sizer.Add(self.__roll_radio_or_less, flag=wx.ALIGN_CENTER)

        # 間の文章
        sentence_3 = wx.StaticText(self.__background, label="の出目が")
        self.__sentence_sizer.Add(sentence_3, flag=wx.ALIGN_CENTER)

        # 出てほしいダイスの個数
        self.__ni_num_dice = wx.SpinCtrl(self.__background, min=1, initial=1)
        self.__sentence_sizer.Add(self.__ni_num_dice, flag=wx.ALIGN_CENTER)

        # 間の文章
        sentence_4 = wx.StaticText(self.__background, label="個")
        self.__sentence_sizer.Add(sentence_4, flag=wx.ALIGN_CENTER)

        self.__dice_num_radio_sizer = wx.BoxSizer(wx.VERTICAL)
        self.__sentence_sizer.Add(self.__dice_num_radio_sizer, flag=wx.ALIGN_CENTER)
        self.__dice_num_radio_or_more = wx.RadioButton(self.__background, wx.ID_ANY, "以上", style=wx.RB_GROUP)
        self.__dice_num_radio_or_less = wx.RadioButton(self.__background, wx.ID_ANY, "以下")
        self.__dice_num_radio_sizer.Add(self.__dice_num_radio_or_more, flag=wx.ALIGN_CENTER)
        self.__dice_num_radio_sizer.Add(self.__dice_num_radio_or_less, flag=wx.ALIGN_CENTER)

        # 間の文章
        sentence_5 = wx.StaticText(self.__background, label="出る確率")
        self.__sentence_sizer.Add(sentence_5, flag=wx.ALIGN_CENTER)

        # 計算実行ボタン
        self.__calc_button = wx.Button(self.__background, label="計算")
        self.__calc_button.Bind(wx.EVT_BUTTON, self.__calc)
        self.__sizer.Add(self.__calc_button, flag=wx.ALIGN_RIGHT | wx.TOP, border=10)

        # 計算結果
        self.__calc_result = wx.StaticText(self.__background, label="計算結果")
        self.__sizer.Add(self.__calc_result, flag=wx.ALIGN_RIGHT | wx.TOP | wx.RIGHT, border=10)

        self.Show()

    def __calc(self, event):
        D = self.__ni_dice.GetValue()
        N = self.__ni_num.GetValue()
        alpha = self.__ni_roll.GetValue()
        is_more_alpha = self.__roll_radio_or_more.GetValue()
        beta = self.__ni_num_dice.GetValue()
        is_more_beta = self.__dice_num_radio_or_more.GetValue()

        probability = 0.0
        for i in range(beta):
            probability += MainWindow.p(i, D, N, alpha, is_more_alpha)

        if is_more_beta:
            probability = 1 - probability
        else:
            probability += MainWindow.p(beta, D, N, alpha, is_more_alpha)

        self.__calc_result.SetLabel(str(probability))
        self.__sizer.Layout()

    @staticmethod
    def p(m, D, N, alpha, is_more_alpha):
        combination = comb(N, m, exact=True)

        p_event = (D - alpha + 1 if is_more_alpha else alpha) / D

        return combination * (p_event ** m) * ((1 - p_event) ** (N - m))


if __name__ == "__main__":
    app = wx.App()
    MainWindow()
    app.MainLoop()
