2024-08-23 10:05:53 -04:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
|
|
2025-11-07 19:55:43 -05:00
|
|
|
package org.wpilib.util;
|
2024-08-23 10:05:53 -04:00
|
|
|
|
2025-11-07 19:56:29 -05:00
|
|
|
import org.wpilib.system.RobotController;
|
2025-11-07 19:55:43 -05:00
|
|
|
import org.wpilib.util.sendable.Sendable;
|
|
|
|
|
import org.wpilib.util.sendable.SendableBuilder;
|
|
|
|
|
import org.wpilib.smartdashboard.SmartDashboard;
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
import java.util.Comparator;
|
2025-08-08 23:04:02 -07:00
|
|
|
import java.util.EnumMap;
|
2024-08-23 10:05:53 -04:00
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
import java.util.Set;
|
|
|
|
|
import java.util.TreeSet;
|
2024-08-23 10:05:53 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Persistent alert to be sent via NetworkTables. Alerts are tagged with a type of {@code kError},
|
|
|
|
|
* {@code kWarning}, or {@code kInfo} to denote urgency. See {@link
|
2025-11-07 19:55:43 -05:00
|
|
|
* org.wpilib.util.Alert.AlertType AlertType} for suggested usage of each type. Alerts can be
|
2024-08-23 10:05:53 -04:00
|
|
|
* displayed on supported dashboards, and are shown in a priority order based on type and recency of
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
* activation, with newly activated alerts first.
|
2024-08-23 10:05:53 -04:00
|
|
|
*
|
|
|
|
|
* <p>Alerts should be created once and stored persistently, then updated to "active" or "inactive"
|
|
|
|
|
* as necessary. {@link #set(boolean)} can be safely called periodically.
|
|
|
|
|
*
|
|
|
|
|
* <p><b>This API is new for 2025, but is likely to change in future seasons to facilitate deeper
|
|
|
|
|
* integration with the robot control system.</b>
|
|
|
|
|
*
|
|
|
|
|
* <pre>
|
|
|
|
|
* class Robot {
|
|
|
|
|
* Alert alert = new Alert("Something went wrong", AlertType.kWarning);
|
|
|
|
|
*
|
|
|
|
|
* periodic() {
|
|
|
|
|
* alert.set(...);
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* </pre>
|
|
|
|
|
*
|
|
|
|
|
* <p>Alternatively, alerts which are only used once at startup can be created and activated inline.
|
|
|
|
|
*
|
|
|
|
|
* <pre>
|
|
|
|
|
* public Robot() {
|
|
|
|
|
* new Alert("Failed to load auto paths", AlertType.kError).set(true);
|
|
|
|
|
* }
|
|
|
|
|
* </pre>
|
|
|
|
|
*/
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
public class Alert implements AutoCloseable {
|
|
|
|
|
/** Represents an alert's level of urgency. */
|
|
|
|
|
public enum AlertType {
|
|
|
|
|
/**
|
|
|
|
|
* High priority alert - displayed first on the dashboard with a red "X" symbol. Use this type
|
|
|
|
|
* for problems which will seriously affect the robot's functionality and thus require immediate
|
|
|
|
|
* attention.
|
|
|
|
|
*/
|
|
|
|
|
kError,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Medium priority alert - displayed second on the dashboard with a yellow "!" symbol. Use this
|
|
|
|
|
* type for problems which could affect the robot's functionality but do not necessarily require
|
|
|
|
|
* immediate attention.
|
|
|
|
|
*/
|
|
|
|
|
kWarning,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Low priority alert - displayed last on the dashboard with a green "i" symbol. Use this type
|
|
|
|
|
* for problems which are unlikely to affect the robot's functionality, or any other alerts
|
|
|
|
|
* which do not fall under the other categories.
|
|
|
|
|
*/
|
|
|
|
|
kInfo
|
|
|
|
|
}
|
2024-08-23 10:05:53 -04:00
|
|
|
|
|
|
|
|
private final AlertType m_type;
|
|
|
|
|
private boolean m_active;
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
private long m_activeStartTime;
|
2024-08-23 10:05:53 -04:00
|
|
|
private String m_text;
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
private Set<PublishedAlert> m_activeAlerts;
|
2024-08-23 10:05:53 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new alert in the default group - "Alerts". If this is the first to be instantiated,
|
|
|
|
|
* the appropriate entries will be added to NetworkTables.
|
|
|
|
|
*
|
|
|
|
|
* @param text Text to be displayed when the alert is active.
|
|
|
|
|
* @param type Alert urgency level.
|
|
|
|
|
*/
|
|
|
|
|
public Alert(String text, AlertType type) {
|
|
|
|
|
this("Alerts", text, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new alert. If this is the first to be instantiated in its group, the appropriate
|
|
|
|
|
* entries will be added to NetworkTables.
|
|
|
|
|
*
|
|
|
|
|
* @param group Group identifier, used as the entry name in NetworkTables.
|
|
|
|
|
* @param text Text to be displayed when the alert is active.
|
|
|
|
|
* @param type Alert urgency level.
|
|
|
|
|
*/
|
2024-08-24 06:52:04 -07:00
|
|
|
@SuppressWarnings("this-escape")
|
2024-08-23 10:05:53 -04:00
|
|
|
public Alert(String group, String text, AlertType type) {
|
|
|
|
|
m_type = type;
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
m_text = text;
|
|
|
|
|
m_activeAlerts = SendableAlerts.forGroup(group).getActiveAlertsStorage(type);
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2024-10-04 01:20:53 -04:00
|
|
|
* Sets whether the alert should currently be displayed. This method can be safely called
|
|
|
|
|
* periodically.
|
2024-08-23 10:05:53 -04:00
|
|
|
*
|
|
|
|
|
* @param active Whether to display the alert.
|
|
|
|
|
*/
|
|
|
|
|
public void set(boolean active) {
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
if (active == m_active) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (active) {
|
2024-11-16 10:43:38 -05:00
|
|
|
m_activeStartTime = RobotController.getTime();
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
m_activeAlerts.add(new PublishedAlert(m_activeStartTime, m_text));
|
|
|
|
|
} else {
|
|
|
|
|
m_activeAlerts.remove(new PublishedAlert(m_activeStartTime, m_text));
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
m_active = active;
|
|
|
|
|
}
|
|
|
|
|
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
/**
|
|
|
|
|
* Gets whether the alert is active.
|
|
|
|
|
*
|
|
|
|
|
* @return whether the alert is active.
|
|
|
|
|
*/
|
|
|
|
|
public boolean get() {
|
|
|
|
|
return m_active;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 10:05:53 -04:00
|
|
|
/**
|
|
|
|
|
* Updates current alert text. Use this method to dynamically change the displayed alert, such as
|
|
|
|
|
* including more details about the detected problem.
|
|
|
|
|
*
|
|
|
|
|
* @param text Text to be displayed when the alert is active.
|
|
|
|
|
*/
|
|
|
|
|
public void setText(String text) {
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
if (text.equals(m_text)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var oldText = m_text;
|
2024-08-23 10:05:53 -04:00
|
|
|
m_text = text;
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
if (m_active) {
|
|
|
|
|
m_activeAlerts.remove(new PublishedAlert(m_activeStartTime, oldText));
|
|
|
|
|
m_activeAlerts.add(new PublishedAlert(m_activeStartTime, m_text));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the current alert text.
|
|
|
|
|
*
|
|
|
|
|
* @return the current text.
|
|
|
|
|
*/
|
|
|
|
|
public String getText() {
|
|
|
|
|
return m_text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the type of this alert.
|
|
|
|
|
*
|
|
|
|
|
* @return the type
|
|
|
|
|
*/
|
|
|
|
|
public AlertType getType() {
|
|
|
|
|
return m_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void close() {
|
|
|
|
|
set(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private record PublishedAlert(long timestamp, String text) implements Comparable<PublishedAlert> {
|
|
|
|
|
private static final Comparator<PublishedAlert> comparator =
|
|
|
|
|
Comparator.comparingLong((PublishedAlert alert) -> alert.timestamp())
|
|
|
|
|
.reversed()
|
|
|
|
|
.thenComparing(Comparator.comparing((PublishedAlert alert) -> alert.text()));
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int compareTo(PublishedAlert o) {
|
|
|
|
|
return comparator.compare(this, o);
|
|
|
|
|
}
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final class SendableAlerts implements Sendable {
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
private static final Map<String, SendableAlerts> groups = new HashMap<String, SendableAlerts>();
|
|
|
|
|
|
2025-08-08 23:04:02 -07:00
|
|
|
private final EnumMap<AlertType, Set<PublishedAlert>> m_alerts = new EnumMap<>(AlertType.class);
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a reference to the set of active alerts for the given type.
|
|
|
|
|
*
|
|
|
|
|
* @param type the type
|
|
|
|
|
* @return reference to the set of active alerts for the type
|
|
|
|
|
*/
|
|
|
|
|
public Set<PublishedAlert> getActiveAlertsStorage(AlertType type) {
|
|
|
|
|
return m_alerts.computeIfAbsent(type, _type -> new TreeSet<>());
|
|
|
|
|
}
|
2024-08-23 10:05:53 -04:00
|
|
|
|
|
|
|
|
private String[] getStrings(AlertType type) {
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
return getActiveAlertsStorage(type).stream().map(a -> a.text()).toArray(String[]::new);
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void initSendable(SendableBuilder builder) {
|
|
|
|
|
builder.setSmartDashboardType("Alerts");
|
|
|
|
|
builder.addStringArrayProperty("errors", () -> getStrings(AlertType.kError), null);
|
|
|
|
|
builder.addStringArrayProperty("warnings", () -> getStrings(AlertType.kWarning), null);
|
|
|
|
|
builder.addStringArrayProperty("infos", () -> getStrings(AlertType.kInfo), null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
* Returns the SendableAlerts for a given group, initializing and publishing if it does not
|
|
|
|
|
* already exist.
|
|
|
|
|
*
|
|
|
|
|
* @param group the group name
|
|
|
|
|
* @return the SendableAlerts for the group
|
2024-08-23 10:05:53 -04:00
|
|
|
*/
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
private static SendableAlerts forGroup(String group) {
|
|
|
|
|
return groups.computeIfAbsent(
|
|
|
|
|
group,
|
|
|
|
|
_group -> {
|
|
|
|
|
var sendable = new SendableAlerts();
|
|
|
|
|
SmartDashboard.putData(_group, sendable);
|
|
|
|
|
return sendable;
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
}
|