// analyze-abc.js — 验证"A为主、B/C为辅"设计的实际效果 // 对历史已打招呼者跑新门槛+评分,对比 [A+B/C] 与 [仅A] 两组的评级分布 'use strict'; const path = require('path'); function tryRequire(names) { for (const n of names) { try { return require(n); } catch (_) {} } throw new Error('需要 better-sqlite3'); } const Database = tryRequire([process.env.SQLITE3_PATH, path.join(__dirname, 'node_modules', 'better-sqlite3'), 'better-sqlite3']); const { CONFIG, evaluateCandidate } = require('./scoring'); const dbPath = process.argv[2] || path.join(__dirname, '..', '..', 'data', 'recruitment.db'); const db = new Database(dbPath, { readonly: true }); const rows = db.prepare(` SELECT name, age, education, experience, raw_text, education_detail, work_detail, cert_detail FROM candidates WHERE greeted = 1`).all(); const groups = { 'A+语言信号': { 推: 0, 待: 0, 不: 0 }, '仅A(无B/C)': { 推: 0, 待: 0, 不: 0 } }; let pass = 0; for (const r of rows) { const res = evaluateCandidate({ rawText: r.raw_text, workDetail: r.work_detail, educationDetail: r.education_detail, certDetail: r.cert_detail, age: r.age, education: r.education, experience: r.experience, }); if (!res.gate.pass) continue; pass++; const edu = r.education_detail || r.raw_text || ''; const cert = (r.cert_detail || '') + '\n' + (r.raw_text || ''); const hasBC = CONFIG.majorKeywords.some(k => edu.includes(k)) || CONFIG.certKeywords.some(k => cert.includes(k)); const g = hasBC ? groups['A+语言信号'] : groups['仅A(无B/C)']; if (res.level === '推荐') g.推++; else if (res.level === '待定') g.待++; else g.不++; } console.log(`历史打招呼 ${rows.length} 人 → 过新门槛 ${pass} 人,分组评级分布:\n`); for (const [name, g] of Object.entries(groups)) { const t = g.推 + g.待 + g.不; if (!t) { console.log(`${name}: 0人`); continue; } console.log(`${name}: ${t}人 | 推荐 ${g.推} (${(g.推 / t * 100).toFixed(0)}%) | 待定 ${g.待} (${(g.待 / t * 100).toFixed(0)}%) | 不推荐 ${g.不} (${(g.不 / t * 100).toFixed(0)}%)`); console.log(` → 会打招呼的(推荐+待定)占 ${(g.推 + g.待) / t * 100}%\n`); }