airpredict/空气质量预测/源码/服务端/iapip-svr/test/material-ranking.test.ts

58 lines
2.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, it, expect } from 'vitest'
import { computeYpt, buildTierClassifier, annotateYpt } from '../src/common/material-ranking'
const M = (methanal: number|null, tvoc: number|null, benzene: number|null, toluene: number|null, pxylene: number|null) => ({
methanal_be_area: methanal, tvoc_be_area: tvoc, benzene_be_area: benzene, toluene_be_area: toluene, p_xylene_be_area: pxylene
})
describe('computeYpt', () => {
it('按权重求和', () => {
// 1*1.8 + 2*0.25 + 3*1 + 4*0.45 + 5*0.38 = 1.8+0.5+3+1.8+1.9 = 9
expect(computeYpt(M(1, 2, 3, 4, 5))).toBeCloseTo(9, 6)
})
it('任一缺值返回 null', () => {
expect(computeYpt(M(1, null, 3, 4, 5))).toBeNull()
expect(computeYpt(M(1, 2, 3, 4, undefined as never))).toBeNull()
})
})
describe('buildTierClassifier', () => {
it('全库三分位: 6 个材料 -> 2A 2B 2C', () => {
// ypt 分别为 1..6(每个只用 methanal 权重 1.8,但相对顺序即 methanal 顺序)
const all = [1, 2, 3, 4, 5, 6].map(v => M(v, 0, 0, 0, 0))
const classify = buildTierClassifier(all)
const ypts = all.map(computeYpt)
expect(ypts.map(classify)).toEqual(['A', 'A', 'B', 'B', 'C', 'C'])
})
it('缺值材料不参与分位、classify(null)=null', () => {
const all = [M(1,0,0,0,0), M(2,0,0,0,0), M(3,0,0,0,0), M(1,null,0,0,0)]
const classify = buildTierClassifier(all)
expect(classify(null)).toBeNull()
})
it('相同 Ypt 落同档(并列不强拆)', () => {
const all = [M(1,0,0,0,0), M(1,0,0,0,0), M(1,0,0,0,0)]
const classify = buildTierClassifier(all)
const tiers = all.map(m => classify(computeYpt(m)))
expect(new Set(tiers).size).toBe(1) // 全相等 -> 同一档
})
it('小 n=1 -> 该材料为 A', () => {
const all = [M(5,0,0,0,0)]
const classify = buildTierClassifier(all)
expect(classify(computeYpt(all[0]))).toBe('A')
})
})
describe('annotateYpt', () => {
it('只挂上 ypt健康档不再实时计算已定格到 health_level', () => {
const all = [M(1,0,0,0,0), M(2,0,0,0,0), M(3,0,0,0,0)]
const out = annotateYpt(all)
expect(out[0].ypt).toBeCloseTo(1.8, 6)
expect(out[2].ypt).toBeCloseTo(5.4, 6)
expect(out[0]).not.toHaveProperty('health_tier')
})
it('缺值材料 ypt=null', () => {
const out = annotateYpt([M(1, null, 0, 0, 0)])
expect(out[0].ypt).toBeNull()
})
})