diff --git a/megamek/src/megamek/client/generator/RandomCallsignGenerator.java b/megamek/src/megamek/client/generator/RandomCallsignGenerator.java index 4a7087aa7a4..9b9f86e9b02 100644 --- a/megamek/src/megamek/client/generator/RandomCallsignGenerator.java +++ b/megamek/src/megamek/client/generator/RandomCallsignGenerator.java @@ -18,105 +18,56 @@ */ package megamek.client.generator; +import megamek.MMConstants; +import megamek.common.util.weightedMaps.WeightedIntMap; +import megamek.logging.MMLogger; + import java.io.File; import java.io.FileInputStream; import java.io.InputStream; -import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.Scanner; -import megamek.MMConstants; -import megamek.common.util.weightedMaps.WeightedIntMap; -import megamek.logging.MMLogger; - /** * Save File Formatting: * callsign, weight * Callsign is a String that does not include a ',' * Weight is an integer weight that is used during generation */ -public class RandomCallsignGenerator implements Serializable { +public class RandomCallsignGenerator { + private final static RandomCallsignGenerator INSTANCE = new RandomCallsignGenerator(); private final static MMLogger logger = MMLogger.create(RandomCallsignGenerator.class); - // region Variable Declarations - private static final long serialVersionUID = 4721410214327210288L; - - private static WeightedIntMap weightedCallsigns; - - private static RandomCallsignGenerator rcg; + private final WeightedIntMap weightedCallsigns = new WeightedIntMap<>(); - private static volatile boolean initialized = false; // volatile to ensure readers get the current version - // endregion Variable Declarations + RandomCallsignGenerator() { + final Map callsigns = new HashMap<>(); + loadCallsignsFromFile(new File(MMConstants.CALLSIGN_FILE_PATH), callsigns); + loadCallsignsFromFile(new File(MMConstants.USER_CALLSIGN_FILE_PATH), callsigns); - // region Constructors - protected RandomCallsignGenerator() { + for (final Map.Entry entry : callsigns.entrySet()) { + getWeightedCallsigns().add(entry.getValue(), entry.getKey()); + } + } + public static RandomCallsignGenerator getInstance() { + return INSTANCE; } - // endregion Constructors // region Getters/Setters - public static WeightedIntMap getWeightedCallsigns() { + public WeightedIntMap getWeightedCallsigns() { return weightedCallsigns; } - public static void setWeightedCallsigns(final WeightedIntMap weightedCallsigns) { - RandomCallsignGenerator.weightedCallsigns = weightedCallsigns; - } - // endregion Getters/Setters - - // region Synchronization - /** - * @return the instance of the RandomCallsignGenerator to use - */ - public static synchronized RandomCallsignGenerator getInstance() { - // only this code reads and writes 'rcg' - if (rcg == null) { - // synchronized ensures this will only be entered exactly once - rcg = new RandomCallsignGenerator(); - rcg.runThreadLoader(); - } - // when getInstance returns, rcg will always be non-null - return rcg; - } - // endregion Synchronization - // region Generation public String generate() { - String callsign = ""; - - if (initialized) { - callsign = getWeightedCallsigns().randomItem(); - } else { - logger.warn("Attempted to generate a callsign before the list was initialized."); - } - - return callsign; + return getWeightedCallsigns().randomItem(); } // endregion Generation - // region Initialization - private void runThreadLoader() { - Thread loader = new Thread(() -> rcg.populateCallsigns(), "Random Callsign Generator initializer"); - loader.setPriority(Thread.NORM_PRIORITY - 1); - loader.start(); - } - - private void populateCallsigns() { - setWeightedCallsigns(new WeightedIntMap<>()); - final Map callsigns = new HashMap<>(); - loadCallsignsFromFile(new File(MMConstants.CALLSIGN_FILE_PATH), callsigns); - loadCallsignsFromFile(new File(MMConstants.USER_CALLSIGN_FILE_PATH), callsigns); - - for (final Map.Entry entry : callsigns.entrySet()) { - getWeightedCallsigns().add(entry.getValue(), entry.getKey()); - } - - initialized = true; - } - - private void loadCallsignsFromFile(final File file, final Map callsigns) { + private void loadCallsignsFromFile(File file, Map callsigns) { if (!file.exists()) { return; } @@ -124,20 +75,26 @@ private void loadCallsignsFromFile(final File file, final Map c int lineNumber = 0; try (InputStream is = new FileInputStream(file); - Scanner input = new Scanner(is, StandardCharsets.UTF_8.name())) { + Scanner input = new Scanner(is, StandardCharsets.UTF_8)) { // skip the first line, as that's the header lineNumber++; input.nextLine(); while (input.hasNextLine()) { lineNumber++; - String[] values = input.nextLine().split(","); - if (values.length == 2) { - callsigns.put(values[0], Integer.parseInt(values[1])); - } else if (values.length < 2) { - logger.error("Not enough fields in " + file + " on " + lineNumber); - } else { - logger.error("Too many fields in " + file + " on " + lineNumber); + String line = input.nextLine(); + int lastCommaIndex = line.lastIndexOf(","); + if (lastCommaIndex == -1 || line.length() == lastCommaIndex + 1) { + logger.debug("Not enough fields in {} on {}",file, lineNumber); + continue; + } + + String[] values = {line.substring(0, lastCommaIndex), line.substring(lastCommaIndex + 1)}; + + try { + callsigns.put(values[0], Integer.parseInt(values[1].trim())); + } catch (NumberFormatException e) { + logger.warn("Invalid weight in {} on {}", file, lineNumber); } } } catch (Exception e) {