trigger_change_ui.cpp
Go to the documentation of this file.
1 //
2 // Created by llljjjqqq on 22-11-4.
3 //
4 
6 
7 namespace rm_referee
8 {
10 {
13 }
14 
15 void TriggerChangeUi::updateForQueue(bool check_repeat)
16 {
17  if (check_repeat)
18  if (graph_->isRepeated())
19  return;
21 }
22 
23 void TriggerChangeUi::updateTwiceForQueue(bool check_repeat)
24 {
25  if (check_repeat)
26  if (graph_->isRepeated())
27  return;
29  for (int i = 0; i < 2; i++)
31 }
32 
34 {
35  for (auto it : graph_vector_)
36  it.second->updateLastConfig();
37  for (auto it : character_vector_)
38  it.second->updateLastConfig();
39 
41 }
42 
43 void TriggerChangeGroupUi::updateForQueue(bool check_repeat)
44 {
45  if (check_repeat)
46  {
47  bool is_repeat = true;
48  for (auto it : graph_vector_)
49  if (!it.second->isRepeated())
50  is_repeat = false;
51  for (auto it : character_vector_)
52  if (!it.second->isRepeated())
53  is_repeat = false;
54  if (is_repeat)
55  return;
56  }
58 }
59 
61 {
62  if (check_repeat)
63  {
64  bool is_repeat = true;
65  for (auto it : graph_vector_)
66  if (!it.second->isRepeated())
67  is_repeat = false;
68  for (auto it : character_vector_)
69  if (!it.second->isRepeated())
70  is_repeat = false;
71  if (is_repeat)
72  return;
73  }
74 
75  for (auto it : graph_vector_)
76  it.second->updateLastConfig();
77  for (auto it : character_vector_)
78  it.second->updateLastConfig();
79 
80  for (int i = 0; i < 2; i++)
82 }
83 
85 {
86  if (s_l_ == rm_msgs::DbusData::MID && s_r_ == rm_msgs::DbusData::UP)
87  updateConfig(chassis_mode_, false, 1, false);
88  else
94  updateTwiceForQueue(true);
95 }
96 
98 {
101  updateConfig(254, 0);
103 
104  updateTwiceForQueue(true);
105 }
106 
108 {
109  static ros::Time trigger_time;
110  static bool is_different = false;
111 
112  if (base_.capacity_recent_mode_ != power_limit_state_ && !is_different)
113  {
114  is_different = true;
115  trigger_time = ros::Time::now();
116  }
117  else if (is_different)
118  {
120  {
121  is_different = false;
122  return;
123  }
124  else if ((ros::Time::now() - trigger_time).toSec() > mode_change_threshold_)
125  {
126  is_different = false;
127  updateForQueue(false);
128  }
129  }
130 }
131 
132 void ChassisTriggerChangeUi::updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode, bool sub_flag,
133  bool extra_flag)
134 {
135  static ros::Time trigger_time;
136  static int expect;
137  static bool delay = false;
138  if (main_mode == 254)
139  {
140  graph_->setContent("Cap reset");
142  return;
143  }
144  graph_->setContent(getChassisState(main_mode));
145  if (sub_mode == 1)
147  else
148  {
150  {
151  trigger_time = ros::Time::now();
152  expect = power_limit_state_;
153  delay = true;
154  }
155  else if (delay)
156  {
157  if (expect != power_limit_state_)
158  {
159  trigger_time = ros::Time::now();
160  expect = power_limit_state_;
161  }
162  else if ((ros::Time::now() - trigger_time).toSec() > 0.2)
163  {
164  if (main_flag)
166  else if (sub_flag)
168  else if (extra_flag)
170  else
172  delay = false;
173  }
174  }
175  else
176  {
177  if (main_flag)
179  else if (sub_flag)
181  else if (extra_flag)
183  else
185  }
186  }
187 }
188 
190 {
191  if (mode == rm_msgs::ChassisCmd::RAW)
192  return "raw";
193  else if (mode == rm_msgs::ChassisCmd::FOLLOW)
194  return "follow";
195  else if (mode == rm_msgs::ChassisCmd::TWIST)
196  return "twist";
197  else if (mode == rm_msgs::ChassisCmd::UP_SLOPE)
198  return "up_slope";
199  else if (mode == rm_msgs::ChassisCmd::FALLEN)
200  return "fallen";
201  else
202  return "error";
203 }
204 
205 void ChassisTriggerChangeUi::updateChassisCmdData(const rm_msgs::ChassisCmd::ConstPtr& data)
206 {
207  chassis_mode_ = data->mode;
208  update();
209 }
210 
211 void ChassisTriggerChangeUi::updateManualCmdData(const rm_msgs::ManualToReferee::ConstPtr data)
212 {
213  power_limit_state_ = data->power_limit_state;
214 }
215 
216 void ChassisTriggerChangeUi::updateDbusData(const rm_msgs::DbusData::ConstPtr& data)
217 {
218  s_l_ = data->s_l;
219  s_r_ = data->s_r;
220  key_ctrl_ = data->key_ctrl;
221  key_shift_ = data->key_shift;
222  key_b_ = data->key_b;
223 }
224 
226 {
228 }
229 
231 {
234  updateForQueue(true);
235 }
236 
237 void ShooterTriggerChangeUi::updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode, bool sub_flag)
238 {
239  graph_->setContent(getShooterState(main_mode));
240  if (sub_mode == rm_common::HeatLimit::LOW)
242  else if (sub_mode == rm_common::HeatLimit::HIGH)
244  else if (sub_mode == rm_common::HeatLimit::BURST)
246 }
247 
248 std::string ShooterTriggerChangeUi::getShooterState(uint8_t state)
249 {
250  if (state == rm_msgs::ShootState::STOP)
251  return "stop";
252  else if (state == rm_msgs::ShootState::READY)
253  return "ready";
254  else if (state == rm_msgs::ShootState::PUSH)
255  return "push";
256  else if (state == rm_msgs::ShootState::BLOCK)
257  return "block";
258  else
259  return "error";
260 }
261 
262 void ShooterTriggerChangeUi::updateShootStateData(const rm_msgs::ShootState::ConstPtr& data)
263 {
264  shooter_mode_ = data->state;
265  update();
266 }
267 
268 void ShooterTriggerChangeUi::updateManualCmdData(rm_msgs::ManualToReferee::ConstPtr data)
269 {
270  shoot_frequency_ = data->shoot_frequency;
271 }
272 
274 {
277 
278  updateTwiceForQueue(true);
279 }
280 
281 void GimbalTriggerChangeUi::updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode, bool sub_flag)
282 {
283  graph_->setContent(getGimbalState(main_mode));
284  if (main_flag)
286  else
288 }
289 
290 std::string GimbalTriggerChangeUi::getGimbalState(uint8_t mode)
291 {
292  if (mode == rm_msgs::GimbalCmd::DIRECT)
293  return "direct";
294  else if (mode == rm_msgs::GimbalCmd::RATE)
295  return "rate";
296  else if (mode == rm_msgs::GimbalCmd::TRACK)
297  return "track";
298  else
299  return "error";
300 }
301 
302 void GimbalTriggerChangeUi::updateGimbalCmdData(const rm_msgs::GimbalCmd::ConstPtr& data)
303 {
304  gimbal_mode_ = data->mode;
305  update();
306 }
307 
308 void GimbalTriggerChangeUi::updateManualCmdData(const rm_msgs::ManualToReferee::ConstPtr data)
309 {
310  gimbal_eject_ = data->gimbal_eject;
311 }
312 
314 {
317  det_color_ == rm_msgs::StatusChangeRequest::RED);
318  else
319  updateConfig(gimbal_eject_, shoot_frequency_, det_armor_target_, det_color_ == rm_msgs::StatusChangeRequest::RED);
321  updateForQueue(true);
322 }
323 
324 void TargetTriggerChangeUi::updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode, bool sub_flag)
325 {
326  graph_->setContent(getTargetState(main_mode, sub_mode));
327  if (main_flag)
329  else if (sub_flag)
331  else
333 }
334 
335 std::string TargetTriggerChangeUi::getTargetState(uint8_t target, uint8_t armor_target)
336 {
338  {
339  if (target == rm_msgs::StatusChangeRequest::SMALL_BUFF)
340  return "small_buff";
341  else if (target == rm_msgs::StatusChangeRequest::BIG_BUFF)
342  return "big_buff";
343  else if (target == rm_msgs::StatusChangeRequest::ARMOR && armor_target == rm_msgs::StatusChangeRequest::ARMOR_ALL)
344  return "armor_all";
345  else if (target == rm_msgs::StatusChangeRequest::ARMOR &&
346  armor_target == rm_msgs::StatusChangeRequest::ARMOR_OUTPOST_BASE)
347  return "armor_base";
348  else
349  return "error";
350  }
351  else
352  {
353  if (target == 1)
354  return "eject";
355  else if (armor_target == rm_msgs::StatusChangeRequest::ARMOR_ALL)
356  return "all";
357  else if (armor_target == rm_msgs::StatusChangeRequest::ARMOR_OUTPOST_BASE)
358  return "base";
359  else
360  return "error";
361  }
362 }
363 
364 void TargetTriggerChangeUi::updateManualCmdData(const rm_msgs::ManualToReferee::ConstPtr data)
365 {
366  det_target_ = data->det_target;
367  shoot_frequency_ = data->shoot_frequency;
368  det_armor_target_ = data->det_armor_target;
369  det_color_ = data->det_color;
370  gimbal_eject_ = data->gimbal_eject;
371 }
372 
373 void TargetTriggerChangeUi::updateShootStateData(const rm_msgs::ShootState::ConstPtr& data)
374 {
375  update();
376 }
377 
379 {
380  updateConfig(track_id_ == 0, false);
382  updateTwiceForQueue(true);
383 }
384 
385 void TargetViewAngleTriggerChangeUi::updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode, bool sub_flag)
386 {
387  if (main_mode)
389  else
391 }
392 
394 {
395  track_id_ = id;
396  update();
397 }
398 
400 {
401  for (auto graph : graph_vector_)
402  graph.second->setOperation(rm_referee::GraphOperation::UPDATE);
403  updateForQueue(true);
404 }
405 
406 void CameraTriggerChangeUi::updateCameraName(const std_msgs::StringConstPtr& data)
407 {
408  current_camera_ = data->data;
409  update();
410 }
411 
412 void CameraTriggerChangeUi::updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode, bool sub_flag)
413 {
417  else if (current_camera_ == camera2_name_)
419  else
421 }
422 
424 {
425  updateConfig();
427  updateForQueue(true);
428 }
429 
430 void StringTriggerChangeUi::updateStringUiData(const std::string& data)
431 {
432  data_ = data;
433  update();
434 }
435 
437 {
441  updateForQueue(true);
442 }
443 
444 void FrictionSpeedTriggerChangeUi::updateFrictionSpeedUiData(const rm_msgs::ShootCmdConstPtr& data)
445 {
446  wheel_speed_ = data->wheel_speed;
447  update();
448 }
449 
451 {
452  graph_->setIntNum(std::floor(wheel_speed_));
454  updateForQueue(true);
455 }
456 
457 void VisualizeStateTriggerChangeUi::updateUiColor(const std::vector<bool>& data)
458 {
459  for (int i = 0; i < static_cast<int>(data.size()); i++)
460  {
461  graph_vector_.find(std::to_string(i))
462  ->second->setColor(data[i] ? rm_referee::GraphColor::GREEN : rm_referee::GraphColor::PINK);
463  }
464  update();
465 }
466 
468 {
469  for (auto graph : graph_vector_)
470  graph.second->setOperation(rm_referee::GraphOperation::UPDATE);
471  updateForQueue(true);
472 }
473 
474 } // namespace rm_referee
rm_referee::WHITE
@ WHITE
Definition: protocol.h:161
rm_referee::ChassisTriggerChangeUi::power_limit_state_
uint8_t power_limit_state_
Definition: trigger_change_ui.h:77
rm_referee::GimbalTriggerChangeUi::gimbal_mode_
uint8_t gimbal_mode_
Definition: trigger_change_ui.h:116
rm_referee::GroupUiBase::graph_vector_
std::map< std::string, Graph * > graph_vector_
Definition: ui_base.h:93
rm_referee::Base::robot_id_
int robot_id_
Definition: data.h:148
rm_referee::FrictionSpeedTriggerChangeUi::wheel_speed_
double wheel_speed_
Definition: trigger_change_ui.h:253
rm_referee::GimbalTriggerChangeUi::updateManualCmdData
void updateManualCmdData(const rm_msgs::ManualToReferee::ConstPtr data) override
Definition: trigger_change_ui.cpp:308
rm_referee::CameraTriggerChangeUi::updateCameraName
void updateCameraName(const std_msgs::StringConstPtr &data)
Definition: trigger_change_ui.cpp:406
rm_referee::BLUE_ENGINEER
@ BLUE_ENGINEER
Definition: protocol.h:116
rm_referee::StringTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:436
rm_referee::ShooterTriggerChangeUi::shooter_mode_
uint8_t shooter_mode_
Definition: trigger_change_ui.h:97
rm_referee::ShooterTriggerChangeUi::updateConfig
void updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode=0, bool sub_flag=false) override
Definition: trigger_change_ui.cpp:237
rm_referee
Definition: data.h:100
rm_referee::FrictionSpeedTriggerChangeUi::updateFrictionSpeedUiData
void updateFrictionSpeedUiData(const rm_msgs::ShootCmdConstPtr &data)
Definition: trigger_change_ui.cpp:444
rm_referee::TargetViewAngleTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:378
rm_referee::ChassisTriggerChangeUi::updateDbusData
void updateDbusData(const rm_msgs::DbusData::ConstPtr &data)
Definition: trigger_change_ui.cpp:216
rm_referee::CameraTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:423
rm_referee::FrictionSpeedTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:450
rm_referee::TriggerChangeGroupUi::updateForQueue
void updateForQueue() override
Definition: trigger_change_ui.cpp:33
rm_referee::TargetTriggerChangeUi::getTargetState
std::string getTargetState(uint8_t target, uint8_t armor_target)
Definition: trigger_change_ui.cpp:335
rm_referee::TargetTriggerChangeUi::updateManualCmdData
void updateManualCmdData(const rm_msgs::ManualToReferee::ConstPtr data) override
Definition: trigger_change_ui.cpp:364
rm_referee::Graph::setIntNum
void setIntNum(int num)
Definition: graph.h:56
rm_referee::StringTriggerChangeUi::data_
std::string data_
Definition: trigger_change_ui.h:240
rm_referee::ChassisTriggerChangeUi::displayInCapacity
void displayInCapacity()
Definition: trigger_change_ui.cpp:97
rm_referee::CameraTriggerChangeUi::current_camera_
std::string current_camera_
Definition: trigger_change_ui.h:227
rm_referee::ChassisTriggerChangeUi::key_b_
uint8_t key_b_
Definition: trigger_change_ui.h:77
rm_referee::ChassisTriggerChangeUi::s_l_
uint8_t s_l_
Definition: trigger_change_ui.h:77
rm_referee::Base::capacity_recent_mode_
int capacity_recent_mode_
Definition: data.h:149
rm_referee::CYAN
@ CYAN
Definition: protocol.h:159
rm_referee::StringTriggerChangeUi::updateStringUiData
void updateStringUiData(const std::string &data)
Definition: trigger_change_ui.cpp:430
rm_referee::CameraTriggerChangeUi::camera2_name_
std::string camera2_name_
Definition: trigger_change_ui.h:227
rm_referee::PolygonTriggerChangeGroupUi::update
void update() override
Definition: trigger_change_ui.cpp:399
rm_referee::Graph::setContent
void setContent(const std::string &content)
Definition: graph.h:38
rm_referee::ShooterTriggerChangeUi::shoot_frequency_
uint8_t shoot_frequency_
Definition: trigger_change_ui.h:97
rm_referee::ORANGE
@ ORANGE
Definition: protocol.h:156
rm_referee::ChassisTriggerChangeUi::key_ctrl_
uint8_t key_ctrl_
Definition: trigger_change_ui.h:77
rm_referee::ChassisTriggerChangeUi::chassis_mode_
uint8_t chassis_mode_
Definition: trigger_change_ui.h:77
rm_referee::BLUE_HERO
@ BLUE_HERO
Definition: protocol.h:115
rm_referee::RED_ENGINEER
@ RED_ENGINEER
Definition: protocol.h:106
rm_referee::TargetTriggerChangeUi::updateShootStateData
void updateShootStateData(const rm_msgs::ShootState::ConstPtr &data)
Definition: trigger_change_ui.cpp:373
rm_referee::ChassisTriggerChangeUi::key_shift_
uint8_t key_shift_
Definition: trigger_change_ui.h:77
rm_referee::ChassisTriggerChangeUi::updateChassisCmdData
void updateChassisCmdData(const rm_msgs::ChassisCmd::ConstPtr &data)
Definition: trigger_change_ui.cpp:205
rm_referee::ChassisTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:84
rm_common::PowerLimit::CHARGE
CHARGE
rm_referee::ChassisTriggerChangeUi::updateCapacityResetStatus
void updateCapacityResetStatus()
Definition: trigger_change_ui.cpp:225
rm_referee::ShooterTriggerChangeUi::getShooterState
std::string getShooterState(uint8_t mode)
Definition: trigger_change_ui.cpp:248
rm_referee::ChassisTriggerChangeUi::checkModeChange
void checkModeChange()
Definition: trigger_change_ui.cpp:107
rm_referee::ChassisTriggerChangeUi::s_r_
uint8_t s_r_
Definition: trigger_change_ui.h:77
rm_referee::TargetTriggerChangeUi::det_color_
uint8_t det_color_
Definition: trigger_change_ui.h:139
rm_referee::TargetTriggerChangeUi::gimbal_eject_
uint8_t gimbal_eject_
Definition: trigger_change_ui.h:139
rm_referee::ShooterTriggerChangeUi::updateShootStateData
void updateShootStateData(const rm_msgs::ShootState::ConstPtr &data)
Definition: trigger_change_ui.cpp:262
rm_referee::GroupUiBase::character_vector_
std::map< std::string, Graph * > character_vector_
Definition: ui_base.h:94
rm_referee::Graph::isRepeated
bool isRepeated()
Definition: graph.h:93
rm_referee::RED_HERO
@ RED_HERO
Definition: protocol.h:105
rm_referee::UiBase::updateForQueue
virtual void updateForQueue()
Definition: ui_base.cpp:38
rm_referee::ShooterTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:230
rm_referee::TargetTriggerChangeUi::det_armor_target_
uint8_t det_armor_target_
Definition: trigger_change_ui.h:139
rm_referee::TargetViewAngleTriggerChangeUi::updateConfig
void updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode=0, bool sub_flag=false) override
Definition: trigger_change_ui.cpp:385
rm_referee::TargetTriggerChangeUi::updateConfig
void updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode=0, bool sub_flag=false) override
Definition: trigger_change_ui.cpp:324
rm_referee::TargetViewAngleTriggerChangeUi::track_id_
int track_id_
Definition: trigger_change_ui.h:155
rm_referee::Graph::setColor
void setColor(const rm_referee::GraphColor &color)
Definition: graph.h:34
rm_referee::UiBase::base_
Base & base_
Definition: ui_base.h:58
rm_referee::TriggerChangeUi::updateTwiceForQueue
void updateTwiceForQueue(bool check_repeat=true)
Definition: trigger_change_ui.cpp:23
rm_referee::GimbalTriggerChangeUi::gimbal_eject_
uint8_t gimbal_eject_
Definition: trigger_change_ui.h:116
rm_referee::PINK
@ PINK
Definition: protocol.h:158
rm_referee::GREEN
@ GREEN
Definition: protocol.h:155
rm_referee::ShooterTriggerChangeUi::updateManualCmdData
void updateManualCmdData(const rm_msgs::ManualToReferee::ConstPtr data) override
Definition: trigger_change_ui.cpp:268
rm_referee::TargetViewAngleTriggerChangeUi::updateTrackID
void updateTrackID(int id)
Definition: trigger_change_ui.cpp:393
rm_referee::GimbalTriggerChangeUi::updateConfig
void updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode=0, bool sub_flag=false) override
Definition: trigger_change_ui.cpp:281
rm_referee::Graph::setOperation
void setOperation(const rm_referee::GraphOperation &operation)
Definition: graph.h:17
rm_referee::GimbalTriggerChangeUi::updateGimbalCmdData
void updateGimbalCmdData(const rm_msgs::GimbalCmd ::ConstPtr &data)
Definition: trigger_change_ui.cpp:302
rm_referee::TargetTriggerChangeUi::shoot_frequency_
uint8_t shoot_frequency_
Definition: trigger_change_ui.h:139
rm_referee::GimbalTriggerChangeUi::getGimbalState
std::string getGimbalState(uint8_t mode)
Definition: trigger_change_ui.cpp:290
rm_referee::Graph::updateLastConfig
void updateLastConfig()
Definition: graph.h:101
rm_referee::ChassisTriggerChangeUi::updateManualCmdData
void updateManualCmdData(const rm_msgs::ManualToReferee::ConstPtr data) override
Definition: trigger_change_ui.cpp:211
rm_referee::CameraTriggerChangeUi::camera1_name_
std::string camera1_name_
Definition: trigger_change_ui.h:227
rm_common::HeatLimit::LOW
LOW
rm_referee::TriggerChangeGroupUi::updateTwiceForQueue
void updateTwiceForQueue(bool check_repeat=true)
Definition: trigger_change_ui.cpp:60
rm_referee::CameraTriggerChangeUi::updateConfig
void updateConfig(uint8_t main_mode=0, bool main_flag=false, uint8_t sub_mode=0, bool sub_flag=false) override
Definition: trigger_change_ui.cpp:412
rm_referee::TargetTriggerChangeUi::det_target_
uint8_t det_target_
Definition: trigger_change_ui.h:139
rm_referee::GroupUiBase::updateForQueue
void updateForQueue() override
Definition: ui_base.cpp:91
rm_referee::ChassisTriggerChangeUi::updateConfig
void updateConfig(uint8_t main_mode, bool main_flag, uint8_t sub_mode=0, bool sub_flag=false, bool extra_flag=false)
Definition: trigger_change_ui.cpp:132
ros::Time
rm_referee::BLACK
@ BLACK
Definition: protocol.h:160
rm_referee::TriggerChangeUi::updateForQueue
void updateForQueue() override
Definition: trigger_change_ui.cpp:9
trigger_change_ui.h
rm_common::PowerLimit::NORMAL
NORMAL
rm_referee::ChassisTriggerChangeUi::getChassisState
std::string getChassisState(uint8_t mode)
Definition: trigger_change_ui.cpp:189
rm_referee::VisualizeStateTriggerChangeUi::updateUiColor
void updateUiColor(const std::vector< bool > &data)
Definition: trigger_change_ui.cpp:457
rm_common::PowerLimit::BURST
BURST
rm_common::HeatLimit::HIGH
HIGH
rm_common::HeatLimit::BURST
BURST
rm_referee::UPDATE
@ UPDATE
Definition: protocol.h:147
rm_referee::VisualizeStateTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:467
rm_referee::UiBase::graph_
Graph * graph_
Definition: ui_base.h:59
rm_common::PowerLimit::ALLOFF
ALLOFF
rm_referee::YELLOW
@ YELLOW
Definition: protocol.h:154
rm_referee::TargetTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:313
ros::Time::now
static Time now()
rm_referee::GimbalTriggerChangeUi::update
void update() override
Definition: trigger_change_ui.cpp:273
rm_referee::ChassisTriggerChangeUi::mode_change_threshold_
double mode_change_threshold_
Definition: trigger_change_ui.h:78


rm_referee
Author(s): Qiayuan Liao
autogenerated on Tue May 6 2025 02:23:49