Air quality index in pure MoonBit: IAQI interpolation, the Chinese HJ 633-2026 and US EPA breakpoint tables, the dominant pollutant, and the EPA NowCast.
///|
let table = @moonaqi.hj633_2026(@moonaqi.Pm25, @moonaqi.Daily).unwrap()
let sub = @moonaqi.iaqi(table, 60.0) // Some(100)
///|
let readings = [
@moonaqi.Reading::of(@moonaqi.Pm25, @moonaqi.Daily, 60.0),
@moonaqi.Reading::of(@moonaqi.No2, @moonaqi.Daily, 40.0),
]
let air = @moonaqi.aqi(readings).unwrap()
air.index() // 100
air.category().name() // "Good"
air.dominant() // [Pm25]IAQI = (I_high - I_low) / (C_high - C_low) * (C - C_low) + I_low///|
let iaqi = @moonaqi.iaqi(
[
@moonaqi.Breakpoint::new(0.0, 35.0, 0, 50),
@moonaqi.Breakpoint::new(35.0, 75.0, 50, 100),
@moonaqi.Breakpoint::new(75.0, 115.0, 100, 150),
],
55.0,
)| Pollutant | One hour | Eight hours | Daily |
|---|---|---|---|
| PM2.5 | — | — | ✓ |
| PM10 | — | — | ✓ |
| SO₂ | ✓ | — | ✓ |
| NO₂ | ✓ | — | ✓ |
| CO | ✓ | — | ✓ |
| O₃ | ✓ | ✓ | — |
///|
let air = @moonaqi.aqi([
@moonaqi.Reading::of(@moonaqi.Pm25, @moonaqi.Daily, 60.0),
@moonaqi.Reading::of(@moonaqi.No2, @moonaqi.Daily, 40.0),
]).unwrap()| China | EPA | |
|---|---|---|
| Rounding | carried up | nearest integer |
| Before the lookup | as measured | truncated to 1–3 places |
| Units | µg/m³, mg/m³ | µg/m³, ppm, ppb |
///|
let air = @moonaqi.aqi_with(@moonaqi.Epa, [
@moonaqi.Reading::new(@moonaqi.Pm25, @moonaqi.Daily, 20.0),
@moonaqi.Reading::new(@moonaqi.O3, @moonaqi.EightHour, 0.07),
]).unwrap()///|
let nowcast = @moonaqi.nowcast_pm25([Some(30.0), Some(20.0), Some(10.0)])| Index | Band | 中文 | Colour |
|---|---|---|---|
| 0–50 | Excellent | 优 | Green 绿色 |
| 51–100 | Good | 良 | Yellow 黄色 |
| 101–150 | Lightly polluted | 轻度污染 | Orange 橙色 |
| 151–200 | Moderately polluted | 中度污染 | Red 红色 |
| 201–300 | Heavily polluted | 重度污染 | Purple 紫色 |
| 301+ | Severely polluted | 严重污染 | Maroon 褐红色 |
$ moon run cmd/main
daily report (日报)
pollutant concentration IAQI
PM2.5 115 ug/m3 150
PM10 120 ug/m3 100
SO2 50 ug/m3 50
NO2 40 ug/m3 50
CO 4 mg/m3 100
O3 160 ug/m3 100
AQI 150 Lightly polluted / 轻度污染
primary pollutant PM2.5
over the limit PM2.5$ moon run cmd/main -- --json
{
"report": "daily",
"aqi": 150,
"category": "Lightly polluted",
"chinese_category": "轻度污染",
...
}moon testpub(all) enum AqiCategory {
Excellent
Good
LightlyPolluted
ModeratelyPolluted
HeavilyPolluted
SeverelyPolluted
}pub(all) enum Averaging {
OneHour
EightHour
Daily
}pub struct Breakpoint {
concentration_low : Double
concentration_high : Double
index_low : Int
index_high : Int
}fn Breakpoint::new(concentration_low : Double, concentration_high : Double, index_low : Int, index_high : Int) -> Breakpointpub(all) enum Pollutant {
Pm25
Pm10
So2
No2
Co
O3
}pub(all) enum Report {
Daily
RealTime
}pub struct Rgb {
red : Int
green : Int
blue : Int
}pub(all) enum Rounding {
CarryUp
Nearest
}pub(all) enum Standard {
China
China2012
Epa
}fn breakpoints(standard : Standard, pollutant : Pollutant, averaging : Averaging) -> Array[Breakpoint]?Install
Download zipAir quality index in pure MoonBit: IAQI interpolation, the Chinese HJ 633-2026 and US EPA breakpoint tables, the dominant pollutant, and the EPA NowCast.