Java tutorial
/* * This program 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 3 of the License, or * (at your option) any later version. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ /** * SupernovaCSV.java * Copyright (C) 2017 University of Waikato, Hamilton, New Zealand */ package nz.ac.waikato.cms.supernova; import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.ArgumentParser; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.internal.HelpScreenException; import nz.ac.waikato.cms.supernova.core.Registry; import nz.ac.waikato.cms.supernova.gui.ColorHelper; import nz.ac.waikato.cms.supernova.io.AbstractOutputGenerator; import nz.ac.waikato.cms.supernova.io.AbstractOutputGeneratorWithDimensions; import nz.ac.waikato.cms.supernova.io.PNG; import nz.ac.waikato.cms.supernova.triangle.AbstractTriangleCenterCalculation; import nz.ac.waikato.cms.supernova.triangle.Incenter; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import java.awt.Color; import java.io.File; import java.io.FileReader; import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Generates output for "I am supernova". * * @author fracpete (fracpete at waikato dot ac dot nz) */ public class SupernovaCSV { public static final String BACKGROUND = "background"; public static final String OPACITY = "opacity"; public static final String WIDTH = "width"; public static final String HEIGHT = "height"; public static final String OUTPUT = "output"; public static final String CSV = "csv"; public static final String ID = "id"; public static final String MEASURE = "measure"; public static final String SCORE = "score"; public static final String PERCENTILE = "percentile"; public static final String COLOR_SUFFIX = "_color"; public static final String VERBOSE = "verbose"; public static final String CENTER = "center"; public static final String GENERATOR = "generator"; public static final String MARGIN = "margin"; public static final String MEASURE_LIST = AbstractOutputGenerator.OPENNESS + "," + AbstractOutputGenerator.EXTRAVERSION + "," + AbstractOutputGenerator.AGREEABLENESS + "," + AbstractOutputGenerator.CONSCIENTIOUSNESS + "," + AbstractOutputGenerator.NEUROTICISM; public static void main(String[] args) throws Exception { ArgumentParser parser; parser = ArgumentParsers.newArgumentParser("I am supernova"); parser.description("Generates output according to 'I am supernova' by Keith Soo.\n" + "Loads scores/percentiles from a CSV file to generate multiple outputs at once.\n" + "Expected four columns (name of column is irrelevant):\n" + "- ID: the filename (excluding path and extension)\n" + "- Measure: the measure (" + MEASURE_LIST + ")\n" + "- Score: the score of the measure\n" + "- Percentile: the percentile of the measure\n" + "\n" + "Project homepage:\n" + "https://github.com/fracpete/i-am-supernova"); // colors parser.addArgument("--" + AbstractOutputGenerator.OPENNESS + COLOR_SUFFIX) .metavar(AbstractOutputGenerator.OPENNESS + COLOR_SUFFIX).type(String.class) .setDefault(ColorHelper.toHex(Color.ORANGE)) .help("The color for '" + AbstractOutputGenerator.OPENNESS + "' in hex format (e.g., " + ColorHelper.toHex(Color.ORANGE) + ")."); parser.addArgument("--" + AbstractOutputGenerator.EXTRAVERSION + COLOR_SUFFIX) .metavar(AbstractOutputGenerator.EXTRAVERSION + COLOR_SUFFIX).type(String.class) .setDefault(ColorHelper.toHex(Color.YELLOW)) .help("The color for '" + AbstractOutputGenerator.EXTRAVERSION + "' in hex format (e.g., " + ColorHelper.toHex(Color.YELLOW) + ")."); parser.addArgument("--" + AbstractOutputGenerator.AGREEABLENESS + COLOR_SUFFIX) .metavar(AbstractOutputGenerator.AGREEABLENESS + COLOR_SUFFIX).type(String.class) .setDefault(ColorHelper.toHex(Color.GREEN)) .help("The color for '" + AbstractOutputGenerator.AGREEABLENESS + "' in hex format (e.g., " + ColorHelper.toHex(Color.GREEN) + ")."); parser.addArgument("--" + AbstractOutputGenerator.CONSCIENTIOUSNESS + COLOR_SUFFIX) .metavar(AbstractOutputGenerator.CONSCIENTIOUSNESS + COLOR_SUFFIX).type(String.class) .setDefault(ColorHelper.toHex(Color.BLUE)) .help("The color for '" + AbstractOutputGenerator.CONSCIENTIOUSNESS + "' in hex format (e.g., " + ColorHelper.toHex(Color.BLUE) + ")."); parser.addArgument("--" + AbstractOutputGenerator.NEUROTICISM + COLOR_SUFFIX) .metavar(AbstractOutputGenerator.NEUROTICISM + COLOR_SUFFIX).type(String.class) .setDefault(ColorHelper.toHex(Color.RED)) .help("The color for '" + AbstractOutputGenerator.NEUROTICISM + "' in hex format (e.g., " + ColorHelper.toHex(Color.RED) + ")."); // other parameters parser.addArgument("--" + CSV).metavar(CSV).type(String.class).required(true) .help("The CSV file containing the scores/percentiles (header must be present)."); parser.addArgument("--" + ID).metavar(ID).type(Integer.class).setDefault(1) .help("The 1-based index of the column in the CSV file containing the ID for the output file."); parser.addArgument("--" + MEASURE).metavar(MEASURE).type(Integer.class).setDefault(2) .help("The 1-based index of the column in the CSV file containing the measure name.\n" + "Allowed values: " + MEASURE_LIST); parser.addArgument("--" + SCORE).metavar(SCORE).type(Integer.class).setDefault(3) .help("The 1-based index of the column in the CSV file containing the scores."); parser.addArgument("--" + PERCENTILE).metavar(PERCENTILE).type(Integer.class).setDefault(4) .help("The 1-based index of the column in the CSV file containing the percentiles."); parser.addArgument("--" + BACKGROUND).metavar(BACKGROUND).type(String.class) .setDefault(ColorHelper.toHex(Color.BLACK)).help("The background color."); parser.addArgument("--" + OPACITY).metavar(OPACITY).type(Double.class).setDefault(0.1) .help("The opacity (0-1)."); parser.addArgument("--" + MARGIN).metavar(MARGIN).type(Double.class).setDefault(0.2) .help("The margin in the output (0-1)."); parser.addArgument("--" + WIDTH).metavar(WIDTH).type(Integer.class).setDefault(2000) .help("The width of the output."); parser.addArgument("--" + HEIGHT).metavar(HEIGHT).type(Integer.class).setDefault(2000) .help("The height of the output."); parser.addArgument("--" + CENTER).metavar(CENTER).type(String.class).setDefault(Incenter.class.getName()) .help("The name of the algorithm for calculating the center of a triangle.\n" + "Available: " + Registry.toString(Registry.getCenters(), true)); parser.addArgument("--" + GENERATOR).metavar(GENERATOR).type(String.class).setDefault(PNG.class.getName()) .help("The name of the generator class to use.\n" + "Available: " + Registry.toString(Registry.getGenerators(), true)); parser.addArgument("--" + OUTPUT).metavar(OUTPUT).type(String.class) .help("The directory to store the output in."); parser.addArgument("--" + VERBOSE).metavar(VERBOSE).type(Boolean.class).action(Arguments.storeTrue()) .help("Whether to output logging information."); Namespace namespace; try { namespace = parser.parseArgs(args); } catch (Exception e) { if (!(e instanceof HelpScreenException)) parser.printHelp(); return; } // colors Map<String, Color> colors = new HashMap<>(); colors.put(AbstractOutputGenerator.OPENNESS, ColorHelper .valueOf(namespace.getString(AbstractOutputGenerator.OPENNESS + COLOR_SUFFIX), Color.ORANGE)); colors.put(AbstractOutputGenerator.EXTRAVERSION, ColorHelper .valueOf(namespace.getString(AbstractOutputGenerator.EXTRAVERSION + COLOR_SUFFIX), Color.YELLOW)); colors.put(AbstractOutputGenerator.AGREEABLENESS, ColorHelper .valueOf(namespace.getString(AbstractOutputGenerator.AGREEABLENESS + COLOR_SUFFIX), Color.GREEN)); colors.put(AbstractOutputGenerator.CONSCIENTIOUSNESS, ColorHelper.valueOf( namespace.getString(AbstractOutputGenerator.CONSCIENTIOUSNESS + COLOR_SUFFIX), Color.BLUE)); colors.put(AbstractOutputGenerator.NEUROTICISM, ColorHelper .valueOf(namespace.getString(AbstractOutputGenerator.NEUROTICISM + COLOR_SUFFIX), Color.RED)); File outdir = new File(namespace.getString(OUTPUT)); String centerCls = namespace.getString(CENTER); if (!centerCls.contains(".")) centerCls = AbstractTriangleCenterCalculation.class.getPackage().getName() + "." + centerCls; String generatorCls = namespace.getString(GENERATOR); if (!generatorCls.contains(".")) generatorCls = AbstractOutputGenerator.class.getPackage().getName() + "." + generatorCls; AbstractOutputGenerator generator = (AbstractOutputGenerator) Class.forName(generatorCls).newInstance(); generator.setVerbose(namespace.getBoolean(VERBOSE)); generator.setColors(colors); generator.setBackground(ColorHelper.valueOf(namespace.getString(BACKGROUND), Color.BLACK)); generator.setOpacity(namespace.getDouble(OPACITY)); generator.setMargin(namespace.getDouble(MARGIN)); generator.setCenter((AbstractTriangleCenterCalculation) Class.forName(centerCls).newInstance()); if (generator instanceof AbstractOutputGeneratorWithDimensions) { AbstractOutputGeneratorWithDimensions pixel = (AbstractOutputGeneratorWithDimensions) generator; pixel.setWidth(namespace.getInt(WIDTH)); pixel.setHeight(namespace.getInt(HEIGHT)); } int colID = namespace.getInt(ID) - 1; int colMeasure = namespace.getInt(MEASURE) - 1; int colScore = namespace.getInt(SCORE) - 1; int colPercentile = namespace.getInt(PERCENTILE) - 1; Reader reader = new FileReader(namespace.getString(CSV)); CSVParser csvparser = new CSVParser(reader, CSVFormat.EXCEL.withHeader()); String oldID = ""; Map<String, List<Double>> test = new HashMap<>(); for (CSVRecord rec : csvparser) { if (rec.size() < 4) continue; String id = rec.get(colID); if (!id.equals(oldID)) { if (!test.isEmpty()) { File outfile = new File(outdir + File.separator + oldID + "." + generator.getExtension()); String msg = generator.generate(test, outfile); if (msg != null) System.err.println("Failed to generate output for ID: " + oldID); } test.clear(); oldID = id; } String measure = rec.get(colMeasure); double score = Double.parseDouble(rec.get(colScore)); double percentile = Double.parseDouble(rec.get(colPercentile)); test.put(measure, new ArrayList<>(Arrays.asList(new Double[] { score, percentile }))); } if (!test.isEmpty()) { File outfile = new File(outdir + File.separator + oldID + "." + generator.getExtension()); String msg = generator.generate(test, outfile); if (msg != null) System.err.println("Failed to generate output for ID: " + oldID); } } }