OSDN Git Service

marshal database generator & accessor
[amulettoolsmh4/main.git] / model / skillminmaxtable.py
1 # -*- coding: utf-8 -*-
2
3 u"""
4 お守りID、スキルIDから取りうるスキルの最大値への組み合わせテーブルの作成・アクセスをするモジュール
5 2013/12/19 written by kei9
6 """
7
8 import sqlite3
9 import csv
10
11 import skilltable
12 import amulettable
13
14 # for minmax table
15 MASTER_NAME = u"skill_minmax_master"
16 NAME = u"skill_minmax_{amulet_id}"
17 COL_AMULET_ID = u"amulet_id"
18 COL_SKILL_TABLE_NAME = u"skill_table_name"
19 COL_MIN1 = u"min1"
20 COL_MIN2 = u"min2"
21 COL_MAX1 = u"max1"
22 COL_MAX2 = u"max2"
23 COL_SKILL_ID = u"skill_id"
24 CREATE_MASTER_SQL = u"""create table if not exists {master}
25     (id integer primary key, {amulet_id} integer, {table_name} varchar,
26     foreign key(amulet_id) references {amulet_table}(id));""".format(
27         master=MASTER_NAME,
28         amulet_id=COL_AMULET_ID,
29         amulet_table=amulettable.NAME,
30         table_name=COL_SKILL_TABLE_NAME)
31 CREATE_SQL = u"""create table if not exists {{table_name}} 
32     (id integer primary key, {skill_id} integer,
33     {min1} integer, {max1} integer, {min2} integer, {max2} integer, 
34     foreign key(skill_id) references {skill_table}({skill_id_col}));""".format(
35         skill_id=COL_SKILL_ID,
36         min1=COL_MIN1, min2=COL_MIN2,
37         max1=COL_MAX1, max2=COL_MAX2,
38         skill_table=skilltable.NAME,
39         skill_id_col=skilltable.COL_SKILL_ID)
40 INSERT_MASTER_SQL = u"""insert into {master}
41     ({amulet_id}, {table_col}) values(?,?);""".format(
42         master=MASTER_NAME,
43         table_col=COL_SKILL_TABLE_NAME,
44         amulet_id=COL_AMULET_ID)
45 INSERT_SQL = u"""insert into {{table_name}}
46     ({skill_id}, {min1}, {max1}, {min2}, {max2}) values(?,?,?,?,?)""".format(
47         skill_id=COL_SKILL_ID,
48         min1=COL_MIN1, min2=COL_MIN2,
49         max1=COL_MAX1, max2=COL_MAX2)
50 SELECT_MASTER_ALL_SQL = u"""select {amu_id}, {table_col} from {table}""".format(
51         amu_id=COL_AMULET_ID,
52         table_col=COL_SKILL_TABLE_NAME,
53         table=MASTER_NAME)
54 SELECT_ALL_SQL = u"""select {skill_id}, {min1}, {max1}, {min2}, {max2} from {{table_name}} """.format(
55         skill_id=COL_SKILL_ID,
56         min1=COL_MIN1, max1=COL_MAX1,
57         min2=COL_MIN2, max2=COL_MAX2)
58 SELECT_NON_ZERO_SKILL1_ID_SQL = u"""select {skill_id} from {{table_name}} 
59     where {min1} != 0 and {max1} != 0""".format(
60         skill_id=COL_SKILL_ID,
61         min1=COL_MIN1, max1=COL_MAX1)
62 SELECT_NON_ZERO_SKILL2_ID_SQL = u"""select {skill_id} from {{table_name}} 
63     where {min2} != 0 and {max2} != 0""".format(
64         skill_id=COL_SKILL_ID,
65         min2=COL_MIN2, max2=COL_MAX2)
66 SELECT_MIN1_SQL = u"""select min({col}) from {{table_name}} """.format(
67         col=COL_MIN1)
68 SELECT_MAX1_SQL = u"""select max({col}) from {{table_name}} """.format(
69         col=COL_MAX1)
70 SELECT_MIN2_SQL = u"""select min({col}) from {{table_name}} """.format(
71         col=COL_MIN2)
72 SELECT_MAX2_SQL = u"""select max({col}) from {{table_name}} """.format(
73         col=COL_MAX2)
74 SELECT_MAX1_OF_SKILL_SQL = u"""select max({col}) from {{table_name}} 
75     where skill_id={{skill_id}}""".format(
76         col=COL_MAX1)
77 SELECT_MAX2_OF_SKILL_SQL = u"""select max({col}) from {{table_name}} 
78     where skill_id={{skill_id}}""".format(
79         col=COL_MAX2)
80
81 class SkillMinMaxTableGenerator(object):
82     u"""お守りID、スキルIDから取りうるスキルの最大値への組み合わせテーブルの作成クラス"""
83     def __init__(self):
84         u""" コンストラクタ """
85         self._amulet_id2skill1_filename_dict = {}
86         self._amulet_id2skill2_filename_dict = {}
87
88     def insert_master_data(self, db_cursor, csv_reader):
89         u""" マスターテーブルを作成する。
90         """
91         db_cursor.execute(CREATE_MASTER_SQL)
92         accessor = amulettable.AmuletTableAccessor(db_cursor)
93         amu_id2name, amu_name2id = accessor.get_dict()
94
95         csv_reader.next()   # skip header row
96         for row in csv_reader:
97             amulet_name = row[0].strip()
98             skill1_file, skill2_file = row[1].strip(), row[2].strip()
99             amulet_id = amu_name2id[amulet_name]
100             table_name = NAME.format(amulet_id=amulet_id)
101             self._amulet_id2skill1_filename_dict[amulet_id] = skill1_file
102             self._amulet_id2skill2_filename_dict[amulet_id] = skill2_file
103             db_cursor.execute(INSERT_MASTER_SQL, (amulet_id, table_name))
104
105     def get_skill_filenames(self):
106         u""" スキル1, スキル2の最大最小が記載されたファイル名をお守りIDに関連付けて返す
107         return {amulet_id:(skill1_filename, skill2_filename)}"""
108         result_dict = {}
109         for amu_id in self._amulet_id2skill1_filename_dict.keys():
110             result_dict[amu_id] = (self._amulet_id2skill1_filename_dict[amu_id],
111                     self._amulet_id2skill2_filename_dict[amu_id])
112         return result_dict
113
114     def insert_data(self, db_cursor, amulet_id2csv_readers_dict):
115         u""" お守りIDと関連付けられたcsv_reader(skill1,skill2)からデータを読み込み、
116         db_cursorへデータを挿入する。
117         ammulet_id2csv_readers_dict:{amulet_id:(csv_reader_skill1, csv_reader_skill2)}"""
118         accessor = skilltable.SkillTableAccessor(db_cursor)
119         skill_id2name, skill_name2id = accessor.get_dict()
120
121         for amulet_id in amulet_id2csv_readers_dict.keys():
122             table_name = NAME.format(amulet_id=amulet_id)
123             db_cursor.execute(CREATE_SQL.format(table_name=table_name))
124             skill1_reader, skill2_reader = amulet_id2csv_readers_dict[amulet_id]
125             insert_values = {}
126
127             skill1_reader.next()   # skip header row
128             for row in skill1_reader:  # (skill_name, min1, max1)
129                 skill_name = row[0].strip()
130                 min1, max1 = int(row[1].strip()), int(row[2].strip())
131                 skill_id = skill_name2id[skill_name]
132                 insert_values[skill_id] = (skill_id, min1, max1, 0, 0)
133
134             if skill2_reader is not None:
135                 skill2_reader.next()   # skip header row
136                 for row in skill2_reader:  # (skill_name, min2, max2)
137                     skill_name = row[0].strip()
138                     min2, max2 = int(row[1].strip()), int(row[2].strip())
139                     skill_id = skill_name2id[skill_name]
140                     if skill_id in insert_values:
141                         val = insert_values[skill_id]
142                         insert_values[skill_id] = (skill_id, val[1], val[2], min2, max2)
143                     else:
144                         insert_values[skill_id] = (skill_id, 0, 0, min2, max2)
145             sql = INSERT_SQL.format(table_name=table_name)
146             for skill_id, values in insert_values.items():
147                 db_cursor.execute(sql, values)
148
149 class SkillMinMaxTableAccessor(object):
150     u""" お守りID、スキルIDから取りうるスキルの最大値への組み合わせテーブルのアクセスクラス"""
151     def __init__(self, db_cursor):
152         u""" db_cursor: cursor of sqlite3 database """
153         self._cursor = db_cursor
154         accessor = amulettable.AmuletTableAccessor(db_cursor)
155         self._amu_id2name, self._amu_name2id = accessor.get_dict()
156
157         accessor = skilltable.SkillTableAccessor(db_cursor)
158         self._skill_id2name, self._skill_name2id = accessor.get_dict()
159         self._amu_id2table_name = {}
160
161         self._cursor.execute(SELECT_MASTER_ALL_SQL)
162         for row in self._cursor.fetchall():
163             amu_id, table_name = row
164             self._amu_id2table_name[amu_id] = table_name
165
166     def get_minmax_by_amulet(self, amulet_id):
167         u""" 指定されたお守りIDにおけるスキルIDと最大値、最小値の組み合わせを返す
168         return {skill1_id:(min1,max1)}, {skill2_id;(min2,max2)}"""
169         skill1_dict, skill2_dict = {}, {}
170         if amulet_id in self._amu_id2table_name:
171             table_name = self._amu_id2table_name[amulet_id]
172             #get non zero skill1_ids
173             sql = SELECT_NON_ZERO_SKILL1_ID_SQL.format(table_name=table_name)
174             self._cursor.execute(sql)
175             skill1_ids = [row[0] for row in self._cursor.fetchall()]
176
177             #get non zero skill2_ids
178             sql = SELECT_NON_ZERO_SKILL2_ID_SQL.format(table_name=table_name)
179             self._cursor.execute(sql)
180             skill2_ids = [row[0] for row in self._cursor.fetchall()]
181
182             self._cursor.execute(SELECT_ALL_SQL.format(table_name=table_name))
183             for (skill_id, min1, max1, min2, max2) in self._cursor.fetchall():
184                 if skill_id in skill1_ids:
185                     skill1_dict[skill_id] = (min1, max1)
186                 if skill_id in skill2_ids:
187                     skill2_dict[skill_id] = (min2, max2)
188
189         return (skill1_dict, skill2_dict)
190
191     def get_minmax_by_id(self):
192         u""" お守りIDごとのスキルIDと最大値、最小値の組み合わせを辞書として返す
193         return {amulet_id:({skill1_id:(min1,max1)}, {skill2_id;(min2,max2)})}"""
194         result_dict = {}
195         for amu_id in self._amu_id2name.keys():
196             result_dict[amu_id] = self.get_minmax_by_amulet(amu_id)
197         return result_dict
198
199     def get_minmax_by_name(self):
200         u""" お守り名ごとのスキルIDと最大値、最小値の組み合わせを辞書として返す
201         return {amulet_name:({skill1_name:(min1,max1)}, {skill2_name;(min2,max2)})}"""
202         result_dict = {}
203         for amu_id in self._amu_id2name.keys():
204             id_dict1, id_dict2 = self.get_minmax_by_amulet(amu_id)
205             name_dict1, name_dict2 = {}, {}
206             for skill_id, vals in id_dict1.items():
207                 name_dict1[self._skill_id2name[skill_id]] = vals
208             for skill_id, vals in id_dict2.items():
209                 name_dict2[self._skill_id2name[skill_id]] = vals
210             result_dict[self._amu_id2name[amu_id]] = (name_dict1, name_dict2)
211         return result_dict