summaryrefslogtreecommitdiff
path: root/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsResult.java
blob: 12726c0b6976242d42583947fe244399a0f43a50 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package cuchaz.enigma.gui.stats;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.GsonBuilder;

public final class StatsResult {
	private final int total;
	private final int unmapped;
	private final Tree<Integer> tree;

	public StatsResult(int total, int unmapped, Tree<Integer> tree) {
		this.total = total;
		this.unmapped = unmapped;
		this.tree = tree;
	}

	public int getTotal() {
		return total;
	}

	public int getUnmapped() {
		return unmapped;
	}

	public int getMapped() {
		return total - unmapped;
	}

	public double getPercentage() {
		return (getMapped() * 100.0f) / total;
	}

	public String getTreeJson() {
		return new GsonBuilder().setPrettyPrinting().create().toJson(tree.root);
	}

	@Override
	public String toString() {
		return String.format("%s/%s %.1f%%", getMapped(), total, getPercentage());
	}

	public static class Tree<T> {
		public final Node<T> root;
		private final Map<String, Node<T>> nodes = new HashMap<>();

		public static class Node<T> {
			public String name;
			public T value;
			public List<Node<T>> children = new ArrayList<>();
			private final transient Map<String, Node<T>> namedChildren = new HashMap<>();

			public Node(String name, T value) {
				this.name = name;
				this.value = value;
			}
		}

		public Tree() {
			root = new Node<>("", null);
		}

		public Node<T> getNode(String name) {
			Node<T> node = nodes.get(name);

			if (node == null) {
				node = root;

				for (String part : name.split("\\.")) {
					Node<T> child = node.namedChildren.get(part);

					if (child == null) {
						child = new Node<>(part, null);
						node.namedChildren.put(part, child);
						node.children.add(child);
					}

					node = child;
				}

				nodes.put(name, node);
			}

			return node;
		}

		public void collapse(Node<T> node) {
			while (node.children.size() == 1) {
				Node<T> child = node.children.get(0);
				node.name = node.name.isEmpty() ? child.name : node.name + "." + child.name;
				node.children = child.children;
				node.value = child.value;
			}

			for (Node<T> child : node.children) {
				collapse(child);
			}
		}
	}
}