/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2014 Ausenco Engineering Canada Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaamsim.Thresholds;
import java.util.ArrayList;
import com.jaamsim.DisplayModels.ShapeModel;
import com.jaamsim.basicsim.Entity;
import com.jaamsim.events.EventHandle;
import com.jaamsim.events.EventManager;
import com.jaamsim.events.ProcessTarget;
import com.jaamsim.input.BooleanInput;
import com.jaamsim.input.ColourInput;
import com.jaamsim.input.Keyword;
import com.jaamsim.input.Output;
import com.jaamsim.math.Color4d;
import com.jaamsim.states.StateEntity;
import com.jaamsim.units.DimensionlessUnit;
public class Threshold extends StateEntity {
@Keyword(description = "The colour of the threshold graphic when the threshold is open.",
exampleList = { "green" })
private final ColourInput openColour;
@Keyword(description = "The colour of the threshold graphic when the threshold is closed.",
exampleList = { "red" })
private final ColourInput closedColour;
@Keyword(description = "A Boolean value. If TRUE, the threshold is displayed when it is open.",
exampleList = { "FALSE" })
private final BooleanInput showWhenOpen;
@Keyword(description = "A Boolean value. If TRUE, the threshold is displayed when it is closed.",
exampleList = { "FALSE" })
private final BooleanInput showWhenClosed;
private final ArrayList<ThresholdUser> userList;
private boolean open;
private boolean initialOpenValue;
private long openCount;
private long closedCount;
{
workingStateListInput.setHidden(true);
openColour = new ColourInput("OpenColour", "Graphics", ColourInput.GREEN);
this.addInput(openColour);
this.addSynonym(openColour, "OpenColor");
closedColour = new ColourInput("ClosedColour", "Graphics", ColourInput.RED);
this.addInput(closedColour);
this.addSynonym(closedColour, "ClosedColor");
showWhenOpen = new BooleanInput("ShowWhenOpen", "Graphics", true);
this.addInput(showWhenOpen);
showWhenClosed = new BooleanInput("ShowWhenClosed", "Graphics", true);
this.addInput(showWhenClosed);
}
public Threshold() {
userList = new ArrayList<>();
initialOpenValue = true;
open = true;
}
@Override
public void earlyInit() {
super.earlyInit();
thresholdChangedTarget.users.clear();
open = initialOpenValue;
openCount = 0L;
closedCount = 0L;
userList.clear();
for (Entity each : Entity.getClonesOfIterator(Entity.class)) {
if (each instanceof ThresholdUser) {
ThresholdUser tu = (ThresholdUser)each;
if (tu.getThresholds().contains(this))
userList.add(tu);
}
}
}
public void setInitialOpenValue(boolean bool) {
initialOpenValue = bool;
}
@Override
public String getInitialState() {
if (initialOpenValue)
return "Open";
else
return "Closed";
}
@Override
public boolean isValidState(String state) {
return "Open".equals(state) || "Closed".equals(state);
}
@Override
public boolean isValidWorkingState(String state) {
return "Open".equals(state);
}
private static final EventHandle thresholdChangedHandle = new EventHandle();
private static final ThresholdChangedTarget thresholdChangedTarget = new ThresholdChangedTarget();
private static class ThresholdChangedTarget extends ProcessTarget {
public final ArrayList<ThresholdUser> users = new ArrayList<>();
public ThresholdChangedTarget() {}
@Override
public void process() {
for( int i = 0; i < users.size(); i++ )
users.get( i ).thresholdChanged();
users.clear();
}
@Override
public String getDescription() {
return "UpdateAllThresholdUsers";
}
}
public boolean isOpen() {
return open;
}
public final void setOpen(boolean bool) {
// If setting to the same value as current, return
if (open == bool)
return;
if (isTraceFlag()) trace(0, "setOpen(%s)", bool);
open = bool;
if (open) {
setPresentState("Open");
openCount++;
}
else {
setPresentState("Closed");
closedCount++;
}
for (ThresholdUser user : this.userList) {
if (!thresholdChangedTarget.users.contains(user))
thresholdChangedTarget.users.add(user);
}
if (!thresholdChangedTarget.users.isEmpty() && !thresholdChangedHandle.isScheduled())
this.scheduleProcessTicks(0, 2, false, thresholdChangedTarget, thresholdChangedHandle);
}
@Override
public void clearStatistics() {
openCount = 0L;
closedCount = 0L;
}
@Override
public void updateGraphics( double time ) {
super.updateGraphics(time);
// Determine the colour for the square
Color4d col;
if (open) {
col = openColour.getValue();
setTagVisibility(ShapeModel.TAG_CONTENTS, showWhenOpen.getValue());
setTagVisibility(ShapeModel.TAG_OUTLINES, showWhenOpen.getValue());
}
else {
col = closedColour.getValue();
setTagVisibility(ShapeModel.TAG_CONTENTS, showWhenClosed.getValue());
setTagVisibility(ShapeModel.TAG_OUTLINES, showWhenClosed.getValue());
}
setTagColour( ShapeModel.TAG_CONTENTS, col );
setTagColour( ShapeModel.TAG_OUTLINES, ColourInput.BLACK );
}
@Output(name = "Open",
description = "If open, then return TRUE. Otherwise, return FALSE.",
unitType = DimensionlessUnit.class,
sequence = 0)
public Boolean getOpen(double simTime) {
return open;
}
@Output(name = "OpenFraction",
description = "The fraction of total simulation time that the threshold is open.",
unitType = DimensionlessUnit.class,
reportable = true,
sequence = 1)
public double getOpenFraction(double simTime) {
long simTicks = EventManager.secsToNearestTick(simTime);
long openTicks = this.getTicksInState(simTicks, getState("Open"));
long closedTicks = this.getTicksInState(simTicks, getState("Closed"));
long totTicks = openTicks + closedTicks;
return (double)openTicks / totTicks;
}
@Output(name = "ClosedFraction",
description = "The fraction of total simulation time that the threshold is closed.",
unitType = DimensionlessUnit.class,
sequence = 2)
public double getClosedFraction(double simTime) {
long simTicks = EventManager.secsToNearestTick(simTime);
long openTicks = this.getTicksInState(simTicks, getState("Open"));
long closedTicks = this.getTicksInState(simTicks, getState("Closed"));
long totTicks = openTicks + closedTicks;
return (double)closedTicks / totTicks;
}
@Output(name = "OpenCount",
description = "The number of times the threshold's state has changed from closed to open.",
unitType = DimensionlessUnit.class,
sequence = 3)
public long getOpenCount(double simTime) {
return openCount;
}
@Output(name = "ClosedCount",
description = "The number of times the threshold's state has changed from open to closed.",
unitType = DimensionlessUnit.class,
sequence = 4)
public long getClosedCount(double simTime) {
return closedCount;
}
}