mirror of
https://github.com/modrinth/code.git
synced 2026-08-30 19:46:33 +00:00
day distribution logic
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use chrono::{Datelike, Months};
|
||||
use chrono::{Datelike, Months, NaiveDate};
|
||||
use dashmap::DashMap;
|
||||
use eyre::{Result, eyre};
|
||||
use rust_decimal::Decimal;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use xredis::RedisPool;
|
||||
|
||||
use crate::{
|
||||
@@ -15,19 +16,20 @@ use crate::{
|
||||
|
||||
const REDIS_KEY: &str = "aditude_month_estimate_v1";
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PeriodEstimate {
|
||||
pub period: YearMonth,
|
||||
pub days: Vec<DayEstimate>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DayEstimate {
|
||||
pub day: u32,
|
||||
pub date: NaiveDate,
|
||||
pub raw_estimated_revenue_usd: Decimal,
|
||||
pub impressions: u128,
|
||||
}
|
||||
|
||||
/// Get per-month and per-day estimated ad provider info.
|
||||
pub async fn estimate(
|
||||
aditude: &aditude::Client,
|
||||
redis: &RedisPool,
|
||||
@@ -93,7 +95,7 @@ async fn fetch_estimates(
|
||||
|
||||
let day = date.day();
|
||||
days.push(DayEstimate {
|
||||
day,
|
||||
date,
|
||||
raw_estimated_revenue_usd: row
|
||||
.revenue
|
||||
.wrap_err_with(|| eyre!("no revenue data for day {day}"))?,
|
||||
@@ -107,7 +109,7 @@ async fn fetch_estimates(
|
||||
// we have no clue if the Aditude row return order is stable,
|
||||
// so for safety sort the days here
|
||||
for period in map.values_mut() {
|
||||
period.days.sort_unstable_by_key(|day| day.day);
|
||||
period.days.sort_unstable_by_key(|day| day.date);
|
||||
}
|
||||
|
||||
Ok(map.into_iter().collect::<DashMap<_, _>>())
|
||||
|
||||
@@ -62,4 +62,84 @@
|
||||
//! epoch)
|
||||
//! - the decimal fraction of variance to apply
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use rust_decimal::{Decimal, dec};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod estimate;
|
||||
|
||||
/// Fraction defining much of the net revenue goes to the platform.
|
||||
const PLATFORM_REVENUE_SPLIT: Decimal = dec!(0.25);
|
||||
|
||||
/// How input revenue is distributed for a specific day.
|
||||
///
|
||||
/// This may refer to either estimated or actual revenue.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DayDistribution {
|
||||
pub raw_revenue_usd: Decimal,
|
||||
pub fees_usd: Decimal,
|
||||
pub variance_usd: Decimal,
|
||||
pub sum_adjustments_usd: Decimal,
|
||||
pub net_revenue_usd: Decimal,
|
||||
pub platform_net_revenue_usd: Decimal,
|
||||
pub creator_net_revenue_usd: Decimal,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PayoutVariance {
|
||||
pub starts_at: NaiveDate,
|
||||
pub frac: Decimal,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PayoutVariances {
|
||||
pub fracs: Vec<PayoutVariance>,
|
||||
pub default_frac: Decimal,
|
||||
}
|
||||
|
||||
impl PayoutVariances {
|
||||
pub const ZERO: Self = Self {
|
||||
fracs: Vec::new(),
|
||||
default_frac: Decimal::ZERO,
|
||||
};
|
||||
}
|
||||
|
||||
/// Compute the [`DayDistribution`] for an input revenue and impressions amount.
|
||||
///
|
||||
/// This logic may be used on both estimated and actual revenue. For actual
|
||||
/// revenue, [`PayoutVariances::ZERO`] should be used, since variance only
|
||||
/// applies to estimated days.
|
||||
pub fn distribution_for_day(
|
||||
date: NaiveDate,
|
||||
raw_revenue_usd: Decimal,
|
||||
impressions: u128,
|
||||
sum_adjustments_usd: Decimal,
|
||||
variances: &PayoutVariances,
|
||||
) -> DayDistribution {
|
||||
let fees_usd = {
|
||||
let clean_io_cpm = Decimal::from(8) / Decimal::from(1000);
|
||||
clean_io_cpm * Decimal::from(impressions) / Decimal::from(1000)
|
||||
};
|
||||
let variance_frac = variances
|
||||
.fracs
|
||||
.iter()
|
||||
.find(|v| v.starts_at >= date)
|
||||
.map(|v| v.frac)
|
||||
.unwrap_or(variances.default_frac);
|
||||
let variance_usd = raw_revenue_usd * variance_frac;
|
||||
|
||||
let net_estimated_revenue_usd =
|
||||
raw_revenue_usd - fees_usd - variance_usd + sum_adjustments_usd;
|
||||
|
||||
DayDistribution {
|
||||
raw_revenue_usd,
|
||||
fees_usd,
|
||||
variance_usd,
|
||||
sum_adjustments_usd,
|
||||
net_revenue_usd: net_estimated_revenue_usd,
|
||||
platform_net_revenue_usd: net_estimated_revenue_usd
|
||||
* PLATFORM_REVENUE_SPLIT,
|
||||
creator_net_revenue_usd: net_estimated_revenue_usd
|
||||
* (dec!(1) - PLATFORM_REVENUE_SPLIT),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user