new margins

This commit is contained in:
Brandon Thomas committed 2026-06-12 12:36:41 -04:00
1 parent ac5f5e01b0
commit 9ebe28c949
30 files changed
+754 -737

No files matched your search

@@ -14,7 +14,7 @@ use crate::generate::generate_image::providers::artcraft::midjourney_7::request:
/// Kinovi-side math (historical, 22,000-credit package at 193 credits/$1):
/// 12 Kinovi credits per Midjourney task → batches 1/2/4 land on 6/12/25¢;
/// batch 3 is `ceil((12 × 3 / 193) × 100) = 19`. Under the current
/// 500,000-credit package (231 credits/$1) Kinovi costs only 6/11/21¢ —
/// 525,000-credit package (243 credits/$1) Kinovi costs only 5/10/20¢ —
/// user pricing is intentionally kept at the 193-derived values.
#[derive(Clone, Debug)]
pub struct ArtcraftMidjourney7CostState {
@@ -131,8 +131,8 @@ mod tests {
// ── Cost coverage vs Kinovi for batches 1/2/4 ──
//
// Kinovi midjourney_7 costs 6/11/21¢ for batches 1/2/4 under the
// 500,000-credit package. The artcraft user price (6/12/25¢) must always
// Kinovi midjourney_7 costs 5/10/20¢ for batches 1/2/4 under the
// 525,000-credit package. The artcraft user price (6/12/25¢) must always
// cover the provider cost.
mod kinovi_margin {
@@ -144,7 +144,7 @@ mod tests {
fn batch_1_covers_kinovi_cost() {
let kinovi = KinoviMidjourney7CostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(1);
@@ -159,7 +159,7 @@ mod tests {
fn batch_2_covers_kinovi_cost() {
let kinovi = KinoviMidjourney7CostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(2);
@@ -174,7 +174,7 @@ mod tests {
fn batch_4_covers_kinovi_cost() {
let kinovi = KinoviMidjourney7CostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(4);
@@ -93,7 +93,7 @@ mod tests {
fn batch_1_covers_kinovi_cost() {
let kinovi = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(1);
@@ -108,7 +108,7 @@ mod tests {
fn batch_2_covers_kinovi_cost() {
let kinovi = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(2);
@@ -123,7 +123,7 @@ mod tests {
fn batch_4_covers_kinovi_cost() {
let kinovi = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(4);
@@ -93,7 +93,7 @@ mod tests {
fn batch_1_covers_kinovi_cost() {
let kinovi = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(1);
@@ -108,7 +108,7 @@ mod tests {
fn batch_2_covers_kinovi_cost() {
let kinovi = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(2);
@@ -123,7 +123,7 @@ mod tests {
fn batch_4_covers_kinovi_cost() {
let kinovi = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
// Under the 500,000-credit package (~231 credits/$1) Kinovi's cost
// Under the 525,000-credit package (~243 credits/$1) Kinovi's cost
// sits below this artcraft user price. Assert the user price covers
// the provider cost (1¢ tolerance for Kinovi's round-up).
let artcraft_cents = cost_cents(4);
@@ -86,27 +86,27 @@ mod tests {
}
}
// ── USD pricing (231 credits per dollar; rounded up) ──
// ── USD pricing (243 credits per dollar; rounded up) ──
mod usd {
use super::*;
#[test]
fn batch_one_is_six_cents() {
// 12/231 × 100 = 5.19 → 6¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::One), 6); // rounds UP
fn batch_one_is_five_cents() {
// 12/243 × 100 = 4.94 → 5¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::One), 5); // rounds UP
}
#[test]
fn batch_two_is_eleven_cents() {
// 24/231 × 100 = 10.39 → 11¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Two), 11); // rounds UP
fn batch_two_is_ten_cents() {
// 24/243 × 100 = 9.88 → 10¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Two), 10); // rounds UP
}
#[test]
fn batch_four_is_twentyone_cents() {
// 48/231 × 100 = 20.78 → 21¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Four), 21);
fn batch_four_is_twenty_cents() {
// 48/243 × 100 = 19.75 → 20¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Four), 20);
}
}
@@ -56,11 +56,11 @@ mod tests {
use super::*;
#[test]
fn batch_one_is_twelve_credits_and_six_cents() {
fn batch_one_is_twelve_credits_and_five_cents() {
let cost = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(12));
assert_eq!(cost.cost_in_usd_cents, Some(6)); // 1200/231 = 5.19 -> rounds UP
assert_eq!(cost.cost_in_usd_cents, Some(5)); // 1200/243 = 4.94 -> rounds UP
}
#[test]
@@ -68,7 +68,7 @@ mod tests {
let cost = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(24));
assert_eq!(cost.cost_in_usd_cents, Some(11)); // 2400/231 = 10.39 -> rounds UP
assert_eq!(cost.cost_in_usd_cents, Some(10)); // 2400/243 = 9.88 -> rounds UP
}
#[test]
@@ -76,7 +76,7 @@ mod tests {
let cost = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(48));
assert_eq!(cost.cost_in_usd_cents, Some(21));
assert_eq!(cost.cost_in_usd_cents, Some(20));
}
#[test]
@@ -56,11 +56,11 @@ mod tests {
use super::*;
#[test]
fn batch_one_is_twelve_credits_and_six_cents() {
fn batch_one_is_twelve_credits_and_five_cents() {
let cost = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(12));
assert_eq!(cost.cost_in_usd_cents, Some(6)); // 1200/231 = 5.19 -> rounds UP
assert_eq!(cost.cost_in_usd_cents, Some(5)); // 1200/243 = 4.94 -> rounds UP
}
#[test]
@@ -68,7 +68,7 @@ mod tests {
let cost = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(24));
assert_eq!(cost.cost_in_usd_cents, Some(11)); // 2400/231 = 10.39 -> rounds UP
assert_eq!(cost.cost_in_usd_cents, Some(10)); // 2400/243 = 9.88 -> rounds UP
}
#[test]
@@ -76,6 +76,6 @@ mod tests {
let cost = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(48));
assert_eq!(cost.cost_in_usd_cents, Some(21));
assert_eq!(cost.cost_in_usd_cents, Some(20));
}
}
@@ -15,7 +15,7 @@ use crate::generate::generate_video::providers::artcraft::happy_horse_1p0::reque
// Default resolution (None) is 720p.
// Batch count multiplies the total cost.
// Credit package (historical): 22,000 credits for $114 (~193 credits/$1).
// The upstream package is now 500,000 credits for $2,159.09 (~231 credits/$1),
// The upstream package is now 525,000 credits for $2,159.0909 (~243 credits/$1),
// but user pricing is intentionally kept at the 193-derived rates.
//
// ArtCraft credits: 100 credits = $1.00, so ArtCraft credits = USD cents.
@@ -237,7 +237,7 @@ mod tests {
.estimate_cost()
.expect("kinovi estimate_cost");
// Under the 500,000-credit package (~231 credits/$1) Kinovi's
// Under the 525,000-credit package (~243 credits/$1) Kinovi's
// cost sits below the artcraft user-facing price. Assert the
// user price covers the provider cost (1¢ tolerance for
// Kinovi's round-up).
@@ -20,7 +20,7 @@ use crate::generate::generate_video::providers::artcraft::seedance_2p0::request:
/// happens once at the end after multiplying by duration × batch.
///
/// NB: Derivation is historical (193 credits/$1 package). The upstream
/// package is now 500,000 credits for $2,159.09 (~231 credits/$1), but
/// package is now 525,000 credits for $2,159.0909 (~243 credits/$1), but
/// user pricing is intentionally kept at these 193-derived rates.
const CENTS_PER_SECOND_480P: f64 = 7.772;
const CENTS_PER_SECOND_720P: f64 = 16.0;
@@ -231,7 +231,7 @@ mod tests {
let resolutions = [
Some(RouterResolution::FourEightyP),
Some(RouterResolution::TenEightyP),
// NB: Still underpriced even at 231 credits/$1
// NB: Still underpriced even at 243 credits/$1
// (e.g. 5s: kinovi 87¢ vs user price 80¢).
//Some(RouterResolution::SevenTwentyP),
//None,
@@ -256,7 +256,7 @@ mod tests {
.estimate_cost()
.expect("kinovi estimate_cost");
// Under the 500,000-credit package (~231 credits/$1) Kinovi's
// Under the 525,000-credit package (~243 credits/$1) Kinovi's
// cost sits below the artcraft user-facing price. Assert the
// user price covers the provider cost (1¢ tolerance for
// Kinovi's round-up).
@@ -297,7 +297,7 @@ mod tests {
.estimate_cost()
.expect("kinovi estimate_cost");
// Under the 500,000-credit package (~231 credits/$1) Kinovi's
// Under the 525,000-credit package (~243 credits/$1) Kinovi's
// cost sits below the artcraft user-facing price. Assert the
// user price covers the provider cost (1¢ tolerance for
// Kinovi's round-up).
@@ -320,10 +320,12 @@ mod tests {
fn artcraft_price_covers_kinovi_cost_all_combos_with_video_reference() {
let resolutions = [
Some(RouterResolution::SevenTwentyP),
Some(RouterResolution::TenEightyP),
Some(RouterResolution::FourEightyP),
// NB: Still underpriced even at 231 credits/$1
// (e.g. 5s: kinovi 87¢ vs user price 80¢).
// NB: 1080p with a video reference became profitable at 243
// credits/$1 (e.g. 5s: kinovi 223¢ vs user price 233¢), so it no
// longer belongs in this not-covered sweep — see
// price_comparison_tests for the exact margins.
//Some(RouterResolution::TenEightyP),
//None,
];
@@ -379,15 +381,17 @@ mod tests {
// -- Price comparison with Kinovi, case by case --
//
// Every combination of resolution (480p/720p/1080p), duration (4/5/10/15s),
// and video references (with/without), at batch 1. Split into the combos
// where the artcraft user price covers Kinovi's cost (with the exact margin)
// and the combos where it does not (with the exact shortfall).
// This model runs on Kinovi Seedance 2.0 (RouterVideoModel::Seedance2p0).
// Every combination of resolution (480p/720p/1080p), duration (4/5/10/15s), and
// video references (with/without), at batch 1.
// Split into the combos where the artcraft user price covers the cost
// (with the exact margin) and the combos where it does not (exact shortfall).
mod price_comparison_tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -398,159 +402,159 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: margin is 5 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(5);
asserting("480p 4s no-ref: margin is 6 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(6);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: margin is 6 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(6);
asserting("480p 5s no-ref: margin is 8 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(8);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: margin is 13 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(13);
asserting("480p 10s no-ref: margin is 16 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(16);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: margin is 19 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(19);
asserting("480p 15s no-ref: margin is 24 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(24);
// -- 1080p, no video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(false));
asserting("1080p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 4s no-ref: margin is 31 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(31);
asserting("1080p 4s no-ref: margin is 38 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(38);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(false));
asserting("1080p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 5s no-ref: margin is 38 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(38);
asserting("1080p 5s no-ref: margin is 47 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(47);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(false));
asserting("1080p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 10s no-ref: margin is 76 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(76);
asserting("1080p 10s no-ref: margin is 95 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(95);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(false));
asserting("1080p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 15s no-ref: margin is 114 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(114);
asserting("1080p 15s no-ref: margin is 143 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(143);
// -- 1080p, with video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(true));
asserting("1080p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 4s with-ref: margin is 9 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(9);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(true));
asserting("1080p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 5s with-ref: margin is 10 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(10);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(true));
asserting("1080p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 10s with-ref: margin is 21 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(21);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(true));
asserting("1080p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 15s with-ref: margin is 32 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(32);
}
#[test]
fn kinovi_cost_not_covered_by_artcraft_price() {
// -- 720p, no video references (720p is underpriced even without refs) --
// -- 720p, no video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: shortfall is 6 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(6);
asserting("720p 4s no-ref: shortfall is 2 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(2);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: shortfall is 7 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(7);
asserting("720p 5s no-ref: shortfall is 3 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(3);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: shortfall is 14 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(14);
asserting("720p 10s no-ref: shortfall is 5 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(5);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: shortfall is 20 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(20);
asserting("720p 15s no-ref: shortfall is 7 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(7);
// -- 480p, with video references (the surcharge outruns the margin) --
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: shortfall is 2 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(2);
asserting("480p 4s with-ref: shortfall is 1 cent")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(1);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: shortfall is 3 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(3);
asserting("480p 5s with-ref: shortfall is 1 cent")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(1);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: shortfall is 5 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(5);
asserting("480p 10s with-ref: shortfall is 1 cent")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(1);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: shortfall is 7 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(7);
asserting("480p 15s with-ref: shortfall is 1 cent")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(1);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: shortfall is 20 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(20);
asserting("720p 4s with-ref: shortfall is 16 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(16);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: shortfall is 24 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(24);
asserting("720p 5s with-ref: shortfall is 19 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(19);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: shortfall is 48 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(48);
asserting("720p 10s with-ref: shortfall is 38 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(38);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: shortfall is 72 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(72);
// -- 1080p, with video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(true));
asserting("1080p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 4s with-ref: shortfall is 1 cent")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(1);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(true));
asserting("1080p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 5s with-ref: shortfall is 1 cent")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(1);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(true));
asserting("1080p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 10s with-ref: shortfall is 2 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(2);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(true));
asserting("1080p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 15s with-ref: shortfall is 3 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(3);
asserting("720p 15s with-ref: shortfall is 57 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(57);
}
// -- Helpers --
@@ -572,6 +576,7 @@ mod tests {
video_references: VideoReferences,
) -> ComparedPrices {
let artcraft = GenerateVideoRequestBuilder {
model: RouterVideoModel::Seedance2p0,
provider: RouterProvider::Artcraft,
resolution: Some(resolution),
duration_seconds: Some(duration.0),
@@ -588,6 +593,7 @@ mod tests {
.expect("artcraft estimate_cost");
let kinovi = GenerateVideoRequestBuilder {
model: RouterVideoModel::Seedance2p0,
provider: RouterProvider::Seedance2Pro,
resolution: Some(resolution),
duration_seconds: Some(duration.0),
@@ -165,6 +165,7 @@ mod tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -175,156 +176,156 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: margin is 14 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(14);
asserting("480p 4s no-ref: margin is 15 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(15);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: margin is 17 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(17);
asserting("480p 5s no-ref: margin is 19 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(19);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: margin is 35 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(35);
asserting("480p 10s no-ref: margin is 38 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(38);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: margin is 52 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(52);
asserting("480p 15s no-ref: margin is 57 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(57);
// -- 720p, no video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: margin is 30 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(30);
asserting("720p 4s no-ref: margin is 34 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(34);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: margin is 38 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(38);
asserting("720p 5s no-ref: margin is 42 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(42);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: margin is 76 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(76);
asserting("720p 10s no-ref: margin is 85 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(85);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: margin is 115 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(115);
asserting("720p 15s no-ref: margin is 128 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(128);
// -- 1080p, no video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(false));
asserting("1080p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 4s no-ref: margin is 44 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(44);
asserting("1080p 4s no-ref: margin is 51 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(51);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(false));
asserting("1080p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 5s no-ref: margin is 55 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(55);
asserting("1080p 5s no-ref: margin is 64 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(64);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(false));
asserting("1080p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 10s no-ref: margin is 110 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(110);
asserting("1080p 10s no-ref: margin is 129 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(129);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(false));
asserting("1080p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 15s no-ref: margin is 165 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(165);
asserting("1080p 15s no-ref: margin is 194 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(194);
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: margin is 7 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(7);
asserting("480p 4s with-ref: margin is 8 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(8);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: margin is 8 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(8);
asserting("480p 5s with-ref: margin is 10 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(10);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: margin is 17 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(17);
asserting("480p 10s with-ref: margin is 21 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(21);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: margin is 26 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(26);
asserting("480p 15s with-ref: margin is 32 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(32);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: margin is 16 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(16);
asserting("720p 4s with-ref: margin is 20 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(20);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: margin is 21 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(21);
asserting("720p 5s with-ref: margin is 26 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(26);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: margin is 42 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(42);
asserting("720p 10s with-ref: margin is 52 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(52);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: margin is 63 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(63);
asserting("720p 15s with-ref: margin is 78 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(78);
// -- 1080p, with video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(true));
asserting("1080p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 4s with-ref: margin is 12 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(12);
asserting("1080p 4s with-ref: margin is 22 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(22);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(true));
asserting("1080p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 5s with-ref: margin is 16 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(16);
asserting("1080p 5s with-ref: margin is 27 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(27);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(true));
asserting("1080p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 10s with-ref: margin is 32 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(32);
asserting("1080p 10s with-ref: margin is 55 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(55);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(true));
asserting("1080p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 15s with-ref: margin is 48 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(48);
asserting("1080p 15s with-ref: margin is 83 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(83);
}
// -- Helpers --
@@ -136,6 +136,7 @@ mod tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -146,104 +147,104 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: margin is 11 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(11);
asserting("480p 4s no-ref: margin is 12 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(12);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: margin is 14 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(14);
asserting("480p 5s no-ref: margin is 16 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(16);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: margin is 29 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(29);
asserting("480p 10s no-ref: margin is 32 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(32);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: margin is 44 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(44);
asserting("480p 15s no-ref: margin is 48 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(48);
// -- 720p, no video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: margin is 31 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(31);
asserting("720p 4s no-ref: margin is 33 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(33);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: margin is 39 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(39);
asserting("720p 5s no-ref: margin is 42 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(42);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: margin is 78 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(78);
asserting("720p 10s no-ref: margin is 84 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(84);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: margin is 118 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(118);
asserting("720p 15s no-ref: margin is 127 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(127);
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: margin is 4 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(4);
asserting("480p 4s with-ref: margin is 6 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(6);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: margin is 6 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(6);
asserting("480p 5s with-ref: margin is 7 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(7);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: margin is 12 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(12);
asserting("480p 10s with-ref: margin is 15 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(15);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: margin is 18 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(18);
asserting("480p 15s with-ref: margin is 23 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(23);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: margin is 21 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(21);
asserting("720p 4s with-ref: margin is 24 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(24);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: margin is 26 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(26);
asserting("720p 5s with-ref: margin is 30 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(30);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: margin is 52 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(52);
asserting("720p 10s with-ref: margin is 60 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(60);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: margin is 79 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(79);
asserting("720p 15s with-ref: margin is 90 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(90);
}
// -- Helpers --
@@ -165,6 +165,7 @@ mod tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -175,156 +176,156 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: margin is 14 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(14);
asserting("480p 4s no-ref: margin is 15 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(15);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: margin is 17 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(17);
asserting("480p 5s no-ref: margin is 19 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(19);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: margin is 35 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(35);
asserting("480p 10s no-ref: margin is 38 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(38);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: margin is 52 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(52);
asserting("480p 15s no-ref: margin is 57 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(57);
// -- 720p, no video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: margin is 30 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(30);
asserting("720p 4s no-ref: margin is 34 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(34);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: margin is 38 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(38);
asserting("720p 5s no-ref: margin is 42 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(42);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: margin is 76 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(76);
asserting("720p 10s no-ref: margin is 85 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(85);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: margin is 115 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(115);
asserting("720p 15s no-ref: margin is 128 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(128);
// -- 1080p, no video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(false));
asserting("1080p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 4s no-ref: margin is 44 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(44);
asserting("1080p 4s no-ref: margin is 51 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(51);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(false));
asserting("1080p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 5s no-ref: margin is 55 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(55);
asserting("1080p 5s no-ref: margin is 64 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(64);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(false));
asserting("1080p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 10s no-ref: margin is 110 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(110);
asserting("1080p 10s no-ref: margin is 129 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(129);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(false));
asserting("1080p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 15s no-ref: margin is 165 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(165);
asserting("1080p 15s no-ref: margin is 194 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(194);
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: margin is 7 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(7);
asserting("480p 4s with-ref: margin is 8 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(8);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: margin is 8 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(8);
asserting("480p 5s with-ref: margin is 10 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(10);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: margin is 17 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(17);
asserting("480p 10s with-ref: margin is 21 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(21);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: margin is 26 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(26);
asserting("480p 15s with-ref: margin is 32 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(32);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: margin is 16 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(16);
asserting("720p 4s with-ref: margin is 20 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(20);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: margin is 21 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(21);
asserting("720p 5s with-ref: margin is 26 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(26);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: margin is 42 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(42);
asserting("720p 10s with-ref: margin is 52 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(52);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: margin is 63 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(63);
asserting("720p 15s with-ref: margin is 78 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(78);
// -- 1080p, with video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(true));
asserting("1080p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 4s with-ref: margin is 12 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(12);
asserting("1080p 4s with-ref: margin is 22 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(22);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(true));
asserting("1080p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 5s with-ref: margin is 16 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(16);
asserting("1080p 5s with-ref: margin is 27 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(27);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(true));
asserting("1080p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 10s with-ref: margin is 32 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(32);
asserting("1080p 10s with-ref: margin is 55 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(55);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(true));
asserting("1080p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("1080p 15s with-ref: margin is 48 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(48);
asserting("1080p 15s with-ref: margin is 83 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(83);
}
// -- Helpers --
@@ -136,6 +136,7 @@ mod tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -146,104 +147,104 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: margin is 11 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(11);
asserting("480p 4s no-ref: margin is 12 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(12);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: margin is 14 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(14);
asserting("480p 5s no-ref: margin is 16 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(16);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: margin is 29 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(29);
asserting("480p 10s no-ref: margin is 32 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(32);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: margin is 44 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(44);
asserting("480p 15s no-ref: margin is 48 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(48);
// -- 720p, no video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: margin is 31 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(31);
asserting("720p 4s no-ref: margin is 33 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(33);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: margin is 39 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(39);
asserting("720p 5s no-ref: margin is 42 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(42);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: margin is 78 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(78);
asserting("720p 10s no-ref: margin is 84 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(84);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: margin is 118 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(118);
asserting("720p 15s no-ref: margin is 127 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(127);
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: margin is 4 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(4);
asserting("480p 4s with-ref: margin is 6 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(6);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: margin is 6 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(6);
asserting("480p 5s with-ref: margin is 7 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(7);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: margin is 12 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(12);
asserting("480p 10s with-ref: margin is 15 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(15);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: margin is 18 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(18);
asserting("480p 15s with-ref: margin is 23 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(23);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: margin is 21 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(21);
asserting("720p 4s with-ref: margin is 24 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(24);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: margin is 26 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(26);
asserting("720p 5s with-ref: margin is 30 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(30);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: margin is 52 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(52);
asserting("720p 10s with-ref: margin is 60 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(60);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: margin is 79 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(79);
asserting("720p 15s with-ref: margin is 90 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(90);
}
// -- Helpers --
@@ -14,7 +14,7 @@ use crate::generate::generate_video::providers::artcraft::seedance_2p0_fast::req
/// USD cents per second by resolution, derived from upstream Fast rates:
/// 480p: 10 upstream-credits/sec / 193 upstream-credits/$1 * 100 ~= 5.181 c/s
/// (historical 193 credits/$1 derivation; the upstream package is now
/// ~231 credits/$1 but user pricing is intentionally unchanged)
/// ~243 credits/$1 but user pricing is intentionally unchanged)
/// 720p: 28 upstream-credits/sec / 220 upstream-credits/$1 * 100 ~= 12.727 c/s
///
/// We keep these as f64 because per-second rates are fractional; rounding
@@ -242,6 +242,7 @@ mod tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -252,26 +253,26 @@ mod tests {
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: margin is 2 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(2);
asserting("720p 4s no-ref: margin is 4 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(4);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: margin is 3 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(3);
asserting("720p 5s no-ref: margin is 6 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(6);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: margin is 5 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(5);
asserting("720p 10s no-ref: margin is 11 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(11);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost is below the artcraft price")
.that(&prices.kinovi_usd_cents).is_less_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: margin is 9 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(9);
asserting("720p 15s no-ref: margin is 18 cents")
.that(&(prices.artcraft_usd_cents - prices.kinovi_usd_cents)).is_equal_to(18);
}
#[test]
@@ -281,78 +282,78 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: shortfall is 4 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(4);
asserting("480p 4s no-ref: shortfall is 3 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(3);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: shortfall is 5 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(5);
asserting("480p 5s no-ref: shortfall is 3 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(3);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: shortfall is 9 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(9);
asserting("480p 10s no-ref: shortfall is 6 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(6);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: shortfall is 13 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(13);
asserting("480p 15s no-ref: shortfall is 9 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(9);
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: shortfall is 11 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(11);
asserting("480p 4s with-ref: shortfall is 9 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(9);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: shortfall is 13 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(13);
asserting("480p 5s with-ref: shortfall is 12 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(12);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: shortfall is 26 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(26);
asserting("480p 10s with-ref: shortfall is 23 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(23);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: shortfall is 39 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(39);
asserting("480p 15s with-ref: shortfall is 34 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(34);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: shortfall is 8 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(8);
asserting("720p 4s with-ref: shortfall is 5 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(5);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: shortfall is 10 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(10);
asserting("720p 5s with-ref: shortfall is 6 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(6);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: shortfall is 21 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(21);
asserting("720p 10s with-ref: shortfall is 13 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(13);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: shortfall is 30 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(30);
asserting("720p 15s with-ref: shortfall is 19 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(19);
}
// -- Helpers --
@@ -170,6 +170,7 @@ mod tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -180,156 +181,156 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: shortfall is 4 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(4);
asserting("480p 4s no-ref: shortfall is 3 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(3);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: shortfall is 5 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(5);
asserting("480p 5s no-ref: shortfall is 3 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(3);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: shortfall is 10 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(10);
asserting("480p 10s no-ref: shortfall is 7 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(7);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: shortfall is 16 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(16);
asserting("480p 15s no-ref: shortfall is 11 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(11);
// -- 720p, no video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: shortfall is 25 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(25);
asserting("720p 4s no-ref: shortfall is 21 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(21);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: shortfall is 31 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(31);
asserting("720p 5s no-ref: shortfall is 27 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(27);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: shortfall is 62 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(62);
asserting("720p 10s no-ref: shortfall is 53 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(53);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: shortfall is 92 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(92);
asserting("720p 15s no-ref: shortfall is 79 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(79);
// -- 1080p, no video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(false));
asserting("1080p 4s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 4s no-ref: shortfall is 25 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(25);
asserting("1080p 4s no-ref: shortfall is 18 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(18);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(false));
asserting("1080p 5s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 5s no-ref: shortfall is 31 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(31);
asserting("1080p 5s no-ref: shortfall is 22 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(22);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(false));
asserting("1080p 10s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 10s no-ref: shortfall is 63 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(63);
asserting("1080p 10s no-ref: shortfall is 44 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(44);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(false));
asserting("1080p 15s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 15s no-ref: shortfall is 95 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(95);
asserting("1080p 15s no-ref: shortfall is 66 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(66);
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: shortfall is 11 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(11);
asserting("480p 4s with-ref: shortfall is 10 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(10);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: shortfall is 14 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(14);
asserting("480p 5s with-ref: shortfall is 12 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(12);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: shortfall is 28 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(28);
asserting("480p 10s with-ref: shortfall is 24 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(24);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: shortfall is 42 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(42);
asserting("480p 15s with-ref: shortfall is 36 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(36);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: shortfall is 39 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(39);
asserting("720p 4s with-ref: shortfall is 35 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(35);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: shortfall is 48 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(48);
asserting("720p 5s with-ref: shortfall is 43 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(43);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: shortfall is 96 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(96);
asserting("720p 10s with-ref: shortfall is 86 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(86);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: shortfall is 144 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(144);
asserting("720p 15s with-ref: shortfall is 129 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(129);
// -- 1080p, with video references --
let prices = compare_prices(RouterResolution::TenEightyP, Duration(4), VideoReferences(true));
asserting("1080p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 4s with-ref: shortfall is 57 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(57);
asserting("1080p 4s with-ref: shortfall is 47 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(47);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(5), VideoReferences(true));
asserting("1080p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 5s with-ref: shortfall is 70 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(70);
asserting("1080p 5s with-ref: shortfall is 59 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(59);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(10), VideoReferences(true));
asserting("1080p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 10s with-ref: shortfall is 141 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(141);
asserting("1080p 10s with-ref: shortfall is 118 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(118);
let prices = compare_prices(RouterResolution::TenEightyP, Duration(15), VideoReferences(true));
asserting("1080p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("1080p 15s with-ref: shortfall is 212 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(212);
asserting("1080p 15s with-ref: shortfall is 177 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(177);
}
// -- Helpers --
@@ -155,6 +155,7 @@ mod tests {
use speculoos::prelude::*;
use tokens::tokens::media_files::MediaFileToken;
use crate::api::router_video_model::RouterVideoModel;
use crate::api::video_list_ref::VideoListRef;
use super::*;
@@ -165,104 +166,104 @@ mod tests {
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(false));
asserting("480p 4s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 4s no-ref: shortfall is 10 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(10);
asserting("480p 4s no-ref: shortfall is 9 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(9);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(false));
asserting("480p 5s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 5s no-ref: shortfall is 12 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(12);
asserting("480p 5s no-ref: shortfall is 10 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(10);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(false));
asserting("480p 10s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 10s no-ref: shortfall is 24 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(24);
asserting("480p 10s no-ref: shortfall is 21 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(21);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(false));
asserting("480p 15s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 15s no-ref: shortfall is 36 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(36);
asserting("480p 15s no-ref: shortfall is 32 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(32);
// -- 720p, no video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(false));
asserting("720p 4s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 4s no-ref: shortfall is 13 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(13);
asserting("720p 4s no-ref: shortfall is 11 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(11);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(false));
asserting("720p 5s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 5s no-ref: shortfall is 16 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(16);
asserting("720p 5s no-ref: shortfall is 13 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(13);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(false));
asserting("720p 10s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 10s no-ref: shortfall is 32 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(32);
asserting("720p 10s no-ref: shortfall is 26 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(26);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(false));
asserting("720p 15s no-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 15s no-ref: shortfall is 48 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(48);
asserting("720p 15s no-ref: shortfall is 39 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(39);
// -- 480p, with video references --
let prices = compare_prices(RouterResolution::FourEightyP, Duration(4), VideoReferences(true));
asserting("480p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 4s with-ref: shortfall is 17 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(17);
asserting("480p 4s with-ref: shortfall is 15 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(15);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(5), VideoReferences(true));
asserting("480p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 5s with-ref: shortfall is 20 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(20);
asserting("480p 5s with-ref: shortfall is 19 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(19);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(10), VideoReferences(true));
asserting("480p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 10s with-ref: shortfall is 41 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(41);
asserting("480p 10s with-ref: shortfall is 38 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(38);
let prices = compare_prices(RouterResolution::FourEightyP, Duration(15), VideoReferences(true));
asserting("480p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("480p 15s with-ref: shortfall is 62 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(62);
asserting("480p 15s with-ref: shortfall is 57 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(57);
// -- 720p, with video references --
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(4), VideoReferences(true));
asserting("720p 4s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 4s with-ref: shortfall is 23 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(23);
asserting("720p 4s with-ref: shortfall is 20 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(20);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(5), VideoReferences(true));
asserting("720p 5s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 5s with-ref: shortfall is 29 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(29);
asserting("720p 5s with-ref: shortfall is 25 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(25);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(10), VideoReferences(true));
asserting("720p 10s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 10s with-ref: shortfall is 58 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(58);
asserting("720p 10s with-ref: shortfall is 50 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(50);
let prices = compare_prices(RouterResolution::SevenTwentyP, Duration(15), VideoReferences(true));
asserting("720p 15s with-ref: kinovi cost exceeds the artcraft price")
.that(&prices.kinovi_usd_cents).is_greater_than(prices.artcraft_usd_cents);
asserting("720p 15s with-ref: shortfall is 87 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(87);
asserting("720p 15s with-ref: shortfall is 76 cents")
.that(&(prices.kinovi_usd_cents - prices.artcraft_usd_cents)).is_equal_to(76);
}
// -- Helpers --
@@ -98,8 +98,8 @@ mod tests {
#[test]
fn usd_cents_720p() {
assert_eq!(usd_cents(None, 5, None), 72); // 16500/231 = 71.43 -> rounds UP
assert_eq!(usd_cents(None, 15, None), 215); // 49500/231 = 214.29 -> rounds UP
assert_eq!(usd_cents(None, 5, None), 68); // 16500/243 = 67.90 -> rounds UP
assert_eq!(usd_cents(None, 15, None), 204); // 49500/243 = 203.70 -> rounds UP
}
}
@@ -129,10 +129,10 @@ mod tests {
#[test]
fn usd_cents_1080p() {
let r = Some(KinoviHappyHorse1p0OutputResolution::TenEightyP);
// 330 credits; 33000/231 = 142.86 → rounds UP to 143¢
assert_eq!(usd_cents(r, 5, None), 143);
// 990 credits; 99000/231 = 428.57 → rounds UP to 429¢
assert_eq!(usd_cents(r, 15, None), 429);
// 330 credits; 33000/243 = 135.80 → rounds UP to 136¢
assert_eq!(usd_cents(r, 5, None), 136);
// 990 credits; 99000/243 = 407.41 → rounds UP to 408¢
assert_eq!(usd_cents(r, 15, None), 408);
}
}
@@ -236,7 +236,7 @@ mod tests {
);
let cost = KinoviHappyHorse1p0CostState::from_request(&req);
assert_eq!(cost.estimate_cost().cost_in_credits, Some(330));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(143));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(136));
}
}
@@ -103,26 +103,26 @@ mod tests {
#[test]
fn cost_720p_batch_1() {
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 70);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 87);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 6, KinoviBatchCount::One), 104);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 7, KinoviBatchCount::One), 122);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 174);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 260);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 66);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 83);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 6, KinoviBatchCount::One), 99);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 7, KinoviBatchCount::One), 116);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 165);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 247);
}
#[test]
fn cost_720p_batch_2() {
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Two), 139);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 174);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Two), 520);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Two), 132);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 165);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Two), 494);
}
#[test]
fn cost_720p_batch_4() {
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Four), 278);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 347);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Four), 1039);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Four), 264);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 330);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Four), 988);
}
}
@@ -133,20 +133,20 @@ mod tests {
#[test]
fn cost_480p_batch_1() {
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 4, KinoviBatchCount::One), 26);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 33);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 10, KinoviBatchCount::One), 65);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 15, KinoviBatchCount::One), 98);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 4, KinoviBatchCount::One), 25);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 31);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 10, KinoviBatchCount::One), 62);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 15, KinoviBatchCount::One), 93);
}
#[test]
fn cost_480p_batch_2() {
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Two), 65);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Two), 62);
}
#[test]
fn cost_480p_batch_4() {
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Four), 130);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Four), 124);
}
}
@@ -157,20 +157,20 @@ mod tests {
#[test]
fn cost_1080p_batch_1() {
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 4, KinoviBatchCount::One), 156);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 5, KinoviBatchCount::One), 195);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 10, KinoviBatchCount::One), 390);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 15, KinoviBatchCount::One), 585);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 4, KinoviBatchCount::One), 149);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 5, KinoviBatchCount::One), 186);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 10, KinoviBatchCount::One), 371);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 15, KinoviBatchCount::One), 556);
}
#[test]
fn cost_1080p_batch_2() {
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 5, KinoviBatchCount::Two), 390);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 5, KinoviBatchCount::Two), 371);
}
#[test]
fn cost_1080p_batch_4() {
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 5, KinoviBatchCount::Four), 780);
assert_eq!(usd_cents(KinoviOutputResolution::TenEightyP, 5, KinoviBatchCount::Four), 741);
}
}
@@ -219,10 +219,10 @@ mod tests {
};
let without = base.estimate_cost();
let with = KinoviSeedance2p0CostState { has_video_reference: true, ..base }.estimate_cost();
// 720p surcharge is +8 credits/s: 200 -> 240 credits (24000/231 = 103.90 -> 104 cents).
// 720p surcharge is +8 credits/s: 200 -> 240 credits (24000/243 = 98.77 -> 99 cents).
assert_eq!(without.cost_in_credits, Some(200));
assert_eq!(with.cost_in_credits, Some(240));
assert_eq!(with.cost_in_usd_cents, Some(104));
assert_eq!(with.cost_in_usd_cents, Some(99));
}
// ── from_request() tests ──
@@ -238,7 +238,7 @@ mod tests {
assert_eq!(cost.duration_seconds, 5);
assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One)));
assert!(!cost.has_video_reference);
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(87));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(83));
}
#[test]
@@ -246,21 +246,21 @@ mod tests {
let req = make_request_state(None, 5, KinoviBatchCount::One, false);
let cost = KinoviSeedance2p0CostState::from_request(&req);
assert!(cost.resolution.is_none()); // None defaults to 720p pricing
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(87));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(83));
}
#[test]
fn from_request_480p() {
let req = make_request_state(Some(KinoviOutputResolution::FourEightyP), 5, KinoviBatchCount::One, false);
let cost = KinoviSeedance2p0CostState::from_request(&req);
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(33));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(31));
}
#[test]
fn from_request_1080p_batch_2() {
let req = make_request_state(Some(KinoviOutputResolution::TenEightyP), 5, KinoviBatchCount::Two, false);
let cost = KinoviSeedance2p0CostState::from_request(&req);
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(390));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(371));
}
#[test]
@@ -270,7 +270,7 @@ mod tests {
assert!(cost.has_video_reference);
// Video refs add a +8 credits/s surcharge at 720p: 240 credits -> 125 cents.
assert_eq!(cost.estimate_cost().cost_in_credits, Some(240));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(104));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(99));
}
#[test]
@@ -294,7 +294,7 @@ mod tests {
assert_eq!(cost.duration_seconds, 5);
assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One)));
assert!(!cost.has_video_reference);
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(87));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(83));
}
#[test]
@@ -302,7 +302,7 @@ mod tests {
let draft = make_draft(5, 1, Some(RouterResolution::FourEightyP), false);
let cost = KinoviSeedance2p0CostState::from_draft(&draft);
assert!(matches!(cost.resolution, Some(KinoviOutputResolution::FourEightyP)));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(33));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(31));
}
#[test]
@@ -311,7 +311,7 @@ mod tests {
let cost = KinoviSeedance2p0CostState::from_draft(&draft);
assert!(matches!(cost.resolution, Some(KinoviOutputResolution::TenEightyP)));
assert!(matches!(cost.batch_count, Some(KinoviBatchCount::Four)));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(780));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(741));
}
#[test]
@@ -321,7 +321,7 @@ mod tests {
assert!(cost.has_video_reference);
// Video refs add a +8 credits/s surcharge at 720p: 240 credits -> 125 cents.
assert_eq!(cost.estimate_cost().cost_in_credits, Some(240));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(104));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(99));
}
#[test]
@@ -337,7 +337,7 @@ mod tests {
let cost = KinoviSeedance2p0CostState::from_draft(&draft);
assert_eq!(cost.duration_seconds, 15);
assert!(matches!(cost.batch_count, Some(KinoviBatchCount::Two)));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(520));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(494));
}
}
@@ -100,51 +100,51 @@ mod tests {
// ── Direct estimate_cost() tests ──
// These must match the reference implementation values exactly.
// -- 720p (28 credits/sec, 231 credits/$1) --
// -- 720p (28 credits/sec, 243 credits/$1) --
mod pricing_720p {
use super::*;
#[test]
fn cost_720p_batch_1() {
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 49);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 61);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 122);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 182);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 47);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 58);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 116);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 173);
}
#[test]
fn cost_720p_batch_2() {
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 122);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 116);
}
#[test]
fn cost_720p_batch_4() {
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 243);
assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 231);
}
}
// -- 480p (14 credits/sec, 231 credits/$1) --
// -- 480p (14 credits/sec, 243 credits/$1) --
mod pricing_480p {
use super::*;
#[test]
fn cost_480p_batch_1() {
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 4, KinoviBatchCount::One), 25);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 31);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 10, KinoviBatchCount::One), 61);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 15, KinoviBatchCount::One), 91);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 4, KinoviBatchCount::One), 24);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 29);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 10, KinoviBatchCount::One), 58);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 15, KinoviBatchCount::One), 87);
}
#[test]
fn cost_480p_batch_2() {
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Two), 61);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Two), 58);
}
#[test]
fn cost_480p_batch_4() {
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Four), 122);
assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Four), 116);
}
}
@@ -191,10 +191,10 @@ mod tests {
};
let without = base.estimate_cost();
let with = KinoviSeedance2p0FastCostState { has_video_reference: true, ..base }.estimate_cost();
// Fast 720p surcharge is +6 credits/s: 140 -> 170 credits (17000/231 = 73.59 -> 74 cents).
// Fast 720p surcharge is +6 credits/s: 140 -> 170 credits (17000/243 = 69.96 -> 70 cents).
assert_eq!(without.cost_in_credits, Some(140));
assert_eq!(with.cost_in_credits, Some(170));
assert_eq!(with.cost_in_usd_cents, Some(74));
assert_eq!(with.cost_in_usd_cents, Some(70));
}
// ── from_request() tests ──
@@ -210,7 +210,7 @@ mod tests {
assert_eq!(cost.duration_seconds, 5);
assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One)));
assert!(!cost.has_video_reference);
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(61));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(58));
}
#[test]
@@ -218,14 +218,14 @@ mod tests {
let req = make_request_state(None, 5, KinoviBatchCount::One, false);
let cost = KinoviSeedance2p0FastCostState::from_request(&req);
assert!(cost.resolution.is_none());
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(61));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(58));
}
#[test]
fn from_request_480p() {
let req = make_request_state(Some(KinoviOutputResolution::FourEightyP), 5, KinoviBatchCount::One, false);
let cost = KinoviSeedance2p0FastCostState::from_request(&req);
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(31));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(29));
}
#[test]
@@ -235,7 +235,7 @@ mod tests {
assert!(cost.has_video_reference);
// Video refs add a +6 credits/s surcharge at 720p: 170 credits -> 89 cents.
assert_eq!(cost.estimate_cost().cost_in_credits, Some(170));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(74));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(70));
}
#[test]
@@ -259,7 +259,7 @@ mod tests {
assert_eq!(cost.duration_seconds, 5);
assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One)));
assert!(!cost.has_video_reference);
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(61));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(58));
}
#[test]
@@ -267,7 +267,7 @@ mod tests {
let draft = make_draft(5, 1, Some(RouterResolution::FourEightyP), false);
let cost = KinoviSeedance2p0FastCostState::from_draft(&draft);
assert!(matches!(cost.resolution, Some(KinoviOutputResolution::FourEightyP)));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(31));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(29));
}
#[test]
@@ -277,7 +277,7 @@ mod tests {
assert!(cost.has_video_reference);
// Video refs add a +6 credits/s surcharge at 720p: 170 credits -> 89 cents.
assert_eq!(cost.estimate_cost().cost_in_credits, Some(170));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(74));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(70));
}
#[test]
@@ -293,7 +293,7 @@ mod tests {
let cost = KinoviSeedance2p0FastCostState::from_draft(&draft);
assert_eq!(cost.duration_seconds, 15);
assert!(matches!(cost.batch_count, Some(KinoviBatchCount::Two)));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(364));
assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(346));
}
}
@@ -1,5 +1,9 @@
/// Kinovi credits per US dollar.
/// Previously: Credit package: 22,000 credits for $114 (~192.98 credits/$1, rounded to 193).
/// Previously: pub const CREDITS_PER_DOLLAR: u64 = 193;
/// Now: ~231.58 credits/$1, rounded down to 231.
pub const CREDITS_PER_DOLLAR: u64 = 231;
///
/// Current package: 525,000 credits for $2,159.0909 (~243.16 credits/$1,
/// rounded down to 243).
///
/// Historical packages, for reference:
/// - 500,000 credits for $2,159.09 (~231.58 credits/$1, rounded down to 231)
/// - 22,000 credits for $114 (~192.98 credits/$1, rounded to 193)
pub const CREDITS_PER_DOLLAR: u64 = 243;
@@ -50,14 +50,14 @@ mod tests {
#[test]
fn exact_dollar_boundaries_do_not_round() {
// 231 credits = exactly $1.00 — all three representations agree.
let cost = KinoviGenerationCost::from_kinovi_credits(231);
assert_eq!(cost.kinovi_credits, 231);
// 243 credits = exactly $1.00 — all three representations agree.
let cost = KinoviGenerationCost::from_kinovi_credits(243);
assert_eq!(cost.kinovi_credits, 243);
assert_eq!(cost.usd_cents_rounded_up, 100);
assert_eq!(cost.usd_cents_rounded_down, 100);
assert!((cost.usd_cents_fractional - 100.0).abs() < FLOAT_TOLERANCE);
let cost = KinoviGenerationCost::from_kinovi_credits(462);
let cost = KinoviGenerationCost::from_kinovi_credits(486);
assert_eq!(cost.usd_cents_rounded_up, 200);
assert_eq!(cost.usd_cents_rounded_down, 200);
assert!((cost.usd_cents_fractional - 200.0).abs() < FLOAT_TOLERANCE);
@@ -65,22 +65,22 @@ mod tests {
#[test]
fn fractional_cents_round_in_both_directions() {
// 232 credits = 100.432... cents.
let cost = KinoviGenerationCost::from_kinovi_credits(232);
// 244 credits = 100.411... cents.
let cost = KinoviGenerationCost::from_kinovi_credits(244);
assert_eq!(cost.usd_cents_rounded_up, 101);
assert_eq!(cost.usd_cents_rounded_down, 100);
assert!((cost.usd_cents_fractional - (23200.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert!((cost.usd_cents_fractional - (24400.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// 1 credit = 0.432... cents.
let cost = KinoviGenerationCost::from_kinovi_credits(1);
assert_eq!(cost.usd_cents_rounded_up, 1);
assert_eq!(cost.usd_cents_rounded_down, 0);
assert!((cost.usd_cents_fractional - (100.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert!((cost.usd_cents_fractional - (100.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
#[test]
fn rounded_bounds_bracket_the_fractional_value() {
for credits in [0, 1, 12, 75, 200, 231, 232, 450, 1350] {
for credits in [0, 1, 12, 75, 200, 243, 244, 450, 1350] {
let cost = KinoviGenerationCost::from_kinovi_credits(credits);
assert!(cost.usd_cents_rounded_down as f64 <= cost.usd_cents_fractional);
assert!(cost.usd_cents_fractional <= cost.usd_cents_rounded_up as f64);
@@ -50,11 +50,11 @@ mod tests {
assert!(cost.video_reference_surcharge_cost.is_none());
// Base: 200 credits; 20000/231 = 86.58.
// Base: 200 credits; 20000/243 = 82.30.
assert_eq!(cost.base_cost.kinovi_credits, 200);
assert_eq!(cost.base_cost.usd_cents_rounded_up, 87);
assert_eq!(cost.base_cost.usd_cents_rounded_down, 86);
assert!((cost.base_cost.usd_cents_fractional - (20000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(cost.base_cost.usd_cents_rounded_up, 83);
assert_eq!(cost.base_cost.usd_cents_rounded_down, 82);
assert!((cost.base_cost.usd_cents_fractional - (20000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Total equals base when there's no surcharge.
assert_eq!(cost.total_cost, cost.base_cost);
@@ -64,24 +64,24 @@ mod tests {
fn with_surcharge() {
let cost = KinoviSeedanceGenerationCost::from_base_and_surcharge(200, Some(40));
// Base: 200 credits; 20000/231 = 86.58.
// Base: 200 credits; 20000/243 = 82.30.
assert_eq!(cost.base_cost.kinovi_credits, 200);
assert_eq!(cost.base_cost.usd_cents_rounded_up, 87);
assert_eq!(cost.base_cost.usd_cents_rounded_down, 86);
assert!((cost.base_cost.usd_cents_fractional - (20000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(cost.base_cost.usd_cents_rounded_up, 83);
assert_eq!(cost.base_cost.usd_cents_rounded_down, 82);
assert!((cost.base_cost.usd_cents_fractional - (20000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Surcharge: 40 credits; 4000/231 = 17.32.
// Surcharge: 40 credits; 4000/243 = 16.46.
let surcharge = cost.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 40);
assert_eq!(surcharge.usd_cents_rounded_up, 18);
assert_eq!(surcharge.usd_cents_rounded_down, 17);
assert!((surcharge.usd_cents_fractional - (4000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(surcharge.usd_cents_rounded_up, 17);
assert_eq!(surcharge.usd_cents_rounded_down, 16);
assert!((surcharge.usd_cents_fractional - (4000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Total: 240 credits; 24000/231 = 103.90.
// Total: 240 credits; 24000/243 = 98.77.
assert_eq!(cost.total_cost.kinovi_credits, 240);
assert_eq!(cost.total_cost.usd_cents_rounded_up, 104);
assert_eq!(cost.total_cost.usd_cents_rounded_down, 103);
assert!((cost.total_cost.usd_cents_fractional - (24000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(cost.total_cost.usd_cents_rounded_up, 99);
assert_eq!(cost.total_cost.usd_cents_rounded_down, 98);
assert!((cost.total_cost.usd_cents_fractional - (24000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
#[test]
@@ -99,10 +99,10 @@ mod tests {
let cost = KinoviSeedanceGenerationCost::from_base_and_surcharge(200, Some(40));
let surcharge = cost.video_reference_surcharge_cost.unwrap();
// Parts round up to 87 + 18 = 105, but the total (240 credits) rounds
// once to 104 — one cent less than summing the rounded parts.
assert_eq!(cost.base_cost.usd_cents_rounded_up + surcharge.usd_cents_rounded_up, 105);
assert_eq!(cost.total_cost.usd_cents_rounded_up, 104);
// Parts round up to 83 + 17 = 100, but the total (240 credits) rounds
// once to 99 — one cent less than summing the rounded parts.
assert_eq!(cost.base_cost.usd_cents_rounded_up + surcharge.usd_cents_rounded_up, 100);
assert_eq!(cost.total_cost.usd_cents_rounded_up, 99);
// …but the fractional parts always sum exactly to the fractional total.
let parts = cost.base_cost.usd_cents_fractional + surcharge.usd_cents_fractional;
@@ -288,17 +288,17 @@ mod tests {
}
#[test]
fn usd_cents_batch_one_is_six() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 6); // 1200/231 = 5.19 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 5);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 231.0)).abs() < 1e-9);
fn usd_cents_batch_one_is_five() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 5); // 1200/243 = 4.94 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 4);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn usd_cents_batch_four_is_twentyone() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 21); // 4800/231 = 20.78 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 20);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 231.0)).abs() < 1e-9);
fn usd_cents_batch_four_is_twenty() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 20); // 4800/243 = 19.75 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 19);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 243.0)).abs() < 1e-9);
}
/// Pricing must match the inner module byte-for-byte (sanity that no
@@ -286,17 +286,17 @@ mod tests {
}
#[test]
fn usd_cents_batch_one_is_six() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 6); // 1200/231 = 5.19 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 5);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 231.0)).abs() < 1e-9);
fn usd_cents_batch_one_is_five() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 5); // 1200/243 = 4.94 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 4);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn usd_cents_batch_four_is_twentyone() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 21); // 4800/231 = 20.78 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 20);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 231.0)).abs() < 1e-9);
fn usd_cents_batch_four_is_twenty() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 20); // 4800/243 = 19.75 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 19);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 243.0)).abs() < 1e-9);
}
/// Pricing must match the inner module exactly.
@@ -283,17 +283,17 @@ mod tests {
}
#[test]
fn usd_cents_batch_one_is_six() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 6); // 1200/231 = 5.19 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 5);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 231.0)).abs() < 1e-9);
fn usd_cents_batch_one_is_five() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 5); // 1200/243 = 4.94 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 4);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn usd_cents_batch_four_is_twentyone() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 21); // 4800/231 = 20.78 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 20);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 231.0)).abs() < 1e-9);
fn usd_cents_batch_four_is_twenty() {
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 20); // 4800/243 = 19.75 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 19);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 243.0)).abs() < 1e-9);
}
/// Pricing must match the inner module exactly.
@@ -63,7 +63,7 @@ pub enum KinoviHappyHorse1p0BatchCount {
//
// Default resolution (None) is 720p.
// Batch count multiplies the total cost.
// Credit package: 500,000 credits for $2,159.09 (~231.58 credits/$1, rounded down to 231).
// Credit package: 525,000 credits for $2,159.0909 (~243.16 credits/$1, rounded down to 243).
impl GenerateHappyHorse1p0Request {
/// Estimate the credit cost for this generation request.
@@ -334,52 +334,52 @@ mod tests {
/// (USD cents are always rounded UP when fractional.)
#[test]
fn costs_720p_5s() {
// 33 credits/s × 5s = 165 credits; 16500/231 = 71.43 → rounds UP to 72¢
// 33 credits/s × 5s = 165 credits; 16500/243 = 67.90 → rounds UP to 68¢
let costs = r720(5).calculate_costs();
assert_eq!(costs.kinovi_credits, 165);
assert_eq!(costs.usd_cents_rounded_up, 72);
assert_eq!(costs.usd_cents_rounded_down, 71);
assert!((costs.usd_cents_fractional - (16500.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.usd_cents_rounded_up, 68);
assert_eq!(costs.usd_cents_rounded_down, 67);
assert!((costs.usd_cents_fractional - (16500.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn costs_1080p_5s() {
// 66 credits/s × 5s = 330 credits; 33000/231 = 142.86 → 143¢
// 66 credits/s × 5s = 330 credits; 33000/243 = 135.80 → 136¢
let costs = r1080(5).calculate_costs();
assert_eq!(costs.kinovi_credits, 330);
assert_eq!(costs.usd_cents_rounded_up, 143);
assert_eq!(costs.usd_cents_rounded_down, 142);
assert!((costs.usd_cents_fractional - (33000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.usd_cents_rounded_up, 136);
assert_eq!(costs.usd_cents_rounded_down, 135);
assert!((costs.usd_cents_fractional - (33000.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn costs_720p_15s() {
// 33 credits/s × 15s = 495 credits; 49500/231 = 214.29 → rounds UP to 215¢
// 33 credits/s × 15s = 495 credits; 49500/243 = 203.70 → rounds UP to 204¢
let costs = r720(15).calculate_costs();
assert_eq!(costs.kinovi_credits, 495);
assert_eq!(costs.usd_cents_rounded_up, 215);
assert_eq!(costs.usd_cents_rounded_down, 214);
assert!((costs.usd_cents_fractional - (49500.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.usd_cents_rounded_up, 204);
assert_eq!(costs.usd_cents_rounded_down, 203);
assert!((costs.usd_cents_fractional - (49500.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn costs_1080p_15s() {
// 66 credits/s × 15s = 990 credits; 99000/231 = 428.57 → 429¢
// 66 credits/s × 15s = 990 credits; 99000/243 = 407.41 → 408¢
let costs = r1080(15).calculate_costs();
assert_eq!(costs.kinovi_credits, 990);
assert_eq!(costs.usd_cents_rounded_up, 429);
assert_eq!(costs.usd_cents_rounded_down, 428);
assert!((costs.usd_cents_fractional - (99000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.usd_cents_rounded_up, 408);
assert_eq!(costs.usd_cents_rounded_down, 407);
assert!((costs.usd_cents_fractional - (99000.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn costs_batch_2_720p_5s() {
// 165 credits × 2 = 330 credits; 33000/231 = 142.86 → 143¢
// 165 credits × 2 = 330 credits; 33000/243 = 135.80 → 136¢
let costs = make_request(5, None, Some(KinoviHappyHorse1p0BatchCount::Two)).calculate_costs();
assert_eq!(costs.kinovi_credits, 330);
assert_eq!(costs.usd_cents_rounded_up, 143);
assert_eq!(costs.usd_cents_rounded_down, 142);
assert!((costs.usd_cents_fractional - (33000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.usd_cents_rounded_up, 136);
assert_eq!(costs.usd_cents_rounded_down, 135);
assert!((costs.usd_cents_fractional - (33000.0 / 243.0)).abs() < 1e-9);
}
/// The deprecated shims return the corresponding struct fields.
@@ -72,7 +72,7 @@ pub enum KinoviSeedance2p0BatchCount {
//
// Default resolution (None) is 720p.
// Batch count multiplies the total cost.
// Credit package: 500,000 credits for $2,159.09 (~231.58 credits/$1, rounded down to 231).
// Credit package: 525,000 credits for $2,159.0909 (~243.16 credits/$1, rounded down to 243).
impl GenerateSeedance2p0Request {
/// Calculate the cost of this generation request, in Kinovi credits and
@@ -292,19 +292,19 @@ mod tests {
fn test_without_reference_video() {
let costs = r480(5).calculate_costs();
// Base: 15 credits/s × 5s = 75 credits; 7500/231 = 32.4675.
// Base: 15 credits/s × 5s = 75 credits; 7500/243 = 30.8642.
assert_eq!(costs.base_cost.kinovi_credits, 75);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 33);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 32);
assert!((costs.base_cost.usd_cents_fractional - (7500.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 30);
assert!((costs.base_cost.usd_cents_fractional - (7500.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// No reference video: no surcharge, and the total equals the base.
assert!(costs.video_reference_surcharge_cost.is_none());
assert_eq!(costs.total_cost.kinovi_credits, 75);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 33);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 32);
assert!((costs.total_cost.usd_cents_fractional - (7500.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 30);
assert!((costs.total_cost.usd_cents_fractional - (7500.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
#[test]
@@ -313,24 +313,24 @@ mod tests {
request.reference_video_urls = Some(vec!["https://example.com/ref.mp4".to_string()]);
let costs = request.calculate_costs();
// Base: 15 credits/s × 5s = 75 credits; 7500/231 = 32.4675.
// Base: 15 credits/s × 5s = 75 credits; 7500/243 = 30.8642.
assert_eq!(costs.base_cost.kinovi_credits, 75);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 33);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 32);
assert!((costs.base_cost.usd_cents_fractional - (7500.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 30);
assert!((costs.base_cost.usd_cents_fractional - (7500.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Surcharge: 4 credits/s × 5s = 20 credits; 2000/231 = 8.6580.
// Surcharge: 4 credits/s × 5s = 20 credits; 2000/243 = 8.2305.
let surcharge = costs.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 20);
assert_eq!(surcharge.usd_cents_rounded_up, 9);
assert_eq!(surcharge.usd_cents_rounded_down, 8);
assert!((surcharge.usd_cents_fractional - (2000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert!((surcharge.usd_cents_fractional - (2000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Total: 75 + 20 = 95 credits; 9500/231 = 41.1255.
// Total: 75 + 20 = 95 credits; 9500/243 = 39.0947.
assert_eq!(costs.total_cost.kinovi_credits, 95);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 42);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 41);
assert!((costs.total_cost.usd_cents_fractional - (9500.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 40);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 39);
assert!((costs.total_cost.usd_cents_fractional - (9500.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
}
@@ -342,19 +342,19 @@ mod tests {
fn test_without_reference_video() {
let costs = r720(5).calculate_costs();
// Base: 40 credits/s × 5s = 200 credits; 20000/231 = 86.5801.
// Base: 40 credits/s × 5s = 200 credits; 20000/243 = 82.3045.
assert_eq!(costs.base_cost.kinovi_credits, 200);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 87);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 86);
assert!((costs.base_cost.usd_cents_fractional - (20000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 83);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 82);
assert!((costs.base_cost.usd_cents_fractional - (20000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// No reference video: no surcharge, and the total equals the base.
assert!(costs.video_reference_surcharge_cost.is_none());
assert_eq!(costs.total_cost.kinovi_credits, 200);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 87);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 86);
assert!((costs.total_cost.usd_cents_fractional - (20000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 83);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 82);
assert!((costs.total_cost.usd_cents_fractional - (20000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
#[test]
@@ -363,24 +363,24 @@ mod tests {
request.reference_video_urls = Some(vec!["https://example.com/ref.mp4".to_string()]);
let costs = request.calculate_costs();
// Base: 40 credits/s × 5s = 200 credits; 20000/231 = 86.5801.
// Base: 40 credits/s × 5s = 200 credits; 20000/243 = 82.3045.
assert_eq!(costs.base_cost.kinovi_credits, 200);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 87);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 86);
assert!((costs.base_cost.usd_cents_fractional - (20000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 83);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 82);
assert!((costs.base_cost.usd_cents_fractional - (20000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Surcharge: 8 credits/s × 5s = 40 credits; 4000/231 = 17.3160.
// Surcharge: 8 credits/s × 5s = 40 credits; 4000/243 = 16.4609.
let surcharge = costs.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 40);
assert_eq!(surcharge.usd_cents_rounded_up, 18);
assert_eq!(surcharge.usd_cents_rounded_down, 17);
assert!((surcharge.usd_cents_fractional - (4000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(surcharge.usd_cents_rounded_up, 17);
assert_eq!(surcharge.usd_cents_rounded_down, 16);
assert!((surcharge.usd_cents_fractional - (4000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Total: 200 + 40 = 240 credits; 24000/231 = 103.8961.
// Total: 200 + 40 = 240 credits; 24000/243 = 98.7654.
assert_eq!(costs.total_cost.kinovi_credits, 240);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 104);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 103);
assert!((costs.total_cost.usd_cents_fractional - (24000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 99);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 98);
assert!((costs.total_cost.usd_cents_fractional - (24000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
}
@@ -392,19 +392,19 @@ mod tests {
fn test_without_reference_video() {
let costs = r1080(5).calculate_costs();
// Base: 90 credits/s × 5s = 450 credits; 45000/231 = 194.8052.
// Base: 90 credits/s × 5s = 450 credits; 45000/243 = 185.1852.
assert_eq!(costs.base_cost.kinovi_credits, 450);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 195);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 194);
assert!((costs.base_cost.usd_cents_fractional - (45000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 186);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 185);
assert!((costs.base_cost.usd_cents_fractional - (45000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// No reference video: no surcharge, and the total equals the base.
assert!(costs.video_reference_surcharge_cost.is_none());
assert_eq!(costs.total_cost.kinovi_credits, 450);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 195);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 194);
assert!((costs.total_cost.usd_cents_fractional - (45000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 186);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 185);
assert!((costs.total_cost.usd_cents_fractional - (45000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
#[test]
@@ -413,24 +413,24 @@ mod tests {
request.reference_video_urls = Some(vec!["https://example.com/ref.mp4".to_string()]);
let costs = request.calculate_costs();
// Base: 90 credits/s × 5s = 450 credits; 45000/231 = 194.8052.
// Base: 90 credits/s × 5s = 450 credits; 45000/243 = 185.1852.
assert_eq!(costs.base_cost.kinovi_credits, 450);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 195);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 194);
assert!((costs.base_cost.usd_cents_fractional - (45000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 186);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 185);
assert!((costs.base_cost.usd_cents_fractional - (45000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Surcharge: 18 credits/s × 5s = 90 credits; 9000/231 = 38.9610.
// Surcharge: 18 credits/s × 5s = 90 credits; 9000/243 = 37.0370.
let surcharge = costs.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 90);
assert_eq!(surcharge.usd_cents_rounded_up, 39);
assert_eq!(surcharge.usd_cents_rounded_down, 38);
assert!((surcharge.usd_cents_fractional - (9000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(surcharge.usd_cents_rounded_up, 38);
assert_eq!(surcharge.usd_cents_rounded_down, 37);
assert!((surcharge.usd_cents_fractional - (9000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Total: 450 + 90 = 540 credits; 54000/231 = 233.7662.
// Total: 450 + 90 = 540 credits; 54000/243 = 222.2222.
assert_eq!(costs.total_cost.kinovi_credits, 540);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 234);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 233);
assert!((costs.total_cost.usd_cents_fractional - (54000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 223);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 222);
assert!((costs.total_cost.usd_cents_fractional - (54000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
}
@@ -592,72 +592,72 @@ mod tests {
/// (USD cents are always rounded UP when fractional.)
#[test]
fn costs_480p_5s() {
// 15 credits/s × 5s = 75 credits; 7500/231 = 32.47 → 33¢
// 15 credits/s × 5s = 75 credits; 7500/243 = 30.86 → 31¢
let costs = r480(5).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 75);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 33);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 32);
assert!((costs.total_cost.usd_cents_fractional - (7500.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 30);
assert!((costs.total_cost.usd_cents_fractional - (7500.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 75);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_720p_5s() {
// 40 credits/s × 5s = 200 credits; 20000/231 = 86.58 → 87¢
// 40 credits/s × 5s = 200 credits; 20000/243 = 82.30 → 83¢
let costs = r720(5).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 200);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 87);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 86);
assert!((costs.total_cost.usd_cents_fractional - (20000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 83);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 82);
assert!((costs.total_cost.usd_cents_fractional - (20000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 200);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_1080p_5s() {
// 90 credits/s × 5s = 450 credits; 45000/231 = 194.81 → rounds UP to 195¢
// 90 credits/s × 5s = 450 credits; 45000/243 = 185.19 → rounds UP to 186¢
let costs = r1080(5).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 450);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 195);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 194);
assert!((costs.total_cost.usd_cents_fractional - (45000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 186);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 185);
assert!((costs.total_cost.usd_cents_fractional - (45000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 450);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_720p_15s() {
// 40 credits/s × 15s = 600 credits; 60000/231 = 259.74 → 260¢
// 40 credits/s × 15s = 600 credits; 60000/243 = 246.91 → 247¢
let costs = r720(15).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 600);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 260);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 259);
assert!((costs.total_cost.usd_cents_fractional - (60000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 247);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 246);
assert!((costs.total_cost.usd_cents_fractional - (60000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 600);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_1080p_15s() {
// 90 credits/s × 15s = 1350 credits; 135000/231 = 584.42 → rounds UP to 585¢
// 90 credits/s × 15s = 1350 credits; 135000/243 = 555.56 → rounds UP to 556¢
let costs = r1080(15).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 1350);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 585);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 584);
assert!((costs.total_cost.usd_cents_fractional - (135000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 556);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 555);
assert!((costs.total_cost.usd_cents_fractional - (135000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 1350);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_batch_4_720p_5s() {
// 200 credits × 4 = 800 credits; 80000/231 = 346.32 → 347¢
// 200 credits × 4 = 800 credits; 80000/243 = 329.22 → 330¢
let costs = build_request(5, None, Some(KinoviSeedance2p0BatchCount::Four)).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 800);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 347);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 346);
assert!((costs.total_cost.usd_cents_fractional - (80000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 330);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 329);
assert!((costs.total_cost.usd_cents_fractional - (80000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 800);
assert!(costs.video_reference_surcharge_cost.is_none());
}
@@ -720,14 +720,14 @@ mod tests {
#[test]
fn surcharge_includes_usd_cents() {
// 720p 5s + video ref = 200 + 40 = 240 credits; 24000/231 = 103.90 → 104¢
// 720p 5s + video ref = 200 + 40 = 240 credits; 24000/243 = 98.77 → 99¢
let costs = with_video_ref(r720(5)).calculate_costs();
assert_eq!(costs.base_cost.kinovi_credits, 200);
assert_eq!(costs.video_reference_surcharge_cost.map(|c| c.kinovi_credits), Some(40));
assert_eq!(costs.total_cost.kinovi_credits, 240);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 104);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 103);
assert!((costs.total_cost.usd_cents_fractional - (24000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 99);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 98);
assert!((costs.total_cost.usd_cents_fractional - (24000.0 / 243.0)).abs() < 1e-9);
}
/// The base and surcharge parts each carry their own USD conversions.
@@ -735,17 +735,17 @@ mod tests {
fn parts_have_their_own_usd_conversions() {
let costs = with_video_ref(r720(5)).calculate_costs();
// Base: 200 credits; 20000/231 = 86.58.
assert_eq!(costs.base_cost.usd_cents_rounded_up, 87);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 86);
assert!((costs.base_cost.usd_cents_fractional - (20000.0 / 231.0)).abs() < 1e-9);
// Base: 200 credits; 20000/243 = 82.30.
assert_eq!(costs.base_cost.usd_cents_rounded_up, 83);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 82);
assert!((costs.base_cost.usd_cents_fractional - (20000.0 / 243.0)).abs() < 1e-9);
// Surcharge: 40 credits; 4000/231 = 17.32.
// Surcharge: 40 credits; 4000/243 = 16.46.
let surcharge = costs.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 40);
assert_eq!(surcharge.usd_cents_rounded_up, 18);
assert_eq!(surcharge.usd_cents_rounded_down, 17);
assert!((surcharge.usd_cents_fractional - (4000.0 / 231.0)).abs() < 1e-9);
assert_eq!(surcharge.usd_cents_rounded_up, 17);
assert_eq!(surcharge.usd_cents_rounded_down, 16);
assert!((surcharge.usd_cents_fractional - (4000.0 / 243.0)).abs() < 1e-9);
}
#[test]
@@ -70,7 +70,7 @@ pub enum KinoviSeedance2p0FastBatchCount {
//
// Default resolution (None) is 720p.
// Batch count multiplies the total cost.
// Credit package: 500,000 credits for $2,159.09 (~231.58 credits/$1, rounded down to 231).
// Credit package: 525,000 credits for $2,159.0909 (~243.16 credits/$1, rounded down to 243).
impl GenerateSeedance2p0FastRequest {
/// Calculate the cost of this generation request, in Kinovi credits and
@@ -282,19 +282,19 @@ mod tests {
fn test_without_reference_video() {
let costs = r480(5).calculate_costs();
// Base: 14 credits/s × 5s = 70 credits; 7000/231 = 30.3030.
// Base: 14 credits/s × 5s = 70 credits; 7000/243 = 28.8066.
assert_eq!(costs.base_cost.kinovi_credits, 70);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 30);
assert!((costs.base_cost.usd_cents_fractional - (7000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 29);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 28);
assert!((costs.base_cost.usd_cents_fractional - (7000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// No reference video: no surcharge, and the total equals the base.
assert!(costs.video_reference_surcharge_cost.is_none());
assert_eq!(costs.total_cost.kinovi_credits, 70);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 30);
assert!((costs.total_cost.usd_cents_fractional - (7000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 29);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 28);
assert!((costs.total_cost.usd_cents_fractional - (7000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
#[test]
@@ -303,24 +303,24 @@ mod tests {
request.reference_video_urls = Some(vec!["https://example.com/ref.mp4".to_string()]);
let costs = request.calculate_costs();
// Base: 14 credits/s × 5s = 70 credits; 7000/231 = 30.3030.
// Base: 14 credits/s × 5s = 70 credits; 7000/243 = 28.8066.
assert_eq!(costs.base_cost.kinovi_credits, 70);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 30);
assert!((costs.base_cost.usd_cents_fractional - (7000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 29);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 28);
assert!((costs.base_cost.usd_cents_fractional - (7000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Surcharge: 4 credits/s × 5s = 20 credits; 2000/231 = 8.6580.
// Surcharge: 4 credits/s × 5s = 20 credits; 2000/243 = 8.2305.
let surcharge = costs.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 20);
assert_eq!(surcharge.usd_cents_rounded_up, 9);
assert_eq!(surcharge.usd_cents_rounded_down, 8);
assert!((surcharge.usd_cents_fractional - (2000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert!((surcharge.usd_cents_fractional - (2000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Total: 70 + 20 = 90 credits; 9000/231 = 38.9610.
// Total: 70 + 20 = 90 credits; 9000/243 = 37.0370.
assert_eq!(costs.total_cost.kinovi_credits, 90);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 39);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 38);
assert!((costs.total_cost.usd_cents_fractional - (9000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 38);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 37);
assert!((costs.total_cost.usd_cents_fractional - (9000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
}
@@ -332,19 +332,19 @@ mod tests {
fn test_without_reference_video() {
let costs = r720(5).calculate_costs();
// Base: 28 credits/s × 5s = 140 credits; 14000/231 = 60.6061.
// Base: 28 credits/s × 5s = 140 credits; 14000/243 = 57.6132.
assert_eq!(costs.base_cost.kinovi_credits, 140);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 61);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 60);
assert!((costs.base_cost.usd_cents_fractional - (14000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 58);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 57);
assert!((costs.base_cost.usd_cents_fractional - (14000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// No reference video: no surcharge, and the total equals the base.
assert!(costs.video_reference_surcharge_cost.is_none());
assert_eq!(costs.total_cost.kinovi_credits, 140);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 61);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 60);
assert!((costs.total_cost.usd_cents_fractional - (14000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 58);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 57);
assert!((costs.total_cost.usd_cents_fractional - (14000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
#[test]
@@ -353,24 +353,24 @@ mod tests {
request.reference_video_urls = Some(vec!["https://example.com/ref.mp4".to_string()]);
let costs = request.calculate_costs();
// Base: 28 credits/s × 5s = 140 credits; 14000/231 = 60.6061.
// Base: 28 credits/s × 5s = 140 credits; 14000/243 = 57.6132.
assert_eq!(costs.base_cost.kinovi_credits, 140);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 61);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 60);
assert!((costs.base_cost.usd_cents_fractional - (14000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.base_cost.usd_cents_rounded_up, 58);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 57);
assert!((costs.base_cost.usd_cents_fractional - (14000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Surcharge: 6 credits/s × 5s = 30 credits; 3000/231 = 12.9870.
// Surcharge: 6 credits/s × 5s = 30 credits; 3000/243 = 12.3457.
let surcharge = costs.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 30);
assert_eq!(surcharge.usd_cents_rounded_up, 13);
assert_eq!(surcharge.usd_cents_rounded_down, 12);
assert!((surcharge.usd_cents_fractional - (3000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert!((surcharge.usd_cents_fractional - (3000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
// Total: 140 + 30 = 170 credits; 17000/231 = 73.5931.
// Total: 140 + 30 = 170 credits; 17000/243 = 69.9588.
assert_eq!(costs.total_cost.kinovi_credits, 170);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 74);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 73);
assert!((costs.total_cost.usd_cents_fractional - (17000.0 / 231.0)).abs() < FLOAT_TOLERANCE);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 70);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 69);
assert!((costs.total_cost.usd_cents_fractional - (17000.0 / 243.0)).abs() < FLOAT_TOLERANCE);
}
}
@@ -498,60 +498,60 @@ mod tests {
/// (USD cents are always rounded UP when fractional.)
#[test]
fn costs_480p_5s() {
// 14 credits/s × 5s = 70 credits; 7000/231 = 30.30 → rounds UP to 31¢
// 14 credits/s × 5s = 70 credits; 7000/243 = 28.81 → rounds UP to 29¢
let costs = r480(5).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 70);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 31);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 30);
assert!((costs.total_cost.usd_cents_fractional - (7000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 29);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 28);
assert!((costs.total_cost.usd_cents_fractional - (7000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 70);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_720p_5s() {
// 28 credits/s × 5s = 140 credits; 14000/231 = 60.61 → 61¢
// 28 credits/s × 5s = 140 credits; 14000/243 = 57.61 → 58¢
let costs = r720(5).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 140);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 61);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 60);
assert!((costs.total_cost.usd_cents_fractional - (14000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 58);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 57);
assert!((costs.total_cost.usd_cents_fractional - (14000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 140);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_720p_15s() {
// 28 credits/s × 15s = 420 credits; 42000/231 = 181.82 → 182¢
// 28 credits/s × 15s = 420 credits; 42000/243 = 172.84 → 173¢
let costs = r720(15).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 420);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 182);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 181);
assert!((costs.total_cost.usd_cents_fractional - (42000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 173);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 172);
assert!((costs.total_cost.usd_cents_fractional - (42000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 420);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_480p_15s() {
// 14 credits/s × 15s = 210 credits; 21000/231 = 90.91 → 91¢
// 14 credits/s × 15s = 210 credits; 21000/243 = 86.42 → 87¢
let costs = r480(15).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 210);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 91);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 90);
assert!((costs.total_cost.usd_cents_fractional - (21000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 87);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 86);
assert!((costs.total_cost.usd_cents_fractional - (21000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 210);
assert!(costs.video_reference_surcharge_cost.is_none());
}
#[test]
fn costs_batch_2_720p_5s() {
// 140 credits × 2 = 280 credits; 28000/231 = 121.21 → 122¢
// 140 credits × 2 = 280 credits; 28000/243 = 115.23 → 116¢
let costs = build_request(5, None, Some(KinoviSeedance2p0FastBatchCount::Two)).calculate_costs();
assert_eq!(costs.total_cost.kinovi_credits, 280);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 122);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 121);
assert!((costs.total_cost.usd_cents_fractional - (28000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 116);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 115);
assert!((costs.total_cost.usd_cents_fractional - (28000.0 / 243.0)).abs() < 1e-9);
assert_eq!(costs.base_cost.kinovi_credits, 280);
assert!(costs.video_reference_surcharge_cost.is_none());
}
@@ -610,14 +610,14 @@ mod tests {
#[test]
fn surcharge_includes_usd_cents() {
// 720p 5s + video ref = 140 + 30 = 170 credits; 17000/231 = 73.59 → 74¢
// 720p 5s + video ref = 140 + 30 = 170 credits; 17000/243 = 69.96 → 70¢
let costs = with_video_ref(r720(5)).calculate_costs();
assert_eq!(costs.base_cost.kinovi_credits, 140);
assert_eq!(costs.video_reference_surcharge_cost.map(|c| c.kinovi_credits), Some(30));
assert_eq!(costs.total_cost.kinovi_credits, 170);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 74);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 73);
assert!((costs.total_cost.usd_cents_fractional - (17000.0 / 231.0)).abs() < 1e-9);
assert_eq!(costs.total_cost.usd_cents_rounded_up, 70);
assert_eq!(costs.total_cost.usd_cents_rounded_down, 69);
assert!((costs.total_cost.usd_cents_fractional - (17000.0 / 243.0)).abs() < 1e-9);
}
/// The base and surcharge parts each carry their own USD conversions.
@@ -625,17 +625,17 @@ mod tests {
fn parts_have_their_own_usd_conversions() {
let costs = with_video_ref(r720(5)).calculate_costs();
// Base: 140 credits; 14000/231 = 60.61.
assert_eq!(costs.base_cost.usd_cents_rounded_up, 61);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 60);
assert!((costs.base_cost.usd_cents_fractional - (14000.0 / 231.0)).abs() < 1e-9);
// Base: 140 credits; 14000/243 = 57.61.
assert_eq!(costs.base_cost.usd_cents_rounded_up, 58);
assert_eq!(costs.base_cost.usd_cents_rounded_down, 57);
assert!((costs.base_cost.usd_cents_fractional - (14000.0 / 243.0)).abs() < 1e-9);
// Surcharge: 30 credits; 3000/231 = 12.99.
// Surcharge: 30 credits; 3000/243 = 12.35.
let surcharge = costs.video_reference_surcharge_cost.expect("should have surcharge");
assert_eq!(surcharge.kinovi_credits, 30);
assert_eq!(surcharge.usd_cents_rounded_up, 13);
assert_eq!(surcharge.usd_cents_rounded_down, 12);
assert!((surcharge.usd_cents_fractional - (3000.0 / 231.0)).abs() < 1e-9);
assert!((surcharge.usd_cents_fractional - (3000.0 / 243.0)).abs() < 1e-9);
}
#[test]
@@ -22,7 +22,7 @@ const CREDITS_PER_MIDJOURNEY_TASK: u32 = 12;
/// Newer Kinovi credit-package rate. Used to convert credits to USD for the
/// Midjourney image generation flow.
///
/// 500,000 credits / $2,159.09 = 231.58 ≈ 231 credits per dollar (rounded down).
/// 500,000 credits / $2,159.09 = 231.58 ≈ 243 credits per dollar (rounded down).
/// Kinovi only currently exposes a single Midjourney resolution preset.
const MIDJOURNEY_RESOLUTION: &str = "1k";
@@ -416,26 +416,26 @@ mod tests {
#[test]
fn usd_cents_batch_one() {
// 12/231 × 100 = 5.19¢ → 6¢
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 6); // 1200/231 = 5.19 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 5);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 231.0)).abs() < 1e-9);
// 12/243 × 100 = 4.94¢ → 5¢
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_up, 5); // 1200/243 = 4.94 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_rounded_down, 4);
assert!((make_request(KinoviMidjourneyBatchCount::One).calculate_costs().usd_cents_fractional - (1200.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn usd_cents_batch_two() {
// 24/231 × 100 = 10.39¢ → 11¢
assert_eq!(make_request(KinoviMidjourneyBatchCount::Two).calculate_costs().usd_cents_rounded_up, 11); // 2400/231 = 10.39 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Two).calculate_costs().usd_cents_rounded_down, 10);
assert!((make_request(KinoviMidjourneyBatchCount::Two).calculate_costs().usd_cents_fractional - (2400.0 / 231.0)).abs() < 1e-9);
// 24/243 × 100 = 9.88¢ → 10¢
assert_eq!(make_request(KinoviMidjourneyBatchCount::Two).calculate_costs().usd_cents_rounded_up, 10); // 2400/243 = 9.88 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Two).calculate_costs().usd_cents_rounded_down, 9);
assert!((make_request(KinoviMidjourneyBatchCount::Two).calculate_costs().usd_cents_fractional - (2400.0 / 243.0)).abs() < 1e-9);
}
#[test]
fn usd_cents_batch_four() {
// 48/231 × 100 = 20.78¢ → 21¢
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 21); // 4800/231 = 20.78 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 20);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 231.0)).abs() < 1e-9);
// 48/243 × 100 = 19.75¢ → 20¢
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_up, 20); // 4800/243 = 19.75 -> rounds UP
assert_eq!(make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_rounded_down, 19);
assert!((make_request(KinoviMidjourneyBatchCount::Four).calculate_costs().usd_cents_fractional - (4800.0 / 243.0)).abs() < 1e-9);
}
/// Batch 4 should be exactly 4× the credit cost of batch 1, and the USD
@@ -141,7 +141,7 @@ impl KinoviGenerateVideoRequest {
/// Credits per dollar for billing conversion.
///
/// Legacy 720p pricing uses the original Kinovi credit package rates.
/// All other model/resolution combos use the newer rate: 500,000 credits / $2,159.09.
/// All other model/resolution combos use the newer rate: 525,000 credits / $2,159.0909.
fn credits_per_dollar(&self) -> f64 {
match (self.model_type, self.output_resolution) {
// Legacy: Seedance 2.0 Pro @ 720p — 25,000 credits for $99.99
@@ -152,8 +152,8 @@ impl KinoviGenerateVideoRequest {
(KinoviModelType::Seedance2Fast, None)
| (KinoviModelType::Seedance2Fast, Some(KinoviOutputResolution::SevenTwentyP)) => 220.0,
// New pricing: 500,000 credits for $2,159.09 (~231.58 credits/$1)
_ => 231.0,
// New pricing: 525,000 credits for $2,159.0909 (~243.16 credits/$1)
_ => 243.0,
}
}
@@ -669,7 +669,7 @@ mod tests {
#[test]
fn usd_cents_legacy_fast_720p() {
// 220 credits/$1: 140 credits = 63.6 → 64¢
// 220 credits/$1: 140 credits = 57.61 → 58¢
assert_eq!(fast(5, KinoviBatchCount::One).estimate_cost_in_usd_cents(), 64);
assert_eq!(fast(10, KinoviBatchCount::One).estimate_cost_in_usd_cents(), 127);
}
@@ -678,24 +678,24 @@ mod tests {
#[test]
fn usd_cents_new_pro_480p() {
// 231 credits/$1: 75 credits = 32.47 → 32¢
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 32);
assert_eq!(pro_res(10, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 65);
// 243 credits/$1: 75 credits = 30.86 → 31¢
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 31);
assert_eq!(pro_res(10, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 62);
}
#[test]
fn usd_cents_new_pro_1080p() {
// 231 credits/$1: 450 credits = 194.81 → 195¢
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).estimate_cost_in_usd_cents(), 195);
// 900 credits = 389.61 → 390¢
assert_eq!(pro_res(10, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).estimate_cost_in_usd_cents(), 390);
// 243 credits/$1: 450 credits = 185.19 → 185¢
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).estimate_cost_in_usd_cents(), 185);
// 900 credits = 370.37 → 370¢
assert_eq!(pro_res(10, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).estimate_cost_in_usd_cents(), 370);
}
#[test]
fn usd_cents_new_fast_480p() {
// 231 credits/$1: 50 credits = 21.65 → 22¢
assert_eq!(fast_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 22);
assert_eq!(fast_res(10, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 43);
// 243 credits/$1: 50 credits = 20.58 → 21¢
assert_eq!(fast_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 21);
assert_eq!(fast_res(10, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).estimate_cost_in_usd_cents(), 41);
}
// ── credits_per_dollar: verify the rates directly ──
@@ -711,11 +711,11 @@ mod tests {
#[test]
fn credits_per_dollar_new_rate() {
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).credits_per_dollar(), 231.0);
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).credits_per_dollar(), 231.0);
assert_eq!(fast_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).credits_per_dollar(), 231.0);
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).credits_per_dollar(), 243.0);
assert_eq!(pro_res(5, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).credits_per_dollar(), 243.0);
assert_eq!(fast_res(5, KinoviBatchCount::One, KinoviOutputResolution::FourEightyP).credits_per_dollar(), 243.0);
// Fast 1080p (not officially supported) also uses new rate
assert_eq!(fast_res(5, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).credits_per_dollar(), 231.0);
assert_eq!(fast_res(5, KinoviBatchCount::One, KinoviOutputResolution::TenEightyP).credits_per_dollar(), 243.0);
}
}
@@ -150,7 +150,7 @@ impl WorkflowRunTaskRequest {
/// Credits per dollar for billing conversion.
///
/// Legacy 720p pricing uses the original Kinovi credit package rates.
/// All other model/resolution combos use the newer rate: 500,000 credits / $2,159.09.
/// All other model/resolution combos use the newer rate: 525,000 credits / $2,159.0909.
fn credits_per_dollar(&self) -> f64 {
match (self.model_type, self.output_resolution) {
// Legacy: Seedance 2.0 Pro @ 720p — 25,000 credits for $99.99
@@ -161,8 +161,8 @@ impl WorkflowRunTaskRequest {
(KinoviModelTypeRaw::Seedance2Fast, None)
| (KinoviModelTypeRaw::Seedance2Fast, Some(KinoviOutputResolutionRaw::SevenTwentyP)) => 220.0,
// New pricing: 500,000 credits for $2,159.09 (~231.58 credits/$1)
_ => 231.0,
// New pricing: 525,000 credits for $2,159.0909 (~243.16 credits/$1)
_ => 243.0,
}
}
@@ -661,20 +661,20 @@ mod tests {
#[test]
fn usd_cents_new_pro_480p() {
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 32);
assert_eq!(pro_res(10, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 65);
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 31);
assert_eq!(pro_res(10, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 62);
}
#[test]
fn usd_cents_new_pro_1080p() {
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).estimate_cost_in_usd_cents(), 195);
assert_eq!(pro_res(10, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).estimate_cost_in_usd_cents(), 390);
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).estimate_cost_in_usd_cents(), 185);
assert_eq!(pro_res(10, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).estimate_cost_in_usd_cents(), 370);
}
#[test]
fn usd_cents_new_fast_480p() {
assert_eq!(fast_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 22);
assert_eq!(fast_res(10, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 43);
assert_eq!(fast_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 21);
assert_eq!(fast_res(10, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).estimate_cost_in_usd_cents(), 41);
}
#[test]
@@ -687,10 +687,10 @@ mod tests {
#[test]
fn credits_per_dollar_new_rate() {
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).credits_per_dollar(), 231.0);
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).credits_per_dollar(), 231.0);
assert_eq!(fast_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).credits_per_dollar(), 231.0);
assert_eq!(fast_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).credits_per_dollar(), 231.0);
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).credits_per_dollar(), 243.0);
assert_eq!(pro_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).credits_per_dollar(), 243.0);
assert_eq!(fast_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).credits_per_dollar(), 243.0);
assert_eq!(fast_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).credits_per_dollar(), 243.0);
}
// ── Happy Horse 1.0 ──
@@ -724,17 +724,17 @@ mod tests {
#[test]
fn happy_horse_uses_new_pricing_rate() {
// All Happy Horse resolutions use the new 231 credits/$1 rate (not legacy)
assert_eq!(happy_horse(5, KinoviBatchCountRaw::One).credits_per_dollar(), 231.0);
assert_eq!(happy_horse_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::SevenTwentyP).credits_per_dollar(), 231.0);
assert_eq!(happy_horse_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).credits_per_dollar(), 231.0);
assert_eq!(happy_horse_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).credits_per_dollar(), 231.0);
// All Happy Horse resolutions use the new 243 credits/$1 rate (not legacy)
assert_eq!(happy_horse(5, KinoviBatchCountRaw::One).credits_per_dollar(), 243.0);
assert_eq!(happy_horse_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::SevenTwentyP).credits_per_dollar(), 243.0);
assert_eq!(happy_horse_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::FourEightyP).credits_per_dollar(), 243.0);
assert_eq!(happy_horse_res(5, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).credits_per_dollar(), 243.0);
}
#[test]
fn happy_horse_usd_cents_1080p() {
// 231 credits/$1: 360 credits (4s×90) = 155.84 → 156¢
assert_eq!(happy_horse_res(4, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).estimate_cost_in_usd_cents(), 156);
// 243 credits/$1: 360 credits (4s×90) = 148.15 → 148¢
assert_eq!(happy_horse_res(4, KinoviBatchCountRaw::One, KinoviOutputResolutionRaw::TenEightyP).estimate_cost_in_usd_cents(), 148);
}
}