ad_json_6.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. # coding=utf-8
  2. """ ad.json 操作
  3. 支持版本 6.*
  4. """
  5. import os
  6. import json
  7. from common.logging import Logging
  8. import strategy_generator
  9. class AD_TYPE(object):
  10. """ 广告类型
  11. BANNER: 横幅
  12. INTERSTITIAL: 插屏
  13. VIDEO: 视频
  14. """
  15. BANNER, INTERSTITIAL, VIDEO = range(3)
  16. @staticmethod
  17. def key_string(type):
  18. return {
  19. AD_TYPE.BANNER: "banners",
  20. AD_TYPE.INTERSTITIAL: "interstitials",
  21. AD_TYPE.VIDEO: "videos",
  22. }[type]
  23. class AD_PLATFROM(object):
  24. """ 广告平台 """
  25. ADMOB, FACEBOOK, UNITY, CRITEO, UNKNOWN = range(5)
  26. @staticmethod
  27. def string(platform):
  28. return {
  29. AD_PLATFROM.ADMOB: "admob",
  30. AD_PLATFROM.FACEBOOK: "facebook",
  31. AD_PLATFROM.UNITY: "unity",
  32. AD_PLATFROM.CRITEO: "criteo",
  33. AD_PLATFROM.UNKNOWN: "unknown"
  34. }[platform]
  35. class RED_SDK_AD_PLATFORM(object):
  36. """ RedSdk的配置文件中,所使用到的平台的ID """
  37. ADMOB = 0
  38. FACEBOOK = 1
  39. CHARTBOOST = 2
  40. APPLOVIN = 3
  41. VUNGLE = 4
  42. UNITY = 5
  43. IRONSOURCE = 7
  44. TAPJOY = 8
  45. FACEBOOK_BID = 9
  46. CRITEO = 10
  47. @staticmethod
  48. def string(platform):
  49. return {
  50. RED_SDK_AD_PLATFORM.ADMOB: "Admob",
  51. RED_SDK_AD_PLATFORM.FACEBOOK: "Facebook",
  52. RED_SDK_AD_PLATFORM.CHARTBOOST: "Chartboost",
  53. RED_SDK_AD_PLATFORM.APPLOVIN: "Applovin",
  54. RED_SDK_AD_PLATFORM.VUNGLE: "Vungle",
  55. RED_SDK_AD_PLATFORM.UNITY: "Unity",
  56. RED_SDK_AD_PLATFORM.IRONSOURCE: "Ironsource",
  57. RED_SDK_AD_PLATFORM.TAPJOY: "Tapjoy",
  58. RED_SDK_AD_PLATFORM.FACEBOOK_BID: "Facebook_bid",
  59. RED_SDK_AD_PLATFORM.CRITEO: "Criteo",
  60. }[platform]
  61. class AdPool:
  62. """ 广告池子配置
  63. "admob": {
  64. "am_5": 9,
  65. "am_4": 7,
  66. "am_3": 5,
  67. "am_2": 3,
  68. "am_1": 2
  69. }
  70. dic_pool_items: {} 原始json文件
  71. arr_ordered_pool_items: [] 从大到小的广告配置项 {ad_id:adid, priority:3}
  72. """
  73. def __init__(self, pool_item_dic=None):
  74. """
  75. :param pool_item_dic: {} 原始配置
  76. """
  77. self.ori_json = {}
  78. self.ordered_pool_item_arr = []
  79. if pool_item_dic is not None:
  80. self.ori_json = pool_item_dic
  81. self.__parse(pool_item_dic)
  82. def __parse(self, pool_item_dic):
  83. pool_arr = []
  84. for ad_id in pool_item_dic:
  85. priority = pool_item_dic[ad_id]
  86. pool_arr.append({
  87. "ad_id": ad_id,
  88. "priority": priority
  89. })
  90. self.ordered_pool_item_arr = sorted(pool_arr, key=lambda e: e.__getitem__("priority"), reverse=True)
  91. def max_priority(self):
  92. """ :return: int """
  93. return self.ordered_pool_item_arr[0]["priority"]
  94. def max_priority_ad_id(self):
  95. """ :return: string """
  96. return self.ordered_pool_item_arr[0]["ad_id"]
  97. def add_ad_id(self, adId, priority):
  98. self.ori_json[adId] = priority
  99. self.__parse(self.ori_json)
  100. def print_desc(self):
  101. for item in self.ordered_pool_item_arr:
  102. print "{}:\t{}".format(item["priority"], item["ad_id"])
  103. class AdStrategy:
  104. """ 广告策略配置
  105. {
  106. "root": "am_3",
  107. "strategy": {
  108. "am_4": {
  109. "fail": 2,
  110. "platform": "admob",
  111. "suc": 2
  112. },
  113. "am_5": {
  114. "fail": 1,
  115. "platform": "admob",
  116. "suc": 2,
  117. "fail_next": "am_4"
  118. },
  119. "am_3": {
  120. "fail": 1,
  121. "platform": "admob",
  122. "suc": 1,
  123. "fail_next": "am_2",
  124. "suc_next": "am_5"
  125. },
  126. "am_2": {
  127. "fail": 1,
  128. "platform": "admob",
  129. "suc": 2,
  130. "fail_next": "am_1"
  131. },
  132. "am_1": {
  133. "fail": 2,
  134. "platform": "admob",
  135. "suc": 2
  136. }
  137. }
  138. }
  139. """
  140. def __init__(self, platform=AD_PLATFROM.UNKNOWN, strategy_dic=None, is_admob_5_floor_strategy=False):
  141. self.platform = platform
  142. self.is_admob_5_floor_strategy = is_admob_5_floor_strategy
  143. self.root_ad_id = ""
  144. self.strategy_json = {}
  145. self.ordered_ad_id_arr = []
  146. self.ori_json = {}
  147. if strategy_dic is not None:
  148. self.ori_json = strategy_dic
  149. self.__parse(strategy_dic)
  150. def __parse(self, strategy_dic):
  151. self.root_ad_id = strategy_dic["root"]
  152. self.strategy_json = strategy_dic["strategy"]
  153. self.is_admob_5_floor_strategy = (strategy_dic["strategy"][self.root_ad_id]["suc"] == 1)
  154. if self.is_admob_5_floor_strategy:
  155. self.ordered_ad_id_arr = [""] * 5
  156. self.ordered_ad_id_arr[2] = self.root_ad_id
  157. self.ordered_ad_id_arr[3] = self.strategy_json[self.ordered_ad_id_arr[2]]["fail_next"]
  158. self.ordered_ad_id_arr[4] = self.strategy_json[self.ordered_ad_id_arr[3]]["fail_next"]
  159. self.ordered_ad_id_arr[1] = self.strategy_json[self.ordered_ad_id_arr[2]]["suc_next"]
  160. self.ordered_ad_id_arr[0] = self.strategy_json[self.ordered_ad_id_arr[1]]["fail_next"]
  161. else:
  162. self.ordered_ad_id_arr = []
  163. self.ordered_ad_id_arr.append(self.root_ad_id)
  164. now_ad_id = self.root_ad_id
  165. while self.strategy_json[now_ad_id]["fail"] != 2:
  166. now_ad_id = self.strategy_json[now_ad_id]["fail_next"]
  167. self.ordered_ad_id_arr.append(now_ad_id)
  168. def update(self, ordered_ad_id_arr):
  169. """ 按从大到小的顺序排好
  170. ori_json 原始的json文件
  171. ordered_ad_ids: 从小到大 [fb_4, fb_3, fb_2]
  172. """
  173. dic = strategy_generator.generate_ordered_floor_strategy(ordered_ad_id_arr, AD_PLATFROM.string(self.platform))
  174. self.ori_json["root"] = dic["root"]
  175. self.ori_json["strategy"] = dic["strategy"]
  176. self.__parse(self.ori_json)
  177. def get_desc(self):
  178. string = self.ordered_ad_id_arr[0]
  179. for i in range(1, len(self.ordered_ad_id_arr)):
  180. string = "{} --> {}".format(string, self.ordered_ad_id_arr[i])
  181. return string
  182. def print_desc(self):
  183. print self.get_desc()
  184. class AdPage:
  185. """ 广告配置页面 | 版位
  186. page_name 页面名称
  187. """
  188. def __init__(self, page_name, page_dic=None):
  189. self.page_name = page_name
  190. self.ori_json = {}
  191. if page_dic is not None:
  192. self.ori_json = page_dic
  193. self.__parse(page_dic)
  194. def __parse(self, page_dic):
  195. self.pools = page_dic["pools"]
  196. self.ctrl = page_dic["ctrl"]
  197. def add_pool(self, pool_name):
  198. if not self.pools.__contains__(pool_name):
  199. self.pools.append(pool_name)
  200. class AdBidders:
  201. """ 竞价广告配置 """
  202. def __init__(self, bidder_dic=None):
  203. self.ori_json = {}
  204. if bidder_dic is not None:
  205. self.ori_json = bidder_dic
  206. def add_bidder(self, platform, adId):
  207. self.ori_json[AD_PLATFROM.string(platform)] = adId
  208. class AdPlatformId:
  209. """ 广告平台的app_id配置 """
  210. def __init__(self, platform_dic=None, platform=None, app_id=None):
  211. self.ori_json = {}
  212. self.platform = ""
  213. self.app_id = ""
  214. if platform_dic is not None:
  215. self.ori_json = platform_dic
  216. self.platform = platform_dic["p"]
  217. self.app_id = platform_dic["aid"]
  218. if platform is not None and app_id is not None:
  219. self.platform = platform
  220. self.app_id = app_id
  221. self.ori_json = {
  222. "p": platform,
  223. "aid": app_id
  224. }
  225. def get_desc(self):
  226. return "%s:\t\t%s" % (RED_SDK_AD_PLATFORM.string(self.platform), self.app_id)
  227. class AdPageCtrl:
  228. """ 广告页面配置 版位
  229. 参数列表:
  230. key: string
  231. value: number
  232. is_deprecated: bool
  233. config_name: string
  234. """
  235. def __init__(self, key, value):
  236. self.key = key
  237. self.value = value
  238. self.is_deprecated = False
  239. if self.key == "d":
  240. self.config_name = "展示天数"
  241. elif self.key == "level":
  242. self.config_name = "展示关数"
  243. else:
  244. self.is_deprecated = True
  245. self.config_name = "未配置或已废弃"
  246. def get_desc(self):
  247. return "{}: {}".format(self.config_name, self.value)
  248. class AdJson6:
  249. def __init__(self):
  250. self.ori_json = {}
  251. def read(self, file_path):
  252. if not os.path.exists(file_path):
  253. Logging.error("文件不存在: %s" % file_path)
  254. self.ori_json = json.load(open(file_path))
  255. if not self.ori_json.has_key("ad"):
  256. Logging.error("不存在ad根节点: %s" % file_path)
  257. check_keys = ["platform_ids", "global", "banners", "interstitials", "videos"]
  258. for key in check_keys:
  259. if not self.ori_json["ad"].has_key(key):
  260. Logging.error("ad节点下不存在子节点: %s: %s" % (key, file_path))
  261. def __dic_ad_type(self, ad_type):
  262. return self.ori_json["ad"][AD_TYPE.key_string(ad_type)]
  263. # 获取池子的配置
  264. def get_pool(self, ad_type, ad_platform):
  265. if ad_type == AD_TYPE.BANNER:
  266. Logging.error("error: banner不支持获取池")
  267. return None
  268. platform_str = AD_PLATFROM.string(ad_platform)
  269. if not self.__dic_ad_type(ad_type)["pools"].__contains__(platform_str):
  270. return None
  271. return AdPool(self.__dic_ad_type(ad_type)["pools"][platform_str])
  272. def add_pool(self, ad_type, ad_platform, ad_pool):
  273. self.__dic_ad_type(ad_type)["pools"][AD_PLATFROM.string(ad_platform)] = ad_pool.ori_json
  274. def remove_pool(self, ad_type, ad_platform):
  275. self.__dic_ad_type(ad_type)["pools"].__delitem__(AD_PLATFROM.string(ad_platform))
  276. def get_strategy(self, ad_type, ad_platform):
  277. platform_str = AD_PLATFROM.string(ad_platform)
  278. if ad_type == AD_TYPE.BANNER:
  279. return AdStrategy(ad_platform, self.__dic_ad_type(ad_type)["load_strategy"])
  280. if ad_type == AD_TYPE.INTERSTITIAL:
  281. if not self.__dic_ad_type(ad_type)["pools_load_strategy"].__contains__(platform_str):
  282. return None
  283. return AdStrategy(ad_platform, self.__dic_ad_type(ad_type)["pools_load_strategy"][platform_str])
  284. def add_strategy(self, ad_type, ad_platform, strategy):
  285. if ad_type == AD_TYPE.BANNER:
  286. Logging.error("error: banner不支持添加策略")
  287. if ad_type == AD_TYPE.INTERSTITIAL:
  288. self.__dic_ad_type(ad_type)["pools_load_strategy"][AD_PLATFROM.string(ad_platform)] = strategy.ori_json
  289. def remove_strategy(self, ad_type, ad_platform):
  290. self.__dic_ad_type(ad_type)["pools_load_strategy"].__delitem__(AD_PLATFROM.string(ad_platform))
  291. def get_bidders(self, ad_type):
  292. if ad_type == AD_TYPE.BANNER:
  293. Logging.error("error: banner不支持")
  294. dic_ad_type = self.__dic_ad_type(ad_type)
  295. if not dic_ad_type.has_key("bidders"):
  296. dic_ad_type["bidders"] = {}
  297. return AdBidders(dic_ad_type["bidders"])
  298. def get_ad_pages(self, ad_type):
  299. if ad_type == AD_TYPE.BANNER:
  300. Logging.error("error: banner不支持")
  301. pages = self.__dic_ad_type(ad_type)["pages"]
  302. arr = []
  303. for page_name in pages:
  304. dic_page = pages[page_name]
  305. ad_page = AdPage(page_name, dic_page)
  306. arr.append(ad_page)
  307. return arr
  308. def get_platform_ids(self):
  309. platform_id_arr = self.ori_json["ad"]["platform_ids"]
  310. arr = []
  311. for platform_id_dic in platform_id_arr:
  312. platform_id = AdPlatformId(platform_id_dic)
  313. arr.append(platform_id)
  314. return arr
  315. def add_platform_id(self, ad_platform, app_id):
  316. platform_id = AdPlatformId(platform=ad_platform, app_id=app_id)
  317. self.ori_json["ad"]["platform_ids"].append(platform_id.ori_json)
  318. def write(self, to_path):
  319. json.dump(self.ori_json, open(to_path, "w"))
  320. def print_desc(self):
  321. print "参数配置"
  322. param = json.loads(self.ori_json["parameters"])
  323. print "\t关卡工具发送比例: {}%".format(int(param["LSR"]) / 10)
  324. print "\tGT工具发送比例: {}%".format(int(param["GTSR"]) / 10)
  325. print "平台ID:"
  326. platforms = self.get_platform_ids()
  327. for p in platforms:
  328. print "\t{}".format(p.get_desc())
  329. print "全局配置:"
  330. global_json = self.ori_json["ad"]["global"]
  331. print "\tBanner刷新时间: \t{}".format(global_json["bci"])
  332. print "\t两次广告展示间隔: \t{}".format(global_json["showGap"])
  333. print "Banner广告配置:"
  334. print "\t展示条件:"
  335. banner_ctrl_dic = self.ori_json["ad"]["banners"]["ctrl"]
  336. for key in banner_ctrl_dic:
  337. value = banner_ctrl_dic[key]
  338. ad_page_ctrl = AdPageCtrl(key, value)
  339. print "\t\t{}".format(ad_page_ctrl.get_desc())
  340. print "\t加载策略:"
  341. banner_load_strategy = AdStrategy(AD_PLATFROM.ADMOB, self.ori_json["ad"]["banners"]["load_strategy"])
  342. print "\t\t{}".format(banner_load_strategy.get_desc())
  343. ad_type_names = ["插屏", "奖励视频"]
  344. ad_types = [AD_TYPE.INTERSTITIAL, AD_TYPE.VIDEO]
  345. for i in range(2):
  346. print "{}展示配置:".format(ad_type_names[i])
  347. inter_pools = self.ori_json["ad"][AD_TYPE.key_string(ad_types[i])]["pools"]
  348. arr_pool_ad_ids = []
  349. for pool_name in inter_pools:
  350. pool_config = inter_pools[pool_name]
  351. for ad_id in pool_config:
  352. priority = pool_config[ad_id]
  353. arr_pool_ad_ids.append({
  354. "ad_id": ad_id,
  355. "p": priority
  356. })
  357. arr_pool_ad_ids = sorted(arr_pool_ad_ids, key=lambda e: e.__getitem__("p"), reverse=True)
  358. print "\t瀑布流池子配置:"
  359. for ad_id_info in arr_pool_ad_ids:
  360. print "\t\t{}:\t{}".format(ad_id_info["p"], ad_id_info["ad_id"])
  361. print "\tBidders:"
  362. bidders = self.get_bidders(ad_types[i])
  363. if len(bidders.ori_json) >= 1:
  364. for platform_str in bidders.ori_json:
  365. ad_id = bidders.ori_json[platform_str]
  366. print "\t\t{}:\t{}".format(platform_str, ad_id)
  367. print "\t页面版位配置:"
  368. inter_pages = self.get_ad_pages(ad_types[i])
  369. for page in inter_pages:
  370. print "\t\t{}".format(page.page_name)
  371. string = "\t\t\t池子:\t"
  372. string = "{}{}".format(string, page.pools[0])
  373. for i in range(1, len(page.pools)):
  374. string = "{}, {}".format(string, page.pools[i])
  375. print string
  376. string = "\t\t\t展示条件:"
  377. for key in page.ctrl:
  378. value = page.ctrl[key]
  379. ctrl_info = AdPageCtrl(key, value)
  380. if not ctrl_info.is_deprecated:
  381. string = "{}\t{}".format(string, ctrl_info.get_desc())
  382. print string
  383. if __name__ == '__main__':
  384. ad_json = AdJson6()
  385. ad_json.read("/Users/zhuge/Temp/20201217/ad.json")
  386. ad_json.print_desc()
  387. new_facebook_id = "fb_ad_new"
  388. facebook_pool = ad_json.get_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK)
  389. facebook_pool.print_desc()
  390. max_facebook_adid = facebook_pool.max_priority_ad_id()
  391. print max_facebook_adid
  392. max_facebook_priority = facebook_pool.max_priority()
  393. facebook_pool.add_ad_id(new_facebook_id, max_facebook_priority + 1)
  394. facebook_pool.print_desc()
  395. strategy = ad_json.get_strategy(AD_TYPE.BANNER, AD_PLATFROM.ADMOB)
  396. strategy.print_desc()
  397. strategy = ad_json.get_strategy(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK)
  398. strategy.print_desc()
  399. strategy.ordered_ad_id_arr.insert(0, new_facebook_id)
  400. strategy.update(list(reversed(strategy.ordered_ad_id_arr)))
  401. strategy.print_desc()
  402. unity_ids = [
  403. "unity_inter_I1_lv1",
  404. "unity_inter_I1_lv2",
  405. "unity_inter_I2_lv1",
  406. "unity_inter_I2_lv2"
  407. ]
  408. unity_id_priorites = [
  409. 4, 6, 8, 10
  410. ]
  411. pools = {
  412. unity_ids[0]: unity_id_priorites[0],
  413. unity_ids[1]: unity_id_priorites[1],
  414. unity_ids[2]: unity_id_priorites[2],
  415. unity_ids[3]: unity_id_priorites[3]
  416. }
  417. pool = AdPool()
  418. pool.print_desc()
  419. for i in range(0, 4):
  420. pool.add_ad_id(unity_ids[i], unity_id_priorites[i])
  421. pool.print_desc()
  422. ad_json.add_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.UNITY, pool)
  423. strategy = AdStrategy(AD_PLATFROM.UNITY)
  424. strategy.update(unity_ids)
  425. strategy.print_desc()
  426. ad_json.add_strategy(AD_TYPE.INTERSTITIAL, AD_PLATFROM.UNITY, strategy)
  427. pages = ad_json.get_ad_pages(AD_TYPE.INTERSTITIAL)
  428. for page in pages:
  429. page.add_pool("unity")
  430. pages = ad_json.get_ad_pages(AD_TYPE.VIDEO)
  431. for page in pages:
  432. page.add_pool("unity")
  433. facebook_pool = ad_json.get_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK)
  434. max_ecpm_facebook_ad_id = facebook_pool.max_priority_ad_id()
  435. ad_json.remove_pool(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK)
  436. ad_json.remove_strategy(AD_TYPE.INTERSTITIAL, AD_PLATFROM.FACEBOOK)
  437. ad_bidders = ad_json.get_bidders(AD_TYPE.INTERSTITIAL)
  438. ad_bidders.add_bidder(AD_PLATFROM.FACEBOOK, "fb_bidding_id")
  439. ad_bidders.add_bidder(AD_PLATFROM.CRITEO, "crite_inter_i1_lv1")
  440. pages = ad_json.get_ad_pages(AD_TYPE.INTERSTITIAL)
  441. for page in pages:
  442. page.add_pool(AD_PLATFROM.string(AD_PLATFROM.CRITEO))
  443. ad_json.add_platform_id(RED_SDK_AD_PLATFORM.CRITEO, "criteo")
  444. ad_json.write("/Users/zhuge/Temp/20201217/ad_t.json")
  445. ad_json.print_desc()