Skip to content

Commit 3a3e9a9

Browse files
committed
appraisal.rs: Factor out comparing assets to separate function
1 parent 0fefe9c commit 3a3e9a9

File tree

2 files changed

+87
-17
lines changed

2 files changed

+87
-17
lines changed

src/asset.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,32 @@ impl Asset {
195195
)
196196
}
197197

198+
/// Create a new commissioned asset
199+
///
200+
/// This is only used for testing. WARNING: These assets always have an ID of zero, so can
201+
/// create hash collisions. Use with care.
202+
#[cfg(test)]
203+
pub fn new_commissioned(
204+
agent_id: AgentID,
205+
process: Rc<Process>,
206+
region_id: RegionID,
207+
capacity: Capacity,
208+
commission_year: u32,
209+
) -> Result<Self> {
210+
Self::new_with_state(
211+
AssetState::Commissioned {
212+
id: AssetID(0),
213+
agent_id,
214+
mothballed_year: None,
215+
},
216+
process,
217+
region_id,
218+
capacity,
219+
commission_year,
220+
None,
221+
)
222+
}
223+
198224
/// Private helper to create an asset with the given state
199225
fn new_with_state(
200226
state: AssetState,

src/simulation/investment/appraisal.rs

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Calculation for investment tools such as Levelised Cost of X (LCOX) and Net Present Value (NPV).
22
use super::DemandMap;
33
use crate::agent::ObjectiveType;
4-
use crate::asset::AssetRef;
4+
use crate::asset::{Asset, AssetRef};
55
use crate::commodity::Commodity;
66
use crate::finance::{lcox, profitability_index};
77
use crate::model::Model;
@@ -67,25 +67,28 @@ impl AppraisalOutput {
6767
"Appraisal metrics must be equal"
6868
);
6969

70-
// Favour commissioned assets over non-commissioned
71-
if self.asset.is_commissioned() && !other.asset.is_commissioned() {
72-
return Ordering::Less;
73-
}
74-
if !self.asset.is_commissioned() && other.asset.is_commissioned() {
75-
return Ordering::Greater;
76-
}
70+
compare_asset_fallback(&self.asset, &other.asset)
71+
}
72+
}
7773

78-
// if both commissioned, favour newer ones
79-
if self.asset.is_commissioned() && other.asset.is_commissioned() {
80-
return self
81-
.asset
82-
.commission_year()
83-
.cmp(&other.asset.commission_year())
84-
.reverse();
85-
}
74+
fn compare_asset_fallback(asset1: &Asset, asset2: &Asset) -> Ordering {
75+
// Favour commissioned assets over non-commissioned
76+
if asset1.is_commissioned() && !asset2.is_commissioned() {
77+
return Ordering::Less;
78+
}
79+
if !asset1.is_commissioned() && asset2.is_commissioned() {
80+
return Ordering::Greater;
81+
}
8682

87-
Ordering::Equal
83+
// if both commissioned, favour newer ones
84+
if asset1.is_commissioned() && asset2.is_commissioned() {
85+
return asset1
86+
.commission_year()
87+
.cmp(&asset2.commission_year())
88+
.reverse();
8889
}
90+
91+
Ordering::Equal
8992
}
9093

9194
/// Calculate LCOX for a hypothetical investment in the given asset.
@@ -192,3 +195,44 @@ pub fn appraise_investment(
192195
};
193196
appraisal_method(model, asset, max_capacity, commodity, coefficients, demand)
194197
}
198+
199+
#[cfg(test)]
200+
mod tests {
201+
use super::*;
202+
use crate::agent::AgentID;
203+
use crate::asset::Asset;
204+
use crate::fixture::{agent_id, process, region_id};
205+
use crate::process::Process;
206+
use crate::region::RegionID;
207+
use crate::units::Capacity;
208+
use rstest::rstest;
209+
use std::rc::Rc;
210+
211+
#[rstest]
212+
fn test_compare_assets_fallback(process: Process, region_id: RegionID, agent_id: AgentID) {
213+
let process = Rc::new(process);
214+
let capacity = Capacity(2.0);
215+
let asset1 = Asset::new_commissioned(
216+
agent_id.clone(),
217+
process.clone(),
218+
region_id.clone(),
219+
capacity,
220+
2015,
221+
)
222+
.unwrap();
223+
let asset2 =
224+
Asset::new_candidate(process.clone(), region_id.clone(), capacity, 2015).unwrap();
225+
let asset3 =
226+
Asset::new_commissioned(agent_id, process, region_id.clone(), capacity, 2010).unwrap();
227+
228+
assert!(compare_asset_fallback(&asset1, &asset1).is_eq());
229+
assert!(compare_asset_fallback(&asset2, &asset2).is_eq());
230+
assert!(compare_asset_fallback(&asset3, &asset3).is_eq());
231+
assert!(compare_asset_fallback(&asset1, &asset2).is_lt());
232+
assert!(compare_asset_fallback(&asset2, &asset1).is_gt());
233+
assert!(compare_asset_fallback(&asset1, &asset3).is_lt());
234+
assert!(compare_asset_fallback(&asset3, &asset1).is_gt());
235+
assert!(compare_asset_fallback(&asset3, &asset2).is_lt());
236+
assert!(compare_asset_fallback(&asset2, &asset3).is_gt());
237+
}
238+
}

0 commit comments

Comments
 (0)