OSDN Git Service

marshal database generator & accessor
[amulettoolsmh4/main.git] / model / db_generator.py
1 # -*- coding: utf-8 -*-
2
3 # databaseの生成用スクリプト
4 # 2013/12/09 written by kei9 
5
6 import sqlite3
7 import csv
8 import os.path
9 import os
10 import sys
11 import tempfile
12 import zipfile
13 import cStringIO
14
15 import db_supports
16 import mh4constnumbers
17 import skilltable
18 import amulettable
19 import skillminmaxtable
20 import seed2skill2table
21 import seed2tablenumbertable
22 import seed2thresholdtable
23 import seed2inishietable
24 import sufficienttable
25 import seed1tenuntable
26
27 class DataBaseGenerator(object):
28     u""" this is generate class of database """
29     def __init__(self, db_name=None):
30         if db_name is None:
31             self._db_name = ":memory:"
32         else :
33             self._db_name = db_name
34         self._tmp_db = None
35         self._dict_skill_id = {}
36         self._dict_amulet_id = {}
37
38     def generate_db(self, over_write=True):
39         u""" DBを作成する関数。over_writeがTrueで既存のDBがある場合は上書きする """
40         if self._db_name == ":memory:":
41             # nothing to do
42             pass
43         elif os.path.exists(self._db_name) and os.path.isfile(self._db_name):
44             if over_write is False:
45                 return
46             with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
47                 self._tmp_db = tmp_file.name
48
49         self._open()
50
51         # read data from zip file
52         self._zipfile = zipfile.ZipFile(db_supports.ZIP_FILE, "r")
53
54         # db generation
55         self._create_skill_table()
56         self._create_amulet_table()
57         self._create_min_max_table()
58         self._create_seed2_skill2_table()
59         self._create_seed2_threshold_table()
60         self._create_seed2_inishie_table()
61         self._create_sufficient_value_table()
62         self._create_seed1_tenun_table()
63
64         self._zipfile.close()
65         self._close()
66
67         # rename operation of tmp file
68         if self._tmp_db is not None:
69             with tempfile.NamedTemporaryFile(delete=True) as tmp_file:
70                 tmp_name = tmp_file.name
71             os.rename(self._db_name, tmp_name)
72             os.rename(self._tmp_db, self._db_name)
73             os.remove(tmp_name)
74
75     def _open(self):
76         if self._tmp_db is None:
77             self._connect = sqlite3.connect(self._db_name)
78         else:
79             self._connect = sqlite3.connect(self._tmp_db)
80         self._connect.text_factory = str   # for usage of utf-8
81         self._cursor = self._connect.cursor()
82
83     def _close(self):
84         self._connect.commit()
85         self._cursor.close()
86         self._connect.close()
87
88     def _get_skill_id(self, skill_name):
89         u""" 与えられたスキル名からスキルのIDを得る関数。スキルが存在しなければNoneを返す """
90         skill_name = unicode(skill_name, 'utf-8')
91
92         if skill_name in self._dict_skill_id:
93             return self._dict_skill_id[skill_name]
94         else:
95             sql = db_supports.SKILL_TABLE_SKILL2ID_SQL.format(skill_name=skill_name)
96             self._cursor.execute(sql)
97             skill_ids = []
98             for val in self._cursor.fetchall():
99                 skill_ids.append(val[0])
100             if len(skill_ids) < 1:
101                 return None
102             else:
103                 self._dict_skill_id[skill_name] = skill_ids[0]
104                 return skill_ids[0]
105
106     def _get_amulet_id(self, amulet_name):
107         u""" 与えられたお守り名からお守りのIDを得る関数。スキルが存在しなければNoneを返す """
108         amulet_name = unicode(amulet_name, 'utf-8')
109
110         if amulet_name in self._dict_amulet_id:
111             return self._dict_amulet_id[amulet_name]
112         else:
113             sql = db_supports.AMULET_TABLE_AMULET2ID_SQL.format(amulet_name=amulet_name)
114             self._cursor.execute(sql)
115             amulet_ids = []
116             for val in self._cursor.fetchall():
117                 amulet_ids.append(val[0])
118             if len(amulet_ids) < 1:
119                 return None
120             else:
121                 self._dict_amulet_id[amulet_name] = amulet_ids[0]
122                 return amulet_ids[0]
123
124     def _create_skill_table(self):
125         u"""スキルとIDの組み合わせテーブルを作成する"""
126         print "create skill table"
127         generator = skilltable.SkillTableGenerator()
128
129         # read from zip file with StringIO wrapper
130         f = cStringIO.StringIO(self._zipfile.read(db_supports.SKILL_FILE_NAME, "r"))
131         reader = csv.reader(f)  # (id, skillName)
132         generator.insert_data(self._cursor, reader)
133
134         self._connect.commit()
135         f.close()
136
137     def _create_amulet_table(self):
138         u"""お守り名とIDの組み合わせテーブルを作成する"""
139         print "create amulet table"
140         generator = amulettable.AmuletTableGenerator()
141         # read from zip file with StringIO wrapper
142         f = cStringIO.StringIO(self._zipfile.read(db_supports.AMULET_FILE_NAME, "r"))
143         reader = csv.reader(f)  # (amuleteName)
144         generator.insert_data(self._cursor, reader)
145
146         self._connect.commit()
147         f.close()
148
149     def _create_min_max_table(self):
150         u"""お守り名と対応するスキルの最大最小値の記載されたcsvファイルから
151         お守りごとのスキルの最大最小値を記載したテーブルを作成する
152         """
153         print "load min & max of skill" 
154         # create master table of skill min max
155         generator = skillminmaxtable.SkillMinMaxTableGenerator()
156         # read from zip file with StringIO wrapper
157         f = cStringIO.StringIO(self._zipfile.read(db_supports.MIN_MAX_FILE_NAME, "r"))
158         reader = csv.reader(f)  # (name, filename of minmax1, filename of minmax2)
159
160         generator.insert_master_data(self._cursor, reader)
161         filenames_dict = generator.get_skill_filenames()
162         reader_dict, filelist = {}, []
163         for key, value in filenames_dict.items():
164             fname1, fname2 = value
165             if fname1 in self._zipfile.namelist():
166                 file_minmax1 = cStringIO.StringIO(self._zipfile.read(fname1, "r"))
167                 reader1 = csv.reader(file_minmax1)  # (name of skill, min1, max1)
168                 filelist.append(file_minmax1)
169             else:
170                 reader1 = None
171
172             if fname2 in self._zipfile.namelist():
173                 file_minmax2 = cStringIO.StringIO(self._zipfile.read(fname2, "r"))
174                 reader2 = csv.reader(file_minmax2)  # (name of skill, min1, max1)
175                 filelist.append(file_minmax2)
176             else:
177                 reader2 = None
178             reader_dict[key] = (reader1, reader2)
179         generator.insert_data(self._cursor, reader_dict)
180
181         for _file in filelist:
182             _file.close()
183
184         self._connect.commit()
185         f.close()
186
187     def _create_seed2_skill2_table(self):
188         u"""csvファイルからSEED2から第2スキルへの表を生成する
189         """
190         print "load Second skill"
191         # create master table of seed2 to skill2
192         generator = seed2skill2table.Seed2Skill2TableGenerator()
193         # read from zip file with StringIO wrapper
194         f = cStringIO.StringIO(self._zipfile.read(db_supports.SEED2_SKILL2_FILE_NAME, "r"))
195         reader = csv.reader(f)  # (omamori_name, filename of Second_skill)
196
197         generator.insert_master_data(self._cursor, reader)
198         filenames_dict = generator.get_skill_filenames()
199         reader_dict, filelist = {}, []
200         for key, fname in filenames_dict.items():
201             if fname in self._zipfile.namelist():
202                 file_skill2 = cStringIO.StringIO(self._zipfile.read(fname, "r"))
203                 reader = csv.reader(file_skill2)  # (seed2, skillname1,..., skillname7)
204                 filelist.append(file_skill2)
205                 reader_dict[key] = reader
206         generator.insert_data(self._cursor, reader_dict)
207
208         for _file in filelist:
209             _file.close()
210
211         self._connect.commit()
212         f.close()
213
214         self._create_seed2_table_no_table()
215         self._connect.commit()
216
217     def _create_seed2_table_no_table(self):
218         u""" Seed2に対応するテーブル値を格納するテーブルを作成する """
219         generator = seed2tablenumbertable.Seed2TableNumberTableGenerator()
220
221         # read from zip file with StringIO wrapper
222         f = cStringIO.StringIO(self._zipfile.read(db_supports.SEED2_TABLE_NO_FILE_NAME, "r"))
223         reader = csv.reader(f)  # (seed2, table_no, no)
224         generator.insert_data(self._cursor, reader)
225         self._connect.commit()
226         f.close()
227
228     def _create_seed2_inishie_table(self):
229         u""" いにしえの錬金の第2Seed対応テーブルを作成する """
230         generator = seed2inishietable.Seed2InishieTableGenerator()
231
232         # read from zip file with StringIO wrapper
233         f = cStringIO.StringIO(self._zipfile.read(db_supports.SEED2_INISHIE_FILE_NAME, "r"))
234         reader = csv.reader(f)  # (seed2, skill_name, threshold1, threshold2)
235         generator.insert_data(self._cursor, reader)
236         self._connect.commit()
237         f.close()
238
239     def _create_seed2_threshold_table(self):
240         u""" csvファイルよりSEED2から判定値1,2へのテーブルを作成する
241         """
242         print "load Threshold1,2"
243         generator = seed2thresholdtable.Seed2ThresholdTableGenerator()
244
245         # for threshold1 table
246         # read from zip file with StringIO wrapper
247         f = cStringIO.StringIO(self._zipfile.read(db_supports.SEED2_THRESHOLD1_FILE_NAME, "r"))
248         reader = csv.reader(f)  # (seed2, threshold1_1, threshold1_2, ..., threshold1_7)
249         generator.insert_data(self._cursor, reader, 1)
250         f.close()
251
252         # for threshold2 table
253         # read from zip file with StringIO wrapper
254         f = cStringIO.StringIO(self._zipfile.read(db_supports.SEED2_THRESHOLD2_FILE_NAME, "r"))
255         reader = csv.reader(f)  # (seed2, threshold2_1, threshold2_2, ..., threshold2_7)
256         generator.insert_data(self._cursor, reader, 2)
257         f.close()
258
259         self._connect.commit()
260
261     def _create_sufficient_value_table(self):
262         u"""csvファイルから充足値の表を生成する
263         """
264         print "load Sufficient Value"
265         # create master table of sufficient value
266         generator = sufficienttable.SufficientTableGenerator()
267         # read from zip file with StringIO wrapper
268         f = cStringIO.StringIO(self._zipfile.read(db_supports.SUFFICIENT_FILE_NAME, "r"))
269         reader = csv.reader(f)  # (omamori_name, filename of sufficient values)
270
271         generator.insert_master_data(self._cursor, reader)
272         filenames_dict = generator.get_skill_filenames()
273         reader_dict, filelist = {}, []
274         for key, fname in filenames_dict.items():
275             if fname in self._zipfile.namelist():
276                 file_suff = cStringIO.StringIO(self._zipfile.read(fname, "r"))
277                 reader = csv.reader(file_suff)  # (seed2, skillname1,..., skillname7)
278                 filelist.append(file_suff)
279                 reader_dict[key] = reader
280         generator.insert_data(self._cursor, reader_dict)
281
282         for _file in filelist:
283             _file.close()
284
285         self._connect.commit()
286         f.close()
287
288     def _create_seed1_tenun_table(self):
289         u""" csvファイルより天運の錬金結果からSEED1へのテーブルを作成する
290         """
291         print "load seed1"
292         # for seed1 table
293         # tenun555
294         generator = seed1tenuntable.Seed1TenunTableGenerator()
295         # read from zip file with StringIO wrapper
296         f = cStringIO.StringIO(self._zipfile.read(db_supports.SEED1_TENUN555_FILE_NAME, "r"))
297         reader = csv.reader(f)
298         generator.insert_data(self._cursor, reader, mh4constnumbers.KEY_TENUN555)
299         f.close()
300
301         # tenun888
302         # read from zip file with StringIO wrapper
303         f = cStringIO.StringIO(self._zipfile.read(db_supports.SEED1_TENUN888_FILE_NAME, "r"))
304         reader = csv.reader(f)
305         generator.insert_data(self._cursor, reader, mh4constnumbers.KEY_TENUN888)
306         f.close()
307         self._connect.commit()
308
309
310 if __name__ == "__main__":
311     #db = DataBaseGenerator(DB_FILE_NAME)
312     db = DataBaseGenerator("test.sqlite3")
313     #db = DataBaseGenerator()    # for memory
314     db.generate_db()
315