118 lines
4.7 KiB
Python
118 lines
4.7 KiB
Python
# -*- 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)")
|