package com.amadornes.framez.modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import com.amadornes.framez.api.modifier.IFrameModifier; import com.amadornes.framez.api.modifier.IFrameModifierRegistry; import com.amadornes.framez.api.modifier.IFrameSideModifier; import com.amadornes.framez.api.movement.IFrame; import com.amadornes.framez.util.SorterElementCount; import com.amadornes.framez.util.SorterModifierType; public class FrameModifierRegistry implements IFrameModifierRegistry { private static final FrameModifierRegistry instance = new FrameModifierRegistry(); public static FrameModifierRegistry instance() { return instance; } private List<IFrameModifier> registered = new ArrayList<IFrameModifier>(); private Map<Class<? extends IFrame>, List<List<IFrameModifier>>> combinations = new HashMap<Class<? extends IFrame>, List<List<IFrameModifier>>>(); @Override public void registerModifier(IFrameModifier modifier) { if (modifier == null) throw new RuntimeException("Attempted to register a null frame modifier"); if (modifier.getType() == null) throw new RuntimeException("Attempted to register a frame modifier with a null identifier"); if (findModifier(modifier.getType()) != null) throw new RuntimeException("Attempted to register a frame modifier that has already been registered"); registered.add(modifier); } @Override public Collection<IFrameModifier> getRegisteredModifiers() { return registered; } @Override public IFrameModifier findModifier(String type) { for (IFrameModifier m : registered) if (m.getType().equals(type)) return m; return null; } public Collection<List<IFrameModifier>> getAllCombinations(Class<? extends IFrame> frameClazz) { if (combinations.containsKey(frameClazz)) return combinations.get(frameClazz); List<List<IFrameModifier>> combinations = new ArrayList<List<IFrameModifier>>(); for (IFrameModifier p : registered) { if (p instanceof IFrameSideModifier) continue; List<List<IFrameModifier>> pos = new ArrayList<List<IFrameModifier>>(); pos.add(Arrays.asList(new IFrameModifier[] { p })); addModifiers(pos, Arrays.asList(new IFrameModifier[] { p })); for (List<IFrameModifier> l : pos) { boolean found = false; for (List<IFrameModifier> l2 : combinations) { Collections.sort(l, new SorterModifierType()); Collections.sort(l2, new SorterModifierType()); found = l.equals(l2); if (found) break; } if (!found) combinations.add(l); } } removeDuplicates(combinations); Collections.sort(combinations, new SorterElementCount()); this.combinations.put(frameClazz, combinations); return combinations; } private void addModifiers(List<List<IFrameModifier>> possibilities, List<IFrameModifier> current) { for (IFrameModifier p : registered) { if (current.contains(p)) continue; if (!areCompatible(current, p)) continue; if (p instanceof IFrameSideModifier) continue; List<IFrameModifier> l = new ArrayList<IFrameModifier>(); l.addAll(current); l.add(p); possibilities.add(l); addModifiers(possibilities, l); } } private boolean areCompatible(List<IFrameModifier> mods, IFrameModifier m) { for (IFrameModifier mod : mods) if (!mod.isCompatibleWith(m) || !m.isCompatibleWith(mod)) return false; return true; } private void removeDuplicates(List<List<IFrameModifier>> possibilities) { List<List<IFrameModifier>> removed = new ArrayList<List<IFrameModifier>>(); for (List<IFrameModifier> l1 : possibilities) { if (removed.contains(l1)) continue; for (List<IFrameModifier> l2 : possibilities) { if (removed.contains(l2)) continue; if (l1 == l2) continue; if (l1.size() != l2.size()) continue; Collections.sort(l1, new SorterModifierType()); Collections.sort(l2, new SorterModifierType()); boolean error = false; for (int i = 0; i < l1.size(); i++) { if (l1 != l2) { error = true; break; } } if (!error) removed.add(l2); } } possibilities.removeAll(removed); } }