001// Copyright (c) Choreo contributors
002
003package choreo.util;
004
005import java.util.ArrayList;
006import java.util.List;
007import java.util.function.Function;
008import org.wpilib.util.Alert;
009import org.wpilib.util.Alert.Level;
010
011/** A utility class for creating alerts under the "Choreo Alerts" group. */
012public class ChoreoAlert {
013  /**
014   * Creates an alert under the "Choreo" group, using the name as the displayed text.
015   *
016   * @param name The name of the alert; this must be unique within the group
017   * @param level The level of alert
018   * @return an Alert published under the "Choreo" group
019   */
020  public static Alert alert(String name, Level level) {
021    return alert(name, name, level);
022  }
023
024  /**
025   * Creates an alert under the "Choreo" group.
026   *
027   * @param name The name of the alert; this must be unique within the group
028   * @param text The text to display when the alert is active
029   * @param level The level of alert
030   * @return an Alert published under the "Choreo" group
031   */
032  public static Alert alert(String name, String text, Level level) {
033    return new Alert(name, text, level);
034  }
035
036  /**
037   * Creates a {@link MultiAlert} under the "Choreo" group, using the text generated from an empty
038   * list of causes as the name.
039   *
040   * @param textGenerator A function that accepts a list of causes and returns an alert message
041   * @param level The level of alert
042   * @return a MultiAlert published under the "Choreo" group
043   */
044  public static MultiAlert multiAlert(Function<List<String>, String> textGenerator, Level level) {
045    return multiAlert(textGenerator.apply(List.of()), textGenerator, level);
046  }
047
048  /**
049   * Creates a {@link MultiAlert} under the "Choreo" group.
050   *
051   * @param name The name of the alert; this must be unique within the group
052   * @param textGenerator A function that accepts a list of causes and returns an alert message
053   * @param level The level of alert
054   * @return a MultiAlert published under the "Choreo" group
055   */
056  public static MultiAlert multiAlert(
057      String name, Function<List<String>, String> textGenerator, Level level) {
058    return new MultiAlert(name, textGenerator, level);
059  }
060
061  /**
062   * An alert that can have multiple causes. Utilizes a function to generate an error message from a
063   * list of causes.
064   */
065  public static class MultiAlert extends Alert {
066    private final Function<List<String>, String> textGenerator;
067    private final List<String> causes = new ArrayList<>();
068
069    MultiAlert(Function<List<String>, String> textGenerator, Level level) {
070      this(textGenerator.apply(List.of()), textGenerator, level);
071    }
072
073    MultiAlert(String name, Function<List<String>, String> textGenerator, Level level) {
074      super(name, textGenerator.apply(List.of()), level);
075      this.textGenerator = textGenerator;
076    }
077
078    /**
079     * Adds an error causer to this alert, and pushes the alert to NetworkTables if it is not
080     * already present.
081     *
082     * @param name The name of the error causer
083     */
084    public void addCause(String name) {
085      causes.add(name);
086      setText(textGenerator.apply(causes));
087      set(true);
088    }
089  }
090
091  /** Factory class. */
092  private ChoreoAlert() {}
093
094  /**
095   * An alert to be used when alliance-dependent logic is called before an alliance has been
096   * determined.
097   */
098  public static final Alert allianceNotReady =
099      ChoreoAlert.alert("Alliance used but not ready", Level.HIGH);
100}