package com.airbnb.aerosolve.core.function;

import com.airbnb.aerosolve.core.ModelRecord;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

/**
 * Test linear function
 */

public class LinearTest {
  private float func(float x) {
    return 0.2f + 1.5f * (x + 6.0f) / 11.0f;
  }

  private Linear createLinearTestExample() {
    float [] weights = {0.2f, 1.5f};
    return new Linear(-6.0f, 5.0f, weights);
  }

  @Test
  public void testLinearEvaluate() {
    Linear linearFunc = createLinearTestExample();
    testLinear(linearFunc);
  }

  @Test
  public void testLinearModelRecordConstructor() {
    ModelRecord record = new ModelRecord();
    record.setFeatureFamily("TEST");
    record.setFeatureName("a");
    List<Double> weightVec = new ArrayList<>();
    weightVec.add(0.2);
    weightVec.add(1.5);
    record.setWeightVector(weightVec);
    record.setMinVal(-6.0f);
    record.setMaxVal(5.0f);
    Linear linearFunc = new Linear(record);
    testLinear(linearFunc);
  }

  @Test
  public void testLinearToModelRecord() {
    Linear linearFunc = createLinearTestExample();
    ModelRecord record = linearFunc.toModelRecord("family", "name");
    assertEquals(record.getFeatureFamily(), "family");
    assertEquals(record.getFeatureName(), "name");
    List<Double> weightVector = record.getWeightVector();
    assertEquals(0.2f, weightVector.get(0).floatValue(), 0.01f);
    assertEquals(1.5f, weightVector.get(1).floatValue(), 0.01f);
    assertEquals(-6.0f, record.getMinVal(), 0.01f);
    assertEquals(5.0f, record.getMaxVal(), 0.01f);
  }

  @Test
  public void testLinearUpdate() {
    Linear linearFunc = new Linear(-6.0f, 5.0f, new float[2]);
    Random rnd = new java.util.Random(123);
    for (int i = 0; i < 1000; i++) {
      float x = (float) (rnd.nextDouble() * 10.0 - 5.0);
      float y = func(x);
      float tmp = linearFunc.evaluate(x);
      float delta = 0.5f * (y - tmp);
      linearFunc.update(delta, x);
    }
    testLinear(linearFunc);
  }

  @Test
  public void testLinearClone() throws CloneNotSupportedException {
    Linear linearFunc = new Linear(-6.0f, 5.0f, new float[2]);
    Linear linearCopy = linearFunc.clone();
    linearCopy.setWeights(new float[]{1.0f, 2.0f, 3.0f});
    assertArrayEquals(linearFunc.weights, new float[2], 0);
    linearCopy.minVal = 0f;
    assertEquals(linearFunc.minVal, -6f, 0);
  }

  private void testLinear(Linear linearFunc) {
    assertEquals(0.2f + 1.5f * 6.0f / 11.0f, linearFunc.evaluate(0.0f), 0.01f);
    assertEquals(0.2f + 1.5f * 7.0f / 11.0f, linearFunc.evaluate(1.0f), 0.01f);
    assertEquals(0.2f + 1.5f * 5.0f / 11.0f, linearFunc.evaluate(-1.0f), 0.01f);
  }
}

@@ -2321,19 +2321,18 @@
 opy.
-setW
+w
 eights
-(
+ = 
 new 
@@ -2356,17 +2356,16 @@
 f, 3.0f%7D
-)
 ;%0A    as

fix unit test