def init_bbs_country(_cls, _self, data): payload = {"event": "init_bbs_country"} data = [] #DBから会議室の内容を集める try: user_id = _self.get_secure_cookie("user_id").decode('utf-8') db = DBSingleton() country = db.select("country_id", table="user", where="user_id=" + "\"" + str(user_id) + "\"") country = country[0]["country_id"] query = "select user.user_name, user.icon_id, bbs_country.date, bbs_country.article from user " \ "inner join bbs_country "\ "on user.user_id=bbs_country.user_id "\ "where bbs_country.country_id = " + str(country) + \ " order by bbs_country.date desc limit 20;" result = db.exec(query, True) for article in result: data.append({ "name": article[0], "icon": article[1], "date": article[2].strftime("%Y-%m-%d %H:%M:%S"), "article": article[3] }) except DBError as e: logging.error(u"init_bbs_country.py: 会議室の情報取得失敗。\nmessage = " + str(e)) raise Exception("会議室の情報取得失敗") #送信するデータ組み立て payload["data"] = data _self.send_you(payload)
def get_unvisible_area(visibility, timestamp=None): """ 可視権から不可視範囲のグリッドを取得 :param visibility: :param [timestamp]: オプション。この時刻オブジェクト以降に変更されたグリッドのみ取得する :return: list[dict[col, row, type]] """ result = None try: # 可視権による条件 where = str(visibility) + " = 0" # タイムスタンプによる条件 if timestamp is not None: datetime = BJTime.encode_to_sql(timestamp) where += " and timestamp >= \"" + datetime + "\"" db = DBSingleton() result = db.select("col", "row", "type", table="hex_grid", where=where) except DBError as e: logging.error(e.message) raise Exception("DBエラー : visibilityが" + str(visibility) + u"の不可視範囲のグリッド取得失敗") return return result
def update_hex(col, row, **kargs): """ ヘックスのレコードを更新 :param col: 該当ヘックスcol :param row: 該当ヘックスrow :param kargs: {key : value, ...} :return: 成功 ? True : False """ try: db = DBSingleton() sentence = "update hex_grid set" for key, value in kargs.items(): sentence = sentence + " " + str(key) + " = \"" + str(value) + "\"" sentence += " where col = " + str(col) + " and row = " + str(row) db.exec(sentence) return True except DBError as e: logging.error(e.message, detailed_error.get_error()) return False
def get_own_area(country_id, timestamp=None): """ 領地を取得 :param country_id: :return: 成功 ? area : None """ try: db = DBSingleton() where = "country_id = " + str(country_id) # タイムスタンプによる条件 if timestamp is not None: datetime = BJTime.encode_to_sql(timestamp) where += " and timestamp >= \"" + datetime + "\"" result = db.select("col", "row", "type", "country_id", "food", "money", table="hex_grid", where=where) if len(result) == 0: return None else: return result except DBError as e: logging.error(e.message, detailed_error.get_error()) return None
def get_division_info_by_colrow(col, row): try: db = DBSingleton() result = db.select( "division_id", # 部隊ID "division_name", # 部隊名 "col", # 座標 "row", # 座標 "branch_id", # 兵科ID "user_id", # 所有ユーザー "country_id", # 所属国 "status", # 状態 "food", # 食糧 "money", # 資金 "level", # 練度 "quantity", # 規模 table="division", where="col=" + str(col) + " and row=" + str(row)) except DBError as e: logging.error(e.message) raise Exception("部隊の情報取得に失敗") return False if len(result) == 0: return False return result[0]
def get_hexinfo(col, row): """ :param col: hex_gridのcol :param row: hex_gridのrow :return: """ try: db = DBSingleton() result = db.select("col", "row", "type", "country_id", "food", "money", "visibility_0", "visibility_1", table="hex_grid", where="col=" + str(col) + " and row = " + str(row)) if len(result) == 0: return None else: return result[0] except DBError as e: logging.error(e.message, detailed_error.get_error()) return None except Exception as e: logging.error(e, detailed_error.get_error()) return None
def get_division_info(division_id): """ 部隊の情報を取得する DBエラーの時はDBErrorをスローする :param division_id: 部隊ID :return: 該当するIDの部隊 ? {divisionテーブルの全てのkey} : false """ try: db = DBSingleton() result = db.select( "division_id", # 部隊ID "division_name", # 部隊名 "col", # 座標 "row", # 座標 "branch_id", # 兵科ID "user_id", # 所有ユーザー "country_id", # 所属国 "status", # 状態 "food", # 食糧 "money", # 資金 "level", # 練度 "quantity", # 規模 table="division", where="division_id = \"" + str(division_id) + "\"") except DBError as e: logging.error(e.message) raise Exception("部隊の情報取得に失敗") return False if len(result) == 0: return False return result[0]
def get_userid_by_username(user_name): """ ユーザー名からユーザーIDを取得 該当のユーザー :param user_name: :return: ユーザーID """ result = None try: db = DBSingleton() result = db.select("user_id", table="user", where="user_name = \"" + str(user_name) + "\"") except DBError as e: logging.error(e.message) raise Exception("DBエラー:ユーザー名取得失敗") return False if len(result) == 0: logging.error("There's no such a player in DB: user_name = " + str(user_name)) raise Exception(u"user_nameが" + str(user_name) + u"のプレイヤーは存在しない") return False return result[0]["user_id"]
def update_bbs_country(_cls, _self, data): payload = { "event" : "update_bbs_country"} send_data = None country = None try: #DBから最新の会議室への書き込みを取得 user_id = _self.get_secure_cookie("user_id").decode('utf-8') db = DBSingleton() country = db.select("country_id", table="user", where="user_id=" + "\""+str(user_id) + "\"") country = country[0]["country_id"] query = "select user.user_name, user.icon_id, bbs_country.date, bbs_country.article from user " \ "inner join bbs_country "\ "on user.user_id=bbs_country.user_id "\ "where bbs_country.country_id = " + str(country) + \ " order by bbs_country.date desc limit 1;" result = db.exec(query, True) send_data= {"name" : result[0][0], "icon" : result[0][1], "date" : result[0][2].strftime("%Y-%m-%d %H:%M:%S"), "article" : result[0][3]} except DBError as e: logging.error(u"init_bbs_country.py: 会議室の情報取得失敗。\nmessage = " + e.message) raise Exception(u"会議室の情報取得失敗") #送信するデータ組み立て payload["data"] = send_data print(payload) _cls.send_member_by_country(payload, country)
def get_movable_area_by_division_id(division_id, col, row): """ 部隊IDから移動可能なエリアを取得 DBエラー、または部隊IDの部隊がなければExceptionをスロー :param division_id: :param col: プレイヤーのcol :param row: プレイヤーのrow :return: [{col, row, time(速度補正)}] """ result = None try: db = DBSingleton() # 部隊の兵科と座標 from lib.DB.division_controller import get_division_info division = get_division_info(division_id) # 兵科の情報 from lib.DB.branch_controller import get_branch_info branch = get_branch_info(division["branch_id"]) # 隣接する座標を計算 adjacent_area = get_adjacent_area(col, row, 1) # エリアの地形取得 where = "" for hex in adjacent_area: where += " (col = " + str(hex["col"]) + " and row = " + str( hex["row"]) + ") or" where = where[:-3] terrian_type = db.select("col", "row", "type", table="hex_grid", where=where) # 兵科速度 * 地形補正から所要時間を計算 result = [] for hex in terrian_type: result.append({ "col": hex["col"], "row": hex["row"], "time": branch["speed"] * branch[hex["type"]] }) except DBError as e: logging.error(e.message) raise Exception("DBエラー") return False except Exception as e: raise e return result
def get_players_by_visibility(visibility, isVisible, hexes=None): """ 可視権から可視範囲上のプレイヤー情報を取得 :param visibility: 可視権 :param isVisible: true ? 可視なプレイヤー : 不可視なプレイヤー :param [hexes]: 指定されたグリッド [ [col, row, ...], ... ] :return: [{user_name, col, row, icon_id, country_id}] """ print("on get_players_by_visibility") logger = logging.getLogger(sys._getframe().f_code.co_name) results = None try: db = DBSingleton() where = "where hex_grid." + visibility if isVisible: where += " > 0 " else: where += " = 0 " # ヘックスが指定されていれば条件追加 print("hexes = ", hexes) if hexes is not None: print(hexes) where += "and (" for hex in hexes: where = where + " (hex_grid.col=" + str( hex["col"]) + " and hex_grid.row=" + str( hex["row"]) + ") or" where = where[:-3] where += ");" query = "select user_name, user.col, user.row, icon_id, user.country_id from user " \ "inner join hex_grid "\ "on user.col=hex_grid.col and user.row=hex_grid.row " \ + where results = db.exec(query, True) except DBError as e: logging.error(" message = " + e.message) return False result = [] for player in results: record = { "user_name": player[0], "col": player[1], "row": player[2], "icon_id": player[3], "country_id": player[4] } result.append(record) return result
def update_visible_area(visibility, division_id, switch): """ 部隊の視界内のヘックスの可視性を変更 :param visibility: 可視権 :param division_id: 部隊ID :param switch: True ? 可算 : 減算 :return: 成功 ? True : False """ try: # 部隊の情報 from lib.DB.division_controller import get_division_info division = get_division_info(division_id) # 兵科の情報 from lib.DB.branch_controller import get_branch_info branch = get_branch_info(division["branch_id"]) # 現在の部隊の視界 visible_area = get_adjacent_area(division["col"], division["row"], branch["visible_range"]) visible_area.append({"col": division["col"], "row": division["row"]}) # 更新 if switch: switch = str("+") else: switch = str("-") where = "where " for hex in visible_area: where = where + "(col=" + str(hex["col"]) + " and row=" + str( hex["row"]) + ") or" where = where[:-3] query = "update hex_grid set " + \ visibility + " = " + visibility + " " + switch + " 1 " + where db = DBSingleton() db.exec(query) print("update p6") except DBError as e: logging.error(e.message, detailed_error.get_error()) return False except Exception as e: logging.error(e, detailed_error.get_error()) return False return True
def update_user_before_move(user_id, wait_untill): """ 移動に伴うユーザー情報の更新 :param user_id: :param wait_untill: 到着予定時刻を表す時刻オブジェクト :param status: 移動中の状態 :return: 更新成功 ? : Exception """ try: db = DBSingleton() query = "update user set" + \ " wait_untill = \"" + BJTime.encode_to_sql(wait_untill)+ "\"" \ " where user_id = \"" + str(user_id) + "\"" result = db.exec(query) except DBError as e: logging.error(e.message) raise Exception("DBエラー : 移動前のユーザー情報更新失敗")
def move_division(division_id, dest_col, dest_row): """ 部隊を移動させる :param division_id: 部隊ID :param dest_col: 目的地col :param dest_row: 目的地row :return: 成功 ? True : False """ try: db = DBSingleton() query = "update division set col=" + dest_col + ", row=" + dest_row where = " where division_id = \"" + division_id + "\"" db.exec(query + where, False) return True except DBError as e: logging.error(e.message) return False
def move_user(user_id, dest_col, dest_row): """ プレイヤーを移動させる :param user_id: ユーザーID :param dest_col: 目的地col :param dest_row: 目的地row :return: 成功 ? True : False """ try: db = DBSingleton() query = "update user set col=" + dest_col + ", row=" + dest_row where = " where user_id = \"" + user_id + "\"" db.exec(query + where, False) return True except DBError as e: logging.error(e.message) return False
def get_adjacent_area(col, row, _range=1): """ あるヘックスからレンジ内の隣接するヘックスを取得 rangeが1より小さい時Exceptionをスロー :param col: :param row: :param range: :return: [ [col, row], ... ] """ if _range < 1: logging.error("_range : " + str(_range) + " must be over 1") raise Exception("レンジの指定は1以上でなければならない。") return False # レンジ内の隣接するヘックス hexes = None where = "" for i in range(1, _range + 1): for j in range(0, _range + 1): where += " (col = " + str(col + j) + " and row = " + str(row - i + j) + ") or" where += " (col = " + str(col + i - j) + " and row = " + str(row + i) + ") or" where += " (col = " + str(col - i) + " and row = " + str(row - j) + ") or" where = where[:-3] # そのうちDBに実在するもの try: db = DBSingleton() hexex = db.select("col", "row", table="hex_grid", where=where) except DBError as e: logging.error(e.message) raise Exception("DBエラー") return False return hexex
def update_division_before_move(division_id, food, money, status="moving"): """ 移動に伴う部隊情報の更新 :param division_id: 部隊ID :param food: 消費物資 :param money: 消費資金 :return: 更新成功 ? True : False """ try: db = DBSingleton() query = "update division set" + \ " food = food - " + str(food) + \ ", money =money-" + str(money) + \ " where division_id = \"" + str(division_id) + "\"" db.exec(query) return True except DBError as e: logging.error(e.message) return False
def update_division(division_id, **kwargs): """ 部隊の情報更新 :param division_id: :param kwargs: :return: 成功 ? True : False """ try: db = DBSingleton() sentence = "update division set " for key, value in kwargs.items(): sentence = sentence + key + " = \"" + str(value) + "\"," sentence = sentence[:-1] sentence + " where division_id = \"" + str(division_id) + "\"" db.exec(sentence) return True except DBError as e: return False
def run(cls): u"""ゲームのメインエンジンを起動する 内部でイベントループを違うスレッドで起動させる""" db = DBSingleton() status = db.select("status", table="game_status") # TODO: 情勢実装 affair = AffairTest() map = MapTest() cls._game_settings = {"affair": affair, "map": map} print("status: ", status) if status[0]["status"] != "ongoing": cls.__start_new_year() # イベントループスレッド起動 loop = threading.Thread(target=cls.loop, daemon=False) loop.start() cls._logger.info("Game system started running")
def update_division_status(division_id, status): """ 部隊のステータスを変更 :param division_id: :param status:新しいステータス :return: 成功 ? True : False """ if len(status) == 0: logging.error(u"statusが空") return False try: db = DBSingleton() query = "update division set" + \ " status = \"" + str(status) + "\"" \ " where division_id = \"" + str(division_id) + "\"" db.exec(query) return True except DBError as e: return False
def get_countryinfo_by_id(country_id): try: db = DBSingleton() result = db.select("country_id", "capital_col", "capital_row", "leader", "country_name", table="country", where="country_id = " + str(country_id)) if len(result) == 0: return None return result[0] except DBError as e: logging.error(e.message) return None
def write_bbs_country(_cls, _self, data): """会議室へ書き込み""" try: #DBへ書き込みを追加 user_id = _self.get_secure_cookie("user_id").decode('utf-8') db = DBSingleton() country = db.select("country_id", table="user", where="user_id=" + "\""+str(user_id) + "\"") country = country[0] data = data.replace("\n", "<br>") db.insert(table="bbs_country", user_id=str(user_id), country_id=str(country["country_id"]), article=str(data)) except DBError as e: logging.error(u"init_bbs_country.write_bbs_country: 会議室への書き込み失敗。\nmessage = " + e.message) raise Exception(u"会議室への書き込み失敗") #更新を通知 update_bbs_country(_cls, _self, {})
def get_playerinfo_by_id(user_id): """ ユーザーIDからプレイヤーの全情報を取得 :param user_id: :return: dict[info_name, ...] """ result = None try: db = DBSingleton() result = db.select( "user_name", "user_pass", "user_id", "col", "row", "country_id", "icon_id", "division_id", # 配下の部隊ID "status", # 現在の状態 table="user", where="user_id = \"" + str(user_id) + "\"") # TODO : 可視権が国番号のみ result[0]["visibility"] = "visibility_" + str(result[0]["country_id"]) except DBError as e: logging.error(e.message) raise Exception(u"DBエラー: ユーザー名取得失敗") if len(result) == 0: logging.error("There's no such a player in DB: user_id = " + str(user_id)) raise Exception(u"user_idが" + str(user_id) + u"のプレイヤーは存在しない") return return result[0]
def get_all_countryinfo(): """ 全ての国の情報を取得 :return: """ try: db = DBSingleton() result = db.select("country_id", "capital_col", "capital_row", "leader", "country_name", table="country") if len(result) == 0: return None return result except DBError as e: logging.error(e.message) return None
user_id = _self.get_secure_cookie("user_id").decode('utf-8') db = DBSingleton() country = db.select("country_id", table="user", where="user_id=" + "\""+str(user_id) + "\"") country = country[0] data = data.replace("\n", "<br>") db.insert(table="bbs_country", user_id=str(user_id), country_id=str(country["country_id"]), article=str(data)) except DBError as e: logging.error(u"init_bbs_country.write_bbs_country: 会議室への書き込み失敗。\nmessage = " + e.message) raise Exception(u"会議室への書き込み失敗") #更新を通知 update_bbs_country(_cls, _self, {}) if __name__ == "__main__": db = DBSingleton() country = 0 query = "select user.user_name, user.icon_id, bbs_country.date, bbs_country.article from user " \ "inner join bbs_country "\ "on user.user_id=bbs_country.user_id "\ "where bbs_country.country_id = " + str(country) + \ " order by bbs_country.date limit 20;" result = db.exec(query, True) print(result[0][2]) print(result[0][2].strftime("%Y-%m-%d %H:%M:%S"))
def init_hexgrid(_cls, _self, data): """ クライアントのhex_gridへ初期化情報を送信する :param _cls: BJSocketHandlerのクラス :param _self: SocketHandlerのインスタンス :param data: 空 :return: """ payload = {"event": "init_hexgrid"} data = {} #DBから初期化情報を集める try: db = DBSingleton() # ヘックスグリッドの情報 # TODO: map/map_*.pyからgame_statusのWHLを設定 """ result_whl = db.select("width", "height", "length", table="game_status") data["width"] = result_whl[0][0] data["height"] = result_whl[0][1] data["length"] = result_whl[0][2] """ data["width"] = 1500 data["height"] = 1500 data["length"] = 50 # プレイヤー情報(可視権含む)取得 user_id = _self.get_secure_cookie("user_id").decode('utf-8') player = get_playerinfo_by_id(user_id) if not player: raise Exception("hex_grid上の自身のプレイヤー情報取得失敗") print("p0") # 可視範囲の全プレイヤー取得 visible_players = get_players_by_visibility(player["visibility"], True) # 自身の情報をペイロードに格納 data["player_self"] = { "name": player["user_name"], "col": player["col"], "row": player["row"], "icon_id": player["icon_id"], "country": player["country_id"] } # 可視範囲の全プレイヤーの情報をペイロードに格納 payload_players = [] for visible_player in visible_players: payload_players.append({ "col": visible_player["col"], "row": visible_player["row"], "icon_id": visible_player["icon_id"], "country": visible_player["country_id"] }) data["new_players"] = payload_players # 領地の情報 own_area = get_own_area(player["country_id"]) data["own_area"] = [] for hex in own_area: data["own_area"].append(hex) # 可視範囲のヘックスの情報 visible_area = get_visible_area(player["visibility"]) data["visible_area"] = [] for hex in visible_area: data["visible_area"].append(hex) # 不可視領域のヘックスの情報 unvisible_area = get_unvisible_area(player["visibility"]) data["unvisible_area"] = [] for hex in unvisible_area: data["unvisible_area"].append(hex) except Exception as e: logging.error(u"ヘックスグリッドの情報取得失敗。\n" u"message = " + str(e)) _self.send_error(u"ヘックスグリッドの情報取得失敗") return # 送信するデータ組み立て payload["data"] = data # 送信 _self.send_you(payload)