فهرست منبع

Switch to using a Tree-based implementation. Simple objects like Initiative don't need indirection, but something like a spell could now have multiple discrete aspects of its effect modified, while also modifying, say, the range.

Sam Jaffe 8 سال پیش
والد
کامیت
5572792970

+ 2 - 2
src/main/lombok/org/leumasjaffe/charsheet/model/features/DDProperty.java

@@ -1,6 +1,6 @@
 package org.leumasjaffe.charsheet.model.features;
 
-import java.util.Map;
+import org.leumasjaffe.collections.Tree;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
@@ -11,5 +11,5 @@ public interface DDProperty {
 		NONE
 	}
 	boolean appliesTo(final Object key);
-	void accumulate(final Map<String, Object> props, final Object... data);
+	void accumulate(final Tree<String, GroupedBonus> props, final Object... data);
 }

+ 58 - 0
src/main/lombok/org/leumasjaffe/charsheet/model/features/GroupedBonus.java

@@ -0,0 +1,58 @@
+package org.leumasjaffe.charsheet.model.features;
+
+import java.util.EnumMap;
+
+import org.leumasjaffe.charsheet.model.features.DDProperty.Group;
+
+public class GroupedBonus extends Number {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 6846423355848966647L;
+	EnumMap<Group, Number> data = new EnumMap<>(Group.class);
+	
+	public void accumulate(Group grp, Integer i) {
+		data.putIfAbsent(grp, 0);
+		data.compute(grp, (g, n) -> g == Group.NONE ? n.intValue() + i : 
+			Math.max(n.intValue(), i));
+	}
+	
+	public void accumulate(Group grp, Long i) {
+		data.putIfAbsent(grp, 0);
+		data.compute(grp, (g, n) -> g == Group.NONE ? n.longValue() + i : 
+			Math.max(n.longValue(), i));
+	}
+	
+	public void accumulate(Group grp, Float i) {
+		data.putIfAbsent(grp, 0);
+		data.compute(grp, (g, n) -> g == Group.NONE ? n.floatValue() + i : 
+			Math.max(n.floatValue(), i));
+	}
+	
+	public void accumulate(Group grp, Double i) {
+		data.putIfAbsent(grp, 0);
+		data.compute(grp, (g, n) -> g == Group.NONE ? n.doubleValue() + i : 
+			Math.max(n.doubleValue(), i));
+	}
+	
+	@Override
+	public int intValue() {
+		return data.values().stream().mapToInt(Number::intValue).sum();
+	}
+
+	@Override
+	public long longValue() {
+		return data.values().stream().mapToLong(Number::longValue).sum();
+	}
+
+	@Override
+	public float floatValue() {
+		return (float) data.values().stream().mapToDouble(Number::floatValue).sum();
+	}
+
+	@Override
+	public double doubleValue() {
+		return data.values().stream().mapToDouble(Number::doubleValue).sum();
+	}
+
+}

+ 5 - 5
src/main/lombok/org/leumasjaffe/charsheet/model/features/impl/Flat.java

@@ -1,9 +1,9 @@
 package org.leumasjaffe.charsheet.model.features.impl;
 
-import java.util.Map;
-
 import org.leumasjaffe.charsheet.model.features.DDFeaturePredicate;
 import org.leumasjaffe.charsheet.model.features.DDProperty;
+import org.leumasjaffe.charsheet.model.features.GroupedBonus;
+import org.leumasjaffe.collections.Tree;
 
 import lombok.AllArgsConstructor;
 
@@ -19,8 +19,8 @@ public class Flat implements DDProperty {
 	}
 
 	@Override
-	public void accumulate(Map<String, Object> props, Object... data) {
-		// TODO: use groups
-		props.compute("value", (k, old) -> old == null ? value : value + (Integer) old);
+	public void accumulate(Tree<String, GroupedBonus> props, Object... data) {
+		props.putIfAbsent(new GroupedBonus());
+		props.get().accumulate(group, value);
 	}
 }

+ 15 - 10
src/main/lombok/org/leumasjaffe/charsheet/model/features/impl/PerSpellLevel.java

