/* * Copyright (C) 2016 MegaMek team * * This file is part of MekHQ. * * MekHQ is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MekHQ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MekHQ. If not, see <http://www.gnu.org/licenses/>. */ package mekhq.campaign.personnel; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; /** * A modifier is some kind of (usually temporary) effect that influences the character's base values. * <p> * Modifiers have three values: Which value they apply to, how much they change the value by (can * be positive or negative) and optionally what type of modifier they are. If a person has * multiple modifiers of the same type, only the highest positive one and the lowest negative * one applies. All modifiers without a type apply fully. * <p> * In addition, modifiers can have a set of string tags, used for filtering and searching in them. */ public class Modifier { public final Value value; public final int mod; public final String type; public final Set<String> tags; public static int calcTotalModifier(Collection<Modifier> mods, Value val) { return calcTotalModifier(mods.stream(), val); } public static int calcTotalModifier(Stream<Modifier> mods, Value val) { final Map<String, Integer> posMods = new HashMap<>(); final Map<String, Integer> negMods = new HashMap<>(); final Collection<Integer> untypedMods = new ArrayList<>(); long result = 0; mods.filter(mod -> (mod.value == val)).forEach(mod -> { if(null != mod.type) { int posMod = Math.max(0, mod.mod); int negMod = Math.min(0, mod.mod); if(posMods.containsKey(mod.type)) { posMods.put(mod.type, Math.max(posMod, posMods.get(mod.type))); negMods.put(mod.type, Math.min(negMod, posMods.get(mod.type))); } else { posMods.put(mod.type, posMod); negMods.put(mod.type, negMod); } } else { untypedMods.add(mod.mod); } }); for(String type : posMods.keySet()) { result += posMods.get(type); result += negMods.get(type); } for(Integer mod : untypedMods) { result += mod.intValue(); } if(result > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } if(result < Integer.MIN_VALUE) { return Integer.MIN_VALUE; } return (int) result; } public Modifier(Value value, int mod) { this(value, mod, null); } public Modifier(Value value, int mod, String type, String ... tags) { this.value = Objects.requireNonNull(value); this.mod = mod; this.type = type; this.tags = (null != tags) ? Arrays.stream(tags).collect(Collectors.toSet()) : new HashSet<>(); } public static enum Value { PILOTING, GUNNERY } }