SQL(オセロのデータ整理001:大きなデータの入力)

■SQLiteで大きなデータを扱う。
以前、Powershellで作ったオセロのゲームをテキストファイルとして保存していた。そのうち整理しようと思っていたけど、前回ちょうどSQLiteにふれたので、それを使ってデータベースに入れる。
対象はランダムとランダムで行った10万回のゲームの結果×10ファイル。1ファイルは1.3GBほどあり、メモ帳で開こうとすると「大きすぎてメモ帳では編集できません」とメッセージが出る。データベースに入れれば、表示や操作ができるようになるものか。

1回のゲームの結果のフォーマットは、下のように出力される。

Game:1| Start Othello
________
________
________
___〇●___
___●〇___
________
________
________
=====Trial:1=====
________
________
________
___〇●___
___〇〇___
___〇____
________
________
=====Trial:2=====
(途中省略)
=====Trial:60=====
〇〇〇〇〇〇〇〇
〇〇〇●●●〇〇
〇〇〇〇〇●〇〇
〇〇〇〇〇●●〇
〇〇●〇〇〇●〇
〇●●●〇〇〇●
〇〇〇〇〇〇●●
〇〇〇〇〇〇〇●
●15vs〇49Game:1| End Othello

Start Othello、End Othello、Trialあたりをキーワードとして文字列操作をした後、下のテーブルに入れる。
ゲームテーブル(ID、Trial00、Trial01、(省略)、Trial68、White_result、Black_result、Result、Note)

お互い問題なく石を置くことができれば、空いている60のスペースは60回のターンで埋まり、初期状態も含めて61の列(カラム)があれば足りる。ただ、置くところがなくパスすることも考えて、69(Trial00が初期状態)のカラムを作っておく。
それぞれのカラムの仕様は下のような感じ。
 ID:ゲームのID(重複しない、1から順に自動的に入力)
 Trialxx:オセロの盤の状態を示す(8×8の64に改行を足した分のテキスト長にする。メモ帳で○を追加・削除しながら保存してファイルサイズを確認すると、○、●、_は3バイト、改行は2バイトだった。なので、64*3バイト+14バイト(206バイト)を確保)
 White(Black)_result:最終的な白(黒)の石の数を入力(数値として入力、整数値tinyint)
 Result:勝ったプレイヤーなどを白、黒、引き分けで入力(W、B、Eの文字として入力、1バイト)
 Note:備考として、後でメモを入れられるようにカラムを設定しておく(32バイト)。

下のコードでゲーム結果をテーブルの形にあうようなリストに変換した。
データベースへの挿入(INSERT)は、別の関数db(game)として定義する。ファイルサイズが大きくても対応できるよう1ゲーム毎にデータベースに入れる。


def txtfile_to_lines(filename):
    f = open(filename, 'r', encoding='UTF-8')
    game = []
    board = ""
    row_no = 0

    flag = -1
    while True:
        line = f.readline()
        if line:
            if line.find("Start Othello") > 0:
                line = f.readline()
                flag = 0
            elif line.find("Trial") > 0:
                game.append(board.strip())
                board = ""
                flag = 0
                line = f.readline()
            elif line.find("End Othello") > 0:
                game.append(board.strip())
                flag = 1

            if flag == 0:
                board = board + line
            elif flag == 1:
                Black = int(line[line.find("●") + 1:line.find("vs")])
                White = int(line[line.find("〇") + 1:line.find("Game")])

                if len(game) < 69:
                    while True:
                        if len(game) == 69:
                            break
                        else:
                            game.append("")

                game.append(White)
                game.append(Black)
                if Black > White:
                    game.append("B")
                elif Black < White:
                    game.append("W")
                elif Black == White:
                    game.append("E")

                db(game)
                # for data in game:
                #    print(data)
                board = ""
                game = []
        else:
            break
    f.close()
    return game

最終的に、1.2GBのデータベースファイルに変換できた。

このファイルに対して、例えば、次のSQL文を実行すると、下のような結果が得られる。
SELECT White_result, Black_result, Result FROM game where White_result > 59

問題なくデータが入力されているよう。
次回、このデータベースに対してSQLのビューやカーソルなど使って何かできないか試してみる。