wowlab_sentinel/strategy/factorial/
types.rs1#[derive(Clone, Debug)]
4pub struct FactorialSlot {
5 pub slot_index: u32,
6 pub items: Vec<FactorialItem>,
7}
8
9#[derive(Clone, Copy, Debug)]
10pub struct FactorialItem {
11 has_effect: bool,
12}
13
14impl FactorialItem {
15 pub(crate) fn new(has_effect: bool) -> Self {
16 Self { has_effect }
17 }
18
19 pub(crate) fn has_effect(self) -> bool {
20 self.has_effect
21 }
22}
23
24#[derive(Clone, Copy, Debug)]
25pub(crate) struct MainEffectEstimate {
26 pub slot_index: u32,
27 pub item_idx: u32,
28 pub effect_dps_x10: i32,
29}
30
31#[derive(Clone, Copy, Debug)]
32pub(crate) struct InteractionEstimate {
33 pub slot_a: u32,
34 pub item_idx_a: u32,
35 pub slot_b: u32,
36 pub item_idx_b: u32,
37 pub interaction_dps_x10: i32,
38}
39
40#[derive(Clone, Debug)]
41pub(crate) struct ScreeningResult {
42 pub survivors: Vec<u64>,
43}
44
45#[derive(Clone, Copy, Debug, Eq, PartialEq)]
46#[non_exhaustive]
47pub(crate) enum WorkUnitKind {
48 Tournament,
49 MainEffect,
50 Interaction,
51}
52
53const KIND_SHIFT: u32 = 62;
55const KIND_MASK: u64 = 0b11 << KIND_SHIFT;
56const MAIN_EFFECT_KIND: u64 = 0b01 << KIND_SHIFT;
57const INTERACTION_KIND: u64 = 0b10 << KIND_SHIFT;
58const PAYLOAD_MASK: u64 = !KIND_MASK;
59const MAIN_SLOT_SHIFT: u32 = 16;
60const MAIN_INDEX_MASK: u64 = 0xFFFF;
61const INTERACTION_FIELD_MASK: u64 = 0xFFF;
62const INTERACTION_SLOT_A_SHIFT: u32 = 36;
63const INTERACTION_ITEM_A_SHIFT: u32 = 24;
64const INTERACTION_SLOT_B_SHIFT: u32 = 12;
65
66pub(crate) const fn encode_main_effect_tag(slot_idx: u32, item_idx: u32) -> u64 {
67 MAIN_EFFECT_KIND | ((slot_idx as u64) << MAIN_SLOT_SHIFT) | (item_idx as u64 & MAIN_INDEX_MASK)
68}
69
70pub(crate) const fn encode_interaction_tag(
71 slot_a: u32,
72 item_a: u32,
73 slot_b: u32,
74 item_b: u32,
75) -> u64 {
76 INTERACTION_KIND
77 | ((slot_a as u64 & INTERACTION_FIELD_MASK) << INTERACTION_SLOT_A_SHIFT)
78 | ((item_a as u64 & INTERACTION_FIELD_MASK) << INTERACTION_ITEM_A_SHIFT)
79 | ((slot_b as u64 & INTERACTION_FIELD_MASK) << INTERACTION_SLOT_B_SHIFT)
80 | (item_b as u64 & INTERACTION_FIELD_MASK)
81}
82
83pub(crate) const fn tag_kind(tag: u64) -> WorkUnitKind {
84 match tag & KIND_MASK {
85 INTERACTION_KIND => WorkUnitKind::Interaction,
86 MAIN_EFFECT_KIND => WorkUnitKind::MainEffect,
87 _ => WorkUnitKind::Tournament,
88 }
89}
90
91pub(crate) const fn decode_main_effect_tag(tag: u64) -> (u32, u32) {
92 let payload = tag & PAYLOAD_MASK;
93 let slot_idx = ((payload >> MAIN_SLOT_SHIFT) & MAIN_INDEX_MASK) as u32;
94 let item_idx = (payload & MAIN_INDEX_MASK) as u32;
95
96 (slot_idx, item_idx)
97}
98
99pub(crate) const fn decode_interaction_tag(tag: u64) -> (u32, u32, u32, u32) {
100 let payload = tag & PAYLOAD_MASK;
101 let slot_a = ((payload >> INTERACTION_SLOT_A_SHIFT) & INTERACTION_FIELD_MASK) as u32;
102 let item_a = ((payload >> INTERACTION_ITEM_A_SHIFT) & INTERACTION_FIELD_MASK) as u32;
103 let slot_b = ((payload >> INTERACTION_SLOT_B_SHIFT) & INTERACTION_FIELD_MASK) as u32;
104 let item_b = (payload & INTERACTION_FIELD_MASK) as u32;
105
106 (slot_a, item_a, slot_b, item_b)
107}