# coding=utf-8 """ ad.json 操作 支持版本 6.* """ import os import json from common.logging import Logging import strategy_generator class AD_TYPE(object): """ 广告类型 BANNER: 横幅 INTERSTITIAL: 插屏 VIDEO: 视频 """ BANNER, INTERSTITIAL, VIDEO = range(3) @staticmethod def key_string(type): return { AD_TYPE.BANNER: "banners", AD_TYPE.INTERSTITIAL: "interstitials", AD_TYPE.VIDEO: "videos", }[type] class AD_PLATFROM(object): """ 广告平台 """ ADMOB, FACEBOOK, UNITY, CRITEO, UNKNOWN = range(5) @staticmethod def string(platform): return { AD_PLATFROM.ADMOB: "admob", AD_PLATFROM.FACEBOOK: "facebook", AD_PLATFROM.UNITY: "unity", AD_PLATFROM.CRITEO: "criteo", AD_PLATFROM.UNKNOWN: "unknown" }[platform] class RED_SDK_AD_PLATFORM(object): """ RedSdk的配置文件中,所使用到的平台的ID """ ADMOB = 0 FACEBOOK = 1 CHARTBOOST = 2 APPLOVIN = 3 VUNGLE = 4 UNITY = 5 IRONSOURCE = 7 TAPJOY = 8 FACEBOOK_BID = 9 CRITEO = 10 @staticmethod def string(platform): return { RED_SDK_AD_PLATFORM.ADMOB: "Admob", RED_SDK_AD_PLATFORM.FACEBOOK: "Facebook", RED_SDK_AD_PLATFORM.CHARTBOOST: "Chartboost", RED_SDK_AD_PLATFORM.APPLOVIN: "Applovin", RED_SDK_AD_PLATFORM.VUNGLE: "Vungle", RED_SDK_AD_PLATFORM.UNITY: "Unity", RED_SDK_AD_PLATFORM.IRONSOURCE: "Ironsource", RED_SDK_AD_PLATFORM.TAPJOY: "Tapjoy", RED_SDK_AD_PLATFORM.FACEBOOK_BID: "Facebook_bid", RED_SDK_AD_PLATFORM.CRITEO: "Criteo", }[platform] class AdPool: """ 广告池子配置 "admob": { "am_5": 9, "am_4": 7, "am_3": 5, "am_2": 3, "am_1": 2 } dic_pool_items: {} 原始json文件 arr_ordered_pool_items: [] 从大到小的广告配置项 {ad_id:adid, priority:3} """ def __init__(self, pool_item_dic=None): """ :param pool_item_dic: {} 原始配置 """ self.ori_json = {} self.ordered_pool_item_arr = [] if pool_item_dic is not None: self.ori_json = pool_item_dic self.__parse(pool_item_dic) def __parse(self, pool_item_dic): pool_arr = [] for ad_id in pool_item_dic: priority = pool_item_dic[ad_id] pool_arr.append({ "ad_id": ad_id, "priority": priority }) self.ordered_pool_item_arr = sorted(pool_arr, key=lambda e: e.__getitem__("priority"), reverse=True) def max_priority(self): """ :return: int """ return self.ordered_pool_item_arr[0]["priority"] def max_priority_ad_id(self): """ :return: string """ return self.ordered_pool_item_arr[0]["ad_id"] def add_ad_id(self, adId, priority): self.ori_json[adId] = priority self.__parse(self.ori_json) def print_desc(self): for item in self.ordered_pool_item_arr: print "{}:\t{}".format(item["priority"], item["ad_id"]) class AdStrategy: """ 广告策略配置 { "root": "am_3", "strategy": { "am_4": { "fail": 2, "platform": "admob", "suc": 2 }, "am_5": { "fail": 1, "platform": "admob", "suc": 2, "fail_next": "am_4" }, "am_3": { "fail": 1, "platform": "admob", "suc": 1, "fail_next": "am_2", "suc_next": "am_5" }, "am_2": { "fail": 1, "platform": "admob", "suc": 2, "fail_next": "am_1" }, "am_1": { "fail": 2, "platform": "admob", "suc": 2 } } } """ def __init__(self, platform=AD_PLATFROM.UNKNOWN, strategy_dic=None, is_admob_5_floor_strategy=False): self.platform = platform self.is_admob_5_floor_strategy = is_admob_5_floor_strategy self.root_ad_id = "" self.strategy_json = {} self.ordered_ad_id_arr = [] self.ori_json = {} if strategy_dic is not None: self.ori_json = strategy_dic self.__parse(strategy_dic) def __parse(self, strategy_dic): self.root_ad_id = strategy_dic["root"] self.strategy_json = strategy_dic["strategy"] self.is_admob_5_floor_strategy = (strategy_dic["strategy"][self.root_ad_id]["suc"] == 1) if self.is_admob_5_floor_strategy: self.ordered_ad_id_arr = [""] * 5 self.ordered_ad_id_arr[2] = self.root_ad_id self.ordered_ad_id_arr[3] = self.strategy_json[self.ordered_ad_id_arr[2]]["fail_next"] self.ordered_ad_id_arr[4] = self.strategy_json[self.ordered_ad_id_arr[3]]["fail_next"] self.ordered_ad_id_arr[1] = self.strategy_json[self.ordered_ad_id_arr[2]]["suc_next"] self.ordered_ad_id_arr[0] = self.strategy_json[self.ordered_ad_id_arr[1]]["fail_next"] else: self.ordered_ad_id_arr = [] self.ordered_ad_id_arr.append(self.root_ad_id) now_ad_id = self.root_ad_id while self.strategy_json[now_ad_id]["fail"] != 2: now_ad_id = self.strategy_json[now_ad_id]["fail_next"] self.ordered_ad_id_arr.append(now_ad_id) def update(self, ordered_ad_id_arr): """ 按从大到小的顺序排好 ori_json 原始的json文件 ordered_ad_ids: 从小到大 [fb_4, fb_3, fb_2] """ dic = strategy_generator.generate_ordered_floor_strategy(ordered_ad_id_arr, AD_PLATFROM.string(self.platform)) self.ori_json["root"] = dic["root"] self.ori_json["strategy"] = dic["strategy"] self.__parse(self.ori_json) def get_desc(self): string = self.ordered_ad_id_arr[0] for i in range(1, len(self.ordered_ad_id_arr)): string = "{} --> {}".format(string, self.ordered_ad_id_arr[i]) return string def print_desc(self): print self.get_desc() class AdPage: """ 广告配置页面 | 版位 page_name 页面名称 """ def __init__(self, page_name, page_dic=None): self.page_name = page_name self.ori_json = {} if page_dic is not None: self.ori_json = page_dic self.__parse(page_dic) def __parse(self, page_dic): self.pools = page_dic["pools"] self.ctrl = page_dic["ctrl"] def add_pool(self, pool_name): if not self.pools.__contains__(pool_name): self.pools.append(pool_name) class AdBidders: """ 竞价广告配置 """ def __init__(self, bidder_dic=None): self.ori_json = {} if bidder_dic is not None: self.ori_json = bidder_dic def add_bidder(self, platform, adId): self.ori_json[AD_PLATFROM.string(platform)] = adId class AdPlatformId: """ 广告平台的app_id配置 """ def __init__(self, platform_dic=None, platform=None, app_id=None): self.ori_json = {} self.platform = "" self.app_id = "" if platform_dic is not None: self.ori_json = platform_dic self.platform = platform_dic["p"] self.app_id = platform_dic["aid"] if platform is not None and app_id is not None: self.platform = platform self.app_id = app_id self.ori_json = { "p": platform, "aid": app_id } def get_desc(self): return "%s:\t\t%s" % (RED_SDK_AD_PLATFORM.string(self.platform), self.app_id) class AdPageCtrl: """ 广告页面配置 版位 参数列表: key: string value: number is_deprecated: bool config_name: string """ def __init__(self, key, value): self.key = key self.value = value self.is_deprecated = False if self.key == "d": self.config_name = "展示天数" elif self.key == "level": self.config_name = "展示关数" else: self.is_deprecated = True self.config_name = "未配置或已废弃" def get_desc(self): return "{}: {}".format(self.config_name, self.value) class AdJson6: def __init__(self): self.ori_json = {} def read(self, file_path): if not os.path.exists(file_path): Logging.error("文件不存在: %s" % file_path) self.ori_json = json.load(open(file_path)) if not self.ori_json.has_key("ad"): Logging.error("不存在ad根节点: %s" % file_path) check_keys = ["platform_ids", "global", "banners", "interstitials", "videos"] for key in check_keys: if not self.ori_json["ad"].has_key(key): Logging.error("ad节点下不存在子节点: %s: %s" % (key, file_path)) def __dic_ad_type(self, ad_type): return self.ori_json["ad"][AD_TYPE.key_string(ad_type)] # 获取池子的配置 def get_pool(self, ad_type, ad_platform): if ad_type == AD_TYPE.BANNER: Logging.error("error: banner不支持获取池") return None platform_str = AD_PLATFROM.string(ad_platform) if not self.__dic_ad_type(ad_type)["pools"].__contains__(platform_str): return None return AdPool(self.__dic_ad_type(ad_type)["pools"][platform_str]) def add_pool(self, ad_type, ad_platform, ad_pool): self.__dic_ad_type(ad_type)["pools"][AD_PLATFROM.string(ad_platform)] = ad_pool.ori_json def remove_pool(self, ad_type, ad_platform): self.__dic_ad_type(ad_type)["pools"].__delitem__(AD_PLATFROM.string(ad_platform)) def get_strategy(self, ad_type, ad_platform): platform_str = AD_PLATFROM.string(ad_platform) if ad_type == AD_TYPE.BANNER: return AdStrategy(ad_platform, self.__dic_ad_type(ad_type)["load_strategy"]) if ad_type == AD_TYPE.INTERSTITIAL: if not self.__dic_ad_type(ad_type)["pools_load_strategy"].__contains__(platform_str): return None return AdStrategy(ad_platform, self.__dic_ad_type(ad_type)["pools_load_strategy"][platform_str]) def add_strategy(self, ad_type, ad_platform, strategy): if ad_type == AD_TYPE.BANNER: Logging.error("error: banner不支持添加策略") if ad_type == AD_TYPE.INTERSTITIAL: self.__dic_ad_type(ad_type)["pools_load_strategy"][AD_PLATFROM.string(ad_platform)] = strategy.ori_json def remove_strategy(self, ad_type, ad_platform): self.__dic_ad_type(ad_type)["pools_load_strategy"].__delitem__(AD_PLATFROM.string(ad_platform)) def get_bidders(self, ad_type): if ad_type == AD_TYPE.BANNER: Logging.error("error: banner不支持") dic_ad_type = self.__dic_ad_type(ad_type) if not dic_ad_type.has_key("bidders"): dic_ad_type["bidders"] = {} return AdBidders(dic_ad_type["bidders"]) def get_ad_pages(self, ad_type): if ad_type == AD_TYPE.BANNER: Logging.error("error: banner不支持") pages = self.__dic_ad_type(ad_type)["pages"] arr = [] for page_name in pages: dic_page = pages[page_name] ad_page = AdPage(page_name, dic_page) arr.append(ad_page) return arr def get_platform_ids(self): platform_id_arr = self.ori_json["ad"]["platform_ids"] arr = [] for platform_id_dic in platform_id_arr: platform_id = AdPlatformId(platform_id_dic) arr.append(platform_id) return arr def add_platform_id(self, ad_platform, app_id): platform_id = AdPlatformId(platform=ad_platform, app_id=app_id) self.ori_json["ad"]["platform_ids"].append(platform_id.ori_json) def write(self, to_path): json.dump(self.ori_json, open(to_path, "w")) def print_desc(self): print "参数配置" param = json.loads(self.ori_json["parameters"]) print "\t关卡工具发送比例: {}%".format(int(param["LSR"]) / 10) print "\tGT工具发送比例: {}%".format(int(param["GTSR"]) / 10) print "平台ID:" platforms = self.get_platform_ids() for p in platforms: print "\t{}".format(p.get_desc()) print "全局配置:" global_json = self.ori_json["ad"]["global"] print "\tBanner刷新时间: \t{}".format(global_json["bci"]) print "\t两次广告展示间隔: \t{}".format(global_json["showGap"]) print "Banner广告配置:" print "\t展示条件:" banner_ctrl_dic = self.ori_json["ad"]["banners"]["ctrl"] for key in banner_ctrl_dic: value = banner_ctrl_dic[key] ad_page_ctrl = AdPageCtrl(key, value) print "\t\t{}".format(ad_page_ctrl.get_desc()) print "\t加载策略:" banner_load_strategy = AdStrategy(AD_PLATFROM.ADMOB, self.ori_json["ad"]["banners"]["load_strategy"]) print "\t\t{}".format(banner_load_strategy.get_desc()) ad_type_names = ["插屏", "奖励视频"] ad_types = [AD_TYPE.INTERSTITIAL, AD_TYPE.VIDEO] for i in range(2): print "{}展示配置:".format(ad_type_names[i]) inter_pools = self.ori_json["ad"][AD_TYPE.key_string(ad_types[i])]["pools"] arr_pool_ad_ids = [] for pool_name in inter_pools: pool_config = inter_pools[pool_name] for ad_id in pool_config: priority = pool_config[ad_id] arr_pool_ad_ids.append({ "ad_id": ad_id, "p": priority }) arr_pool_ad_ids = sorted(arr_pool_ad_ids, key=lambda e: e.__getitem__("p"), reverse=True) print "\t瀑布流池子配置:" for ad_id_info in arr_pool_ad_ids: print "\t\t{}:\t{}".format(ad_id_info["p"], ad_id_info["ad_id"]) print "\tBidders:" bidders = self.get_bidders(ad_types[i]) if len(bidders.ori_json) >= 1: for platform_str in bidders.ori_json: ad_id = bidders.ori_json[platform_str] print "\t\t{}:\t{}".format(platform_str, ad_id) print "\t页面版位配置:" inter_pages = self.get_ad_pages(ad_types[i]) for page in inter_pages: print "\t\t{}".format(page.page_name) string = "\t\t\t池子:\t" string = "{}{}".format(string, page.pools[0]) for i in range(1, len(page.pools)): string = "{}, {}".format(string, page.pools[i]) print string string = "\t\t\t展示条件:" for key in page.ctrl: value = page.ctrl[key] ctrl_info = AdPageCtrl(key, value) if not ctrl_info.is_deprecated: string = "{}\t{}".format(string, ctrl_info.get_desc()) print string if __name__ == '__main__': ad_json = AdJson6() ad_json.read("/Users/zhuge/Temp/20201217/ad.json") ad_json.print_desc() new_facebook_id = "fb_ad_new" facebook_pool = ad_json.get_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK) facebook_pool.print_desc() max_facebook_adid = facebook_pool.max_priority_ad_id() print max_facebook_adid max_facebook_priority = facebook_pool.max_priority() facebook_pool.add_ad_id(new_facebook_id, max_facebook_priority + 1) facebook_pool.print_desc() strategy = ad_json.get_strategy(AD_TYPE.BANNER, AD_PLATFROM.ADMOB) strategy.print_desc() strategy = ad_json.get_strategy(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK) strategy.print_desc() strategy.ordered_ad_id_arr.insert(0, new_facebook_id) strategy.update(list(reversed(strategy.ordered_ad_id_arr))) strategy.print_desc() unity_ids = [ "unity_inter_I1_lv1", "unity_inter_I1_lv2", "unity_inter_I2_lv1", "unity_inter_I2_lv2" ] unity_id_priorites = [ 4, 6, 8, 10 ] pools = { unity_ids[0]: unity_id_priorites[0], unity_ids[1]: unity_id_priorites[1], unity_ids[2]: unity_id_priorites[2], unity_ids[3]: unity_id_priorites[3] } pool = AdPool() pool.print_desc() for i in range(0, 4): pool.add_ad_id(unity_ids[i], unity_id_priorites[i]) pool.print_desc() ad_json.add_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.UNITY, pool) strategy = AdStrategy(AD_PLATFROM.UNITY) strategy.update(unity_ids) strategy.print_desc() ad_json.add_strategy(AD_TYPE.INTERSTITIAL, AD_PLATFROM.UNITY, strategy) pages = ad_json.get_ad_pages(AD_TYPE.INTERSTITIAL) for page in pages: page.add_pool("unity") pages = ad_json.get_ad_pages(AD_TYPE.VIDEO) for page in pages: page.add_pool("unity") facebook_pool = ad_json.get_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK) max_ecpm_facebook_ad_id = facebook_pool.max_priority_ad_id() ad_json.remove_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK) ad_json.remove_strategy(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK) ad_bidders = ad_json.get_bidders(AD_TYPE.INTERSTITIAL) ad_bidders.add_bidder(AD_PLATFROM.FACEBOOK, "fb_bidding_id") ad_bidders.add_bidder(AD_PLATFROM.CRITEO, "crite_inter_i1_lv1") pages = ad_json.get_ad_pages(AD_TYPE.INTERSTITIAL) for page in pages: page.add_pool(AD_PLATFROM.string(AD_PLATFROM.CRITEO)) ad_json.add_platform_id(RED_SDK_AD_PLATFORM.CRITEO, "criteo") ad_json.write("/Users/zhuge/Temp/20201217/ad_t.json") ad_json.print_desc()