1use chrono::DateTime;
2use serde::Serialize;
3
4use crate::{
5 Actual, Language, PartialPowerAverage, PowerAverage, PowerTariffMatches,
6 costs::{CostPeriods, CostPeriodsSimple},
7 hours::Hours,
8};
9
10#[derive(Debug, Clone, Copy, Serialize)]
11#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
12pub struct PowerDivide {
13 pub(crate) hours: Option<Hours>,
14 divider: u8,
15}
16
17impl PowerDivide {
18 pub const fn new(hours: Option<Hours>, divider: u8) -> Self {
19 Self { hours, divider }
20 }
21
22 pub fn hours(&self) -> Option<Hours> {
23 self.hours
24 }
25
26 pub fn divider<Tz: chrono::TimeZone>(&self, timestamp: DateTime<Tz>) -> u8 {
27 if let Some(hours) = self.hours()
28 && hours.matches(timestamp)
29 {
30 self.divider
31 } else {
32 1
33 }
34 }
35
36 pub fn multiplier<Tz: chrono::TimeZone>(&self, timestamp: DateTime<Tz>) -> f64 {
37 1. / self.divider(timestamp) as f64
38 }
39}
40
41#[derive(Debug, Clone, Serialize)]
42#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
43pub enum PowerTariff {
44 Unverified,
45 NotImplemented,
46 Periods {
47 method: TariffCalculationMethod,
48 power_divide: Option<PowerDivide>,
50 periods: CostPeriods,
51 },
52}
53
54impl PowerTariff {
55 pub const fn new(method: TariffCalculationMethod, periods: CostPeriods) -> Self {
56 Self::Periods {
57 method,
58 periods,
59 power_divide: None,
60 }
61 }
62
63 pub const fn add_power_divide(self, power_divide: PowerDivide) -> Self {
64 match self {
65 Self::Unverified => unimplemented!(),
66 Self::NotImplemented => unimplemented!(),
67 Self::Periods {
68 method,
69 power_divide: _,
70 periods,
71 } => Self::Periods {
72 method,
73 power_divide: Some(power_divide),
74 periods,
75 },
76 }
77 }
78
79 pub const fn is_unverified(&self) -> bool {
80 matches!(self, Self::Unverified)
81 }
82
83 pub fn simplified(
84 &self,
85 fuse_size: u16,
86 yearly_consumption: u32,
87 language: Language,
88 ) -> PowerTariffSimplified {
89 PowerTariffSimplified::new(self, fuse_size, yearly_consumption, language)
90 }
91
92 pub fn periods(
93 &self,
94 averages: Vec<PowerAverage<Actual>>,
95 current_power_average: Option<PartialPowerAverage>,
96 ) -> PowerTariffMatches {
97 match self {
98 PowerTariff::Unverified => PowerTariffMatches::new_dummy(),
99 PowerTariff::NotImplemented => PowerTariffMatches::new_dummy(),
100 PowerTariff::Periods {
101 method,
102 periods,
103 power_divide,
104 } => PowerTariffMatches::new(
105 *method,
106 *power_divide,
107 *periods,
108 &averages.iter().map(|a| a.into_virtual(*power_divide)).collect::<Vec<_>>(),
109 current_power_average,
110 ),
111 }
112 }
113}
114
115#[derive(Debug, Clone, Copy, Serialize)]
117#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
118pub enum TariffCalculationMethod {
119 AverageDays(u8),
121 AverageHours(u8),
123}
124
125#[derive(Debug, Clone, Serialize)]
127#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
128pub enum PowerTariffSimplified {
129 Unverified,
130 NotImplemented,
131 Periods {
132 method: TariffCalculationMethod,
133 power_divide: Option<PowerDivide>,
135 periods: CostPeriodsSimple,
136 },
137}
138
139impl PowerTariffSimplified {
140 fn new(fee: &PowerTariff, fuse_size: u16, yearly_consumption: u32, language: Language) -> Self {
141 match *fee {
142 PowerTariff::Unverified => PowerTariffSimplified::Unverified,
143 PowerTariff::NotImplemented => PowerTariffSimplified::NotImplemented,
144 PowerTariff::Periods {
145 method,
146 periods,
147 power_divide,
148 } => PowerTariffSimplified::Periods {
149 method,
150 power_divide,
151 periods: CostPeriodsSimple::new(periods, fuse_size, yearly_consumption, language),
152 },
153 }
154 }
155}