package org.bukkit; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.util.List; import java.util.Random; import org.bukkit.util.Vector; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import com.google.common.collect.ImmutableList; @RunWith(Parameterized.class) public class LocationTest { private static final double δ = 1.0 / 1000000; /** *
     * a² + b² = c², a = b
     * => 2∙(a²) = 2∙(b²) = c², c = 1
     * => 2∙(a²) = 1
     * => a² = 1/2
     * => a = √(1/2) ∎
     * 
*/ private static final double HALF_UNIT = Math.sqrt(1 / 2f); /** *
     * a² + b² = c², c = √(1/2)
     * => a² + b² = √(1/2)², a = b
     * => 2∙(a²) = 2∙(b²) = 1/2
     * => a² = 1/4
     * => a = √(1/4) ∎
     * 
*/ private static final double HALF_HALF_UNIT = Math.sqrt(1 / 4f); @Parameters(name= "{index}: {0}") public static List data() { Random RANDOM = new Random(1l); // Test is deterministic int r = 0; return ImmutableList.of( new Object[] { "X", 1, 0, 0, 270, 0 }, new Object[] { "-X", -1, 0, 0, 90, 0 }, new Object[] { "Z", 0, 0, 1, 0, 0 }, new Object[] { "-Z", 0, 0, -1, 180, 0 }, new Object[] { "Y", 0, 1, 0, 0, -90 // Zero is here as a "default" value }, new Object[] { "-Y", 0, -1, 0, 0, 90 // Zero is here as a "default" value }, new Object[] { "X Z", HALF_UNIT, 0, HALF_UNIT, (270 + 360) / 2, 0 }, new Object[] { "X -Z", HALF_UNIT, 0, -HALF_UNIT, (270 + 180) / 2, 0 }, new Object[] { "-X -Z", -HALF_UNIT, 0, -HALF_UNIT, (90 + 180) / 2, 0 }, new Object[] { "-X Z", -HALF_UNIT, 0, HALF_UNIT, (90 + 0) / 2, 0 }, new Object[] { "X Y Z", HALF_HALF_UNIT, HALF_UNIT, HALF_HALF_UNIT, (270 + 360) / 2, -45 }, new Object[] { "-X -Y -Z", -HALF_HALF_UNIT, -HALF_UNIT, -HALF_HALF_UNIT, (90 + 180) / 2, 45 }, getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++), getRandom(RANDOM, r++) ); } private static Object[] getRandom(Random random, int index) { final double YAW_FACTOR = 360; final double YAW_OFFSET = 0; final double PITCH_FACTOR = 180; final double PITCH_OFFSET = -90; final double CARTESIAN_FACTOR = 256; final double CARTESIAN_OFFSET = -128; Vector vector; Location location; if (random.nextBoolean()) { float pitch = (float) (random.nextDouble() * PITCH_FACTOR + PITCH_OFFSET); float yaw = (float) (random.nextDouble() * YAW_FACTOR + YAW_OFFSET); location = getEmptyLocation(); location.setPitch(pitch); location.setYaw(yaw); vector = location.getDirection(); } else { double x = random.nextDouble() * CARTESIAN_FACTOR + CARTESIAN_OFFSET; double y = random.nextDouble() * CARTESIAN_FACTOR + CARTESIAN_OFFSET; double z = random.nextDouble() * CARTESIAN_FACTOR + CARTESIAN_OFFSET; location = getEmptyLocation(); vector = new Vector(x, y, z).normalize(); location.setDirection(vector); } return new Object[] { "R" + index, vector.getX(), vector.getY(), vector.getZ(), location.getYaw(), location.getPitch() }; } @Parameter(0) public String nane; @Parameter(1) public double x; @Parameter(2) public double y; @Parameter(3) public double z; @Parameter(4) public float yaw; @Parameter(5) public float pitch; @Test public void testExpectedPitchYaw() { Location location = getEmptyLocation().setDirection(getVector()); assertThat((double) location.getYaw(), is(closeTo(yaw, δ))); assertThat((double) location.getPitch(), is(closeTo(pitch, δ))); } @Test public void testExpectedXYZ() { Vector vector = getLocation().getDirection(); assertThat(vector.getX(), is(closeTo(x, δ))); assertThat(vector.getY(), is(closeTo(y, δ))); assertThat(vector.getZ(), is(closeTo(z, δ))); } private Vector getVector() { return new Vector(x, y, z); } private static Location getEmptyLocation() { return new Location(null, 0, 0, 0); } private Location getLocation() { Location location = getEmptyLocation(); location.setYaw(yaw); location.setPitch(pitch); return location; } }