Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(util): add value change notifiers #5

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/main/java/frc/lib/listeners/BaseChangeNotifier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package frc.lib.listeners;

import static edu.wpi.first.util.ErrorMessages.requireNonNullParam;

import java.util.HashSet;
import java.util.Set;

public abstract class BaseChangeNotifier {
private static Set<BaseChangeNotifier> changeNotifiers;

protected static void registerChangeNotifier(BaseChangeNotifier changeNotifier) {
requireNonNullParam(changeNotifier, "changeNotifier", "registerChangeNotifier");

if (changeNotifiers == null) {
changeNotifiers = new HashSet<>();
}

changeNotifiers.add(changeNotifier);
}

protected static void removeChangeListener(BaseChangeNotifier notifier) {
if (changeNotifiers == null) {
return;
}

changeNotifiers.remove(notifier);
}

public static final void updateAllChangeNotifiers() {
if (changeNotifiers != null) {
changeNotifiers.forEach(x -> x.update());
}
}

protected abstract void updateInternalState();

protected abstract boolean shouldNotify();

protected abstract void notifyConsumers();

private void update() {
updateInternalState();
if (shouldNotify()) {
notifyConsumers();
}
}
}
70 changes: 70 additions & 0 deletions src/main/java/frc/lib/listeners/ChangeNotifier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package frc.lib.listeners;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;

public class ChangeNotifier<T> extends BaseChangeNotifier {
private final Supplier<T> m_supplier;
private final List<Consumer<T>> m_consumers;
private T m_currentValue;
private T m_previousValue;

protected ChangeNotifier(Supplier<T> value) {
m_supplier = value;
m_consumers = new ArrayList<>();

registerChangeNotifier(this);
}

@Override
protected void updateInternalState() {
m_previousValue = m_currentValue;
m_currentValue = m_supplier.get();
}

@Override
protected boolean shouldNotify() {
return m_currentValue != null && !m_currentValue.equals(m_previousValue);
}

@Override
protected void notifyConsumers() {
m_consumers.forEach(x -> x.accept(m_currentValue));
}

public ChangeNotifier<T> addListener(Consumer<T> onUpdated) {
m_consumers.add(onUpdated);
return this;
}

public ChangeNotifier<T> addListener(Runnable onUpdated) {
m_consumers.add(x -> onUpdated.run());
return this;
}

public ChangeNotifier<T> addListenerIf(Consumer<T> onUpdated, boolean condition) {
if (!condition) {
return this;
}

return addListener(onUpdated);
}

public ChangeNotifier<T> listenIf(Consumer<T> onUpdated, Supplier<Boolean> condition) {
return addListenerIf(onUpdated, condition.get());
}

public static <T> ChangeNotifier<T> of(Supplier<T> value) {
return new ChangeNotifier<>(value);
}

public static <T> ChangeNotifier<T> ofLogged(String key, Supplier<T> value) {
return new LoggedChangeNotifier<>(key, value);
}

public T getValue() {
return m_currentValue;
}
}
20 changes: 20 additions & 0 deletions src/main/java/frc/lib/listeners/LoggedChangeNotifier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package frc.lib.listeners;

import java.util.function.Supplier;

import org.littletonrobotics.junction.Logger;

public class LoggedChangeNotifier<T> extends ChangeNotifier<T> {
private final String m_key;

protected LoggedChangeNotifier(String key, Supplier<T> value) {
super(value);
m_key = key;
}

@Override
protected void updateInternalState() {
super.updateInternalState();
Logger.getInstance().recordOutput(this.m_key, this.getValue().toString());
}
}
2 changes: 2 additions & 0 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.CommandScheduler;
import frc.lib.advantagekit.LoggerUtil;
import frc.lib.listeners.BaseChangeNotifier;

/**
* The VM is configured to automatically run this class, and to call the
Expand Down Expand Up @@ -43,6 +44,7 @@ public void robotPeriodic() {
// finished or interrupted commands, and running subsystem periodic() methods.
// This must be called from the robot's periodic block in order for anything in
// the Command-based framework to work.
BaseChangeNotifier.updateAllChangeNotifiers();
CommandScheduler.getInstance().run();
}

Expand Down