Files
Hist/scripts/gen_entries_stress.py
T
fukunee 83de329750 Add stress test generator for 1000 synthetic entries
Adds scripts/gen_entries_stress.py to produce a large synthetic
dataset for performance testing, and notes the texture lazy-loading
plan in the README.
2026-09-19 04:26:55 +08:00

115 lines
4.5 KiB
Python

# -*- coding: utf-8 -*-
"""生成 1000 条合成词条,用于压力测试。
与 gen_entries.py 互斥:两者都写 src/data/entries.js,跑哪个就用哪份数据。
切换回真实数据: python scripts/gen_entries.py
"""
import random
import math
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" 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)")