@@ -1,12 +1,11 @@
 package org.leumasjaffe.charsheet.model.features.impl;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.leumasjaffe.charsheet.model.DDCharacterClass;
 import org.leumasjaffe.charsheet.model.features.DDFeaturePredicate;
 import org.leumasjaffe.charsheet.model.features.DDProperty;
+import org.leumasjaffe.charsheet.model.features.GroupedBonus;
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
+import org.leumasjaffe.collections.Tree;
 
 import lombok.AllArgsConstructor;
 
@@ -22,12 +21,18 @@ public class PerSpellLevel implements DDProperty {
 		return applies.accepts(key);
 	}
 
-	@Override @SuppressWarnings("unchecked")
-	public void accumulate(Map<String, Object> props, Object... data) {
-		final int level = DDSpell.class.cast(data[1]).getClassLevel(DDCharacterClass.class.cast(data[0]).getName());
-		// TODO: use groups
-		// TODO: allow multiple things
-		props.putIfAbsent("effect", new HashMap<>());
-		((Map<String, Object>) props.get("effect")).put("value", value * level);
+	@Override
+	public void accumulate(Tree<String, GroupedBonus> props, Object... data) {
+		final DDCharacterClass chara = DDCharacterClass.class.cast(data[0]);
+		final DDSpell spell = DDSpell.class.cast(data[1]);
+		accumulateImpl(props, chara, spell);
+	}
+	
+	private void accumulateImpl(Tree<String, GroupedBonus> props, 
+			DDCharacterClass chara, DDSpell spell) {
+		final int level = spell.getClassLevel(chara.getName());
+		// TODO: allow multiple things?
+		props.get("effect").putIfAbsent(new GroupedBonus());
+		props.get("effect").get().accumulate(group, value * level);
 	}
 }

+ 3 - 3
src/main/lombok/org/leumasjaffe/charsheet/model/features/impl/Simple.java

@@ -1,8 +1,8 @@
 package org.leumasjaffe.charsheet.model.features.impl;
 
-import java.util.Map;
-
 import org.leumasjaffe.charsheet.model.features.DDProperty;
+import org.leumasjaffe.charsheet.model.features.GroupedBonus;
+import org.leumasjaffe.collections.Tree;
 
 import lombok.AllArgsConstructor;
 
@@ -10,5 +10,5 @@ import lombok.AllArgsConstructor;
 public class Simple implements DDProperty {
 	String name;
 	@Override public boolean appliesTo(Object key) { return false; }
-	@Override public void accumulate(Map<String, Object> props, Object... data) {}
+	@Override public void accumulate(Tree<String, GroupedBonus> props, Object... data) {}
 }

+ 2 - 4
src/main/lombok/org/leumasjaffe/charsheet/model/magic/dimension/Effect.java

@@ -1,7 +1,5 @@
 package org.leumasjaffe.charsheet.model.magic.dimension;
 
-import java.util.Map;
-
 import org.leumasjaffe.format.Named;
 import org.leumasjaffe.format.StringHelper;
 
