///|
/// Summary statistics for reproducible monitoring reports.
pub(all) struct TransactionSummary {
count : Int
total_amount : Int
minimum_amount : Int
maximum_amount : Int
customer_count : Int
account_count : Int
}
///|
pub fn summarize(transactions : Array[Transaction]) -> TransactionSummary {
if transactions.length() == 0 {
return {
count: 0,
total_amount: 0,
minimum_amount: 0,
maximum_amount: 0,
customer_count: 0,
account_count: 0,
}
}
let mut total = 0
let mut minimum = transactions[0].amount
let mut maximum = transactions[0].amount
let customers : Array[String] = []
let accounts : Array[String] = []
for tx in transactions {
total += tx.amount
if tx.amount < minimum {
minimum = tx.amount
}
if tx.amount > maximum {
maximum = tx.amount
}
if !contains_string(customers, tx.customer_id) {
customers.push(tx.customer_id)
}
if !contains_string(accounts, tx.account_id) {
accounts.push(tx.account_id)
}
}
{
count: transactions.length(),
total_amount: total,
minimum_amount: minimum,
maximum_amount: maximum,
customer_count: customers.length(),
account_count: accounts.length(),
}
}
///|
pub fn amounts_above(
transactions : Array[Transaction],
threshold : Int,
) -> Array[Int] {
let result : Array[Int] = []
for tx in transactions {
if tx.amount >= threshold {
result.push(tx.amount)
}
}
result
}
///|
pub fn count_by_region(
transactions : Array[Transaction],
region : String,
) -> Int {
let mut count = 0
for tx in transactions {
if tx.region == region {
count += 1
}
}
count
}
///|
pub fn count_by_currency(
transactions : Array[Transaction],
currency : String,
) -> Int {
let mut count = 0
for tx in transactions {
if tx.currency == currency {
count += 1
}
}
count
}
///|
pub fn total_for_customer(
transactions : Array[Transaction],
customer : String,
) -> Int {
let mut total = 0
for tx in transactions {
if tx.customer_id == customer {
total += tx.amount
}
}
total
}
///|
pub fn total_for_account(
transactions : Array[Transaction],
account : String,
) -> Int {
let mut total = 0
for tx in transactions {
if tx.account_id == account {
total += tx.amount
}
}
total
}
///|
pub fn percentile_rank(values : Array[Int], value : Int) -> Int {
if values.length() == 0 {
0
} else {
let mut below = 0
for item in values {
if item <= value {
below += 1
}
}
below * 100 / values.length()
}
}
///|
pub fn moving_totals(
transactions : Array[Transaction],
window : Int,
) -> Array[Int] {
let sorted = sort_by_time(transactions)
let totals : Array[Int] = []
for tx in sorted {
totals.push(customer_volume_in_window(tx, sorted, window))
}
totals
}