/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.pepsoft.worldpainter.tools; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.awt.Point; import org.pepsoft.minecraft.RegionFile; /** * * @author pepijn */ public class FindOutliers { public static void main(String[] args) throws IOException { File[] worldDirs = new File(args[0]).listFiles(); for (File worldDir: worldDirs) { System.out.println("Scanning " + worldDir); File[] regionFiles = new File(worldDir, "region").listFiles(); if ((regionFiles == null) || (regionFiles.length == 0)) { System.out.println(" No regions found"); continue; } int regionCount = 0, chunkCount = 0; int lowestChunkX = Integer.MAX_VALUE, highestChunkX = Integer.MIN_VALUE, lowestChunkZ = Integer.MAX_VALUE, highestChunkZ = Integer.MIN_VALUE; List<Integer> xValues = new ArrayList<>(), zValues = new ArrayList<>(); List<Point> chunks = new ArrayList<>(); for (File file: regionFiles) { String[] nameFrags = file.getName().split("\\."); int regionX = Integer.parseInt(nameFrags[1]); int regionZ = Integer.parseInt(nameFrags[2]); regionCount++; RegionFile regionFile = new RegionFile(file); try { for (int x = 0; x < 32; x++) { for (int z = 0; z < 32; z++) { if (regionFile.containsChunk(x, z)) { chunkCount++; int chunkX = regionX * 32 + x, chunkZ = regionZ * 32 + z; if (chunkX < lowestChunkX) { lowestChunkX = chunkX; } if (chunkX > highestChunkX) { highestChunkX = chunkX; } if (chunkZ < lowestChunkZ) { lowestChunkZ = chunkZ; } if (chunkZ > highestChunkZ) { highestChunkZ = chunkZ; } xValues.add(chunkX); zValues.add(chunkZ); chunks.add(new Point(chunkX, chunkZ)); } } } } finally { regionFile.close(); } } // System.out.println(args[0]); // System.out.println("Region count: " + regionCount); // System.out.println("Chunk count: " + chunkCount); // System.out.println("Size in chunks: " + (highestChunkX - lowestChunkX + 1) + " by " + (highestChunkZ - lowestChunkZ + 1)); // System.out.println("Lowest chunk x: " + lowestChunkX + ", highest chunk x: " + highestChunkX); // System.out.println("Lowest chunk z: " + lowestChunkZ + ", highest chunk z: " + highestChunkZ); Collections.sort(xValues); int p1 = xValues.size() / 4; float q1 = xValues.get(p1) * 0.75f + xValues.get(p1 + 1) * 0.25f; int p2 = xValues.size() / 2; float q2 = (xValues.get(p2) + xValues.get(p2 + 1)) / 2f; int p3 = xValues.size() * 3 / 4; float q3 = xValues.get(p3) * 0.25f + xValues.get(p3 + 1) * 0.75f; float iqr = q3 - q1; int lowerLimit = (int) (q2 - iqr * 1.5f); int upperLimit = (int) (q2 + iqr * 1.5f); Set<Point> outlyingChunks = new HashSet<>(); for (Point chunk: chunks) { if ((chunk.x < lowerLimit) || (chunk.x > upperLimit)) { outlyingChunks.add(chunk); } } Collections.sort(zValues); p1 = zValues.size() / 4; q1 = zValues.get(p1) * 0.75f + zValues.get(p1 + 1) * 0.25f; p2 = zValues.size() / 2; q2 = (zValues.get(p2) + zValues.get(p2 + 1)) / 2f; p3 = zValues.size() * 3 / 4; q3 = zValues.get(p3) * 0.25f + zValues.get(p3 + 1) * 0.75f; iqr = q3 - q1; lowerLimit = (int) (q2 - iqr * 1.5f); upperLimit = (int) (q2 + iqr * 1.5f); for (Point chunk: chunks) { if ((chunk.y < lowerLimit) || (chunk.y > upperLimit)) { outlyingChunks.add(chunk); } } if (! outlyingChunks.isEmpty()) { System.out.println(" Outlying chunk count: " + outlyingChunks.size()); // for (Point outlyingChunk: outlyingChunks) { // System.out.println(outlyingChunk); // } } else { System.out.println(" No outlying chunks found: " + outlyingChunks.size()); } } } }