1
+ use std:: time:: { Duration , SystemTime } ;
2
+
1
3
use color_eyre:: Result ;
2
4
use serde:: { Deserialize , Serialize } ;
3
5
4
6
use context_attribute:: context;
5
- use framework:: MainOutput ;
7
+ use framework:: { AdditionalOutput , MainOutput } ;
6
8
use spl_network_messages:: { SubState , Team } ;
7
9
use types:: {
8
10
filtered_whistle:: FilteredWhistle , game_controller_state:: GameControllerState ,
9
11
world_state:: BallState ,
10
12
} ;
11
13
12
14
#[ derive( Deserialize , Serialize ) ]
13
- pub struct KickingTeamFilter { }
15
+ pub struct KickingTeamFilter {
16
+ time_last_ball_state_became_default : SystemTime ,
17
+ last_ball_state : BallState ,
18
+ last_non_default_ball_state : Option < BallState > ,
19
+ }
14
20
15
21
#[ context]
16
22
pub struct CreationContext { }
17
23
18
24
#[ context]
19
25
pub struct CycleContext {
20
- last_ball_state : CyclerState < BallState , "last_ball_position " > ,
26
+ last_ball_state : CyclerState < BallState , "last_ball_state " > ,
21
27
game_controller_state : RequiredInput < Option < GameControllerState > , "game_controller_state?" > ,
22
28
detected_free_kick_kicking_team : Input < Option < Team > , "detected_free_kick_kicking_team?" > ,
23
29
filtered_whistle : Input < FilteredWhistle , "filtered_whistle" > ,
30
+
31
+ duration_to_keep_non_default_last_ball_state :
32
+ Parameter < Duration , "kicking_team_filter.duration_to_keep_non_default_last_ball_state" > ,
33
+
34
+ additonal_last_ball_state : AdditionalOutput < BallState , "last_ball_state" > ,
24
35
}
25
36
26
37
#[ context]
@@ -30,50 +41,92 @@ pub struct MainOutputs {
30
41
31
42
impl KickingTeamFilter {
32
43
pub fn new ( _context : CreationContext ) -> Result < Self > {
33
- Ok ( KickingTeamFilter { } )
44
+ Ok ( KickingTeamFilter {
45
+ time_last_ball_state_became_default : SystemTime :: now ( ) ,
46
+ last_ball_state : Default :: default ( ) ,
47
+ last_non_default_ball_state : Default :: default ( ) ,
48
+ } )
34
49
}
35
50
36
- pub fn cycle ( & mut self , context : CycleContext ) -> Result < MainOutputs > {
51
+ pub fn cycle ( & mut self , mut context : CycleContext ) -> Result < MainOutputs > {
52
+ context
53
+ . additonal_last_ball_state
54
+ . fill_if_subscribed ( || * context. last_ball_state ) ;
55
+
37
56
let game_controller_state = context. game_controller_state ;
38
57
let sub_state = context. game_controller_state . sub_state ;
39
- let last_ball_state = context. last_ball_state ;
58
+
59
+ let duration_since_last_non_default_ball_state =
60
+ SystemTime :: now ( ) . duration_since ( self . time_last_ball_state_became_default ) ?;
61
+
62
+ if * context. last_ball_state == BallState :: default ( )
63
+ && self . last_ball_state != BallState :: default ( )
64
+ {
65
+ self . time_last_ball_state_became_default = SystemTime :: now ( ) ;
66
+ }
67
+ self . last_ball_state = * context. last_ball_state ;
68
+
69
+ if * context. last_ball_state != BallState :: default ( )
70
+ || * context. last_ball_state == BallState :: default ( )
71
+ && duration_since_last_non_default_ball_state
72
+ >= * context. duration_to_keep_non_default_last_ball_state
73
+ {
74
+ self . last_non_default_ball_state = Some ( * context. last_ball_state ) ;
75
+ }
40
76
41
77
let filtered_kicking_team = if game_controller_state. kicking_team . is_some ( ) {
42
78
game_controller_state. kicking_team
43
79
} else if context. detected_free_kick_kicking_team . is_some ( ) {
44
80
context. detected_free_kick_kicking_team . copied ( )
45
- } else {
81
+ } else if let Some ( last_non_default_ball_state ) = self . last_non_default_ball_state {
46
82
match sub_state {
47
83
Some ( SubState :: CornerKick )
48
- if last_ball_state. ball_in_field . x ( ) . is_sign_positive ( ) =>
84
+ if last_non_default_ball_state
85
+ . ball_in_field
86
+ . x ( )
87
+ . is_sign_positive ( ) =>
49
88
{
50
89
Some ( Team :: Hulks )
51
90
}
52
91
Some ( SubState :: CornerKick )
53
- if last_ball_state. ball_in_field . x ( ) . is_sign_negative ( ) =>
92
+ if last_non_default_ball_state
93
+ . ball_in_field
94
+ . x ( )
95
+ . is_sign_negative ( ) =>
54
96
{
55
97
Some ( Team :: Opponent )
56
98
}
57
99
Some ( SubState :: GoalKick )
58
- if last_ball_state. ball_in_field . x ( ) . is_sign_positive ( ) =>
100
+ if last_non_default_ball_state
101
+ . ball_in_field
102
+ . x ( )
103
+ . is_sign_positive ( ) =>
59
104
{
60
105
Some ( Team :: Opponent )
61
106
}
62
107
Some ( SubState :: GoalKick )
63
- if last_ball_state. ball_in_field . x ( ) . is_sign_negative ( ) =>
108
+ if last_non_default_ball_state
109
+ . ball_in_field
110
+ . x ( )
111
+ . is_sign_negative ( ) =>
64
112
{
65
113
Some ( Team :: Hulks )
66
114
}
67
115
None => match (
68
116
context. filtered_whistle . is_detected ,
69
- last_ball_state. ball_in_field . x ( ) . is_sign_positive ( ) ,
117
+ last_non_default_ball_state
118
+ . ball_in_field
119
+ . x ( )
120
+ . is_sign_positive ( ) ,
70
121
) {
71
122
( true , true ) => Some ( Team :: Opponent ) ,
72
123
( true , false ) => Some ( Team :: Hulks ) ,
73
124
_ => None ,
74
125
} ,
75
126
_ => None ,
76
127
}
128
+ } else {
129
+ None
77
130
} ;
78
131
Ok ( MainOutputs {
79
132
filtered_kicking_team : filtered_kicking_team. into ( ) ,
0 commit comments