# -*- coding: utf-8 -*- """生成 1000 条合成词条,用于压力测试。 与 gen_entries.py 互斥:两者都写 src/data/entries.js,跑哪个就用哪份数据。 切换回真实数据: python scripts/gen_entries.py """ import random import math from region_codes import make_code N = 1000 random.seed(20240101) CATS = ['人', '事', '物'] SKETCHES = [ 'fossil', 'tablet', 'pyramid', 'figure', 'temple', 'crown', 'colosseum', 'scroll', 'horseman', 'ship', 'globe', 'apple', 'machine', 'bell', 'tree', 'atom', 'dove', 'rocket', 'book', 'bridge', 'flag', 'scale', 'sword', ] # 世界主要城市坐标池:制造既分散又带聚集的分布(考验重叠与覆盖) CITY_POOL = [ (39.9, 116.4), (31.2, 121.5), (35.7, 139.7), (37.6, 127.0), (22.3, 114.2), (13.8, 100.5), (1.35, 103.8), (-6.2, 106.8), (21.0, 105.8), (28.6, 77.2), (19.1, 72.9), (23.8, 90.4), (35.7, 51.4), (33.3, 44.4), (24.7, 46.7), (41.0, 29.0), (31.8, 35.2), (30.0, 31.2), (36.8, 3.1), (33.6, -7.6), (6.5, 3.4), (9.0, 38.7), (-1.3, 36.8), (-26.2, 28.0), (-33.9, 18.4), (51.5, -0.1), (48.9, 2.4), (52.5, 13.4), (41.9, 12.5), (40.4, -3.7), (38.7, -9.1), (52.4, 4.9), (50.9, 4.4), (48.2, 16.4), (55.8, 37.6), (59.3, 18.1), (50.5, 30.5), (42.7, 23.3), (40.7, -74.0), (34.1, -118.2), (41.9, -87.6), (37.8, -122.4), (43.7, -79.4), (19.4, -99.1), (-23.6, -46.6), (-22.9, -43.2), (-34.6, -58.4), (-33.4, -70.7), (-12.0, -77.0), (4.7, -74.1), (-33.9, 151.2), (-37.8, 145.0), (-36.8, 174.8), ] def fmt_time(tn): if tn < 0: a = abs(tn) if a >= 1000000: return f"~ BC {a:,}" if a >= 10000: return f"~{a:,} BC" return f"~{a} BC" if tn >= 10000: return f"AD {tn:,}" return f"AD {tn}" def make_year(i): # 前 400 条:公元前(对数分布,远古稀疏、近古密集) # 后 600 条:公元后(线性分布 1..2022) if i < 400: u = i / 399.0 # 0..1 return -int(round(10 ** (u * math.log10(3.2e6)))) u = (i - 400) / 599.0 # 0..1 return int(round(1 + u * 2021)) def esc(s): return s.replace("\\", "\\\\").replace("'", "\\'") entries = [] for i in range(N): tn = make_year(i) cat = CATS[i % 3] sketch = SKETCHES[i % len(SKETCHES)] # 坐标:60% 落在城市池附近(带抖动),40% 均匀随机,制造聚集 + 分散 if random.random() < 0.6: base = random.choice(CITY_POOL) lat = round(base[0] + random.uniform(-0.4, 0.4), 5) lng = round(base[1] + random.uniform(-0.4, 0.4), 5) else: lat = round(random.uniform(-55, 70), 5) lng = round(random.uniform(-180, 180), 5) region = f"压力测试区 {i + 1:03d}" name = f"词条 {i + 1:03d}" desc = "这是一条用于压力测试的合成词条,用来检验在大量数据下三维翻页、时间轴与地理视图的渲染和交互性能表现。" entries.append((fmt_time(tn), tn, region, name, cat, sketch, lat, lng, desc)) # 按年份升序排列,保证时间轴(按列表顺序均布)与年代一致 entries.sort(key=lambda e: e[1]) lines = ["// 压力测试用合成词条数据(1000 条)", "// timeNumeric 用于时间轴排序/定位(公元前为负,公元后为正,单位:年)", "", "export const CATEGORY_INFO = {", " 人: { color: '#a03a2a', en: 'PERSONA' },", " 事: { color: '#2c4a6b', en: 'EVENTUS' },", " 物: { color: '#3f5c3a', en: 'ARTIFEX' },", "};", "", "export const ENTRIES = ["] for i, (time, tn, region, name, cat, sketch, lat, lng, desc) in enumerate(entries, 1): lines.append(" {") lines.append(f" id: 'No.{i:03d}',") lines.append(f" code: '{esc(make_code(tn, region, lat, lng, i, name, cat))}',") lines.append(f" time: '{esc(time)}',") lines.append(f" timeNumeric: {tn},") lines.append(f" region: '{esc(region)}',") lines.append(f" name: '{esc(name)}',") lines.append(f" category: '{esc(cat)}',") lines.append(f" sketch: '{esc(sketch)}',") lines.append(f" lat: {lat}, lng: {lng},") lines.append(f" description: '{esc(desc)}',") lines.append(" },") lines.append("];") lines.append("") lines.append("// 时间轴横向定位:对称对数映射,远古压缩、近代展开") lines.append("export function timelineX(t) {") lines.append(" const sign = t >= 0 ? 1 : -1;") lines.append(" const mag = Math.log10(1 + Math.abs(t) / 50);") lines.append(" return sign * mag * 1.15;") lines.append("}") with open("src/data/entries.js", "w", encoding="utf-8") as f: f.write("\n".join(lines) + "\n") print(f"written entries.js with {len(entries)} entries (stress)")