package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.core.util.Vec3Comparable; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver.SolutionState; import io.github.moulberry.notenoughupdates.util.NEUDebugLogger; import net.minecraft.util.BlockPos; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Assertions; import java.util.ArrayList; class CrystalMetalDetectorSolverTest { class Location { double distance; Vec3Comparable playerPosition; SolutionState expectedState; boolean centerKnown; public Location(double distance, Vec3Comparable playerPosition, SolutionState expectedState, boolean centerKnown) { this.distance = distance; this.playerPosition = playerPosition; this.expectedState = expectedState; this.centerKnown = centerKnown; } } class Solution { ArrayList locations = new ArrayList<>(); BlockPos center = BlockPos.ORIGIN; BlockPos expectedSolution = BlockPos.ORIGIN; } @BeforeEach void setUp() { CrystalMetalDetectorSolver.initWorld(); CrystalMetalDetectorSolver.treasureAllowedPredicate = blockPos -> true; NEUDebugLogger.logMethod = CrystalMetalDetectorSolverTest::neuDebugLog; NEUDebugLogger.allFlagsEnabled = true; } private void findPossibleSolutionsTwice(Location loc, boolean centerNewlyDiscovered) { // Each location has to be received twice to be valid CrystalMetalDetectorSolver.findPossibleSolutions(loc.distance, loc.playerPosition, centerNewlyDiscovered); CrystalMetalDetectorSolver.findPossibleSolutions(loc.distance, loc.playerPosition, false); } private void checkSolution(Solution solution) { boolean centerSet = false; int index = 0; for (Location loc : solution.locations) { if (loc.centerKnown && !centerSet && !solution.center.equals(BlockPos.ORIGIN)) { CrystalMetalDetectorSolver.setMinesCenter(solution.center); centerSet = true; findPossibleSolutionsTwice(loc, true); } else { findPossibleSolutionsTwice(loc, false); } Assertions.assertEquals(loc.expectedState, CrystalMetalDetectorSolver.currentState, "Location index " + index); index++; } Assertions.assertEquals(solution.expectedSolution, CrystalMetalDetectorSolver.getSolution()); } @Test void findPossibleSolutions_single_location_sample_is_ignored() { Location location = new Location(37.3, new Vec3Comparable(779.1057116115207, 70.5, 502.2997937667801), SolutionState.MULTIPLE, false); CrystalMetalDetectorSolver.findPossibleSolutions(location.distance, location.playerPosition, false); Assertions.assertEquals(SolutionState.NOT_STARTED, CrystalMetalDetectorSolver.previousState, "Previous state"); Assertions.assertEquals(SolutionState.NOT_STARTED, CrystalMetalDetectorSolver.currentState, "Current state"); } @Test void findPossibleSolutions_currentState_becomes_previousState() { Location location = new Location(37.3, new Vec3Comparable(779.1057116115207, 70.5, 502.2997937667801), SolutionState.MULTIPLE, false); findPossibleSolutionsTwice(location, false); Assertions.assertEquals(SolutionState.NOT_STARTED, CrystalMetalDetectorSolver.previousState, "Previous state"); Assertions.assertEquals(location.expectedState, CrystalMetalDetectorSolver.currentState, "Current state"); } @Test void findPossibleSolutions_state_is_invalid_when_solution_and_distance_mismatch() { Solution solution = new Solution(); solution.center = new BlockPos(736, 88, 547); solution.expectedSolution = new BlockPos(722, 67, 590); solution.locations.add(new Location(67.5, new Vec3Comparable(757.8235166144441, 68.0, 532.8037800566217), SolutionState.FOUND_KNOWN, true)); // slightly different player position with invalid distance solution.locations.add(new Location(4.0, new Vec3Comparable(757.8235166144441, 69.0, 532.8037800566217), SolutionState.INVALID, true)); checkSolution(solution); } @Test void findPossibleSolutions_state_is_failed_when_second_location_eliminates_all_blocks() { Solution solution = new Solution(); solution.center = new BlockPos(736, 88, 547); solution.locations.add(new Location(29.4, new Vec3Comparable(721.5979761606153, 68.0, 590.9056839507032), SolutionState.MULTIPLE_KNOWN, true)); solution.locations.add(new Location(4.0, // actual distance should be 38.2 new Vec3Comparable(711.858759313838, 67.0, 590.3583935310772), SolutionState.FAILED, true)); checkSolution(solution); } @Test void findPossibleSolutions_state_is_found_known_when_center_found_after_location() { Solution solution = new Solution(); solution.center = new BlockPos(736, 88, 547); solution.locations.add(new Location(67.5, new Vec3Comparable(757.8235166144441, 68.0, 532.8037800566217), SolutionState.MULTIPLE, false)); checkSolution(solution); solution.locations.get(0).centerKnown = true; solution.locations.get(0).expectedState = SolutionState.FOUND_KNOWN; solution.expectedSolution = new BlockPos(722, 67, 590); checkSolution(solution); } @Test void findPossibleSolutions_state_is_found_when_single_known_location() { Solution solution = new Solution(); solution.center = new BlockPos(736, 88, 547); solution.expectedSolution = new BlockPos(722, 67, 590); solution.locations.add(new Location(67.5, new Vec3Comparable(757.8235166144441, 68.0, 532.8037800566217), SolutionState.FOUND_KNOWN, true)); checkSolution(solution); } @Test void findPossibleSolutions_states_are_correct_using_multiple_locations_with_unknown_center() { Solution solution = new Solution(); solution.locations.add(new Location(37.3, new Vec3Comparable(779.1057116115207, 70.5, 502.2997937667801), SolutionState.MULTIPLE, false)); solution.locations.add(new Location(34.8, new Vec3Comparable(782.6999999880791, 71.0, 508.69999998807907), SolutionState.FOUND, false)); solution.expectedSolution = new BlockPos(758, 67, 533); checkSolution(solution); } @Test void findPossibleSolutions_states_are_correct_when_multiple_known_locations_found() { Solution solution = new Solution(); // First, validate that the solution doesn't work without the center solution.locations.add(new Location(29.4, new Vec3Comparable(721.5979761606153, 68.0, 590.9056839507032), SolutionState.MULTIPLE, false)); solution.locations.add(new Location(38.2, new Vec3Comparable(711.858759313838, 67.0, 590.3583935310772), SolutionState.MULTIPLE, false)); checkSolution(solution); // Now validate that the solution works with the center CrystalMetalDetectorSolver.resetSolution(false); solution.locations.get(0).expectedState = SolutionState.MULTIPLE_KNOWN; solution.locations.get(0).centerKnown = true; solution.locations.get(1).expectedState = SolutionState.FOUND_KNOWN; solution.locations.get(1).centerKnown = true; solution.expectedSolution = new BlockPos(748, 66, 578); solution.center = new BlockPos(736, 88, 547); checkSolution(solution); } private static void neuDebugLog(String message) { System.out.println(message); } }