diff --git a/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java b/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java
index 9d23ceddf5349216fa082977b47ca235d6a0e3f1..96570260c5de43c09b24efe897e8ca963b4a0b8c 100644
--- a/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java
+++ b/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java
@@ -11,7 +11,7 @@ class CapacityCalculator {
     private static final I2PAppContext _context = I2PAppContext.getGlobalContext();
     
     /** used to adjust each period so that we keep trying to expand the peer's capacity */
-    static long GROWTH_FACTOR = 5;
+    static final long GROWTH_FACTOR = 5;
     
     /** the calculator estimates over a 1 hour period */
     private static long ESTIMATE_PERIOD = 60*60*1000;
@@ -83,37 +83,42 @@ class CapacityCalculator {
      *
      * Let A = accects, R = rejects, F = fails
      * @return estimated and adjusted accepts per hour, for the given period
-     *         which is, more or less, max(0, 5 + (A * (A / (A + R))) - (4 * F))
+     *         which is, more or less, max(0, 5 + (A * (A / (A + 2R))) - (4 * F))
      */
     private static double estimateCapacity(RateStat acceptStat, RateStat rejectStat, RateStat failedStat, int period) {
         Rate curAccepted = acceptStat.getRate(period);
         Rate curRejected = rejectStat.getRate(period);
         Rate curFailed = failedStat.getRate(period);
 
-        long eventCount = 0;
-        if (curAccepted != null)
+        double eventCount = 0;
+        if (curAccepted != null) {
             eventCount = curAccepted.getCurrentEventCount() + curAccepted.getLastEventCount();
-        // Punish for rejections.
-        // We don't want to simply do eventCount -= rejected or we get to zero with 50% rejection,
-        // and we don't want everybody to be at zero during times of congestion.
-        if (eventCount > 0) {
-            long rejected = curRejected.getCurrentEventCount() + curRejected.getLastEventCount();
-            eventCount = eventCount * eventCount / (eventCount + rejected);
+            // Punish for rejections.
+            // We don't want to simply do eventCount -= rejected or we get to zero with 50% rejection,
+            // and we don't want everybody to be at zero during times of congestion.
+            if (eventCount > 0 && curRejected != null) {
+                long rejected = curRejected.getCurrentEventCount() + curRejected.getLastEventCount();
+                if (rejected > 0)
+                    eventCount *= eventCount / (eventCount + (2 * rejected));
+            }
         }
+
         double stretch = ((double)ESTIMATE_PERIOD) / period;
         double val = eventCount * stretch;
-        long failed = 0;
+
         // Let's say a failure is 4 times worse than a rejection.
         // It's actually much worse than that, but with 2-hop tunnels and a 8-peer
         // fast pool, for example, you have a 1/7 chance of being falsely blamed.
         // We also don't want to drive everybody's capacity to zero, that isn't helpful.
-        if (curFailed != null)
-            failed = (long) (0.5 + (4.0 * (curFailed.getCurrentTotalValue() + curFailed.getLastTotalValue()) / 100.0));
-        if (failed > 0) {
-            //if ( (period <= 10*60*1000) && (curFailed.getCurrentEventCount() > 0) )
-            //    return 0.0d; // their tunnels have failed in the last 0-10 minutes
-            //else
-            val -= failed * stretch;
+        if (curFailed != null) {
+            double failed = curFailed.getCurrentTotalValue() + curFailed.getLastTotalValue();
+            if (failed > 0) {
+                //if ( (period <= 10*60*1000) && (curFailed.getCurrentEventCount() > 0) )
+                //    return 0.0d; // their tunnels have failed in the last 0-10 minutes
+                //else
+                // .04 = 4.0 / 100.0 adjustment to failed
+                val -= 0.04 * failed * stretch;
+            }
         }
         
         val += GROWTH_FACTOR;