统一 Rust 与 TypeScript 格式化门禁

纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口

完成项目 TypeScript/Prettier 与 Rust 全量格式化

修复 Pingora expected executable 门禁的空白敏感误报

同步开发运维文档与 AGC skill pack 格式化忽略规则
This commit is contained in:
2026-09-01 16:26:20 +08:00
parent ae79d50b14
commit 071faa482c
1051 changed files with 28412 additions and 19834 deletions
+153 -49
View File
@@ -3,11 +3,19 @@ import {
detectCustomWorldThemeMode,
resolveCustomWorldCompatibilityTemplateWorldType,
} from '../services/customWorldTheme';
import { CustomWorldItem, CustomWorldProfile, InventoryItem, WorldTemplateType, WorldType } from '../types';
import {
CustomWorldItem,
CustomWorldProfile,
InventoryItem,
WorldTemplateType,
WorldType,
} from '../types';
let runtimeCustomWorldProfile: CustomWorldProfile | null = null;
export function setRuntimeCustomWorldProfile(profile: CustomWorldProfile | null) {
export function setRuntimeCustomWorldProfile(
profile: CustomWorldProfile | null,
) {
runtimeCustomWorldProfile = profile;
}
@@ -17,7 +25,10 @@ export function getRuntimeCustomWorldProfile() {
export function resolveCompatibilityTemplateWorldType(
worldType: WorldType | null | undefined,
customWorldProfile: CustomWorldProfile | null | undefined = runtimeCustomWorldProfile,
customWorldProfile:
| CustomWorldProfile
| null
| undefined = runtimeCustomWorldProfile,
): WorldTemplateType | null {
if (!worldType) return null;
if (worldType === WorldType.CUSTOM) {
@@ -41,22 +52,32 @@ function hashText(value: string) {
}
function compactStrings(values: Array<string | null | undefined | false>) {
return [...new Set(
values
.map(value => typeof value === 'string' ? value.trim() : '')
.filter(Boolean),
)];
return [
...new Set(
values
.map((value) => (typeof value === 'string' ? value.trim() : ''))
.filter(Boolean),
),
];
}
function pickCyclic<T>(items: readonly T[], index: number, fallback: T): T {
return items[index % items.length] ?? fallback;
}
function normalizeInventoryItemId(item: CustomWorldItem, quantity: number, seedKey: string) {
function normalizeInventoryItemId(
item: CustomWorldItem,
quantity: number,
seedKey: string,
) {
return `custom:${item.id}:${quantity}:${hashText(seedKey).toString(36)}`;
}
function toInventoryItem(item: CustomWorldItem, quantity: number, seedKey: string): InventoryItem {
function toInventoryItem(
item: CustomWorldItem,
quantity: number,
seedKey: string,
): InventoryItem {
return {
id: normalizeInventoryItemId(item, quantity, seedKey),
category: item.category,
@@ -89,8 +110,22 @@ export interface RuntimeCustomWorldItemQueryOptions {
rarityFloor?: CustomWorldItem['rarity'];
}
const RARITY_ORDER: CustomWorldItem['rarity'][] = ['common', 'uncommon', 'rare', 'epic', 'legendary'];
const DEFAULT_RUNTIME_CATEGORIES = ['武器', '护甲', '饰品', '消耗品', '材料', '稀有品', '专属物'] as const;
const RARITY_ORDER: CustomWorldItem['rarity'][] = [
'common',
'uncommon',
'rare',
'epic',
'legendary',
];
const DEFAULT_RUNTIME_CATEGORIES = [
'武器',
'护甲',
'饰品',
'消耗品',
'材料',
'稀有品',
'专属物',
] as const;
const CATEGORY_DEFAULT_TAGS: Record<string, string[]> = {
武器: ['weapon', '战斗'],
护甲: ['armor', '防护'],
@@ -146,26 +181,49 @@ function buildRuntimeItemTags(
seed: number,
) {
const baseTags = [...(CATEGORY_DEFAULT_TAGS[category] ?? ['world-item'])];
const preferredTags = [...new Set((options.preferredTags ?? []).map(tag => tag.trim()).filter(Boolean))];
const keywordTags = [...new Set((options.keywords ?? []).map(tag => tag.trim()).filter(Boolean))];
const selectedPreferredTag = preferredTags.length > 0
? preferredTags[seed % preferredTags.length]
: undefined;
const selectedKeywordTag = keywordTags.length > 0
? keywordTags[(seed >>> 3) % keywordTags.length]
: undefined;
const preferredTags = [
...new Set(
(options.preferredTags ?? []).map((tag) => tag.trim()).filter(Boolean),
),
];
const keywordTags = [
...new Set(
(options.keywords ?? []).map((tag) => tag.trim()).filter(Boolean),
),
];
const selectedPreferredTag =
preferredTags.length > 0
? preferredTags[seed % preferredTags.length]
: undefined;
const selectedKeywordTag =
keywordTags.length > 0
? keywordTags[(seed >>> 3) % keywordTags.length]
: undefined;
if (category === '消耗品' && preferredTags.some(tag => /mana|法力|灵气|内息/u.test(tag))) {
if (
category === '消耗品' &&
preferredTags.some((tag) => /mana|法力|灵气|内息/u.test(tag))
) {
baseTags.push('mana');
}
if (category === '消耗品' && preferredTags.some(tag => /heal|疗|血|恢复/u.test(tag))) {
if (
category === '消耗品' &&
preferredTags.some((tag) => /heal|疗|血|恢复/u.test(tag))
) {
baseTags.push('healing');
}
return compactStrings([...baseTags, selectedPreferredTag, selectedKeywordTag]).slice(0, 5);
return compactStrings([
...baseTags,
selectedPreferredTag,
selectedKeywordTag,
]).slice(0, 5);
}
function inferRuntimeItemRarity(seed: number, rarityFloorValue: number): CustomWorldItem['rarity'] {
function inferRuntimeItemRarity(
seed: number,
rarityFloorValue: number,
): CustomWorldItem['rarity'] {
const rolledRarity = [0, 1, 1, 2, 2, 2, 3, 3, 4][seed % 9] ?? 0;
return RARITY_ORDER[Math.max(rarityFloorValue, rolledRarity)] ?? 'common';
}
@@ -194,7 +252,10 @@ function inferRuntimeItemMechanics(
equipmentSlotId: 'armor' as const,
statProfile: {
maxHpBonus: 10 * rarityTier + (seed % 8),
incomingDamageMultiplier: Math.max(0.72, Number((1 - rarityTier * 0.04).toFixed(2))),
incomingDamageMultiplier: Math.max(
0.72,
Number((1 - rarityTier * 0.04).toFixed(2)),
),
},
useProfile: null,
value: 26 * rarityTier,
@@ -218,7 +279,10 @@ function inferRuntimeItemMechanics(
equipmentSlotId: null,
statProfile: null,
useProfile: tags.includes('mana')
? { manaRestore: 12 * rarityTier, cooldownReduction: rarityTier >= 3 ? 1 : 0 }
? {
manaRestore: 12 * rarityTier,
cooldownReduction: rarityTier >= 3 ? 1 : 0,
}
: { hpRestore: 16 * rarityTier },
value: 18 * rarityTier,
};
@@ -241,7 +305,11 @@ function buildProceduralRuntimeItem(
const themeMode = detectCustomWorldThemeMode(profile);
const seed = hashText(`${profile.id}:${seedKey}:${index}`);
const defaultCategory = DEFAULT_RUNTIME_CATEGORIES[0] ?? 'world-item';
const categories = compactStrings(options.categories?.length ? options.categories : [...DEFAULT_RUNTIME_CATEGORIES]);
const categories = compactStrings(
options.categories?.length
? options.categories
: [...DEFAULT_RUNTIME_CATEGORIES],
);
const category = pickCyclic(categories, seed, defaultCategory);
const rarityFloorValue = getRarityFloorValue(options.rarityFloor);
const rarity = inferRuntimeItemRarity(seed, rarityFloorValue);
@@ -251,7 +319,9 @@ function buildProceduralRuntimeItem(
const fallbackNounPool = ['sigil', 'relic', 'token', 'seal', 'core', 'mark'];
const resolvedNounPool = nounPool ?? fallbackNounPool;
const worldSeed = getWorldSeedLabel(profile);
const optionSeed = sanitizeNameFragment((options.preferredTags ?? [])[0] ?? '') || sanitizeNameFragment((options.keywords ?? [])[0] ?? '');
const optionSeed =
sanitizeNameFragment((options.preferredTags ?? [])[0] ?? '') ||
sanitizeNameFragment((options.keywords ?? [])[0] ?? '');
const prefix = pickCyclic(prefixPool, seed >>> 2, prefixPool[0] ?? 'world');
const noun = pickCyclic(resolvedNounPool, seed >>> 5, fallbackNounPool[0]);
const name = `${prefix}${optionSeed || worldSeed}${noun}${index + 1}`;
@@ -277,10 +347,16 @@ function matchesRuntimeQuery(
options: RuntimeCustomWorldItemQueryOptions,
rarityFloorValue: number,
) {
if (options.categories?.length && !options.categories.includes(item.category)) {
if (
options.categories?.length &&
!options.categories.includes(item.category)
) {
return false;
}
if (options.tags?.length && !options.tags.some(tag => item.tags.includes(tag))) {
if (
options.tags?.length &&
!options.tags.some((tag) => item.tags.includes(tag))
) {
return false;
}
if (rarityFloorValue >= 0) {
@@ -292,18 +368,26 @@ function matchesRuntimeQuery(
return true;
}
function scoreItemRelevance(item: CustomWorldItem, options: RuntimeCustomWorldItemQueryOptions) {
const haystack = normalizeLookupText([
item.name,
item.category,
item.description,
...(item.tags ?? []),
].join(' '));
const itemTags = new Set((item.tags ?? []).map(tag => normalizeLookupText(tag)));
function scoreItemRelevance(
item: CustomWorldItem,
options: RuntimeCustomWorldItemQueryOptions,
) {
const haystack = normalizeLookupText(
[item.name, item.category, item.description, ...(item.tags ?? [])].join(
' ',
),
);
const itemTags = new Set(
(item.tags ?? []).map((tag) => normalizeLookupText(tag)),
);
let score = 0;
const preferredTags = [...new Set((options.preferredTags ?? []).map(normalizeLookupText).filter(Boolean))];
preferredTags.forEach(tag => {
const preferredTags = [
...new Set(
(options.preferredTags ?? []).map(normalizeLookupText).filter(Boolean),
),
];
preferredTags.forEach((tag) => {
if (itemTags.has(tag)) {
score += 10;
return;
@@ -313,8 +397,14 @@ function scoreItemRelevance(item: CustomWorldItem, options: RuntimeCustomWorldIt
}
});
const keywords = [...new Set((options.keywords ?? []).map(normalizeLookupText).filter(keyword => keyword.length >= 2))];
keywords.forEach(keyword => {
const keywords = [
...new Set(
(options.keywords ?? [])
.map(normalizeLookupText)
.filter((keyword) => keyword.length >= 2),
),
];
keywords.forEach((keyword) => {
if (!haystack.includes(keyword)) {
return;
}
@@ -331,10 +421,15 @@ function scoreItemRelevance(item: CustomWorldItem, options: RuntimeCustomWorldIt
return score;
}
function rankItems(items: CustomWorldItem[], seedKey: string, options: RuntimeCustomWorldItemQueryOptions = {}) {
function rankItems(
items: CustomWorldItem[],
seedKey: string,
options: RuntimeCustomWorldItemQueryOptions = {},
) {
const seed = hashText(seedKey);
return [...items].sort((left, right) => {
const relevanceDelta = scoreItemRelevance(right, options) - scoreItemRelevance(left, options);
const relevanceDelta =
scoreItemRelevance(right, options) - scoreItemRelevance(left, options);
if (relevanceDelta !== 0) {
return relevanceDelta;
}
@@ -353,13 +448,20 @@ export function pickRuntimeCustomWorldItems(
if (!profile) return [] as CustomWorldItem[];
const rarityFloorValue = getRarityFloorValue(options.rarityFloor);
const sourceItems = Array.from({ length: Math.max(16, (options.count ?? 1) * 10) }, (_, index) =>
buildProceduralRuntimeItem(profile, seedKey, options, index),
const sourceItems = Array.from(
{ length: Math.max(16, (options.count ?? 1) * 10) },
(_, index) => buildProceduralRuntimeItem(profile, seedKey, options, index),
);
const filtered = sourceItems.filter(item => matchesRuntimeQuery(item, options, rarityFloorValue));
const filtered = sourceItems.filter((item) =>
matchesRuntimeQuery(item, options, rarityFloorValue),
);
return rankItems(filtered.length > 0 ? filtered : sourceItems, seedKey, options).slice(0, options.count ?? 1);
return rankItems(
filtered.length > 0 ? filtered : sourceItems,
seedKey,
options,
).slice(0, options.count ?? 1);
}
export function buildRuntimeCustomWorldInventoryItems(
@@ -369,5 +471,7 @@ export function buildRuntimeCustomWorldInventoryItems(
const count = options.count ?? 1;
return pickRuntimeCustomWorldItems(seedKey, options)
.slice(0, count)
.map((item, index) => toInventoryItem(item, options.quantity ?? 1, `${seedKey}:${index}`));
.map((item, index) =>
toInventoryItem(item, options.quantity ?? 1, `${seedKey}:${index}`),
);
}