pyoe2_craftpath/calc/statistics/
helpers.rs

1use std::mem::size_of;
2
3use tracing::instrument;
4
5use crate::{
6    api::{
7        calculator::{ItemMatrix, ItemMatrixNode, ItemRoute, ItemRouteNode},
8        currency::CraftCurrencyList,
9        item::ItemSnapshot,
10        provider::{item_info::ItemInfoProvider, market_prices::MarketPriceProvider},
11    },
12    explicit_type,
13    utils::{fraction_utils::Fraction, hash_utils::hash_value},
14};
15
16#[derive(Clone, Debug)]
17pub struct ItemRouteNodeRef<'a> {
18    pub item: &'a ItemSnapshot,
19    pub chance: &'a Fraction,
20    pub currency_list: &'a CraftCurrencyList,
21}
22
23#[derive(Clone, Debug)]
24pub struct ItemRouteRef<'a> {
25    pub route: Vec<ItemRouteNodeRef<'a>>,
26    pub weight: RouteCustomWeight,
27    pub chance: RouteChance,
28}
29
30/// Calculates RAM usage in bytes for an ItemRouteNodeRef<'a>.
31pub fn ram_usage_item_route_node_ref<'a>(_node: &ItemRouteNodeRef<'a>) -> u64 {
32    (size_of::<&ItemSnapshot>() + size_of::<&Fraction>() + size_of::<&CraftCurrencyList>()) as u64
33}
34
35/// Calculates RAM usage for an ItemRouteRef<'a> (includes Vec capacity).
36pub fn ram_usage_item_route_ref<'a>(route_ref: &ItemRouteRef<'a>) -> u64 {
37    let vec_capacity = route_ref.route.capacity();
38    let node_size = size_of::<ItemRouteNodeRef<'a>>();
39    let vec_overhead = size_of::<Vec<ItemRouteNodeRef<'a>>>();
40
41    // route Vec + its allocated elements + f64 weight
42    (vec_overhead + node_size * vec_capacity + size_of::<f64>()) as u64
43}
44
45/// Calculates RAM usage for a stack entry: (Vec<ItemRouteNodeRef>, &ItemMatrixNode)
46pub fn ram_usage_stack_entry<'a>(path: &Vec<ItemRouteNodeRef<'a>>, _node: &ItemMatrixNode) -> u64 {
47    let vec_capacity = path.capacity();
48    let node_size = size_of::<ItemRouteNodeRef<'a>>();
49    let vec_overhead = size_of::<Vec<ItemRouteNodeRef<'a>>>();
50    let node_ref_size = size_of::<&ItemMatrixNode>();
51
52    (vec_overhead + node_size * vec_capacity + node_ref_size) as u64
53}
54
55pub trait StatisticAnalyzerCollectorTrait {
56    fn get_weight(
57        path: &Vec<ItemRouteNodeRef<'_>>,
58        matrix: &ItemMatrix,
59        item_provider: &ItemInfoProvider,
60        market_provider: &MarketPriceProvider,
61    ) -> (RouteCustomWeight, RouteChance);
62}
63
64explicit_type!(RouteCustomWeight, f64);
65explicit_type!(SubpathAmount, u32);
66explicit_type!(RouteChance, f64);
67
68pub trait StatisticAnalyzerCurrencyGroupCollectorTrait {
69    fn get_partial_weights(
70        path: &Vec<ItemRouteNodeRef<'_>>,
71        matrix: &ItemMatrix,
72        item_provider: &ItemInfoProvider,
73        market_provider: &MarketPriceProvider,
74    ) -> Vec<RouteChance>;
75
76    fn calculate_group_weight(
77        currency: &Vec<&CraftCurrencyList>,
78        paths: &Vec<Vec<RouteChance>>,
79    ) -> RouteCustomWeight;
80
81    fn calculate_group_chance(paths: &Vec<Vec<RouteChance>>) -> RouteChance;
82}
83
84#[instrument(skip_all)]
85pub fn finalize_routes(mut routes: Vec<ItemRouteRef<'_>>) -> Vec<ItemRoute> {
86    tracing::info!("Collecting {} routes ...", routes.len());
87    let mut finalized = Vec::new();
88
89    for route_ref in routes.drain(..) {
90        let mut owned_nodes = Vec::with_capacity(route_ref.route.len());
91        for node_ref in route_ref.route {
92            owned_nodes.push(ItemRouteNode {
93                item_matrix_id: hash_value(node_ref.item),
94                chance: node_ref.chance.clone(),
95                currency_list: node_ref.currency_list.clone(),
96            });
97        }
98        finalized.push(ItemRoute {
99            route: owned_nodes,
100            weight: route_ref.weight,
101            chance: route_ref.chance,
102        });
103    }
104
105    tracing::info!("Routes collected successfully.");
106    finalized
107}