import math import random from typing import List, Dict, Optional #首页数据 class indexData: def __init__(self): #提交的模板数据 self.sectors_webSiteData = { "base": { "websiteId": "" }, "style": { "styleId": "" }, "template": { "index": [], "class": [], "list": [], "article": [], "search": [], "aloneList": [], "aloneArticle": [] }, "ad": { "top":{ "width": 830, "height": 110, "name": "", "price": 0, "introduce":"", "website_id": "", "thumb": "http://img.bjzxtw.org.cn/pre/image/png/20250527/1748332370111555.png", "typeid": 2, "ad_tag": "" }, "index": [], "class": [], "list": [], "article": [], "search": [], "aloneList": [], "aloneArticle": [] }, "isSearch": True } #提交的画布数据 self.canvas_data = { "topAd":{ "width": 830, "height": 110, "name": "", "price": "", "introduce": "", "website_id": "", "thumb": "http://192.168.1.234:19000/pre/image/jpeg/20251226/1766715237727691.jpg", "typeid": 2, "ad_tag": "", "ad_url": "" }, "template":{ "index":[], "class": [], "list": [], "article": [], "search": [], "aloneList": [], "aloneArticle": [] } } #创建一个templateData实例 templateData = indexData() # 动态权重计算类 class Sector: def __init__(self, name: str, total: int, weight: int, CNname: str): self.name = name # 名称 self.total = total # 总数 self.weight = weight # 权重 self.remaining = total # 剩余数量 后面我们要对比 剩余数据/总数 来计算权重 self.used_count = 0 # 记录已使用次数 self.CNname = CNname # 中文名称 """ 思路: 1.按照权限的高低选择通栏 2.如果权限一样,随机选择 3.每选择两次新闻通栏后,adSector权重提升 """ class SectorScheduler: def __init__(self, sectors_config: List[Dict]): # 过滤掉total为0的sector(即不存在的sector) self.sectors = [ Sector(sector['name'], sector['total'], sector['weight'], sector['CNname']) for sector in sectors_config if sector['total'] > 0 ] self.history = [] # 记录选择历史 self.consecutive_count = 0 # 连续选择相同权重sector的次数 self.last_weight = None # 上一次选择的权重 # 定义需要随机选择的sector组 self.random_sector_group = {sector['name'] for sector in sectors_config if sector.get('random', False)} def calculate_dynamic_weight(self, sector: Sector) -> float: """计算动态权重 - 更复杂的权重计算""" if sector.remaining <= 0: return 0 base_weight = sector.weight # 1. 基于剩余数量的权重调整 usage_ratio = sector.remaining / sector.total quantity_factor = math.pow(usage_ratio, 0.4) # 剩余数量越多,权重相对越高 # 2. 基于使用频率的权重调整(避免过度使用) if sector.used_count > 0: usage_frequency = 1.0 / (1 + math.log(1 + sector.used_count)) else: usage_frequency = 1.0 # 3. 对于adSector的特殊处理 if sector.name == "adSector": # 检查是否需要插入adSector(每两个相同权重后) if self.consecutive_count >= 2 and self.last_weight == 7: ad_boost = 2.0 # 大幅提升adSector权重 else: # 根据历史中adSector的出现频率调整 recent_ad_count = self.history[-3:].count("adSector") if len(self.history) >= 3 else 0 if recent_ad_count == 0: ad_boost = 1.5 # 一段时间没出现,适当提升 else: ad_boost = 0.8 # 最近出现较多,适当降低 else: ad_boost = 1.0 # 4. 对于高权重sector的保护(确保它们优先被选择) if base_weight >= 8: priority_boost = 1.5 else: priority_boost = 1.0 dynamic_weight = base_weight * quantity_factor * usage_frequency * ad_boost * priority_boost return dynamic_weight def get_random_sector_from_group(self, target_weight: int) -> Optional[Sector]: """从随机组中随机选择一个指定权重的sector""" available_sectors = [ sector for sector in self.sectors if sector.name in self.random_sector_group and sector.weight == target_weight and sector.remaining > 0 ] if available_sectors: return random.choice(available_sectors) return None def select_next(self) -> Optional[str]: """选择下一个sector""" best_sector = None best_weight = -1 current_weight = 7 # 随机选择组的权重 # 首先检查是否需要强制插入adSector if (self.consecutive_count >= 2 and self.last_weight == current_weight and any(s.name == "adSector" and s.remaining > 0 for s in self.sectors)): ad_sector = next(s for s in self.sectors if s.name == "adSector" and s.remaining > 0) ad_sector.remaining -= 1 ad_sector.used_count += 1 # 更新历史记录 self.history.append("adSector") self.consecutive_count = 0 self.last_weight = ad_sector.weight return "adSector" # 正常选择逻辑 for sector in self.sectors: if sector.remaining > 0: # 对于随机选择组的sector,使用统一的权重计算 if sector.name in self.random_sector_group and sector.weight == current_weight: # 使用组内统一的权重值进行比较 dynamic_weight = current_weight else: dynamic_weight = self.calculate_dynamic_weight(sector) if dynamic_weight > best_weight: best_weight = dynamic_weight best_sector = sector if best_sector: # 如果最佳sector属于随机选择组,则随机选择该组中的一个 if best_sector.name in self.random_sector_group and best_sector.weight == current_weight: random_sector = self.get_random_sector_from_group(current_weight) if random_sector: best_sector = random_sector best_sector.remaining -= 1 best_sector.used_count += 1 # 更新连续选择计数 if self.last_weight == best_sector.weight and best_sector.name != "adSector": self.consecutive_count += 1 else: self.consecutive_count = 1 self.last_weight = best_sector.weight self.history.append(best_sector.name) return best_sector.name return None def generate_sequence(self, count: int) -> List[str]: """生成指定长度的序列""" result = [] for i in range(count): next_sector = self.select_next() if next_sector: result.append(next_sector) else: break # 没有可选的sector了 return result