package in.tombo.kashiki.view;

import java.util.concurrent.ExecutionException;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

public enum MovingType {

  LINER {
    @Override
    protected double[] innerGains(int divOfNum) {
      double[] result = new double[divOfNum];
      double gain = 1.0 / divOfNum;
      for (int i = 0; i < divOfNum; i++) {
        result[i] = gain;
      }
      return result;
    }
  },
  SMOOTH {
    @Override
    protected double[] innerGains(int divOfNum) {
      double[] result = new double[divOfNum];
      double gain = 1.0 / divOfNum;
      double g = Math.PI * gain;
      for (int i = 0; i < divOfNum; i++) {
        double divGain = Math.cos(g * i) - Math.cos(g * (i + 1));
        result[i] = (divGain / 2);
      }
      return result;
    }
  },
  BOUND {
    @Override
    protected double[] innerGains(int divOfNum) {
      double[] result = new double[divOfNum];
      double gain = 1.0 / divOfNum;
      double g = Math.PI * 1.5 * gain;
      double qg = Math.PI / 4.0;
      double dd = Math.sin(qg) * 2;
      for (int i = 0; i < divOfNum; i++) {
        double divGain = Math.sin(g * i + qg) - Math.sin(g * (i + 1) + qg);
        result[i] = (divGain / dd);
      }
      return result;
    }
  };

  LoadingCache<Integer, double[]> cache = CacheBuilder.newBuilder().maximumSize(1000)
      .build(new CacheLoader<Integer, double[]>() {
        @Override
        public double[] load(Integer divOfNum) throws Exception {
          return innerGains(divOfNum);
        }
      });

  protected abstract double[] innerGains(int divOfNum);

  public double[] gains(int divOfNum) {
    try {
      return cache.get(divOfNum);
    } catch (ExecutionException e) {
      throw new RuntimeException(e);
    }
  }
}

@@ -874,16 +874,831 @@
  %7D%0A  %7D,%0A
+  SMOOTH_OUT %7B%0A    @Override%0A    protected double%5B%5D innerGains(int divOfNum) %7B%0A      double%5B%5D result = new double%5BdivOfNum%5D;%0A      double gain = 1.0 / divOfNum;%0A      double g = Math.PI * gain / 2.0;%0A      for (int i = 0; i %3C divOfNum; i++) %7B%0A        double divGain = Math.sin(g * (i + 1)) - Math.sin(g * i);%0A        result%5Bi%5D = (divGain);%0A      %7D%0A      return result;%0A    %7D%0A  %7D,%0A  SMOOTH_IN %7B%0A    @Override%0A    protected double%5B%5D innerGains(int divOfNum) %7B%0A      double%5B%5D result = new double%5BdivOfNum%5D;%0A      double gain = 1.0 / divOfNum;%0A      double g = Math.PI * gain / 2.0;%0A      double start = Math.PI * 1.5;%0A      for (int i = 0; i %3C divOfNum; i++) %7B%0A        double divGain = Math.sin(start + (g * (i + 1))) - Math.sin(start + (g * i));%0A        result%5Bi%5D = (divGain);%0A      %7D%0A      return result;%0A    %7D%0A  %7D,%0A
   BOUND 
@@ -1699,16 +1699,16 @@
 BOUND %7B%0A
-
     @Ove
@@ -2190,16 +2190,22 @@
  cache =
+%0A     
  CacheBu
@@ -2240,23 +2240,16 @@
 ze(1000)
-%0A      
 .build(n

add SMOOTH_IN, SMOOTH_OUT (#7)