@@ -2,31 +2,98 @@ use async_trait::async_trait;
2
2
use diesel:: delete;
3
3
use diesel:: query_dsl:: methods:: FilterDsl ;
4
4
use diesel:: sql_query;
5
- use diesel:: sql_types:: { Array , BigInt , Text } ;
5
+ use diesel:: sql_types:: { Array , BigInt , Nullable , Text } ;
6
6
use diesel_async:: { AsyncPgConnection as PgConnection , RunQueryDsl } ;
7
+ use std:: collections:: HashMap ;
7
8
use std:: iter:: Iterator ;
8
9
9
10
use super :: utils:: InvolvedObjects ;
10
11
use super :: GeneratedData ;
11
12
use crate :: diesel:: ExpressionMethods ;
12
13
use crate :: error:: Result ;
13
14
use crate :: infra_cache:: InfraCache ;
14
- use crate :: schema:: ObjectType ;
15
+ use crate :: schema:: sprite_config:: { SpriteConfig , SpriteConfigs } ;
16
+ use crate :: schema:: { LogicalSignal , ObjectType } ;
15
17
use crate :: tables:: infra_layer_signal:: dsl;
16
18
17
19
pub struct SignalLayer ;
18
20
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
+
19
79
#[ async_trait]
20
80
impl GeneratedData for SignalLayer {
21
81
fn table_name ( ) -> & ' static str {
22
82
"infra_layer_signal"
23
83
}
24
84
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 < ( ) > {
26
86
sql_query ( include_str ! ( "sql/generate_signal_layer.sql" ) )
27
87
. bind :: < BigInt , _ > ( infra)
28
88
. execute ( conn)
29
89
. await ?;
90
+ generate_signaling_system_and_sprite (
91
+ conn,
92
+ infra,
93
+ infra_cache,
94
+ infra_cache. signals ( ) . keys ( ) , // All signals
95
+ )
96
+ . await ?;
30
97
Ok ( ( ) )
31
98
}
32
99
@@ -52,11 +119,19 @@ impl GeneratedData for SignalLayer {
52
119
53
120
// Update elements
54
121
if !involved_objects. updated . is_empty ( ) {
122
+ let updated_signals = involved_objects. updated . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
55
123
sql_query ( include_str ! ( "sql/insert_update_signal_layer.sql" ) )
56
124
. bind :: < BigInt , _ > ( infra)
57
- . bind :: < Array < Text > , _ > ( involved_objects . updated . into_iter ( ) . collect :: < Vec < _ > > ( ) )
125
+ . bind :: < Array < Text > , _ > ( & updated_signals )
58
126
. execute ( conn)
59
127
. await ?;
128
+ generate_signaling_system_and_sprite (
129
+ conn,
130
+ infra,
131
+ infra_cache,
132
+ updated_signals. into_iter ( ) ,
133
+ )
134
+ . await ?;
60
135
}
61
136
Ok ( ( ) )
62
137
}
0 commit comments