2 # -*- coding: utf-8 -*-
4 # お守りスキルのSeed特定ツールのコントロールクラス
5 # 2013/12/04 written by kei9
20 SETTING_FILE = u"settings"
21 SETTING_THRESHOLD1 = u"threshold1"
22 SETTING_THRESHOLD2 = u"threshold2"
23 SETTING_SKILLS = u"skills"
26 u""" for pyinstaller 2.1 """
27 if getattr(sys, 'frozen', False):
28 # we are running in a |PyInstaller| bundle
29 basedir = sys._MEIPASS
31 # we are running in a normal Python environment
32 #1basedir = os.path.dirname(__file__)
33 basedir = os.path.dirname(os.path.abspath(__file__))
34 return convertcoding.convert_unicode(basedir)
37 class AmuletToolController(wx.App):
38 u""" アプリケーションの制御クラス """
41 self.frame_view = view.MainFrameView(os.path.join(_get_base_dir(), u"view", view.XRC_MAIN_FRAME))
45 self.frame_view.Show()
47 self.frame_view.DisableNoteBook()
50 self._init_notebook_seed1()
51 self._init_notebook_seed2()
52 self._init_notebook_skill1()
53 self._init_notebook_skill2()
54 self._init_notebook_setting()
55 self._init_notebook_simulator()
56 self._init_notebook_amulet()
58 self.frame_view.EnableNoteBook()
61 def _init_events(self):
63 frame = self.frame_view.frame
66 frame.Bind(wx.EVT_MENU, self.OnClose, id=self.frame_view.ID_MENU_ITEM_EXIT)
67 frame.Bind(wx.EVT_MENU, self.OnAboutBox, id=self.frame_view.ID_MENU_ITEM_ABOUT)
68 frame.Bind(wx.EVT_MENU, self.OnMemoBox, id=self.frame_view.ID_MENU_MEMO)
69 frame.Bind(wx.EVT_CLOSE, self.CloseHandler)
73 def _init_database(self):
76 if not os.path.exists(model.DB_FILE_NAME):
77 u""" DBが存在しない時は再生成する """
78 frame = self.frame_view.frame
80 generator = model.DataBaseGenerator(model.DB_FILE_NAME)
81 #generator = model.DataBaseGenerator()
83 dlg_view = view.GaugeDialogView(os.path.join(_get_base_dir(), u"view", view.XRC_GAUGE_DIALOG))
86 dlg_view.gauge.Pulse()
88 dlg_view.finish_generation()
90 t1 = threading.Thread(target=generator.generate_db)
91 t2 = threading.Thread(target=_loop)
99 except sqlite3.Error as e:
100 self._show_error_dialog(u"データベース生成中にエラーが発生しました")
104 self.db_accessor = model.DataBaseAccessor(model.DB_FILE_NAME)
105 except sqlite3.Error as e:
106 self._show_error_dialog(u"データベースが壊れています")
108 self._minmax_dict = self.db_accessor.get_minmax_dict()
109 self._amulet_names = self.db_accessor.get_id_sorted_amulet_names()
110 self._skill_names = self.db_accessor.get_id_sorted_skill_names()
112 def _init_notebook_seed1(self):
113 u""" Seed1特定タブのviewの初期化 """
114 self.notebook_seed1_view = self.frame_view.notebook_seed1_view
115 self.notebook_seed1_view.bind_button_search(self.OnClickSeed1Search)
116 self.notebook_seed1_view.bind_button_clear(self.OnClickSeed1Clear)
117 self.notebook_seed1_view.bind_button_skill1(self.OnClickSkill1SearchFromSeed1)
118 self.notebook_seed1_view.set_skill1_button_enable(False)
120 u" 各種お守りの第1スキル選択のセット "
122 for name in self._amulet_names:
123 name2skill1s[name] = tuple([x for x in self._skill_names if x in self._minmax_dict[name][0]])
124 self.notebook_seed1_view.set_amuletname_skillnames_dict(self._amulet_names, name2skill1s)
126 def _init_notebook_seed2(self):
127 u""" Seed2特定タブのviewの初期化 """
128 self.notebook_seed2_view = self.frame_view.notebook_seed2_view
129 self.notebook_seed2_view.bind_button_search(self.OnClickSeed2Search)
130 self.notebook_seed2_view.bind_button_clear(self.OnClickSeed2Clear)
131 self.notebook_seed2_view.bind_button_skill2(self.OnClickSkill2SearchFromSeed2)
134 for amu_key, amu_name in zip([view.KEY_AMULET1, view.KEY_AMULET2, view.KEY_AMULET3],
135 [view.NAME_AMULET1, view.NAME_AMULET2, view.NAME_AMULET3]):
136 skill_names = [view.VAL_NO_SKILL] + [x for x in self._skill_names
137 if x in self._minmax_dict[amu_name][1]]
138 self.notebook_seed2_view.set_skill_names(amu_key, skill_names)
139 self.notebook_seed2_view.set_skill_selected_idx(0)
141 def _init_notebook_skill2(self):
142 u""" Seed2によるSkill2一覧タブのviewの初期化 """
143 self.notebook_skill2_view = self.frame_view.notebook_skill2_view
144 self.notebook_skill2_view.bind_button_search(self.OnClickSkill2Search)
145 self.notebook_skill2_view.bind_button_clear(self.OnClickSkill2Clear)
147 def _init_notebook_skill1(self):
148 u""" Seed1によるSkill1一覧タブのviewの初期化 """
149 self.notebook_skill1_view = self.frame_view.notebook_skill1_view
150 self.notebook_skill1_view.bind_button_search(self.OnClickSkill1Search)
151 self.notebook_skill1_view.bind_button_clear(self.OnClickSkill1Clear)
153 def _init_notebook_simulator(self):
154 u""" Seed1,Seed2による錬金シミュレータータブのviewの初期化 """
155 self.notebook_simulator_view = self.frame_view.notebook_simulator_view
156 self.notebook_simulator_view.bind_button_search(self.OnClickSimulatorSearch)
157 self.notebook_simulator_view.bind_button_clear(self.OnClickSimulatorClear)
159 def _update_notebook_amulet_seed2s(self):
160 u"""お守り検索タブのSeed2リストを更新する"""
163 def _init_notebook_amulet(self):
164 u""" お守り検索タブの初期設定 """
165 self.notebook_amulet_view = self.frame_view.notebook_amulet_view
166 self.notebook_amulet_view.set_skillminmax_dict(self._skill_names, self._amulet_names, self._minmax_dict)
167 self.notebook_amulet_view.bind_button_search(self.OnClickAmuletSearch)
168 self.notebook_amulet_view.bind_button_clear(self.OnClickAmuletClear)
169 self.notebook_amulet_view.bind_button_skill2(self.OnClickSkill2SearchFromAmulet)
171 self.notebook_amulet_view.set_selected_amulet(True, view.NAME_AMULET1)
173 def _init_notebook_setting(self):
175 self.notebook_setting_view = self.frame_view.notebook_setting_view
176 self.notebook_setting_view.bind_button_ok(self.OnClickSettingOK)
177 self.notebook_setting_view.bind_button_clear(self.OnClickSettingClear)
178 self.notebook_setting_view.set_skill_strings(self._skill_names)
179 self._update_notebook_setting()
181 def _update_notebook_setting(self):
183 self.notebook_setting_view.set_threshold(self._highlight_threshold1,
184 self._highlight_threshold2)
185 self.notebook_setting_view.set_checked_strings(self._highlight_skills)
187 def _update_highlight(self):
188 u""" update highlight cells """
189 self.notebook_skill2_view.set_skill2_highlight(
190 self._highlight_skills, self._highlight_threshold1, self._highlight_threshold2)
191 self.notebook_skill1_view.update_highlight(self._highlight_skills)
193 u""" Seed1 view's event"""
194 def OnClickSeed1Search(self, evt):
195 u""" search seed1s from selected skill1s """
196 alchemy_type = self.notebook_seed1_view.get_tenun_radio_key()
197 amu_skill_name_list = self.notebook_seed1_view.get_selected_amulets_and_names()
198 if alchemy_type == view.KEY_TENUN555:
199 alchemy_type = model.KEY_TENUN555
200 elif alchemy_type == view.KEY_TENUN888:
201 alchemy_type = model.KEY_TENUN888
203 raise KeyError(u"key '{0}' not found in alchemy type".format(alchemy_type))
204 seed1s = self.db_accessor.select_seed1s(amu_skill_name_list, alchemy_type)
206 self.notebook_seed1_view.set_text_result(u"条件に一致するSeed1は見つかりません")
207 self.notebook_seed1_view.set_skill1_button_enable(False)
208 elif len(seed1s) == 1:
209 seed1 = [x for x in seed1s][0]
210 no, table_no, result_num = self.db_accessor.select_table_nos_from_seed1(seed1, alchemy_type)
211 self.notebook_seed1_view.set_text_result_by_seed1(seed1, table_no, no)
212 self.notebook_seed1_view.set_skill1_button_enable(True)
214 self.notebook_seed1_view.set_text_result(
215 u"Seed1は{0}件あります。条件を絞ってください".format(len(seed1s)))
216 self.notebook_seed1_view.set_skill1_button_enable(False)
218 def OnClickSeed1Clear(self, evt):
219 u""" clear seed1s from selected skill1s """
220 self.notebook_seed1_view.clear_combobox()
221 self.notebook_seed1_view.clear_text_result()
223 def OnClickSkill1SearchFromSeed1(self, evt):
224 u""" change page to skill1 search from seed1"""
225 seed1 = self.notebook_seed1_view.get_result_seed1()
226 alchemy_type = self.notebook_seed1_view.get_tenun_radio_key()
227 if seed1 is not None:
228 self.notebook_skill1_view.set_seed1_value(seed1)
229 self.notebook_skill1_view.set_tenun_radio_key(alchemy_type)
230 self.frame_view.note_book.SetSelection(view.SKILL1_SEARCH_PAGE)
231 self.OnClickSkill1Search(evt)
233 u""" Seed2 view's event """
234 def OnClickSeed2Search(self, evt):
235 u""" search seed2s from selected skill2s """
237 for amu_key, amu_name in zip([view.KEY_AMULET1, view.KEY_AMULET2, view.KEY_AMULET3],
238 [view.NAME_AMULET1, view.NAME_AMULET2, view.NAME_AMULET3]):
239 names = self.notebook_seed2_view.get_selected_skill_names(amu_key)
240 amu2skills_dict[amu_name] = [name if name in self._skill_names else None for name in names]
241 seed_sets = self.db_accessor.select_seed2s(amu2skills_dict)
242 self.notebook_seed2_view.set_result_text(u"""Seedの候補は{0}個です。""".format(len(seed_sets)))
244 if len(seed_sets) > 0:
245 self.notebook_seed2_view.set_seed_lists([u"{0}".format(seed) for seed in sorted(seed_sets)])
246 self.notebook_seed2_view.set_skill2_button_enable(True)
248 self.notebook_seed2_view.clear_seed_list()
249 self.notebook_seed2_view.set_skill2_button_enable(False)
251 def OnClickSeed2Clear(self, evt):
252 u""" reset seed2 search settings of combo box"""
253 self.notebook_seed2_view.set_skill_selected_idx(0)
254 self.notebook_seed2_view.clear_seed_list()
255 self.notebook_seed2_view.set_result_text(u"")
256 self.notebook_seed2_view.set_skill2_button_enable(False)
258 def OnClickSkill2SearchFromSeed2(self, evt):
259 u""" change page to skill2 search from seed2"""
260 seed2 = self.notebook_seed2_view.get_selected_seed2()
261 if seed2 is not None:
262 self.notebook_skill2_view.set_seed2_value(seed2)
263 self.frame_view.note_book.SetSelection(view.SKILL2_SEARCH_PAGE)
264 self.OnClickSkill2Search(evt)
266 u""" Skill1 search from Seed1's event """
267 def OnClickSkill1Search(self, evt):
268 u""" skill1 search from seed1"""
269 seed1 = self.notebook_skill1_view.get_seed1_value()
270 alchemy_type = self.notebook_skill1_view.get_tenun_radio_key()
271 if seed1 is not None:
273 no, table_no, result_num = self.db_accessor.select_table_nos_from_seed1(seed1, alchemy_type)
274 self.notebook_skill1_view.set_text_result_by_seed1(seed1, table_no, no)
275 # list of (no, seed1)
276 near_num = view.NEAR_SEED1_NUMBERS
277 no_seed1_dict = self.db_accessor.select_near_seed1s_from_table_no(
278 no, table_no, near_num, near_num, alchemy_type)
280 # no -> (seed1, result_num, amu_names, skill_names)
281 self.notebook_skill1_view.set_no2seed1s_dict(no_seed1_dict, no)
282 self.notebook_skill1_view.update_highlight(self._highlight_skills)
284 self._show_message_dialog(message=u"指定されたSeed値は存在しません")
286 self._show_message_dialog(message=u"Seed値には数字を入力してください")
288 def OnClickSkill1Clear(self, evt):
289 u""" clear skills from seed """
290 self.notebook_skill1_view.clear_skill1_grid()
291 self.notebook_skill1_view.clear_highlight()
292 self.notebook_skill1_view.clear_result_text()
294 u""" Skill2 search from Seed2's event """
295 def OnClickSkill2Search(self, evt):
296 u""" skill search from seed2"""
297 seed2 = self.notebook_skill2_view.get_seed2_value()
298 if seed2 is not None:
299 table_no, no, skill_dict, th1s, th2s = self.db_accessor.select_names_from_seed2(seed2)
301 for amu_key, amu_name in zip([view.KEY_AMULET1, view.KEY_AMULET2, view.KEY_AMULET3],
302 [view.NAME_AMULET1, view.NAME_AMULET2, view.NAME_AMULET3]):
303 skill_names = skill_dict[amu_name]
304 self.notebook_skill2_view.set_skill2_by_col_key(amu_key, skill_names)
305 th_vals = [u"{0}".format(x) for x in th1s]
306 self.notebook_skill2_view.set_skill2_by_col_key(view.KEY_THRESHOLD1, th_vals)
307 th_vals = [u"{0}".format(x) for x in th2s]
308 self.notebook_skill2_view.set_skill2_by_col_key(view.KEY_THRESHOLD2, th_vals)
310 skill_name, th1, th2 = self.db_accessor.select_inishie_skill2_from_seed2(seed2)
311 self.notebook_skill2_view.set_inishie(skill_name, th1, th2)
313 self.notebook_skill2_view.set_result_text(
314 u"SEED2: {2}, 通し番号: {1}, テーブルNo: {0}".format(table_no, no, seed2))
316 self._show_message_dialog(message=u"指定されたSeed値は存在しません")
318 self._update_highlight()
321 self._show_message_dialog(message=u"Seed値には数字を入力してください")
323 def OnClickSkill2Clear(self, evt):
324 u""" clear skills from seed """
325 self.notebook_skill2_view.clear_skill2_grid()
326 self.notebook_skill2_view.clear_skill2_highlight()
327 self.notebook_skill2_view.clear_result_text()
328 self.notebook_skill2_view.clear_inishie()
330 u""" Alchemy Simulator's event """
331 def OnClickSimulatorSearch(self, evt):
332 u""" alchemy simulation from seed1, seed2"""
333 seeds = self.notebook_simulator_view.get_seed_values()
334 alchemy_type = self.notebook_simulator_view.get_tenun_radio_key()
335 if seeds is not None:
338 result = self.db_accessor.simulate_nazo(seed1, seed2)
339 self.notebook_simulator_view.set_values(view.KEY_NAZO, *result)
340 result = self.db_accessor.simulate_komyou(seed1, seed2)
341 self.notebook_simulator_view.set_values(view.KEY_KOMYOU, *result)
342 result = self.db_accessor.simulate_inishie(seed1, seed2)
343 self.notebook_simulator_view.set_values(view.KEY_INISHIE, *result)
344 result = self.db_accessor.simulate_tenun(seed1, seed2, alchemy_type)
345 self.notebook_simulator_view.set_tenun_values(result)
347 # self._show_message_dialog(message=u"指定されたSeed値は存在しません")
349 self.notebook_simulator_view.update_highlight(self._highlight_skills)
351 self._show_message_dialog(message=u"Seed値には数字を入力してください")
353 def OnClickSimulatorClear(self, evt):
354 u""" clear simulator form """
355 self.notebook_simulator_view.clear_seed_values()
356 self.notebook_simulator_view.clear_grid()
357 self.notebook_simulator_view.clear_highlight()
359 u""" amulet search event """
360 def OnClickAmuletSearch(self, evt):
361 u""" search seeds from amulet condition """
362 search_type = self.notebook_amulet_view.get_selected_search_type()
363 if search_type == view.SEARCH_TYPE_SEED2:
364 skill1_name, skill2_name = self.notebook_amulet_view.get_skill_names()
365 skill1_val, skill2_val = self.notebook_amulet_view.get_skill_values()
366 slot_num = self.notebook_amulet_view.get_slot_value()
367 amulet_name = self.notebook_amulet_view.get_selected_amulet()
368 suff_val, threshold, th1_seed2s, th2_seed2s = self.db_accessor.simple_select_seed2s_from_names(
369 amulet_name, skill1_name, skill1_val, skill2_name, skill2_val, slot_num)
370 self.notebook_amulet_view.set_result_only_seed2(suff_val, threshold, th1_seed2s, th2_seed2s)
371 elif search_type == view.SEARCH_TYPE_SEED1_SEED2:
373 elif search_type == view.SEARCH_TYPE_FIXED_SEED2:
376 def OnClickAmuletClear(self, evt):
377 u""" clear amulet conditions """
378 self.notebook_amulet_view.clear_grid()
379 self.notebook_amulet_view.clear_input_values()
381 def OnClickSkill2SearchFromAmulet(self, evt):
382 u""" change page to skill search from amulet"""
383 seed = self.notebook_amulet_view.get_grid_selected_seed2()
385 self.notebook_skill2_view.set_seed2_value(seed)
386 self.frame_view.note_book.SetSelection(view.SKILL_SEARCH_PAGE)
387 self.OnClickSkillSearch(evt)
389 u""" settings' event """
390 def OnClickSettingOK(self, evt):
391 u""" get settings of setting tab """
392 (self._highlight_threshold1,
393 self._highlight_threshold2) = self.frame_view.notebook_setting_view.get_threshold()
394 self._highlight_skills = set([x for x in self.frame_view.notebook_setting_view.get_checked_strings()
395 if x in self._skill_names])
396 self._update_highlight()
398 def OnClickSettingClear(self, evt):
399 u""" reset settings of setting tab """
400 self._highlight_threshold1 = view.HIGHLIGHT_THRESHOLD1
401 self._highlight_threshold2 = view.HIGHLIGHT_THRESHOLD2
402 self._highlight_skills = set()
403 self._update_notebook_setting()
404 self._update_highlight()
406 def _show_error_dialog(self, message=u"予期せぬエラーが発生しました", caption=u"エラー"):
408 OKボタンが押されたらアプリケーションを終了する
410 dlg = wx.MessageDialog(self.frame_view.frame,
412 caption, wx.OK | wx.ICON_ERROR)
417 def _show_message_dialog(self, message, caption=u"メッセージ"):
420 dlg = wx.MessageDialog(self.frame_view.frame,
422 caption, wx.OK | wx.ICON_INFORMATION)
426 def CloseHandler(self, evt):
427 dlg = wx.MessageDialog(parent = self.frame_view.frame,
428 message = u"終了します。よろしいですか?",
431 result = dlg.ShowModal()
433 if result == wx.ID_YES:
434 self._write_settings()
437 def OnClose(self, evt):
438 self.frame_view.Close()
440 def OnAboutBox(self, evt):
441 info = self.frame_view.GetAboutInfo()
444 def OnMemoBox(self, evt):
445 dlg_view = view.MemoDialogView(os.path.join(_get_base_dir(), u"view", view.XRC_MEMO_DIALOG))
448 def _write_settings(self):
449 with open(SETTING_FILE, mode="w") as f:
450 data = {SETTING_THRESHOLD1:self._highlight_threshold1,
451 SETTING_THRESHOLD2:self._highlight_threshold2,
452 SETTING_SKILLS:self._highlight_skills}
455 def _read_settings(self):
456 if os.path.exists(SETTING_FILE):
457 with open(SETTING_FILE, mode="r") as f:
459 data = pickle.load(f)
460 self._highlight_threshold1 = data[SETTING_THRESHOLD1]
461 self._highlight_threshold2 = data[SETTING_THRESHOLD2]
462 self._highlight_skills = data[SETTING_SKILLS]
464 self._highlight_threshold1 = view.HIGHLIGHT_THRESHOLD1
465 self._highlight_threshold2 = view.HIGHLIGHT_THRESHOLD2
466 self._highlight_skills = set()
468 self._highlight_threshold1 = view.HIGHLIGHT_THRESHOLD1
469 self._highlight_threshold2 = view.HIGHLIGHT_THRESHOLD2
470 self._highlight_skills = set()
472 if __name__ == "__main__":
473 app = AmuletToolController(False)