- 【深基2.例11】[NOIP2017 普及组] 成绩
求问这个rp是怎么计算的
- @ 2025-3-16 22:59:09
如题
4 条评论
-
240101460475 LV 8 @ 2025-3-28 21:45:18这是 Hydro 的 RP 计算 Typescript 文件 但是我没看懂 有没有大佬研究一下
-
@ 2025-3-28 21:44:35/* eslint-disable no-cond-assign / / eslint-disable no-await-in-loop */ // rp文件 import { NumericDictionary, unionWith } from 'lodash'; import { FilterQuery } from 'mongodb'; import { Tdoc, Udoc } from '../interface'; import difficultyAlgorithm from '../lib/difficulty'; import rating from '../lib/rating'; import { PRIV, STATUS } from '../model/builtin'; import * as contest from '../model/contest'; import domain from '../model/domain'; import problem from '../model/problem'; import UserModel from '../model/user'; import db from '../service/db';
export const description = 'Calculate rp of a domain, or all domains';
type ND = NumericDictionary;
interface RpDef { run(domainIds: string[], udict: ND, report: Function): Promise; hidden: boolean; base: number; }
const { log, max, min } = Math;
export const RpTypes: Record<string, RpDef> = { problem: { async run(domainIds, udict, report) { const problems = await problem.getMulti('', { domainId: { in: domainIds }, nAccept: { gt: 0 }, hidden: false }).toArray(); if (problems.length) await report({ message:
Found ${problems.length} problems in ${domainIds[0]}}); for (const pdoc of problems) { const cursor = problem.getMultiStatus( pdoc.domainId, { docId: pdoc.docId, rid: { ne: null }, uid: { ne: pdoc.owner }, score: { $gt: 0 }, }, ); const difficulty = +pdoc.difficulty || difficultyAlgorithm(pdoc.nSubmit, pdoc.nAccept) || 5; const p = difficulty / 100; let psdoc; while (psdoc = await cursor.next()) { udict[psdoc.uid] += min(psdoc.score, 100) * p; } } for (const key in udict) udict[key] = max(0, min(udict[key], log(udict[key]) / log(1.03))); }, hidden: false, base: 0, }, contest: { async run(domainIds, udict, report) { const contests: Tdoc<30>[] = await contest.getMulti('', { domainId: { $in: domainIds }, rated: true }) .limit(10).toArray() as any; if (contests.length) await report({ message:Found ${contests.length} contests in ${domainIds[0]}}); for (const tdoc of contests.reverse()) { const start = Date.now(); const cursor = contest.getMultiStatus(tdoc.domainId, { docId: tdoc.docId, journal: { $ne: null }, }).sort(contest.RULES[tdoc.rule].statusSort); if (!await cursor.count()) continue; const [rankedTsdocs] = await contest.RULES[tdoc.rule].ranked(tdoc, cursor); const users = rankedTsdocs.map((i) => ({ uid: i[1].uid, rank: i[0], old: udict[i[1].uid] })); // FIXME sum(rating.new) always less than sum(rating.old) for (const udoc of rating(users)) udict[udoc.uid] = udoc.new; await report({ case: { status: STATUS.STATUS_ACCEPTED, message: `Contest ${tdoc.title} finished`, time: Date.now() - start, memory: 0, score: 0, }, }); } for (const key in udict) udict[key] = max(1, udict[key] / 4 - 375); }, hidden: false, base: 1500, }, delta: { async run(domainIds, udict) { const dudocs = unionWith( await domain.getMultiUserInDomain( '', { domainId: { in: domainIds }, rpdelta: { exists: true } }, ).toArray(), (a, b) => a.uid === b.uid, ); for (const dudoc of dudocs) udict[dudoc.uid] = dudoc.rpdelta; }, hidden: true, base: 0, }, }; global.Hydro.model.rp = RpTypes;30>export async function calcLevel(domainId: string, report: Function) { const filter = { rp: { $gt: 0 } }; const ducnt = await domain.getMultiUserInDomain(domainId, filter).count(); await domain.setMultiUserInDomain(domainId, {}, { level: 0, rank: null }); if (!ducnt) return; let last = { rp: null }; let rank = 0; let count = 0; const coll = db.collection('domain.user'); const ducur = domain.getMultiUserInDomain(domainId, filter).project({ rp: 1 }).sort({ rp: -1 }); let bulk = coll.initializeUnorderedBulkOp(); // eslint-disable-next-line no-constant-condition while (true) { const dudoc = await ducur.next(); if (!dudoc) break; if ([0, 1].includes(dudoc.uid)) continue; count++; if (!dudoc.rp) dudoc.rp = null; if (dudoc.rp !== last.rp) rank = count; bulk.find({ _id: dudoc._id }).updateOne({ $set: { rank } }); last = dudoc; if (count % 100 === 0) report({ message:
#${count}: Rank ${rank}}); } await bulk.execute(); const levels = global.Hydro.model.builtin.LEVELS; bulk = coll.initializeUnorderedBulkOp(); for (let i = 0; i < levels.length; i++) { const query: FilterQuery = { domainId, and: [{ rank: { lte: (levels[i] * count) / 100 } }], }; if (i < levels.length - 1) query.and.push({ rank: { gt: (levels[i + 1] * count) / 100 } }); bulk.find(query).update({ $set: { level: i } }); } await bulk.execute(); }async function runInDomain(id: string, report: Function) { const info = await domain.getUnion(id); if (info) info.union.unshift(id); const domainIds = info ? info.union : [id]; const results: Record<keyof typeof RpTypes, ND> = {}; const udict = new Proxy({}, { get: (self, key) => self[key] || 0 }); for (const type in RpTypes) { results[type] = new Proxy({}, { get: (self, key) => self[key] || RpTypes[type].base }); await RpTypes[type].run(domainIds, results[type], report); for (const uid in results[type]) { const udoc = await UserModel.getById(id, +uid); if (!udoc?.hasPriv(PRIV.PRIV_USER_PROFILE)) continue; await domain.updateUserInDomain(id, +uid, { set: { [`rpInfo.{type}`]: results[type][uid] } }); udict[+uid] += results[type][uid]; } } await domain.setMultiUserInDomain(id, {}, { rp: 0 }); const bulk = db.collection('domain.user').initializeUnorderedBulkOp(); for (const uid in udict) { bulk.find({ domainId: id, uid: +uid }).upsert().update({ $set: { rp: Math.max(0, udict[uid]) } }); } if (bulk.length) await bulk.execute(); await calcLevel(id, report); }
export async function run({ domainId }, report: Function) { if (!domainId) { const domains = await domain.getMulti().toArray(); await report({ message:
Found ${domains.length} domains}); for (const i in domains) { const start = new Date().getTime(); await runInDomain(domains[i]._id, report); await report({ case: { status: STATUS.STATUS_ACCEPTED, message:Domain ${domains[i]._id} finished, time: new Date().getTime() - start, memory: 0, score: 0, }, progress: Math.floor(((+i + 1) / domains.length) * 100), }); } } else await runInDomain(domainId, report); return true; }export const validate = { domainId: 'string?', };
global.Hydro.script.rp = { run, description, validate };
-
@ 2025-3-28 12:10:19
你交了几道题+你AC了几道题
-
@ 2025-3-19 14:19:23
每道题之和吧(猜的)
❤️ 1🤔 1
- 1
信息
- ID
- 30
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 219
- 已通过
- 74
- 上传者