find-object-bundle-builder/FindObjectBundleBuilder/Tools/config_convert/gen_levels_db.py

543 lines
26 KiB
Python
Raw Normal View History

2025-04-18 07:35:35 +00:00
#!/usr/bin/env python
# coding:utf-8
import json
import os
import sys
import datetime
import time
curr_dir = os.path.split(os.path.abspath(__file__))[0]
sys.path.append(os.path.join(curr_dir, '../'))
sys.path.append(os.path.join(curr_dir, '../google_drive'))
sys.path.append(os.path.join(curr_dir, '../firebase'))
sys.path.append(os.path.join(curr_dir, '../ipm'))
import config as config
import utils as utils
from game_play_type import MainPlayType
from firebase.firebase_helper import FirebaseHelper
from google_drive.google_sheet import GoogleSheetHelper
def get_blob_asset_id(blob):
filename = os.path.split(blob.name)[1]
filename_only = os.path.splitext(filename)[0]
asset_id = filename_only.replace("PackageManifest_", "").replace(".version", "")
return asset_id
# region 更新所有可测试关卡Google Sheet配置表上传到Google Storage生成测试文件更新remote_config
def upload_all_levels_sheet(platform, gameplay_levels_dict):
"""更新所有存在ab包的psd_id的Google Sheet库"""
sheet_helper = GoogleSheetHelper()
sheet = sheet_helper.get_sheet_table(config.sheet_all_level, f"{platform}-{config.table_all_levels}")
2025-05-09 10:26:15 +00:00
sheet.clear() #清除表格中的所有现有数据
2025-04-18 07:35:35 +00:00
for i, gameplay in enumerate(gameplay_levels_dict):
list = gameplay_levels_dict[gameplay]
if len(list) <= 0:
continue
col = i + 1
row_start = 1
row_end = row_start + len(list) - 1
2025-05-09 10:26:15 +00:00
cell_range = sheet.range(row_start, col, row_end, col) # 获取要更新的单元格范围
2025-04-18 07:35:35 +00:00
sheet_helper.sheet_update_cells_value(sheet, cell_range, list)
config.notification_helper.append_msg(f"[{config.sheet_all_level}文件, {platform}-{config.table_all_levels}表格] 更新所有可测试关卡表成功")
def update_all_levels_google_sheet(platform):
try:
"""获取所有的ab包更新Google Sheet上的所有关卡"""
firebase_helper = FirebaseHelper()
mainPlayType = MainPlayType()
gameplay_levels_dict = {}
for gameplay in mainPlayType.all_main_play_type_list:
blobs = firebase_helper.get_files_match(f"Bundles/{platform}/Level/{gameplay}/{gameplay}_", "**.version")
levels_list = []
for a_blob in blobs:
levels_list.append(get_blob_asset_id(a_blob))
if len(levels_list) > 0:
levels_list.insert(0, gameplay)
gameplay_levels_dict[gameplay] = levels_list
upload_all_levels_sheet(platform, gameplay_levels_dict)
except Exception as e:
error = "更新Google Sheet所有可验收关卡信息失败错误信息" + repr(e)
print(error)
config.notification_helper.append_msg(error)
# endregion
# region 更新所有验收过地关卡到Google Sheet
def update_all_acceptance_passed_levels_2_google_sheet(platform):
"""更新所有验收过地关卡到Google Sheet"""
try:
firebase_helper = FirebaseHelper()
mainPlayType = MainPlayType()
gameplay_acceptance_passed_levels_dict = {}
# 获取验收通过关卡列表
for gameplay in mainPlayType.all_main_play_type_list:
blobs = firebase_helper.get_files_match(f"Bundles/{platform}/Level/{gameplay}/{gameplay}_", "**.version")
levels_list = []
for a_blob in blobs:
if config.meta_pass_count not in a_blob.metadata:
continue
pass_count = int(a_blob.metadata[config.meta_pass_count])
if pass_count <= 0:
continue
levels_list.append(get_blob_asset_id(a_blob))
if len(levels_list) > 0:
gameplay_acceptance_passed_levels_dict[gameplay] = levels_list
# 更新Google Sheet
sheet_helper = GoogleSheetHelper()
for gameplay in mainPlayType.all_main_play_type_list:
if gameplay not in gameplay_acceptance_passed_levels_dict:
print(f"{gameplay}玩法没有验收通过地关卡")
continue
levels_list = gameplay_acceptance_passed_levels_dict[gameplay]
if len(levels_list) <= 0:
print(f"{gameplay}玩法验收通过关卡列表为空")
continue
sheet, _ = sheet_helper.get_or_create_sheet_table(f"{platform}-{config.sheet_acceptance_passed_levels}", f"{gameplay}", 10000, 1)
# 过滤已经记录在sheet里地已验收关卡
sheet_datas = sheet.get_all_values(major_dimension='COLUMNS')
print(sheet_datas)
col = 1
row_start = 1
if len(sheet_datas) > 0:
sheet_acceptance_level_list = sheet_datas[0]
row_start = len(sheet_acceptance_level_list) + 1
for acceptance_level in sheet_acceptance_level_list:
if acceptance_level in levels_list:
levels_list.remove(acceptance_level)
# 添加新的验收通过关卡到sheet
if len(levels_list) > 0:
row_end = row_start + len(levels_list) - 1
cell_range = sheet.range(row_start, col, row_end, col)
sheet_helper.sheet_update_cells_value(sheet, cell_range, levels_list)
config.notification_helper.append_msg(f"{gameplay}模式新增关卡{str(levels_list)}")
else:
print(f"{gameplay}玩法模式没有新的验收通过关卡可以添加到sheet")
except Exception as e:
error = "添加新验收过地关卡到验收通过表格失败,错误信息:" + repr(e)
print(error)
config.notification_helper.append_msg(error)
# endregion
2025-05-09 10:26:15 +00:00
# region 更新Find Object关卡文档里地资源表
2025-04-18 07:35:35 +00:00
def update_level_config_assets(platform):
"""更新关卡表里对应玩法资源表每一关属性内容"""
firebase_helper = FirebaseHelper()
mainPlayType = MainPlayType()
gameplay_blobs_dict = {}
# 获取验收通过关卡列表
for gameplay in mainPlayType.all_main_play_type_list:
blobs = firebase_helper.get_files_match(f"Bundles/{platform}/Level/{gameplay}/{gameplay}_", "**.version")
for blob_item in blobs:
asset_id = get_blob_asset_id(blob_item)
if gameplay not in gameplay_blobs_dict:
gameplay_blobs_dict[gameplay] = {}
gameplay_blobs_dict[gameplay][asset_id] = blob_item
sheet_helper = GoogleSheetHelper()
for gameplay in mainPlayType.all_main_play_type_list:
if gameplay not in gameplay_blobs_dict:
print(f"{gameplay}玩法没有验收通过地关卡")
continue
if len(gameplay_blobs_dict[gameplay]) <= 0:
print(f"{gameplay}玩法验收通过关卡列表为空")
continue
# 资源表创建和更新
gameplay_sheet, is_new_create = sheet_helper.get_or_create_sheet_table(config.sheet_level_config, f"{gameplay}资源表", 10000, 27)
if is_new_create:
# 新创建表设置表数据
first_row = []
first_row.append(["Asset_ID", "Asset_Name", "A_G", "I_G", "FindNum", "IsUsed"])
gameplay_sheet.update("A1", first_row, value_input_option="USER_ENTERED")
gameplay_sheet.freeze(rows=1, cols=2)
notes = { "C1": "android version file generation", "D1": "ios version file generation", "E1": "寻找物品个数", "F1": "是否已被主线使用" }
gameplay_sheet.insert_notes(notes)
# 设置表公式
second_row = []
id_formula = f"=ARRAYFORMULA(IF(B2:B<>\"\", ROW(B2:B)-ROW(B$2)+1, \"\"))"
2025-05-09 10:26:15 +00:00
name_formula = "=IMPORTRANGE(" + "\"https://docs.google.com/spreadsheets/d/1mwisjfsQwcSqQ0BJ2TszThSZRCRqOaAqgpHaPGGCzYs\", " + f"\"{gameplay}!A:A\")"
2025-04-18 07:35:35 +00:00
second_row.append([id_formula, name_formula])
gameplay_sheet.update("A2", second_row, value_input_option="USER_ENTERED")
print(f"延时10秒等待公式计算完成")
time.sleep(10)
# 更新表里资源generation等数据
gameplay_sheet_datas = gameplay_sheet.get_all_values(major_dimension='ROWS')
gameplay_blobs_map = gameplay_blobs_dict[gameplay]
cell_list = []
for i, row_values in enumerate(gameplay_sheet_datas):
if i == 0:
continue
row = i + 1
asset_name = row_values[1]
if asset_name not in gameplay_blobs_map:
print(f"{platform}平台{gameplay}玩法资源表里没有找到对应资源{asset_name}")
continue
blob = gameplay_blobs_map[asset_name]
if config.meta_pass_count not in blob.metadata:
continue
pass_count = int(blob.metadata[config.meta_pass_count])
if pass_count <= 0:
continue
a_g = row_values[2]
i_g = row_values[3]
find_num = row_values[4]
str_generation = str(blob.generation)
if platform == "Android" and str_generation != a_g:
cell = gameplay_sheet.cell(row, 3)
cell.value = str_generation
cell_list.append(cell)
time.sleep(1)
if platform == "iOS" and str_generation != i_g:
cell = gameplay_sheet.cell(row, 4)
cell.value = str_generation
cell_list.append(cell)
time.sleep(1)
if blob.metadata is not None and config.meta_find_num in blob.metadata:
if str(blob.metadata[config.meta_find_num]) != find_num:
cell = gameplay_sheet.cell(row, 5)
cell.value = str(blob.metadata[config.meta_find_num])
cell_list.append(cell)
time.sleep(1)
if len(cell_list) > 0:
gameplay_sheet.update_cells(cell_list, value_input_option="USER_ENTERED")
# 关卡表创建
gameplay_level_db_sheet, is_new_create = sheet_helper.get_or_create_sheet_table(config.sheet_level_config, f"{gameplay}_main_db", 10000, 27)
if is_new_create:
time.sleep(5)
# 设置表头
first_row = []
first_row.append(["Level", "Asset_ID", "Asset_Name", "Thumbnail", "A_G", "I_G", "FindNum", "配置合法性"])
gameplay_level_db_sheet.update("A1", first_row, value_input_option="USER_ENTERED")
gameplay_level_db_sheet.freeze(rows=1, cols=4)
# 设置表公式
second_row = []
level_formula = "=ARRAYFORMULA(IF(B2:B<>\"\", ROW(B2:B)-ROW(B$2)+1, \"\"))"
asset_name_formula = f"=ARRAYFORMULA(IF(B2:B<>\"\", VLOOKUP(B2:B, '{gameplay}资源表'!A:E, 2, FALSE), \"\"))"
a_g_formula = f"=ARRAYFORMULA(IF(B2:B<>\"\", VLOOKUP(B2:B, '{gameplay}资源表'!A:E, 3, FALSE), \"\"))"
i_g_formula = f"=ARRAYFORMULA(IF(B2:B<>\"\", VLOOKUP(B2:B, '{gameplay}资源表'!A:E, 4, FALSE), \"\"))"
find_num_formula = f"=ARRAYFORMULA(IF(B2:B<>\"\", VLOOKUP(B2:B, '{gameplay}资源表'!A:E, 5, FALSE), \"\"))"
valid_formula = f"=ARRAYFORMULA(IF(B2:B=\"\", \"\", IF(COUNTIF(B:B, B2:B)>1, \"素材重复\", IF(ISERROR(MATCH(B2:B, '{gameplay}资源表'!A:A, 0)), \"素材缺失\", \"\"))))"
second_row.append([level_formula, "", asset_name_formula, "", a_g_formula, i_g_formula, find_num_formula, valid_formula])
gameplay_level_db_sheet.update("A2", second_row, value_input_option="USER_ENTERED")
# endregion
2025-05-09 10:26:15 +00:00
# region 更新Find object主线关卡配置
2025-04-18 07:35:35 +00:00
# 如果要修改此处逻辑记得下面的update_main_country_level_db方法的逻辑一起修改
###
def update_main_level_db(platform, mode):
sheet_helper = GoogleSheetHelper()
mainPlayType = MainPlayType()
levels_data_dic = {}
record_levels = {}
error = ""
gameplay_list = mainPlayType.debug_enable_main_play_type_list if mode == config.mode.debug.value else mainPlayType.release_enable_main_play_type_list
for gameplay in gameplay_list:
google_sheet_file = sheet_helper.get_sheet_table(config.sheet_level_config, f"{gameplay}_db")
2025-04-18 07:35:35 +00:00
if google_sheet_file is None:
print(f"{gameplay}玩法目前没有配置关卡表")
continue
# 读取所有信息对应列数
col_level, col_asset_id, col_asset_name, col_a_g, col_i_g, col_find_num, col_valid , col_game_play_type ,col_game_play_param, col_game_elements= -1, -1, -1, -1, -1, -1, -1,-1,-1,-1
first_row_datas = google_sheet_file.row_values(1)
for i, value in enumerate(first_row_datas):
if value == "Level":
col_level = i + 1
elif value == "Asset_ID":
col_asset_id = i + 1
elif value == "Asset_Name":
col_asset_name = i + 1
elif value == "A_G":
col_a_g = i + 1
elif value == "I_G":
col_i_g = i + 1
elif value == "FindNum":
col_find_num = i + 1
elif value == "配置合法性":
col_valid = i + 1
# elif value == "GamePlayType":
# col_game_play_type = i + 1
2025-04-18 07:35:35 +00:00
elif value == "GamePlayParam":
col_game_play_param = i + 1
# elif value == "GameElements":
# col_game_elements = i + 1
2025-04-18 07:35:35 +00:00
if col_level == -1 or col_asset_id == -1 or col_asset_name == -1 or col_a_g == -1 or col_i_g == -1 \
or col_find_num == -1 or col_valid == -1:
config.notification_helper.append_msg(f"{gameplay}玩法目前配置关卡表格式不正确")
return
# 验证配置有效性
col_valid_datas = google_sheet_file.col_values(col_valid)
for i, value in enumerate(col_valid_datas):
if i == 0 or value == "":
continue
error += f"{gameplay}玩法第{i + 1}行配置错误:{value}\n"
if error != "":
config.notification_helper.append_msg(error)
return
# 验证所有关卡都有对应generation表示对应平台有资源
col_generation = col_a_g if platform == "Android" else col_i_g
col_generation_datas = google_sheet_file.col_values(col_generation)
for i, value in enumerate(col_generation_datas):
if i == 0:
continue
if value == "":
error += f"{gameplay}玩法第{i + 1}{platform}平台资源没有generation配置\n"
if error != "":
config.notification_helper.append_msg(error)
return
# 读取所有配置好关卡信息
sheet_main_db_datas = google_sheet_file.get_all_values(major_dimension='ROWS')
for i, row_datas in enumerate(sheet_main_db_datas):
if i == 0:
continue
one_level_data = {}
level_id = row_datas[col_asset_name - 1]
# game_play_type = row_datas[col_game_play_type - 1]
# if len(game_play_type) == 0:
# game_play_type = "normal"
2025-04-18 07:35:35 +00:00
game_play_param = row_datas[col_game_play_param - 1]
if len(game_play_param) == 0:
game_play_param = ""
# game_elements_param = row_datas[col_game_elements - 1] if col_game_elements > 0 else ''
2025-04-18 07:35:35 +00:00
level_type = gameplay
level_map_name = ""
level_thum_name = ""
one_level_data["LevelId"] = level_id
one_level_data["LevelMapName"] = level_map_name
one_level_data["LevelType"] = level_type
one_level_data["LevelThumName"] = level_thum_name
# one_level_data["GamePlayType"] = game_play_type
2025-04-18 07:35:35 +00:00
one_level_data["GamePlayParam"] = game_play_param
# one_level_data["GameElements"] = game_elements_param
2025-04-18 07:35:35 +00:00
if gameplay not in levels_data_dic:
levels_data_dic[gameplay] = []
levels_data_dic[gameplay].append(one_level_data)
record_levels[level_id] = True
# debug模式还要获取其他未配置但可以上线地关卡数据
# if mode == config.mode.debug.value:
# sheet_asset = sheet_helper.get_sheet_table(config.sheet_level_config, f"{gameplay}资源表")
# if sheet_asset is None:
# print(f"{gameplay}玩法目前没有资源表")
# continue
# sheet_asset_datas = sheet_asset.get_all_values(major_dimension='ROWS')
# for i, row_datas in enumerate(sheet_asset_datas):
# if i == 0:
# continue
# asset_name = row_datas[1]
# # game_play_type = "normal"
# # if gameplay in levels_data_dic and asset_name in record_levels:
# # continue
# level_id = asset_name
# level_type = gameplay
# level_map_name = ""
# level_thum_name = ""
# game_play_param = ""
# # game_elements_param = ""
# one_level_data = {}
# one_level_data["LevelId"] = level_id
# one_level_data["LevelType"] = level_type
# one_level_data["LevelMapName"] = level_map_name
# one_level_data["LevelThumName"] = level_thum_name
# # one_level_data["GamePlayType"] = game_play_type
# one_level_data["GamePlayParam"] = game_play_param
# # one_level_data["GameElements"] = game_elements_param
# if gameplay not in levels_data_dic:
# levels_data_dic[gameplay] = []
# levels_data_dic[gameplay].append(one_level_data)
2025-04-18 07:35:35 +00:00
if len(levels_data_dic) <= 0:
print(f"没有任何可上线关卡数据")
return
main_level_db = {}
main_level_db["TotalLevelsDataDic"] = levels_data_dic
# print(main_level_db)
# 上传配置到Google Storage
firebase_helper = FirebaseHelper()
_json = json.dumps(main_level_db)
config_json_filename = f"{platform.lower()}_main_level_db_{mode}.json"
utils.write_json_file("gen_file", config_json_filename, _json)
generation = firebase_helper.upload_file(f"Configs/{config_json_filename}", f"gen_file/{config_json_filename}")
# 更新Remote Config
condition = config.remote_condition_android if platform == "Android" else config.remote_condition_ios
value = f"{config.cdn}/Configs/{config_json_filename}?generation={generation}"
firebase_helper.update_remote_config(None, condition, config.remote_key_main_db,
2025-04-18 07:35:35 +00:00
f"main_{mode}", value)
return value
def update_main_country_level_db(platform, mode, all_country_list):
sheet_helper = GoogleSheetHelper()
mainPlayType = MainPlayType()
levels_data_dic = {}
record_levels = {}
error = ""
gameplay_list = mainPlayType.debug_enable_main_play_type_list if mode == config.mode.debug.value else mainPlayType.release_enable_main_play_type_list
country_and_url_list = []
for cur_country in all_country_list:
for gameplay in gameplay_list:
google_sheet_file = sheet_helper.get_sheet_table(config.sheet_level_config, f"{gameplay}_main_db_{cur_country}")
if google_sheet_file is None:
print(f"{gameplay}玩法目前没有{cur_country}的配置关卡表,使用默认表")
google_sheet_file = sheet_helper.get_sheet_table(config.sheet_level_config,f"{gameplay}_main_db")
if google_sheet_file is None:
print(f"{gameplay}玩法目前没有配置关卡表")
continue
# 读取所有信息对应列数
col_level, col_asset_id, col_asset_name, col_a_g, col_i_g, col_find_num, col_valid, col_game_play_type, col_game_play_param, col_game_elements = -1, -1, -1, -1, -1, -1, -1, -1, -1,-1
first_row_datas = google_sheet_file.row_values(1)
for i, value in enumerate(first_row_datas):
if value == "Level":
col_level = i + 1
elif value == "Asset_ID":
col_asset_id = i + 1
elif value == "Asset_Name":
col_asset_name = i + 1
elif value == "A_G":
col_a_g = i + 1
elif value == "I_G":
col_i_g = i + 1
elif value == "FindNum":
col_find_num = i + 1
elif value == "配置合法性":
col_valid = i + 1
# elif value == "GamePlayType":
# col_game_play_type = i + 1
2025-04-18 07:35:35 +00:00
elif value == "GamePlayParam":
col_game_play_param = i + 1
# elif value == "GameElements":
# col_game_elements = i + 1
2025-04-18 07:35:35 +00:00
if col_level == -1 or col_asset_id == -1 or col_asset_name == -1 or col_a_g == -1 or col_i_g == -1 \
or col_find_num == -1 or col_valid == -1:
config.notification_helper.append_msg(f"{gameplay}玩法目前配置关卡表格式不正确")
return
# 验证配置有效性
col_valid_datas = google_sheet_file.col_values(col_valid)
for i, value in enumerate(col_valid_datas):
if i == 0 or value == "":
continue
error += f"{gameplay}玩法第{i + 1}行配置错误:{value}\n"
if error != "":
config.notification_helper.append_msg(error)
return
# 验证所有关卡都有对应generation表示对应平台有资源
col_generation = col_a_g if platform == "Android" else col_i_g
col_generation_datas = google_sheet_file.col_values(col_generation)
for i, value in enumerate(col_generation_datas):
if i == 0:
continue
if value == "":
error += f"{gameplay}玩法第{i + 1}{platform}平台资源没有generation配置\n"
if error != "":
config.notification_helper.append_msg(error)
return
# 读取所有配置好关卡信息
sheet_main_db_datas = google_sheet_file.get_all_values(major_dimension='ROWS')
for i, row_datas in enumerate(sheet_main_db_datas):
if i == 0:
continue
one_level_data = {}
level_id = row_datas[col_asset_name - 1]
# game_play_type = row_datas[col_game_play_type - 1]
# if len(game_play_type) == 0:
# game_play_type = "normal"
2025-04-18 07:35:35 +00:00
game_play_param = row_datas[col_game_play_param - 1]
if len(game_play_param) == 0:
game_play_param = ""
# game_elements_param = row_datas[col_game_elements - 1] if col_game_elements > 0 else ''
2025-04-18 07:35:35 +00:00
level_type = gameplay
level_map_name = ""
level_thum_name = ""
one_level_data["LevelId"] = level_id
one_level_data["LevelMapName"] = level_map_name
one_level_data["LevelType"] = level_type
one_level_data["LevelThumName"] = level_thum_name
# one_level_data["GamePlayType"] = game_play_type
2025-04-18 07:35:35 +00:00
one_level_data["GamePlayParam"] = game_play_param
# one_level_data["GameElements"] = game_elements_param
2025-04-18 07:35:35 +00:00
if gameplay not in levels_data_dic:
levels_data_dic[gameplay] = []
levels_data_dic[gameplay].append(one_level_data)
record_levels[level_id] = True
# # debug模式还要获取其他未配置但可以上线地关卡数据
# if mode == config.mode.debug.value:
# sheet_asset = sheet_helper.get_sheet_table(config.sheet_level_config, f"{gameplay}资源表")
# if sheet_asset is None:
# print(f"{gameplay}玩法目前没有资源表")
# continue
# sheet_asset_datas = sheet_asset.get_all_values(major_dimension='ROWS')
# for i, row_datas in enumerate(sheet_asset_datas):
# if i == 0:
# continue
# asset_name = row_datas[1]
# game_play_type = "normal"
# if gameplay in levels_data_dic and asset_name in record_levels:
# continue
# level_id = asset_name
# level_type = gameplay
# level_map_name = ""
# level_thum_name = ""
# game_play_param = ""
# one_level_data = {}
# one_level_data["LevelId"] = level_id
# one_level_data["LevelType"] = level_type
# one_level_data["LevelMapName"] = level_map_name
# one_level_data["LevelThumName"] = level_thum_name
# one_level_data["GamePlayType"] = game_play_type
# one_level_data["GamePlayParam"] = game_play_param
# if gameplay not in levels_data_dic:
# levels_data_dic[gameplay] = []
# levels_data_dic[gameplay].append(one_level_data)
if len(levels_data_dic) <= 0:
print(f"没有任何可上线关卡数据")
return
main_level_db = {}
main_level_db["TotalLevelsDataDic"] = levels_data_dic
# print(main_level_db)
# 上传配置到Google Storage
firebase_helper = FirebaseHelper()
_json = json.dumps(main_level_db)
config_json_filename = f"{platform.lower()}_main_level_db_{cur_country}.json"
utils.write_json_file("gen_file", config_json_filename, _json)
generation = firebase_helper.upload_file(f"Configs/{config_json_filename}", f"gen_file/{config_json_filename}")
value = f"{config.cdn}/Configs/{config_json_filename}?generation={generation}"
country_and_url_list.append(f"配置{cur_country}的URL为:{value}")
return country_and_url_list
# endregion
if __name__ == '__main__':
pass
# update_all_levels_google_sheet("Android")
# update_all_acceptance_passed_levels_2_google_sheet("Android")
# update_level_config_assets("Android")
# update_main_level_db("Android", "debug")