/******************************************************************************* * Copyright (c) 2003-2005, 2013 Till Zoppke. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Till Zoppke - initial API and implementation ******************************************************************************/ /* * Created on 30.03.2004 */ package eniac.data.model; import java.util.Arrays; import java.util.Observable; import java.util.Observer; import java.util.Timer; import java.util.TimerTask; import org.xml.sax.Attributes; import eniac.Manager; import eniac.data.model.unit.Unit; import eniac.io.XMLUtil; import eniac.simulation.Frequency; import eniac.util.Status; /** * @author zoppke */ public class Benchmark extends EData implements Observer { // circular array of frequencies. One frequency per second. private Frequency[] _freqs; // points to the next frequency to be overwritten private int _pointer = 0; // timer private Timer _timer = new Timer(); // task for updating frequencies. To be scheduled at the timer. private UpdateTask _task = new UpdateTask(); // timestamps from when we computed a frequency last time. private long _lastRealTime = 0L; private long _lastSimTime = 0L; // =============================== lifecycle //============================= /** * @param type */ public Benchmark() { // empty constructor } public void init() { super.init(); ((Unit) getParent()).getHeaters().addObserver(this); // initialize frequencies and schedule task, // in case power is switched on. update(null, null); } public void setAttributes(Attributes attrs) { super.setAttributes(attrs); int size = XMLUtil.parseInt(attrs, Tag.SIZE); _freqs = new Frequency[size]; } public void dispose() { _task.cancel(); _timer.cancel(); super.dispose(); } // =============================== methods //=============================== public void update(Observable o, Object args) { if (hasPower()) { // power switch on. Init frequency array with zero line. Frequency freq = Frequency.getNew(); freq.setLinear(0.01); Arrays.fill(_freqs, freq); // schedule task. _task = new UpdateTask(); _timer.schedule(_task, 0, 1000); } else { // power switched off. Cancel task. _task.cancel(); } } void updateFrequencies() { // init variables long simTime = (long) Status.SIMULATION_TIME.getValue(); long realTime = System.currentTimeMillis(); long simTimeDiff = simTime - _lastSimTime; long realTimeDiff = realTime - _lastRealTime; // compute frequency and its logarithmic scale. // the result will be within [0..1] on a logarithmic scale double freq = CyclingLights.simToReal(simTimeDiff) / (double) realTimeDiff; _freqs[_pointer] = Frequency.getNew(); _freqs[_pointer].setLinear(freq); // adjust pointer and timestamps _pointer = ++_pointer % _freqs.length; _lastSimTime = simTime; _lastRealTime = realTime; // call for repaint setChanged(); notifyObservers(EData.REPAINT); } public Frequency[] getFrequencies() { return _freqs; } public int getPointer() { return _pointer; } public String getAttributes() { return super.getAttributes() + XMLUtil.wrapAttribute(Tag.SIZE, Integer.toString(_freqs.length)); } // ======================= private class UpdateTask //====================== private class UpdateTask extends TimerTask { public UpdateTask() { // empty constructor } public void run() { if (Status.LIFECYCLE.getValue() == Manager.LifeCycle.RUNNING) { updateFrequencies(); } } } }