Skip to content

Commit 36b3c6f

Browse files
committed
editoast: adapt signal layer for new sprite system
1 parent f0dc1e8 commit 36b3c6f

File tree

7 files changed

+106
-10
lines changed

7 files changed

+106
-10
lines changed

editoast/map_layers.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ layers:
2525
geo:
2626
on_field: geographic
2727
cache_duration: 3600
28-
data_expr: signal.data || jsonb_build_object('angle', layer.angle_geo)
28+
data_expr: signal.data - 'logical_signals' || jsonb_build_object('angle', layer.angle_geo, 'signaling_system', layer.signaling_system, 'sprite', layer.sprite)
2929
joins:
3030
- inner join infra_object_signal signal on signal.obj_id = layer.obj_id and signal.infra_id = layer.infra_id
3131
sch:
3232
on_field: schematic
3333
cache_duration: 3600
34-
data_expr: signal.data || jsonb_build_object('angle', layer.angle_sch)
34+
data_expr: signal.data - 'logical_signals' || jsonb_build_object('angle', layer.angle_sch, 'signaling_system', layer.signaling_system, 'sprite', layer.sprite)
3535
joins:
3636
- inner join infra_object_signal signal on signal.obj_id = layer.obj_id and signal.infra_id = layer.infra_id
3737

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE infra_layer_signal DROP signaling_system;
2+
ALTER TABLE infra_layer_signal DROP sprite;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ALTER TABLE infra_layer_signal
2+
ADD signaling_system VARCHAR(255) NULL;
3+
ALTER TABLE infra_layer_signal
4+
ADD sprite VARCHAR(255) NULL;

editoast/src/generated_data/signal.rs

+79-4
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,98 @@ use async_trait::async_trait;
22
use diesel::delete;
33
use diesel::query_dsl::methods::FilterDsl;
44
use diesel::sql_query;
5-
use diesel::sql_types::{Array, BigInt, Text};
5+
use diesel::sql_types::{Array, BigInt, Nullable, Text};
66
use diesel_async::{AsyncPgConnection as PgConnection, RunQueryDsl};
7+
use std::collections::HashMap;
78
use std::iter::Iterator;
89

910
use super::utils::InvolvedObjects;
1011
use super::GeneratedData;
1112
use crate::diesel::ExpressionMethods;
1213
use crate::error::Result;
1314
use crate::infra_cache::InfraCache;
14-
use crate::schema::ObjectType;
15+
use crate::schema::sprite_config::{SpriteConfig, SpriteConfigs};
16+
use crate::schema::{LogicalSignal, ObjectType};
1517
use crate::tables::infra_layer_signal::dsl;
1618

1719
pub struct SignalLayer;
1820

21+
/// Found the corresponding sprite id for a given logical signal
22+
fn find_sprite_id(sprite_config: &SpriteConfigs, logical_signal: &LogicalSignal) -> Option<String> {
23+
let sprite_config = sprite_config.get(&logical_signal.signaling_system)?;
24+
'sprite: for conditional_sprite in &sprite_config.sprites {
25+
for (cond_key, cond_value) in &conditional_sprite.conditions {
26+
match logical_signal.settings.get(&cond_key.clone().into()) {
27+
Some(value) if &value.0 == cond_value => continue,
28+
_ => continue 'sprite,
29+
}
30+
}
31+
// All conditions are met
32+
return Some(conditional_sprite.sprite.clone());
33+
}
34+
Some(sprite_config.default.clone())
35+
}
36+
37+
/// Generate the signaling system and sprite fields of the layer.
38+
/// Only updated_signals are updated
39+
async fn generate_signaling_system_and_sprite<'a, T: Iterator<Item = &'a String>>(
40+
conn: &mut PgConnection,
41+
infra: i64,
42+
infra_cache: &InfraCache,
43+
updated_signals: T,
44+
) -> Result<()> {
45+
let sprite_configs = SpriteConfig::load();
46+
let mut group_by_sprite: HashMap<_, Vec<_>> = HashMap::new();
47+
48+
for signal_id in updated_signals {
49+
let signal = match infra_cache.signals().get(signal_id) {
50+
Some(signal) => signal,
51+
None => continue,
52+
};
53+
let logical_signal = match signal.unwrap_signal().logical_signals.get(0) {
54+
Some(logical_signal) => logical_signal,
55+
None => continue,
56+
};
57+
58+
let signaling_system = &logical_signal.signaling_system;
59+
let sprite_id = find_sprite_id(&sprite_configs, logical_signal);
60+
61+
group_by_sprite
62+
.entry((signaling_system, sprite_id))
63+
.or_default()
64+
.push(signal_id);
65+
}
66+
67+
for ((signaling_system, sprite_id), signals) in group_by_sprite {
68+
sql_query("UPDATE infra_layer_signal SET signaling_system = $2, sprite = $3 WHERE infra_id = $1 AND obj_id = ANY($4)")
69+
.bind::<BigInt, _>(infra)
70+
.bind::<Text, _>(signaling_system)
71+
.bind::<Nullable<Text>, _>(sprite_id)
72+
.bind::<Array<Text>, _>(signals)
73+
.execute(conn)
74+
.await?;
75+
}
76+
Ok(())
77+
}
78+
1979
#[async_trait]
2080
impl GeneratedData for SignalLayer {
2181
fn table_name() -> &'static str {
2282
"infra_layer_signal"
2383
}
2484

