模块:OPDI
来自Blockland Wiki
更多操作
此模块的文档可以在模块:OPDI/doc创建
local p = {}
local function num(v)
if v == nil then return nil end
v = mw.text.trim(tostring(v))
if v == '' then return nil end
return tonumber(v)
end
local function clamp(x, lo, hi)
if x < lo then return lo end
if x > hi then return hi end
return x
end
local function index_linear(value, minv, maxv)
return clamp((value - minv) / (maxv - minv), 0, 1)
end
local function income_index(gdp_pc)
return clamp((math.log(gdp_pc) - math.log(100)) / (math.log(75000) - math.log(100)), 0, 1)
end
local function tertiary_index(share)
return index_linear(share, 20, 80)
end
local function demographic_factor(birth, death)
-- 死亡率和自然增长率只作为轻惩罚项,避免“出生率越低越先进”的单向误判。
local death_penalty = clamp((death - 12) / 28, 0, 0.12)
local growth = birth - death
local growth_penalty = clamp((math.abs(growth - 0.8) - 2.5) / 35, 0, 0.08)
return 1 - death_penalty - growth_penalty
end
local function calc(args)
local male = num(args.male or args['男性预期寿命'])
local female = num(args.female or args['女性预期寿命'])
local literacy = num(args.literacy or args['识字率'])
local gdp_pc = num(args.gdp_pc or args['人均GDP'])
local tertiary = num(args.tertiary or args['第三产业占比'])
local birth = num(args.birth or args['出生率'])
local death = num(args.death or args['死亡率'])
if not (male and female and literacy and gdp_pc and tertiary and birth and death) then
return nil
end
if gdp_pc <= 0 then
return nil
end
local life = (male + female) / 2
local health = index_linear(life, 20, 85)
local education = clamp(literacy / 100, 0, 1)
local income = income_index(gdp_pc)
local structure = tertiary_index(tertiary)
local demo = demographic_factor(birth, death)
-- 加权几何平均:健康、教育、收入为主体;产业结构为轻权重;人口项为修正系数。
local score = (health ^ 0.35) * (education ^ 0.25) * (income ^ 0.30) * (structure ^ 0.10) * demo
return clamp(score, 0, 1)
end
local function grade(score)
if score >= 0.93 then return 'A+' end
if score >= 0.88 then return 'A' end
if score >= 0.84 then return 'A-' end
if score >= 0.80 then return 'B+' end
if score >= 0.76 then return 'B' end
if score >= 0.72 then return 'B-' end
if score >= 0.68 then return 'C+' end
if score >= 0.64 then return 'C' end
if score >= 0.60 then return 'C-' end
if score >= 0.55 then return 'D+' end
if score >= 0.50 then return 'D' end
if score >= 0.45 then return 'D-' end
if score >= 0.38 then return 'E+' end
if score >= 0.30 then return 'E' end
return 'E-'
end
function p.score(frame)
local score = calc(frame.args)
if not score then return '' end
return string.format('%.3f', score)
end
function p.grade(frame)
local score = calc(frame.args)
if not score then return '' end
return grade(score)
end
function p.display(frame)
local score = calc(frame.args)
if not score then return '{{Stay}} 无数据' end
return string.format('%.3f(%s)', score, grade(score))
end
return p