-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathlight_rolling_stock.rs
175 lines (164 loc) · 6.44 KB
/
light_rolling_stock.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
use crate::error::Result;
use crate::models::{rolling_stock::rolling_stock_livery::RollingStockLiveryMetadata, TextArray};
use crate::schema::rolling_stock::light_rolling_stock::{
LightEffortCurves, LightRollingStock, LightRollingStockWithLiveries,
};
use crate::schema::rolling_stock::{EnergySource, Gamma, RollingResistance, RollingStockMetadata};
use crate::tables::rolling_stock;
use crate::views::pagination::{Paginate, PaginatedResponse};
use crate::DbPool;
use actix_web::web::Data;
use diesel::result::Error as DieselError;
use diesel::{sql_query, ExpressionMethods, QueryDsl, SelectableHelper};
use diesel_async::RunQueryDsl;
use diesel_json::Json as DieselJson;
use editoast_derive::Model;
use serde::Serialize;
use std::collections::HashMap;
use utoipa::ToSchema;
#[derive(Debug, Model, Queryable, QueryableByName, Serialize, ToSchema)]
#[model(table = "rolling_stock")]
#[model(retrieve)]
#[diesel(table_name = rolling_stock)]
pub struct LightRollingStockModel {
pub id: i64,
railjson_version: String,
name: String,
#[schema(value_type = LightEffortCurves)]
effort_curves: DieselJson<LightEffortCurves>,
#[schema(value_type = RollingStockLiveryMetadata)]
metadata: DieselJson<RollingStockMetadata>,
length: f64,
max_speed: f64,
startup_time: f64,
startup_acceleration: f64,
comfort_acceleration: f64,
gamma: DieselJson<Gamma>,
inertia_coefficient: f64,
pub base_power_class: Option<String>,
mass: f64,
#[schema(value_type = RollingResistance)]
rolling_resistance: DieselJson<RollingResistance>,
#[schema(value_type = LoadingGaugeType)]
loading_gauge: String,
#[schema(value_type = HashMap<String, String>)]
power_restrictions: Option<DieselJson<HashMap<String, String>>>,
#[schema(value_type = Vec<EnergySource>)]
energy_sources: DieselJson<Vec<EnergySource>>,
locked: bool,
electrical_power_startup_time: Option<f64>,
raise_pantograph_time: Option<f64>,
pub version: i64,
#[diesel(deserialize_as = TextArray)]
supported_signaling_systems: Vec<String>,
}
impl LightRollingStockModel {
pub async fn with_liveries(
self,
db_pool: Data<DbPool>,
) -> Result<LightRollingStockWithLiveries> {
use crate::tables::rolling_stock_livery::dsl as livery_dsl;
let mut conn = db_pool.get().await?;
let liveries = livery_dsl::rolling_stock_livery
.filter(livery_dsl::rolling_stock_id.eq(self.id))
.select(RollingStockLiveryMetadata::as_select())
.load(&mut conn)
.await?;
Ok(LightRollingStockWithLiveries {
rolling_stock: self.into(),
liveries: liveries.into_iter().map(DieselJson).collect(),
})
}
/// List the rolling stocks with their simplified effort curves
pub async fn list(
db_pool: Data<DbPool>,
page: i64,
per_page: i64,
) -> Result<PaginatedResponse<LightRollingStockWithLiveries>> {
let mut conn = db_pool.get().await?;
sql_query(
"WITH liveries_by_rs AS (SELECT rolling_stock_id, jsonb_build_object('id', livery.id, 'name', livery.name, 'compound_image_id', livery.compound_image_id) AS liveries
FROM rolling_stock_livery livery)
SELECT
rolling_stock.*,
COALESCE(ARRAY_AGG(liveries_by_rs.liveries) FILTER (WHERE liveries_by_rs.liveries is not NULL), ARRAY[]::jsonb[]) AS liveries
FROM rolling_stock
LEFT JOIN liveries_by_rs liveries_by_rs ON liveries_by_rs.rolling_stock_id = rolling_stock.id
GROUP BY rolling_stock.id
ORDER BY rolling_stock.id"
)
.paginate(page, per_page)
.load_and_count(&mut conn).await
}
}
impl From<LightRollingStockModel> for LightRollingStock {
fn from(rolling_stock_model: LightRollingStockModel) -> Self {
LightRollingStock {
id: rolling_stock_model.id,
name: rolling_stock_model.name,
railjson_version: rolling_stock_model.railjson_version,
locked: rolling_stock_model.locked,
effort_curves: rolling_stock_model.effort_curves,
base_power_class: rolling_stock_model.base_power_class,
length: rolling_stock_model.length,
max_speed: rolling_stock_model.max_speed,
startup_time: rolling_stock_model.startup_time,
startup_acceleration: rolling_stock_model.startup_acceleration,
comfort_acceleration: rolling_stock_model.comfort_acceleration,
gamma: rolling_stock_model.gamma,
inertia_coefficient: rolling_stock_model.inertia_coefficient,
mass: rolling_stock_model.mass,
rolling_resistance: rolling_stock_model.rolling_resistance,
loading_gauge: rolling_stock_model.loading_gauge,
metadata: rolling_stock_model.metadata,
power_restrictions: rolling_stock_model.power_restrictions,
energy_sources: rolling_stock_model.energy_sources,
version: rolling_stock_model.version,
supported_signaling_systems: rolling_stock_model.supported_signaling_systems,
}
}
}
#[cfg(test)]
pub mod tests {
use crate::fixtures::tests::{db_pool, named_fast_rolling_stock};
use crate::models::Retrieve;
use crate::DbPool;
use actix_web::web::Data;
use rstest::*;
use super::LightRollingStockModel;
#[rstest]
async fn get_light_rolling_stock(db_pool: Data<DbPool>) {
// GIVEN
let rolling_stock = named_fast_rolling_stock(
"fast_rolling_stock_get_light_rolling_stock",
db_pool.clone(),
)
.await;
let rolling_stock_id = rolling_stock.id();
// THEN
assert!(LightRollingStockModel::retrieve(db_pool, rolling_stock_id)
.await
.is_ok());
}
#[rstest]
async fn list_light_rolling_stock(db_pool: Data<DbPool>) {
// GIVEN
let rolling_stock = named_fast_rolling_stock(
"fast_rolling_stock_list_light_rolling_stock",
db_pool.clone(),
)
.await;
// WHEN
let rolling_stocks = LightRollingStockModel::list(db_pool, 1, 1000)
.await
.unwrap();
// THEN
assert!(rolling_stocks.count >= 1);
let ids: Vec<i64> = rolling_stocks
.results
.iter()
.map(|x| x.rolling_stock.id)
.collect();
assert!(ids.contains(&rolling_stock.id()));
}
}