Python3でMJSCORE形式の牌譜を解析

#データベースにしたこと

備忘録を兼ねて何のデータをどのようにとったかまとめておきます。

- 全体データ(whole_data)
　試合データをまとめたもの(list)
- 試合データ(shiai_data)
  局データをまとめたもの(list)
- 局データ(kyoku_data)
  局目・点数・和了データ(流局)・配牌・ドラ表示牌・捨て牌・立直のタイミング・和了のタイミング・終局時の手牌・牌譜を内包したもの(list)

1. 局目
　東一局～南四局までを1~4のintで表したもの
2. 点数
　局ごとの点数の変動をlistにしたもの
3. 和了データ
  和了の役や流局をしたかどうかを取得したもの(2019/04/11現在では流局の情報のみ)
4. 配牌
　配牌をlistで取得したもの
5. ドラ表示牌
　str
6. 捨て牌
  list
7. 立直のタイミング
  int(局時間)
8. 和了のタイミング
　同上
9. 終局時の手牌
　list
10. 牌譜  
  list

以下ソースコード
~~~
file_name=""#ファイル名
target_file=open(file_name,"rb")
lines = target_file.readlines()


tonnanwhich=0


players=["","","",""]#プレイヤーの名前を格納
players_cell=["","","",""]

whole_data=[] #試合データを内包する
shiai_data=[] #局データを内包する
kyoku_data=[] #局目・点数・和了データ(流局)・配牌・ドラ表示牌・捨て牌・立直のタイミング・和了のタイミング・終局時の手牌・牌譜を内包する

haipai_data=["","","",""] #配牌データを東家から北家の順に内包する
ie_num=0 #局目を取得(東一局～南四局)
dpoint_data=[0,0,0,0] #局の点数の収支
kyokugyo=0 #和了の役/流局　から　配牌の四行　を表す行を取得
ryukyoku_flag=0 #流局したら1
paifu_list=[] #＊で始まる行の牌譜を一つなぎのリストにしたもの
paifu_list_kari=[] #↑の一行分
paifugyo=0 #牌譜を書いた行がいつまで続くか記録するもの（ドラが書いてある行で１になってスタート）
tehai_list=[[[],[],[]],[[],[],[]],[[],[],[]],[[],[],[]]] #終局時の手牌をリストにする（[[手牌],[鳴いた牌],[暗槓の牌]]という形で保持する）
sute_hai=[[],[],[],[]] #捨て牌のリスト
kyoku_time=0 #局時間(paifu_cell一個につき1進む)
riichi_kyoku_time=[0,0,0,0] #立直した人とそのタイミング(局時間)
hola_kyoku_time=[0,0,0,0] #和了した人とそのタイミング(局時間)


