Initial commit: Memind H5 portal with MindSpace, Plaza, and agent jobs.
Track application source and tests; exclude local env, user workspaces, and runtime data via .gitignore. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
const DEFAULT_CONFIG = {
|
||||
w_view: 0.1,
|
||||
w_like: 3.0,
|
||||
w_comment: 5.0,
|
||||
w_collect: 4.0,
|
||||
decay_base: 2.0,
|
||||
decay_exp: 1.5,
|
||||
};
|
||||
|
||||
export function computeHotScore(stats, config = DEFAULT_CONFIG, nowMs = Date.now()) {
|
||||
const publishedAt = Number(stats.published_at ?? stats.publishedAt ?? nowMs);
|
||||
const ageHours = Math.max(0, (nowMs - publishedAt) / 3_600_000);
|
||||
const numerator =
|
||||
Number(stats.view_count ?? 0) * config.w_view +
|
||||
Number(stats.like_count ?? 0) * config.w_like +
|
||||
Number(stats.comment_count ?? 0) * config.w_comment +
|
||||
Number(stats.collect_count ?? 0) * config.w_collect;
|
||||
const denominator = Math.pow(ageHours + config.decay_base, config.decay_exp);
|
||||
if (denominator <= 0) return 0;
|
||||
return Math.max(0, numerator / denominator);
|
||||
}
|
||||
|
||||
export async function loadAlgorithmConfig(pool) {
|
||||
const [rows] = await pool.query(`SELECT \`key\`, value FROM plaza_algorithm_config`);
|
||||
const config = { ...DEFAULT_CONFIG };
|
||||
for (const row of rows) {
|
||||
if (row.key in config) config[row.key] = Number(row.value);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
export async function ensureAlgorithmConfig(pool) {
|
||||
const [rows] = await pool.query(`SELECT COUNT(*) AS count FROM plaza_algorithm_config`);
|
||||
if (Number(rows[0]?.count ?? 0) > 0) return;
|
||||
const now = Date.now();
|
||||
const seeds = [
|
||||
['w_view', 0.1, '浏览量权重'],
|
||||
['w_like', 3.0, '点赞权重'],
|
||||
['w_comment', 5.0, '评论权重'],
|
||||
['w_collect', 4.0, '收藏权重'],
|
||||
['decay_base', 2.0, '时间衰减基数'],
|
||||
['decay_exp', 1.5, '时间衰减指数'],
|
||||
];
|
||||
for (const [key, value, description] of seeds) {
|
||||
await pool.query(
|
||||
`INSERT INTO plaza_algorithm_config (\`key\`, value, description, updated_at)
|
||||
VALUES (?, ?, ?, ?)`,
|
||||
[key, value, description, now],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function recalculateHotScores(pool, { windowHours = 48 } = {}) {
|
||||
await ensureAlgorithmConfig(pool);
|
||||
const config = await loadAlgorithmConfig(pool);
|
||||
const now = Date.now();
|
||||
const windowStart = now - windowHours * 3_600_000;
|
||||
const [rows] = await pool.query(
|
||||
`SELECT id, view_count, like_count, comment_count, collect_count, published_at
|
||||
FROM plaza_posts
|
||||
WHERE status = 'published' AND published_at >= ?`,
|
||||
[windowStart],
|
||||
);
|
||||
if (rows.length === 0) return { updated: 0 };
|
||||
|
||||
const conn = await pool.getConnection();
|
||||
try {
|
||||
await conn.beginTransaction();
|
||||
for (const row of rows) {
|
||||
const hotScore = computeHotScore(row, config, now);
|
||||
await conn.query(
|
||||
`UPDATE plaza_posts SET hot_score = ?, hot_updated_at = ?, updated_at = ? WHERE id = ?`,
|
||||
[hotScore, now, now, row.id],
|
||||
);
|
||||
}
|
||||
await conn.commit();
|
||||
} catch (error) {
|
||||
await conn.rollback();
|
||||
throw error;
|
||||
} finally {
|
||||
conn.release();
|
||||
}
|
||||
return { updated: rows.length };
|
||||
}
|
||||
|
||||
export const algorithmInternals = {
|
||||
DEFAULT_CONFIG,
|
||||
computeHotScore,
|
||||
};
|
||||
Reference in New Issue
Block a user