1 //
2 // RateCalculator.java
3 // CocoDonkey
4 // $Id: RateCalculator.java,v 1.4 2002/07/21 18:39:32 fortun Exp $
5 //
6 // Created by Fred Bonzoun on Sat Jun 08 2002.
7 // Copyright (c) 2002 Bonzoun. All rights reserved.
8 //
9 // This library is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published
11 // by the Free Software Foundation; either version 2.1 of the License, or
12 // (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 //
23
24 package net.bonzoun.cocodonkey;
25
26 import java.util;
27
28 /**
29 * This class is intended to calculate a remaining time for a download.
30 * For that, it uses instant download rates and makes complicated averages
31 * on them to finally get a better approximation of the remaining time
32 * than what the instant download rate can give.
33 * A first calculation is done with a floating average of the rate on a
34 * one minute length (MINUTE_LENGTH*MINUTE_PRECISION gives the length of a minute
35 * for the calculation, the unite being the second).
36 * A second estimation uses a one hour length for the floating average (one hour
37 * is HOUR_LENGTH*HOUR_PRECISION long, the unite being the second).
38 * The best of these two calculations is supposed to be the best bet for the current rate.
39 * The addRate() method is used to add a rate. It can be called as often as possible as
40 * the current class only uses the required data (MINUTE_PRECISION determines the amount
41 * of data that will be retained).
42 **/
43 public class RateCalculator {
44
45 /** Minimum amount of seconds between two kept "minute" rates **/
46 private static final int MINUTE_PRECISION = 2;
47 /** Number of rates kept for a "minute" **/
48 private static final int MINUTE_LENGTH = 20;
49 /** Number of rates kept for an "hour" **/
50 private static final int HOUR_LENGTH = 60;
51 /** Minimum amount of seconds between two kept "hour" rates **/
52 private static final int HOUR_PRECISION = 60;
53
54 private RateKeeper lastMinute;
55 private int minuteAddedCount = 0;
56 private RateKeeper lastHour;
57
58 public RateCalculator() {
59 lastMinute = new RateKeeper(MINUTE_PRECISION, MINUTE_LENGTH);
60 lastHour = new RateKeeper(HOUR_PRECISION, HOUR_LENGTH);
61 }
62
63 public void addRate(float rate) {
64 int nbAdded = lastMinute.addRate(rate);
65 minuteAddedCount += nbAdded;
66 if (minuteAddedCount>=HOUR_PRECISION/MINUTE_PRECISION) {
67 minuteAddedCount -= HOUR_PRECISION/MINUTE_PRECISION;
68 lastHour.addRate(lastMinute.meanRate());
69 }
70 }
71
72 public float meanRate() {
73 float minuteRate = lastMinute.meanRate();
74 float hourRate = lastHour.meanRate();
75 return Math.max(minuteRate, hourRate);
76 }
77
78 class RateKeeper {
79 private int precision;
80 private int maxSize;
81 private Vector rateList = new Vector();
82 private float rateTotal = 0;
83 private long lastAddTime = System.currentTimeMillis();
84
85 RateKeeper(int precision, int maxSize) {
86 this.precision = precision;
87 this.maxSize = maxSize;
88 }
89
90 public synchronized int addRate(float rate) {
91 long t = System.currentTimeMillis();
92 if (t-lastAddTime > (long)precision*1000) {
93 // We need to keep this one
94 int nb = 0;
95 for(int i=0; t-lastAddTime > (long)precision*1000 && i<maxSize; i++) {
96 lastAddTime += (long)precision*1000;
97 nb++;
98 addOneRate(rate);
99 }
100 lastAddTime = t;
101 return nb;
102 } else {
103 return 0;
104 }
105 }
106
107 private synchronized void addOneRate(float rate) {
108 if (rate<0 || rate>1000)
109 rate=0;
110 // We need to keep this one
111 rateTotal += rate;
112 rateList.add(0, new Float(rate));
113 // We keep a given size to the list
114 if (rateList.size()>maxSize) {
115 Number r = (Number)rateList.remove(rateList.size()-1);
116 rateTotal -= r.floatValue();
117 }
118 }
119
120 public float meanRate() {
121 if (rateList.size()==0)
122 return -1;
123 else
124 return rateTotal / rateList.size();
125 }
126
127 public boolean isFull() {
128 return rateList.size()==maxSize;
129 }
130 }
131 }
132
133 // $Log: RateCalculator.java,v $
134 // Revision 1.4 2002/07/21 18:39:32 fortun
135 // Proper creator set
136 //
137 // Revision 1.3 2002/07/08 21:40:29 fortun
138 // Comment added
139 //
140 // Revision 1.2 2002/06/14 00:41:52 fortun
141 // Sorter timing
142 //
143 // Revision 1.1 2002/06/09 15:44:24 fortun
144 // Calculates rates, with means over the time
145 //