for row in lines:

    try:
        row = row.decode("utf-8")
    except UnicodeDecodeError:
                # utf-8でないバイト列が含まれる行はスキップする
        row = target_file.readline()
        continue

    rlist = row.split()
    rlistlist = list(rlist)

    if "=====" in row:
        if "東" in row:
            houwhich=1
        else:
            houwhich=2

    elif "持点" in row:
        players_cell[0]=rlist[1]
        players_cell[1]=rlist[3]
        players_cell[2]=rlist[5]
        players_cell[3]=rlist[7]
        i = 0

        for i in range(4):
            player_celllist=list(players_cell[i])
            j=0
            nflag=0
            player_name=""
            for j in range(20):
                if player_celllist[j] == "]":
                    nflag=1
                elif player_celllist[j] == "/":
                    break
                elif nflag==1:
                    player_name+=player_celllist[j]
                else:
                    pass
            players[i]=player_name
    #ツモ率・放銃率・流局率
    elif "局" in row and "本場" in row:
        #局目を取得
        rlistlist0=list(rlist[0])
        ie_index=rlistlist0.index("局")-1
        ie_num=int(rlistlist0[ie_index])
        kyoku_data.append(ie_num)

        #プレイヤーの得点の差分を取得
        rlistlist1=list(rlist[1])
        riichi_honsu=int(rlistlist1[-2])
        rlist_len=len(rlist)
        roop_len=rlist_len-2
        for i in range(roop_len):
            I=i+2
            if I%2==0:
                dpoint_player=players.index(rlist[I])
            else:
                dpoint_num=int(rlist[I])
                dpoint_data[dpoint_player]=dpoint_num
        kyoku_data.append(dpoint_data)
        kyokugyo=1

    elif kyokugyo == 1:
        kyokugyo=2
        #流局したかどうか
        if "流局" in row:
            ryukyoku_flag=1
            kyoku_data.append(ryukyoku_flag)
        #必要なら点数とかその他（手牌から読み取れるよね……？）（ダブロンとか見ないと）


    elif kyokugyo > 1:
        #配牌データを取得する
        rlistlist0=list(rlist[0])
        if rlistlist0[1] == "1":
            haipai_list=rlistlist0[4:]
            haipai_str="".join(haipai_list)
            haipai_data[0]=haipai_str
        elif rlistlist0[1] == "2":
            haipai_list=rlistlist0[4:]
            haipai_str="".join(haipai_list)
            haipai_data[1]=haipai_str
        elif rlistlist0[1] == "3":
            haipai_list=rlistlist0[4:]
            haipai_str="".join(haipai_list)
            haipai_data[2]=haipai_str
        elif rlistlist0[1] == "4":
            haipai_list=rlistlist0[4:]
            haipai_str="".join(haipai_list)
            haipai_data[3]=haipai_str
        kyokugyo+=1
        if kyokugyo == 6:
            kyokugyo = 0
            kyoku_data.append(haipai_data)

    elif "表ドラ" in row and "裏ドラ" in row:
        #ドラ表示牌及び裏ドラを取得する
        rlistlist0=list(rlist[0])
        rlistlist1=list(rlist[1])
        omotedora=rlistlist0[5:]
        uradora=rlistlist1[5:]
        omotedora="".join(omotedora)
        uradora="".join(uradora)
        kyoku_data.append(omotedora)
        paifugyo=1

    elif paifugyo > 0:
        #＊から始まる牌譜をリストにして取得する
        if "*" in row:
            paifu_list_kari=rlist[1:]
            paifu_list_kari_len=len(paifu_list_kari)
            for i in range(paifu_list_kari_len):
                paifu_list.append(paifu_list_kari[i])
        else:
            paifugyo=0
            #得られた牌譜データから最終手牌を作る（鳴きと残り手牌を分けて）
            for i in range(4): #配牌で手牌を初期化
                haipai_data_len=len(haipai_data[i])
                haipai_data_list=list(haipai_data[i])
                haipai_list=[]
                flag = 0
                for j in range(haipai_data_len):
                    if haipai_data_list[j] == "東" or haipai_data_list[j] == "南" or haipai_data_list[j] == "西" or haipai_data_list[j] == "北" or haipai_data_list[j] == "白" or haipai_data_list[j] == "発" or haipai_data_list[j] == "中":
                        haipai_list.append(haipai_data_list[j])
                    elif flag == 1:
                        haipai_the_hai=haipai_data_list[j-1]+haipai_data_list[j]
                        haipai_list.append(haipai_the_hai)
                        flag = 0
                    else:
                        flag = 1
                tehai_list[i][0]=haipai_list
            paifu_list_len=len(paifu_list)
            for i in range(paifu_list_len):
                kyoku_time+=1
                paifu_cell=paifu_list[i]
                paifu_cell_list=list(paifu_cell)
                paifu_cell_list_len=len(paifu_cell_list)
                act_player=int(paifu_cell_list[0])-1
                if "G" == paifu_cell_list[1]: #ツモ牌
                    if paifu_cell_list_len == 4: #ツモ牌が数牌
                        the_hai=paifu_cell_list[2]+paifu_cell_list[3]
                    else:
                        the_hai=paifu_cell_list[2]
                    tehai_list[act_player][0].append(the_hai)
                    act_past_player=act_player
                elif "D" == paifu_cell_list[1] or "d" == paifu_cell_list[1]: #捨てる牌
                    if paifu_cell_list_len == 4: #捨てる牌が数牌
                        the_hai=paifu_cell_list[2]+paifu_cell_list[3]
                    else:
                        the_hai=paifu_cell_list[2]
                    tehai_list[act_player][0].remove(the_hai)
                    sute_hai[act_player].append(the_hai)
                    act_past_player=act_player
                elif "N" == paifu_cell_list[1]: #ポンッ!(cv.亦野誠子)
                    if paifu_cell_list_len == 4: #ポンする牌が字牌
                        the_hai=paifu_cell_list[2]
                        tehai_list[act_player][0].remove(the_hai)
                        tehai_list[act_player][0].remove(the_hai)
                        del sute_hai[act_past_player][-1]
                        for i in range(3):
                            tehai_list[act_player][1].append(the_hai)
                    else:
                        the_hai1=paifu_cell_list[2]+paifu_cell_list[3]
                        the_hai2=paifu_cell_list[4]+paifu_cell_list[5]
                        the_hai3=sute_hai[act_past_player][-1]
                        del sute_hai[act_past_player][-1]
                        tehai_list[act_player][0].remove(the_hai1)
                        tehai_list[act_player][0].remove(the_hai2)
                        tehai_list[act_player][1].append(the_hai1)
                        tehai_list[act_player][1].append(the_hai2)
                        tehai_list[act_player][1].append(the_hai3)

                elif "C" == paifu_cell_list[1]: #チー
                    the_hai1=paifu_cell_list[2]+paifu_cell_list[3]
                    the_hai2=paifu_cell_list[4]+paifu_cell_list[5]
                    the_hai3=sute_hai[act_past_player][-1]
                    tehai_list[act_player][0].remove(the_hai1)
                    tehai_list[act_player][0].remove(the_hai2)
                    del sute_hai[act_past_player][-1]
                    tehai_list[act_player][1].append(the_hai1)
                    tehai_list[act_player][1].append(the_hai2)
                    tehai_list[act_player][1].append(the_hai3)
                elif "K" == paifu_cell_list[1]: #槓
                    if act_past_player == act_player: #暗槓or加槓
                        if paifu_cell_list_len == 4: #ツモ牌が数牌
                            the_hai=paifu_cell_list[2]+paifu_cell_list[3]
                        else:
                            the_hai=paifu_cell_list[2]

                        if the_hai in tehai_list[act_player][1]: #加槓
                            tehai_list[act_player][0].remove(the_hai)
                            tehai_list[act_player][1].append(the_hai)
                        else: #赤牌も考慮
                            if "5" in the_hai:
                                if the_hai == "5P":
                                    if "5p" in tehai_list[act_player][1]:
                                        tehai_list[act_player][0].remove("5P")
                                        tehai_list[act_player][1].append("5P")
                                    else:
                                        tehai_list[act_player][0].remove("5P")
                                        tehai_list[act_player][2].append("5P")
                                        for i in range(3):
                                            tehai_list[act_player][0].remove("5p")
                                            tehai_list[act_player][2].append("5p")
                                if the_hai == "5S":
                                    if "5s" in tehai_list[act_player][1]:
                                        tehai_list[act_player][0].remove("5S")
                                        tehai_list[act_player][1].append("5S")
                                    else:
                                        tehai_list[act_player][0].remove("5S")
                                        tehai_list[act_player][2].append("5S")
                                        for i in range(3):
                                            tehai_list[act_player][0].remove("5s")
                                            tehai_list[act_player][2].append("5s")
                                if the_hai == "5M":
                                    if "5m" in tehai_list[act_player][1]:
                                        tehai_list[act_player][0].remove("5M")
                                        tehai_list[act_player][1].append("5M")
                                    else:
                                        tehai_list[act_player][0].remove("5M")
                                        tehai_list[act_player][2].append("5M")
                                        for i in range(3):
                                            tehai_list[act_player][0].remove("5m")
                                            tehai_list[act_player][2].append("5m")
                            else:
                                for i in range(4):
                                    tehai_list[act_player][0].remove(the_hai)
                                    tehai_list[act_player][2].append(the_hai)
                    else: #大明槓
                        if paifu_cell_list_len == 4: #鳴く牌が数牌
                            the_hai=paifu_cell_list[2]+paifu_cell_list[3]
                        else:
                            the_hai=paifu_cell_list[2]

                        del sute_hai[act_past_player][-1]
                        tehai_list[act_player][1].append(the_hai)
                        if "5" in the_hai:
                            if the_hai=="5p":
                                tehai_list[act_player][0].remove(the_hai)
                                tehai_list[act_player][0].remove(the_hai)
                                tehai_list[act_player][0].remove("5P")
                                tehai_list[act_player][1].append(the_hai)
                                tehai_list[act_player][1].append(the_hai)
                                tehai_list[act_player][1].append("5P")
                            elif the_hai=="5P":
                                for i in range(3):
                                    tehai_list[act_player][0].remove("5p")
                                    tehai_list[act_player][0].append("5p")
                            if the_hai=="5s":
                                tehai_list[act_player][0].remove(the_hai)
                                tehai_list[act_player][0].remove(the_hai)
                                tehai_list[act_player][0].remove("5S")
                                tehai_list[act_player][1].append(the_hai)
                                tehai_list[act_player][1].append(the_hai)
                                tehai_list[act_player][1].append("5S")
                            elif the_hai=="5S":
                                for i in range(3):
                                    tehai_list[act_player][0].remove("5s")
                                    tehai_list[act_player][0].append("5s")
                            if the_hai=="5m":
                                tehai_list[act_player][0].remove(the_hai)
                                tehai_list[act_player][0].remove(the_hai)
                                tehai_list[act_player][0].remove("5M")
                                tehai_list[act_player][1].append(the_hai)
                                tehai_list[act_player][1].append(the_hai)
                                tehai_list[act_player][1].append("5M")
                            elif the_hai=="5M":
                                for i in range(3):
                                    tehai_list[act_player][0].remove("5m")
                                    tehai_list[act_player][0].append("5m")
                        else:
                            for i in range(3):
                                tehai_list[act_player][0].remove(the_hai)
                                tehai_list[act_player][1].append(the_hai)
                elif "R" == paifu_cell_list[1]: #立直のタイミング
                    riichi_kyoku_time[act_player]=kyoku_time
                    kyoku_time+=1
                elif "A" == paifu_cell_list[1]: #和了のタイミング
                    hola_kyoku_time[act_player]=kyoku_time
                    kyoku_time+=1
            kyoku_data.append(sute_hai)
            kyoku_data.append(riichi_kyoku_time)
            kyoku_data.append(hola_kyoku_time)
            kyoku_data.append(tehai_list)
            kyoku_data.append(paifu_list)
            #局データが完成（やったー！）
            shiai_data.append(kyoku_data)
            kyoku_data=[]
            paifu_list=[]
            tehai_list=[[[],[],[]],[[],[],[]],[[],[],[]],[[],[],[]]] #終局時の手牌をリストにする（[[手牌],[鳴いた牌],[暗槓の牌]]という形で保持する）
            sute_hai=[[],[],[],[]] #捨て牌のリスト
            kyoku_time=0
    elif "----" in row:
        whole_data.append(shiai_data)
        shiai_data=[]

~~~

あとはデータベースから必要なデータだけ引っ張ってこればいいので楽ですね。