25-
async fn generate(conn: &mut PgConnection, infra: i64, _cache: &InfraCache) -> Result<()> {
85+
async fn generate(conn: &mut PgConnection, infra: i64, infra_cache: &InfraCache) -> Result<()> {
2686
sql_query(include_str!("sql/generate_signal_layer.sql"))
2787
.bind::<BigInt, _>(infra)
2888
.execute(conn)
2989
.await?;
90+
generate_signaling_system_and_sprite(
91+
conn,
92+
infra,
93+
infra_cache,
94+
infra_cache.signals().keys(), // All signals
95+
)
96+
.await?;
3097
Ok(())
3198
}
3299

@@ -52,11 +119,19 @@ impl GeneratedData for SignalLayer {
52119

53120
// Update elements
54121
if !involved_objects.updated.is_empty() {
122+
let updated_signals = involved_objects.updated.into_iter().collect::<Vec<_>>();
55123
sql_query(include_str!("sql/insert_update_signal_layer.sql"))
56124
.bind::<BigInt, _>(infra)
57-
.bind::<Array<Text>, _>(involved_objects.updated.into_iter().collect::<Vec<_>>())
125+
.bind::<Array<Text>, _>(&updated_signals)
58126
.execute(conn)
59127
.await?;
128+
generate_signaling_system_and_sprite(
129+
conn,
130+
infra,
131+
infra_cache,
132+
updated_signals.into_iter(),
133+
)
134+
.await?;
60135
}
61136
Ok(())
62137
}

editoast/src/infra_cache/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ impl InfraCache {
373373

374374
// Load signal tracks references
375375
sql_query(
376-
"SELECT obj_id, data->>'track' AS track, (data->>'position')::float AS position FROM infra_object_signal WHERE infra_id = $1")
376+
"SELECT obj_id, data->>'track' AS track, (data->>'position')::float AS position, data->'logical_signals' as logical_signals FROM infra_object_signal WHERE infra_id = $1")
377377
.bind::<BigInt, _>(infra_id)
378378
.load::<SignalCache>(conn).await?.into_iter().for_each(|signal|
379379
infra_cache.add(signal)
@@ -799,6 +799,7 @@ pub mod tests {
799799
obj_id: obj_id.as_ref().into(),
800800
track: track.as_ref().into(),
801801
position,
802+
logical_signals: Default::default(),
802803
}
803804
}
804805

editoast/src/schema/signal.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use super::Side;
1212
use crate::infra_cache::Cache;
1313
use crate::infra_cache::ObjectCache;
1414
use derivative::Derivative;
15-
use diesel::sql_types::{Double, Text};
15+
use diesel::sql_types::{Double, Jsonb, Text};
16+
use diesel_json::Json as DieselJson;
1617

1718
use editoast_derive::InfraModel;
1819
use serde::{Deserialize, Serialize};
@@ -91,6 +92,9 @@ pub struct SignalCache {
9192
#[derivative(Hash = "ignore", PartialEq = "ignore")]
9293
#[diesel(sql_type = Double)]
9394
pub position: f64,
95+
#[derivative(Hash = "ignore", PartialEq = "ignore")]
96+
#[diesel(sql_type = Jsonb)]
97+
pub logical_signals: DieselJson<Vec<LogicalSignal>>,
9498
}
9599

96100
impl OSRDTyped for SignalCache {
@@ -116,18 +120,24 @@ impl Cache for SignalCache {
116120
}
117121

118122
impl SignalCache {
119-
pub fn new(obj_id: String, track: String, position: f64) -> Self {
123+
pub fn new(
124+
obj_id: String,
125+
track: String,
126+
position: f64,
127+
logical_signals: Vec<LogicalSignal>,
128+
) -> Self {
120129
Self {
121130
obj_id,
122131
track,
123132
position,
133+
logical_signals: DieselJson(logical_signals),
124134
}
125135
}
126136
}
127137

128138
impl From<Signal> for SignalCache {
129139
fn from(sig: Signal) -> Self {
130-
Self::new(sig.id.0, sig.track.0, sig.position)
140+
Self::new(sig.id.0, sig.track.0, sig.position, sig.logical_signals)
131141
}
132142
}
133143

editoast/src/tables.rs

+4
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ diesel::table! {
156156
infra_id -> Int8,
157157
angle_geo -> Float8,
158158
angle_sch -> Float8,
159+
#[max_length = 255]
160+
signaling_system -> Nullable<Varchar>,
161+
#[max_length = 255]
162+
sprite -> Nullable<Varchar>,
159163
}
160164
}
161165

0 commit comments

Comments
 (0)