@@ -21,8 +19,8 @@ public class Effect {
 	int count, per, beyond;
 	@NonFinal @Setter(AccessLevel.PRIVATE) @Getter(AccessLevel.PRIVATE) int step = 1, upto = Integer.MAX_VALUE;
 	
-	public String getResolved(int level, Map<String, Integer> map) {
-		final int result = map.getOrDefault("value", 0) + count + per * ((Math.min(level, upto)-beyond) / step);
+	public String getResolved(int level, Number val) {
+		final int result = val.intValue() + count + per * ((Math.min(level, upto)-beyond) / step);
 		return resolved == null ? toString() :
 			StringHelper.format(resolved, new Named("atlevel", result));
 	}

+ 5 - 7
src/main/lombok/org/leumasjaffe/charsheet/view/magic/SpellInfoPanel.java

@@ -4,9 +4,6 @@ import javax.swing.JPanel;
 import java.awt.GridBagLayout;
 import java.awt.GridBagConstraints;
 import java.awt.Insets;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
@@ -15,10 +12,12 @@ import javax.swing.JTextArea;
 
 import org.leumasjaffe.charsheet.model.DDCharacter;
 import org.leumasjaffe.charsheet.model.DDCharacterClass;
+import org.leumasjaffe.charsheet.model.features.GroupedBonus;
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
 import org.leumasjaffe.charsheet.model.magic.DDSpell.Component;
 import org.leumasjaffe.charsheet.model.magic.Source;
 import org.leumasjaffe.charsheet.model.observable.IntValue;
+import org.leumasjaffe.collections.Tree;
 
 import javax.swing.JScrollPane;
 import javax.swing.JLabel;
@@ -38,7 +37,7 @@ class SpellInfoPanel extends JPanel {
 
 	public SpellInfoPanel(DDCharacter chara, DDCharacterClass dclass, final DDSpell spell) {
 		final IntValue classLevel = dclass.getLevel();
-		Map<String, Object> props = new HashMap<>();
+		Tree<String, GroupedBonus> props = new Tree<>();
 		chara.getFeatureBonuses(spell).forEach(p -> p.accumulate(props, dclass, spell));
 		
 		GridBagLayout gridBagLayout = new GridBagLayout();
@@ -344,9 +343,8 @@ class SpellInfoPanel extends JPanel {
 		description.setLineWrap(true);
 	}
 
-	@SuppressWarnings("unchecked")
-	private Map<String, Integer> getSpellBonus(String key, Map<String, Object> props) {
-		return (Map<String, Integer>) props.getOrDefault(key, Collections.emptyMap());
+	private Number getSpellBonus(String key, Tree<String, GroupedBonus> props) {
+		return props.get(key).getOrDefault(new GroupedBonus());
 	}
 
 	private <T> String asString(Optional<T> obj, Function<? super T, String> ts) {

+ 4 - 4
src/main/lombok/org/leumasjaffe/charsheet/view/summary/InitiativeLine.java

@@ -11,7 +11,9 @@ import javax.swing.border.LineBorder;
 import org.leumasjaffe.charsheet.config.Constants;
 import org.leumasjaffe.charsheet.model.Ability;
 import org.leumasjaffe.charsheet.model.DDCharacter;
+import org.leumasjaffe.charsheet.model.features.GroupedBonus;
 import org.leumasjaffe.charsheet.observer.helper.AbilModStringify;
+import org.leumasjaffe.collections.Tree;
 import org.leumasjaffe.format.StringHelper;
 import org.leumasjaffe.observer.IndirectObservableListener;
 import org.leumasjaffe.observer.ObservableListener;
@@ -25,8 +27,6 @@ import javax.swing.SwingConstants;
 import java.awt.Dimension;
 import javax.swing.JTextField;
 import java.awt.Insets;
-import java.util.HashMap;
-import java.util.Map;
 
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class InitiativeLine extends JPanel {
@@ -143,9 +143,9 @@ public class InitiativeLine extends JPanel {
 	}
 
 	private int getInitiativeBonuses(DDCharacter v) {
-		Map<String, Object> props = new HashMap<>();
+		Tree<String, GroupedBonus> props = new Tree<>();
 		v.getFeatureBonuses(Constants.INITIATIVE).stream().forEach(f -> f.accumulate(props));
-		return props.values().stream().mapToInt(o -> (Integer) o).sum();
+		return props.getOrDefault(new GroupedBonus()).intValue();
 	}
 
 	public void setModel(DDCharacter model) {

+ 32 - 0
src/main/lombok/org/leumasjaffe/collections/Tree.java

@@ -0,0 +1,32 @@
+package org.leumasjaffe.collections;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Tree<K, V> {
+	V value = null;
+	Map<K, Tree<K, V>> leaves = new HashMap<>();
+	
+	public V get() {
+		return value;
+	}
+	
+	public V getOrDefault(V def) {
+		return get() == null ? def : get();
+	}
+
+	public V put(V newVal) {
+		V tmp = get();
+		value = newVal;
+		return tmp;
+	}
+	
+	public V putIfAbsent(V newVal) {
+		return get() == null ? put(newVal) : get();
+	}
+	
+	public Tree<K, V> get(K key) {
+		leaves.putIfAbsent(key, new Tree<>());
+		return leaves.get(key);
+	}
+}