///|
pub fn blast_radius_for_users(
plan : RolloutPlan,
users : Array[UserProfile],
minute : Int,
) -> BlastRadius {
let exposed = exposed_users(plan, users, minute)
let traffic = total_traffic(exposed)
let all_traffic = total_traffic(users)
let percent_bp = if users.length() == 0 {
0
} else {
exposed.length() * 10000 / users.length()
}
let traffic_bp = if all_traffic == 0 {
0
} else {
traffic * 10000 / all_traffic
}
let risk_score = blast_score(
percent_bp,
traffic_bp,
count_regions(exposed),
count_tiers(exposed),
)
{
exposed_users: exposed.length(),
exposed_traffic_units: traffic,
region_count: count_regions(exposed),
tier_count: count_tiers(exposed),
percent_bp,
risk_score,
}
}
///|
pub fn total_traffic(users : Array[UserProfile]) -> Int {
let mut total = 0
for user in users {
total += user.traffic_units
}
total
}
///|
fn count_regions(users : Array[UserProfile]) -> Int {
let mut na = false
let mut eu = false
let mut apac = false
let mut cn = false
let mut latam = false
let mut mea = false
let mut other = false
for user in users {
match user.region {
NA => na = true
EU => eu = true
APAC => apac = true
CN => cn = true
LATAM => latam = true
MEA => mea = true
OtherRegion => other = true
}
}
bool_count([na, eu, apac, cn, latam, mea, other])
}
///|
fn count_tiers(users : Array[UserProfile]) -> Int {
let mut free = false
let mut pro = false
let mut enterprise = false
let mut staff = false
let mut internal = false
for user in users {
match user.tier {
Free => free = true
Pro => pro = true
Enterprise => enterprise = true
Staff => staff = true
Internal => internal = true
}
}
bool_count([free, pro, enterprise, staff, internal])
}
///|
fn bool_count(values : Array[Bool]) -> Int {
let mut total = 0
for value in values {
if value {
total += 1
}
}
total
}
///|
fn blast_score(
user_bp : Int,
traffic_bp : Int,
region_count : Int,
tier_count : Int,
) -> Int {
let user_part = user_bp / 120
let traffic_part = traffic_bp / 90
let region_part = region_count * 6
let tier_part = tier_count * 4
clamp(user_part + traffic_part + region_part + tier_part, 0, 100)
}
///|
pub fn blast_radius_markdown(blast : BlastRadius) -> String {
let out = StringBuilder()
out.write_string("## Blast Radius\n\n")
out.write_string("- Exposed users: " + blast.exposed_users.to_string() + "\n")
out.write_string(
"- Exposed traffic units: " + blast.exposed_traffic_units.to_string() + "\n",
)
out.write_string("- Regions: " + blast.region_count.to_string() + "\n")
out.write_string("- Tiers: " + blast.tier_count.to_string() + "\n")
out.write_string("- User share: " + percent_text(blast.percent_bp) + "\n")
out.write_string("- Risk score: " + blast.risk_score.to_string() + "/100\n")
out.to_string()
}