Ensure ActionFRequency does reset if time ran backwards.

This commit is contained in:
asofold 2014-07-31 10:02:49 +02:00
parent 2f13529a29
commit 24120f306a

View File

@ -10,6 +10,7 @@ public class ActionFrequency {
/** Reference time for filling in. */
private long time = 0;
private long lastUpdate = 0;
/**
* Buckets to fill weights in, each represents an interval of durBucket duration,
@ -21,7 +22,7 @@ public class ActionFrequency {
/** Duration in milliseconds that oe bucket covers. */
private final long durBucket;
public ActionFrequency(final int nBuckets, final long durBucket){
public ActionFrequency(final int nBuckets, final long durBucket) {
this.buckets = new float[nBuckets];
this.durBucket = durBucket;
}
@ -31,7 +32,7 @@ public class ActionFrequency {
* @param now
* @param amount
*/
public final void add(final long now, final float amount){
public final void add(final long now, final float amount) {
update(now);
buckets[0] += amount;
}
@ -40,42 +41,43 @@ public class ActionFrequency {
* Unchecked addition of amount to the first bucket.
* @param amount
*/
public final void add(final float amount){
public final void add(final float amount) {
buckets[0] += amount;
}
/**
* Update without adding, also updates time.
* Update without adding, also updates time. Detects time running backwards.
* @param now
*/
public final void update(final long now) {
final long diff = now - time;
if (diff < durBucket){
// No update (first bucket).
return;
}
else if (diff >= durBucket * buckets.length || diff < 0){
if (now < lastUpdate || diff >= durBucket * buckets.length) {
// Clear (beyond range).
clear(now);
return;
}
else if (diff < durBucket) {
// No update (first bucket).
return;
}
final int shift = (int) ((float) diff / (float) durBucket);
// Update buckets.
for (int i = 0; i < buckets.length - shift; i++){
for (int i = 0; i < buckets.length - shift; i++) {
buckets[buckets.length - (i + 1)] = buckets[buckets.length - (i + 1 + shift)];
}
for (int i = 0; i < shift; i++){
for (int i = 0; i < shift; i++) {
buckets[i] = 0;
}
// Set time according to bucket duration (!).
time += durBucket * shift;
lastUpdate = now;
}
public final void clear(final long now) {
for (int i = 0; i < buckets.length; i++){
for (int i = 0; i < buckets.length; i++) {
buckets[i] = 0f;
}
time = now;
time = lastUpdate = now;
}
/**
@ -83,7 +85,7 @@ public class ActionFrequency {
* @param factor
* @return
*/
public final float getScore(final float factor){
public final float getScore(final float factor) {
return score(factor);
}
@ -92,7 +94,7 @@ public class ActionFrequency {
* @param factor
* @return
*/
public final float getScore(final int bucket){
public final float getScore(final int bucket) {
return bucketScore(bucket);
}
@ -101,7 +103,7 @@ public class ActionFrequency {
* @param factor
* @return
*/
public final float score(final float factor){
public final float score(final float factor) {
return sliceScore(0, buckets.length, factor);
}
@ -110,7 +112,7 @@ public class ActionFrequency {
* @param bucket
* @return
*/
public final float bucketScore(final int bucket){
public final float bucketScore(final int bucket) {
return buckets[bucket];
}
@ -120,7 +122,7 @@ public class ActionFrequency {
* @param factor
* @return
*/
public final float leadingScore(final int end, float factor){
public final float leadingScore(final int end, float factor) {
return sliceScore(0, end, factor);
}
@ -130,7 +132,7 @@ public class ActionFrequency {
* @param factor
* @return
*/
public final float trailingScore(final int start, float factor){
public final float trailingScore(final int start, float factor) {
return sliceScore(start, buckets.length, factor);
}
@ -141,10 +143,10 @@ public class ActionFrequency {
* @param factor
* @return
*/
public final float sliceScore(final int start, final int end, float factor){
public final float sliceScore(final int start, final int end, float factor) {
float score = buckets[start];
float cf = factor;
for (int i = start + 1; i < end; i++){
for (int i = start + 1; i < end; i++) {
score += buckets[i] * cf;
cf *= factor;
}
@ -156,7 +158,7 @@ public class ActionFrequency {
* @param n
* @param value
*/
public final void setBucket(final int n, final float value){
public final void setBucket(final int n, final float value) {
buckets[n] = value;
}
@ -164,23 +166,32 @@ public class ActionFrequency {
* Set the reference time.
* @param time
*/
public final void setTime(final long time){
public final void setTime(final long time) {
this.time = time;
this.lastUpdate = time;
}
/**
* Get reference time.
* @return
*/
public final long lastAccess(){
public final long lastAccess() { // TODO: Should rename this.
return time;
}
/**
*
* @return
*/
public final long lastUpdate() {
return lastUpdate;
}
/**
* Get the number of buckets.
* @return
*/
public final int numberOfBuckets(){
public final int numberOfBuckets() {
return buckets.length;
}
@ -188,7 +199,7 @@ public class ActionFrequency {
* Get the duration of a bucket in milliseconds.
* @return
*/
public final long bucketDuration(){
public final long bucketDuration() {
return durBucket;
}
@ -196,10 +207,11 @@ public class ActionFrequency {
* Serialize to a String line.
* @return
*/
public final String toLine(){
public final String toLine() {
// TODO: Backwards-compatible lastUpdate ?
final StringBuilder buffer = new StringBuilder(50);
buffer.append(buckets.length + ","+durBucket+","+time);
for (int i = 0; i < buckets.length; i++){
for (int i = 0; i < buckets.length; i++) {
buffer.append("," + buckets[i]);
}
return buffer.toString();
@ -210,7 +222,8 @@ public class ActionFrequency {
* @param line
* @return
*/
public static ActionFrequency fromLine(final String line){
public static ActionFrequency fromLine(final String line) {
// TODO: Backwards-compatible lastUpdate ?
String[] split = line.split(",");
if (split.length < 3) throw new RuntimeException("Bad argument length."); // TODO
final int n = Integer.parseInt(split[0]);
@ -218,12 +231,12 @@ public class ActionFrequency {
final long time = Long.parseLong(split[2]);
final float[] buckets = new float[split.length -3];
if (split.length - 3 != buckets.length) throw new RuntimeException("Bad argument length."); // TODO
for (int i = 3; i < split.length; i ++){
for (int i = 3; i < split.length; i ++) {
buckets[i - 3] = Float.parseFloat(split[i]);
}
ActionFrequency freq = new ActionFrequency(n, durBucket);
freq.setTime(time);
for (int i = 0; i < buckets.length; i ++){
for (int i = 0; i < buckets.length; i ++) {
freq.setBucket(i, buckets[i]);
}
return freq;