package net.zomis.alberi;

import net.zomis.minesweeper.analyze.*;
import org.junit.Test;

import java.util.*;

import static org.junit.Assert.assertEquals;

public class AlberiTest {

    @Test
    public void simpleMap() {
        String map =
                "1112\n" +
                "1322\n" +
                "3342\n" +
                "3444";
        AnalyzeFactory<String> analyze = alberi(map, 1);
        for (RuleConstraint<String> rule : analyze.getRules()) {
            System.out.println(rule);
        }
        AnalyzeResult<String> result = analyze.solve();
        System.out.println(result.getSolutions());

        assertSolution(result, "10", "02", "23", "31");
    }

    public static <T> void assertSolution(AnalyzeResult<T> result, T... trueFields) {
        Set<FieldGroup<T>> allGroups = new HashSet<FieldGroup<T>>(result.getGroups());
        Set<FieldGroup<T>> trueGroups = new HashSet<FieldGroup<T>>();
        for (T field : trueFields) {
            FieldGroup<T> group = result.getGroupFor(field);
            assertEquals("Unexpected probability for " + group, 1.0, group.getProbability(), 0.0001);
            trueGroups.add(group);
        }

        Set<FieldGroup<T>> falseGroups = new HashSet<FieldGroup<T>>(allGroups);
        falseGroups.removeAll(trueGroups);
        for (FieldGroup<T> group : falseGroups) {
            assertEquals("Unexpected probability for " + group, 0.0, group.getProbability(), 0.0001);
            trueGroups.add(group);
        }
    }

    @Test
    public void someMap() {
        String map =
                "1122233\n" +
                "1222223\n" +
                "4255667\n" +
                "4455667\n" +
                "4445557\n" +
                "4455577\n" +
                "4455577";
        AnalyzeFactory<String> analyze = alberi(map, 1);
        AnalyzeResult<String> result = analyze.solve();
        System.out.println(result.getSolutions());

        assertSolution(result, "12", "00", "61", "24", "36", "43", "55");
    }

    public AnalyzeFactory<String> alberi(String map, int count) {
        AnalyzeFactory<String> factory = new AnalyzeFactory<String>();
        String[] lines = map.split("\\n");
        Map<Character, List<String>> groups = new HashMap<Character, List<String>>();
        for (int y = 0; y < lines.length; y++) {
            String line = lines[y];
            if (line.length() != lines.length) {
                throw new IllegalArgumentException("Map format incorrect: " + map + " expected " +
                        lines.length + " columns in row " + y + " but was " + line.length());
            }
            List<String> row = new ArrayList<String>();
            for (int x = 0; x < line.length(); x++) {
                char ch = line.charAt(x);
                addToGroup(groups, ch, x, y);
                row.add(str(x, y));
            }
            factory.addRule(new FieldRule<String>(String.valueOf("row " + y), row, count));
        }

        for (int x = 0; x < lines.length; x++) {
            List<String> col = new ArrayList<String>();
            for (int y = 0; y < lines.length; y++) {
                col.add(str(x, y));
            }
            factory.addRule(new FieldRule<String>(String.valueOf("col " + x), col, count));
        }

        for (Map.Entry<Character, List<String>> ee : groups.entrySet()) {
            factory.addRule(new FieldRule<String>(String.valueOf(ee.getKey()), ee.getValue(), count));
        }

        factory.setListener(new AlberiListener());

        return factory;
    }

    public static String str(int x, int y) {
        int radix = Character.MAX_RADIX;
        return Integer.toString(x, radix) + Integer.toString(y, radix);
    }

    private void addToGroup(Map<Character, List<String>> groups, char ch, int x, int y) {
        List<String> list = groups.get(ch);
        if (list == null) {
            list = new ArrayList<String>();
            groups.put(ch, list);
        }

        list.add(str(x, y));
    }

}

@@ -677,32 +677,789 @@
 , %2231%22);%0A    %7D%0A%0A
+    @Test%0A    public void doubleTrees() %7B%0A        String map =%0A                %2212223333%5Cn%22 +%0A                %2211214343%5Cn%22 +%0A                %2251114444%5Cn%22 +%0A                %2255554444%5Cn%22 +%0A                %2255554444%5Cn%22 +%0A                %2256657777%5Cn%22 +%0A                %2266667877%5Cn%22 +%0A                %2288888888%22;%0A        AnalyzeFactory%3CString%3E analyze = alberi(map, 2);%0A        AnalyzeResult%3CString%3E result = analyze.solve();%0A%0A        for (FieldGroup%3CString%3E group : result.getGroups()) %7B%0A            if (group.getProbability() %3E 0) %7B%0A                System.out.println(group);%0A            %7D%0A        %7D%0A%0A        assertSolution(result, %2245%22, %2247%22, %2204%22, %2206%22, %2251%22, %2253%22,%0A            %2210%22, %2212%22, %2265%22, %2267%22, %2224%22, %2226%22,%0A            %2271%22, %2273%22, %2230%22, %2232%22);%0A    %7D%0A%0A
     public stati

Add test for Alberi double trees