Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Groostav/95cca95fd6f719664eadc1558d65f1c2 to your computer and use it in GitHub Desktop.
Save Groostav/95cca95fd6f719664eadc1558d65f1c2 to your computer and use it in GitHub Desktop.
Ancient java code
package com.empowerops.visualizer;
import com.empowerops.common.*;
import com.empowerops.common.eventbus.EventBus;
import com.empowerops.common.ui.FXController;
import com.empowerops.common.ui.FXMLLoader;
import com.empowerops.dal.OptimizationMetadata;
import com.empowerops.dal.OptimizationModel;
import com.empowerops.jargon.OptimizerService;
import com.empowerops.jargon.events.NewExpensivePointFoundEvent;
import com.empowerops.jargon.events.SimulationFinishedEvent;
import com.empowerops.jargon.events.SimulationStartedEvent;
import com.empowerops.jargon.events.UserSelectedPreviousRunForDisplayEvent;
import com.empowerops.jargon.model.*;
import com.empowerops.linqalike.Factories;
import com.empowerops.linqalike.LinqingMap;
import com.empowerops.linqalike.Queryable;
import com.empowerops.linqalike.QueryableMap;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import javafx.fxml.FXML;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javax.annotation.Nullable;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.empowerops.common.BootstrappingUtilities.getEnvInt;
import static com.empowerops.visualizer.OptimizationResultLineItem.*;
/**
* Created by Josh on 1/7/2015.
*/
public class RuntimeStatisticsController implements FXController, VisualizationController {
private static final Logger log = Logger.getLogger(RuntimeStatisticsController.class.getCanonicalName());
private final EventBus eventBus;
private final ModelUpdaterService updaterService;
private final LinqingMap<OptimizationResultLineItem, ResultItemController> itemControllerByType = new LinqingMap<>();
private final DecimalFormat exponentFormatter = new DecimalFormat("0.000E0#");
private final DecimalFormat simpleFormatter = new DecimalFormat("0.000");
private OptimizationStopWatch stopwatch;
@FXML VBox elements;
@FXML ScrollPane view;
private @UpdateServiced OptimizationMat matrix;
private @UpdateServiced GraphModel graphModel;
public interface Factory {
RuntimeStatisticsController create(OptimizationMat optimizationMat, @Nullable OptimizationMetadata metadata);
}
@Inject
public RuntimeStatisticsController(EventBus eventBus,
FXMLLoader loader,
ResultItemController.Factory factory,
ModelUpdaterService updaterService,
GraphModel graphModel,
OptimizationStopWatch.Factory optimizationProgressFactory,
@Assisted OptimizationMat optimizationMat,
@Assisted @Nullable OptimizationMetadata metadata
) {
this.eventBus = eventBus;
this.updaterService = updaterService;
this.matrix = optimizationMat;
this.graphModel = graphModel;
for (OptimizationResultLineItem type : OptimizationResultLineItem.values()) {
ResultItemController controller = factory.create(type);
itemControllerByType.put(type, controller);
}
stopwatch = optimizationProgressFactory.create(itemControllerByType, graphModel.ofType(ProxyNode.class), metadata);
updaterService.registerForModelPush(this);
eventBus.register(this);
loader.load(this);
}
@Override
public void initialize() {
elements.getChildren().clear();
initializeViewByControllers();
setDisplayingValue();
// because this constructor is called in response to an optimization started,
// we're simply going to start the task from here.
stopwatch.start();
}
private void initializeViewByControllers() {
Queryable<OptimizationResultLineItem> itemsToDisplay = Factories.from(OptimizationResultLineItem.values());
if (! matrix.isSingleObjective()) {
itemsToDisplay = itemsToDisplay.except(OptimizationResultLineItem.OptimumValue);
}
if (! graphModel.ofType(ExternalToolProxyNode.class).any()) {
itemsToDisplay = itemsToDisplay.except(OptimizationResultLineItem.SimulationTimeRemaining);
}
for (OptimizationResultLineItem displayItem : itemsToDisplay) {
ResultItemController controller = itemControllerByType.get(displayItem);
controller.getView().prefWidthProperty().bind(view.widthProperty());
elements.getChildren().add(controller.getView());
}
}
private void setDisplayingValue() {
try {
ResultItemController itemController2 = itemControllerByType.getValueFor(NumberOfFunctionEvaluations);
itemController2.setText(String.valueOf(matrix.size()));
if (matrix.isSingleObjective() && matrix.any()) {
ResultItemController itemController3 = itemControllerByType.getValueFor(OptimumValue);
Optional<Double> bestFeasiblePointFValue = matrix.getBestFeasiblePointFValue();
Double newOptimumValue = bestFeasiblePointFValue.orElseGet(() -> matrix.getBestPointFValue());
itemController3.setText(getTextForOptimumValue(newOptimumValue, bestFeasiblePointFValue.isPresent()));
itemController3.setToolTip("" + newOptimumValue);
}
}
catch (Exception e) {
log.log(Level.WARNING, "Problem in rendering results", e);
}
}
private String getTextForOptimumValue(double newOptimumValue, boolean isFeasible) {
String relativeFormattedString;
if(newOptimumValue <= -1000.0 || newOptimumValue >= +1000.0){
relativeFormattedString = exponentFormatter.format(newOptimumValue);
}
else{
relativeFormattedString = simpleFormatter.format(newOptimumValue);
}
if (! isFeasible) {
relativeFormattedString = relativeFormattedString + " (infeasible)";
}
return relativeFormattedString;
}
@Subscribe
public void refreshResultPanelOnModelChanged(UserSelectedPreviousRunForDisplayEvent event) {
setDisplayingValue();
}
@Override
public void refreshVisualizationsOn(NewExpensivePointFoundEvent event) {
setDisplayingValue();
}
@Override
public Region getView() {
return view;
}
@Override
public void dispose() {
try {
updaterService.unregisterFromModelPush(this);
eventBus.unregister(this);
stopwatch.dispose();
}
catch (Exception exception) {
log.log(Level.WARNING, "encountered error on disposal", exception);
}
}
/**
* Created by Josh on 1/14/2015.
*/
public static class OptimizationStopWatch implements Disposable {
private static final Class<OptimizationStopWatch> clazz = OptimizationStopWatch.class;
private static final Logger log = Logger.getLogger(clazz.getCanonicalName());
//47 is a prime number close to 50.
// - using a prime gives the timer the appearance of tracking values
// all the way down to the thousandth of a second (1ms)
// - 50 ms is slow to a computer but fast to a human,
// thus it makes a good value for a period from both a usability view and a performance view.
private static final int PollPeriodMillis = getEnvInt(clazz, "PollPeriodMillis").orElse(47);
private final ScheduledExecutorService blockableUpdaterThread;
private final EventBus eventBus;
private final QueryableMap<OptimizationResultLineItem, ResultItemController> itemControllerByType;
private final OptimizerService optimizerService;
private final ModelUpdaterService updaterService;
private final @Nullable OptimizationMetadata metadata;
private ScheduledFuture<?> runningTask;
private @UpdateServiced GraphModel graphModel;
private Optional<UUID> runningAppId = Optional.empty();
private Optional<Instant> appStartTime = Optional.empty();
public interface Factory {
OptimizationStopWatch create(QueryableMap<OptimizationResultLineItem, ResultItemController> itemControllerByType,
Queryable<ProxyNode> proxyNodes,
@Assisted("metadata") @Nullable OptimizationMetadata metadata);
}
private final Queryable<ProxyNode> proxyNodes;
private final AtomicBoolean wasDisposed = new AtomicBoolean(false);
@Inject
public OptimizationStopWatch(ThreadFactory threadFactory,
ModelUpdaterService updaterService,
OptimizerService optimizerService,
EventBus eventBus,
GraphModel graphModel,
@Assisted QueryableMap<OptimizationResultLineItem, ResultItemController> itemControllerByType,
@Assisted Queryable<ProxyNode> proxyNodes,
@Assisted("metadata") @Nullable OptimizationMetadata metadata
) {
this.updaterService = updaterService;
this.optimizerService = optimizerService;
this.eventBus = eventBus;
this.itemControllerByType = itemControllerByType;
this.proxyNodes = proxyNodes;
this.graphModel = graphModel;
this.metadata = metadata;
blockableUpdaterThread = threadFactory.createScheduledExecutor(this, Sequential.INSTANCE);
eventBus.register(this);
updaterService.registerForModelPush(this);
}
@Override
public void dispose() {
if (! wasDisposed.getAndSet(true)) {
updaterService.unregisterFromModelPush(this);
if(runningTask != null) runningTask.cancel(false);
eventBus.unregister(this);
}
}
public void start() {
if(metadata == OptimizationMetadata.Companion.getNullInstance()) return;
runningTask = blockableUpdaterThread.scheduleWithFixedDelay(
this::updatedDisplayedTimeValues, 0L,
PollPeriodMillis, TimeUnit.MILLISECONDS
);
}
// TODO: theres a volatile issue on `model` and a thread-confinement issue on setText here.
// TODO: replace with coroutines.
@VisibleForTesting void updatedDisplayedTimeValues() {
//take a snap-shot of the values to avoid the clocks creeping forward while we update the view.
Duration currentRunTime;
Duration simulationTime;
Duration oasisOverheadTime;
Duration sessionTime;
if (optimizerService.isMidExecution()) {
currentRunTime = optimizerService.getCurrentRunTime();
simulationTime = optimizerService.getSimulationTime();
oasisOverheadTime = optimizerService.getOasisOverheadTime();
sessionTime = optimizerService.getSessionTime();
}
else if (metadata != null){
currentRunTime = metadata.getRunTime();
simulationTime = metadata.getSimulationTime();
oasisOverheadTime = metadata.getOasisOverheadTime();
sessionTime = metadata.getSessionTime();
}
else {
throw new IllegalStateException("not running and no metadata provided");
}
setDisplayingTimeWithFormat(CurrentRunTime, currentRunTime);
setDisplayingTimeWithFormat(SimulationExecution, simulationTime);
setDisplayingTimeWithFormat(AlgorithmOverhead, oasisOverheadTime);
setDisplayingTimeWithFormat(SessionTime, sessionTime);
if (! proxyNodes.any() || ! optimizerService.isRunning()) {
return;
}
Duration duration = calculateTimeRemainingBeforeTimeoutOnCurrentSimulation();
ResultItemController itemController = itemControllerByType.getValueFor(SimulationTimeRemaining);
String formattedTime = formatDuration(duration);
itemController.setText(formattedTime);
}
@Subscribe
public synchronized void noteRunningToolOn(SimulationStartedEvent event) {
this.runningAppId = Optional.of(event.getNodeId());
this.appStartTime = Optional.of(event.getTimeOfExecStart());
}
@Subscribe
public synchronized void noteRunningToolOn(SimulationFinishedEvent event) {
this.runningAppId = Optional.empty();
this.appStartTime = Optional.empty();
}
private void setDisplayingTimeWithFormat(OptimizationResultLineItem resultLineItem, Duration duration) {
String formattedTime = formatDuration(duration);
itemControllerByType.getValueFor(resultLineItem).setText(formattedTime);
}
private Duration calculateTimeRemainingBeforeTimeoutOnCurrentSimulation() {
if (graphModel.ofType(ExternalToolProxyNode.class).isEmpty()) {
return Duration.ZERO;
}
if (! runningAppId.isPresent()) {
return Duration.ZERO;
}
Optional<ExternalToolProxyNode> node = graphModel
.ofType(ExternalToolProxyNode.class)
.singleOrDefault(etNode -> etNode.getID().equals(runningAppId.get()));
if (! node.isPresent()) {
log.warning(
"tried generating running time on an ETPN id=" + runningAppId.get() + ", " +
"but that tool doesnt exist on this graph?"
);
return Heartbeat.FOREVER;
}
FormattedDuration timeout = node.get().getToolTemplate().getTimeout();
if (timeout.asDuration() == Durations.Forever) {
return Durations.Forever;
}
Duration elapsedOnApp = Duration.between(appStartTime.get(), Instant.now());
Duration remaining = timeout.asDuration().minus(elapsedOnApp);
return remaining.isNegative() ? Duration.ZERO : remaining;
}
/**
* This is equivalent to
* long hours = seconds / SECONDS_PER_HOUR;
* int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
* int secs = (int) (seconds % SECONDS_PER_MINUTE);
*/
public static String formatDuration(Duration duration) {
duration = duration.compareTo(Durations.Forever) >= 0 ? Duration.ZERO : duration;
long hours = duration.toHours();
long minutes = duration.minusHours(duration.toHours()).toMinutes();
long seconds = duration.minusMinutes(duration.toMinutes()).getSeconds();
long millis = duration.minusSeconds(duration.getSeconds()).toMillis();
String positive = String.format(
"%d:%02d:%02d.%03d",
hours,
minutes,
seconds,
millis
);
return duration.isNegative() ? "-" + positive : positive;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment