custom.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package addata
  2. import (
  3. "math/rand"
  4. "miads/adslib/redis_data"
  5. "miads/adslib/utils"
  6. "strings"
  7. )
  8. func CombineOrderBy(adData *AdData, dsp *utils.DspParam) {
  9. ads_item, extra_item = yield get_ads_infos(dsp, order_type = 1)
  10. if extra_item == None:
  11. raise
  12. gen.Return(infos)
  13. last_target_addition = infos.get('target_addition', [])
  14. extra_item_addition = extra_item.get('target_addition', [])
  15. if len(extra_item_addition) == 0:
  16. raise
  17. gen.Return(infos)
  18. if len(extra_item_addition) == 1:
  19. last_target_addition[0]['urls'].extend(extra_item_addition[0]['urls'])
  20. raise
  21. gen.Return(infos)
  22. else:
  23. last_target_addition[0]['urls'].extend(extra_item_addition[0]['urls'])
  24. last_target_addition[1]['urls'].extend(extra_item_addition[1]['urls'])
  25. infos['target'] = extra_item['target']
  26. infos['js_order_id'] = extra_item['js_order_id']
  27. last_target_addition[1]['type'] = 'CLICK'
  28. raise
  29. gen.Return(infos)
  30. }
  31. // 获取一个广告
  32. func getOneAds(dsp *utils.DspParam, orderType int, fixFlag int) (*redis_data.AdOrderInfo, error){
  33. // 取出广告
  34. orders, err := redis_data.GetOrderInfos(dsp, fixFlag)
  35. if err != nil {
  36. return nil, err
  37. }
  38. if len(orders) == 0 {
  39. return nil, nil
  40. }
  41. gotOrders := make([]redis_data.AdOrderInfo, 0, 1000)
  42. allKpi := int64(0)
  43. for _, order := range orders {
  44. if order.OrderType == int64(orderType) {
  45. gotOrders = append(gotOrders, order)
  46. allKpi += order.ShowKpi
  47. }
  48. }
  49. orderRange := make([]int, 0, 1000)
  50. curRateIdx := 0
  51. // orderRange中记录的是当前同索引位置的gotOrders里的order的比例上限, 比如如果有两个order [ShowKpi:40, ShowKpi: 60]
  52. // 那么orderRange就是 [rate:400, rate: 1000], 所以要按比例取order, 只需要获得在比例上限里随机取一个数, 然后判断落在那个orderRange里,
  53. // 对应去gotOrders取同索引里的order即可, 因为算法里有对小于1的比例做补偿, 所以rate上限可能超出1000, rate乘1000而不是100主要是为了
  54. // 如果showKpi差异过大, 对大量小于1的订单做补偿, 会影响整体流量分布, 这里放到1000倍, 降低补偿1的影响, 算法复杂度是O(n), 只有三个非嵌套循环
  55. for _, order := range gotOrders {
  56. rate := int(float32(order.ShowKpi) / float32(allKpi) * 1000)
  57. // 防止比例过小, 取int后变为0
  58. if rate < 1 {
  59. rate = 1
  60. }
  61. curRateIdx = curRateIdx + rate
  62. orderRange = append(orderRange, curRateIdx)
  63. }
  64. randNum := rand.Intn(curRateIdx)
  65. for i, rateRange := range orderRange {
  66. if randNum <= rateRange {
  67. return &gotOrders[i], nil
  68. }
  69. }
  70. return nil, nil
  71. }
  72. func getSubTimeValue(adData *redis_data.AdOrderInfo, a) {
  73. b_min = int(ads_item['begin_time'])
  74. b_min = datetime.fromtimestamp(b_min)
  75. // 获取当前分钟值
  76. now_minute = b_min.minute + (b_min.hour * 60)
  77. // 不足一天
  78. all_count = 1587820.0
  79. e_time = int(ads_item['end_time'])
  80. // 获取起点分钟
  81. be_minute = now_minute + 2
  82. // 获取分钟数到24点还能跑多少值
  83. key = "time_all_count_" + str(be_minute)
  84. if int(ads_item['line_type']) == 1:
  85. // 定制曲线
  86. key = "time_all_count_{0}_{1}".format(ads_item['order_id'], str(be_minute))
  87. // 起始剩余值
  88. all_count = redis_tools.get_key_int_value(key)
  89. // 计算最后分钟
  90. e_d = datetime.fromtimestamp(e_time)
  91. e_d_min = e_d.minute + (e_d.hour * 60)
  92. if e_d_min > 1439:
  93. e_d_min = e_d_min - 1440 + 2
  94. key = "time_all_count_" + str(e_d_min)
  95. if int(ads_item['line_type']) == 1:
  96. // 定制曲线
  97. key = "time_all_count_{0}_{1}".format(ads_item['order_id'], str(e_d_min))
  98. // 结束的剩余值 - 起始剩余值 = 获取区间能跑的值
  99. all_count = all_count - redis_tools.get_key_int_value(key)
  100. return all_count
  101. }
  102. func GetAdsInfos(dsp *utils.DspParam, advertiser string, orderType int, fixFlag int, xiaomiHasFlag int) {
  103. ua = dsp.ua_client
  104. req_source = dsp.req_source
  105. order, err := getOneAds(dsp, order_type, fix_flag)
  106. if err != nil {
  107. return err
  108. }
  109. if order == nil {
  110. return nil
  111. }
  112. r = rand.Intn( 100)
  113. if xiaomiHasFlag == 1 {
  114. if strings.Index(order.Title, "_ios") > 0 {
  115. return nil
  116. } else {
  117. r = rand.Intn(50)
  118. }
  119. }
  120. a = datetime.now()
  121. // 获取剩余时间内的值
  122. all_count = get_sub_time_value(ads_item, a)
  123. all_count = all_count * 1.0
  124. #已经投放的key
  125. show_key = "order_kpi_%s_%d%d%d_show_kpi" % (ads_item['order_id'], a.year, a.month, a.day)
  126. click_key = "order_kpi_%s_%d%d%d_click_kpi" % (ads_item['order_id'], a.year, a.month, a.day)
  127. over_kpi = redis_tools.get_key_int_value(show_key)
  128. show_kpi = ads_item['show_kpi']
  129. click_kpi = ads_item['click_kpi']
  130. if all_count < 1:
  131. raise
  132. gen.Return((None, None))
  133. plan_key = "plan_all_kpi_%s_%d%d%d_show_kpi" % (ads_item['order_id'], a.year, a.month, a.day)
  134. redis_common.redis_ads().set(plan_key, all_count, 60*24*60)
  135. w_value, rate = get_now_min_value(ads_item, all_count, show_kpi, a)
  136. if w_value < 1:
  137. w_value = 1
  138. plan_key = "plan_kpi_%s_%d%d%d_%d_show_kpi" % (ads_item['order_id'], a.year, a.month, a.day, a.hour*60 + a.minute)
  139. redis_common.redis_ads().set(plan_key, w_value, 60*24*60)
  140. over_key = "order_kpi_%s_%d%d%d_%d_show_kpi" % (ads_item['order_id'], a.year, a.month, a.day, a.hour*60 + a.minute)
  141. o_value = int(redis_tools.get_key_int_value(over_key))
  142. js_order_id = int(ads_item['js_order_id'])
  143. if o_value < w_value:
  144. order_name = ads_item['title']
  145. data =
  146. {
  147. "js_order_id":js_order_id,
  148. "target":"",
  149. "video_url":"",
  150. "duration":5,
  151. "target_addition":[],
  152. "image_url":"",
  153. "result":0,
  154. "msg":0,
  155. "user_agent":ua,
  156. "order_name":order_name
  157. }
  158. #放量
  159. redis_tools.incr_key_value(over_key)
  160. redis_tools.incr_key_value(show_key)
  161. show_url = ads_item['show_url']
  162. click_url = ads_item['click_url']
  163. target = ads_item['target_url']
  164. if order_name.find("_ios") > 0:
  165. ios_imei, ios_ua = get_ios_ua_imei(dsp)
  166. if ios_ua:
  167. data['user_agent'] = ios_ua
  168. if ads_item.get('imei_replace_flag', 0) == 1 and
  169. ios_imei:
  170. show_url = show_url.replace('__IDFA__', ios_imei)
  171. click_url = click_url.replace('__IDFA__', ios_imei)
  172. target = target.replace('__IDFA__', ios_imei)
  173. if order_name.find("__OS__") > 0:
  174. show_url = show_url.replace('__OS__', '1')
  175. click_url = click_url.replace('__OS__', '1')
  176. target = target.replace('__OS__', '1')
  177. elif
  178. order_name.find("_android") > 0 :
  179. ### 判断是否需要替换imei
  180. if ads_item.get('imei_replace_flag', 0) == 1:
  181. show_url = show_url.replace('__IMEI__', dsp.real_md5_imei)
  182. click_url = click_url.replace('__IMEI__', dsp.real_md5_imei)
  183. target = target.replace('__IMEI__', dsp.real_md5_imei)
  184. if order_name.find("__OS__") > 0:
  185. show_url = show_url.replace('__OS__', '0')
  186. click_url = click_url.replace('__OS__', '0')
  187. target = target.replace('__OS__', '0')
  188. else:
  189. if r < 40:
  190. ios_imei, ios_ua = get_ios_ua_imei(dsp)
  191. if ios_ua:
  192. data['user_agent'] = ios_ua
  193. if ads_item.get('imei_replace_flag', 0) == 1 and
  194. ios_imei:
  195. show_url = show_url.replace('__IDFA__', ios_imei)
  196. click_url = click_url.replace('__IDFA__', ios_imei)
  197. target = target.replace('__IDFA__', ios_imei)
  198. if order_name.find("__OS__") > 0:
  199. show_url = show_url.replace('__OS__', '1')
  200. click_url = click_url.replace('__OS__', '1')
  201. target = target.replace('__OS__', '1')
  202. else:
  203. if ads_item.get('imei_replace_flag', 0) == 1:
  204. show_url = show_url.replace('__IMEI__', dsp.real_md5_imei)
  205. click_url = click_url.replace('__IMEI__', dsp.real_md5_imei)
  206. target = target.replace('__IMEI__', dsp.real_md5_imei)
  207. if order_name.find("__OS__") > 0:
  208. show_url = show_url.replace('__OS__', '0')
  209. click_url = click_url.replace('__OS__', '0')
  210. target = target.replace('__OS__', '0')
  211. if order_name.find("__IP__") > 0:
  212. show_url = show_url.replace('__IP__', dsp.ip)
  213. click_url = click_url.replace('__IP__', dsp.ip)
  214. target = target.replace('__IP__', dsp.ip)
  215. if order_type == 0:
  216. addi = get_monitor_url('VIEW', 5, order_name, req_source, show_url)
  217. else:
  218. addi = get_monitor_url('VIEW', 5, order_name, 'follow', show_url)
  219. #addi['urls'].append(show_url)
  220. data['target_addition'].append(addi)
  221. r = random.randint(0, 1000)
  222. c_rate = click_kpi * 1.0 / (ads_item['show_kpi']) * 1000
  223. if r < c_rate:
  224. #下发点击
  225. addi = get_monitor_url('CLICK', 1, order_name, req_source, click_url)
  226. #addi['urls'].append(click_url)
  227. data['target_addition'].append(addi)
  228. md5_skip = hashlib.md5(target).hexdigest()
  229. redis_tools.incr_key_value(click_key)
  230. real_target = ads_config.Host + "?action=LOADING&req_source={0}&advertiser={2}&skip={1}&skip_other={3}".format(
  231. req_source, '', order_name, md5_skip)
  232. ### 塞入缓存中
  233. redis_tools.set_skip_info(md5_skip, target)
  234. data['target'] = real_target
  235. raise
  236. gen.Return((None, data))
  237. #获取当前已经放出去的次数
  238. raise gen.Return((None, None))
  239. }~