kopia lustrzana https://github.com/neopoly/tagcloud
Refector and documentations
rodzic
4ac3f97e18
commit
0b53dd9baf
|
@ -3,7 +3,7 @@ inputFile=input.txt
|
|||
outputFile=out.png
|
||||
width=500
|
||||
height=636
|
||||
minSize=4
|
||||
minSize=8
|
||||
maxSize=38
|
||||
colors=#000000,#3a3a3a,#787878,#b2b2b2
|
||||
background=#ffffff
|
||||
|
|
|
@ -1,10 +1,26 @@
|
|||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Utility class to transform and parse colors.
|
||||
*/
|
||||
public class ColorHelper {
|
||||
public static int transform(Color c){
|
||||
/**
|
||||
* Transforms a java.awt.Color to processings internal int representation.
|
||||
*
|
||||
* @param c the color to be transformed
|
||||
* @return A processing color value
|
||||
*/
|
||||
public static int transform(Color c) {
|
||||
return (c.getAlpha() << 24) | (c.getRed() << 16) | (c.getGreen() << 8) | c.getBlue();
|
||||
}
|
||||
|
||||
public static int decode(String c){
|
||||
/**
|
||||
* Decodes a color string in HEX-Values
|
||||
*
|
||||
* @param c the color string to be transformed
|
||||
* @return A processing color value
|
||||
*/
|
||||
public static int decodeHex(String c) {
|
||||
return transform(Color.decode(c));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,70 @@
|
|||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Singleton holding the TagCloud configuration.
|
||||
*/
|
||||
public class Configuration {
|
||||
private static Configuration instance = null;
|
||||
|
||||
private Properties prop = new Properties();
|
||||
|
||||
private Configuration(){}
|
||||
private Configuration() {
|
||||
}
|
||||
|
||||
public String getShapeFile(){ return prop.getProperty("shapeFile"); }
|
||||
public String getInputFile(){ return prop.getProperty("inputFile"); }
|
||||
public String getOutputFile(){ return prop.getProperty("outputFile"); }
|
||||
public int getWidth() { return Integer.parseInt(prop.getProperty("width")); }
|
||||
public int getHeight(){ return Integer.parseInt(prop.getProperty("height")); }
|
||||
public int getMinSize(){ return Integer.parseInt(prop.getProperty("minSize")); }
|
||||
public int getMaxSize(){ return Integer.parseInt(prop.getProperty("maxSize")); }
|
||||
public String getColors(){ return prop.getProperty("colors"); }
|
||||
public String getBackgroundColor(){return prop.getProperty("background"); }
|
||||
public boolean isDebug(){
|
||||
public String getShapeFile() {
|
||||
return prop.getProperty("shapeFile");
|
||||
}
|
||||
|
||||
public String getInputFile() {
|
||||
return prop.getProperty("inputFile");
|
||||
}
|
||||
|
||||
public String getOutputFile() {
|
||||
return prop.getProperty("outputFile");
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return Integer.parseInt(prop.getProperty("width"));
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return Integer.parseInt(prop.getProperty("height"));
|
||||
}
|
||||
|
||||
public int getMinSize() {
|
||||
return Integer.parseInt(prop.getProperty("minSize"));
|
||||
}
|
||||
|
||||
public int getMaxSize() {
|
||||
return Integer.parseInt(prop.getProperty("maxSize"));
|
||||
}
|
||||
|
||||
public String getColors() {
|
||||
return prop.getProperty("colors");
|
||||
}
|
||||
|
||||
public String getBackgroundColor() {
|
||||
return prop.getProperty("background");
|
||||
}
|
||||
|
||||
public boolean isDebug() {
|
||||
return prop.getProperty("debug") != null && prop.getProperty("debug").equals("true");
|
||||
}
|
||||
|
||||
public void load(){
|
||||
try {
|
||||
prop.load(new FileInputStream("config.properties"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/**
|
||||
* Load configuration from an input stream
|
||||
*
|
||||
* @param inputStream to load from
|
||||
* @throws IOException
|
||||
*/
|
||||
public void load(InputStream inputStream) throws IOException {
|
||||
prop.load(inputStream);
|
||||
}
|
||||
|
||||
public static Configuration getInstance(){
|
||||
if(instance == null){
|
||||
public static Configuration getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Configuration();
|
||||
}
|
||||
return instance;
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import wordcram.Word;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class InputWords {
|
||||
private String file;
|
||||
|
||||
public InputWords(String file){
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public Word[] getWords(){
|
||||
ArrayList<Word> words = new ArrayList<Word>();
|
||||
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return new Word[0];
|
||||
}
|
||||
|
||||
String line = null;
|
||||
try {
|
||||
while((line = reader.readLine()) != null){
|
||||
String[] values = line.split(",");
|
||||
if(values.length == 2){
|
||||
words.add( new Word(values[0].trim(), Float.parseFloat(values[1].trim())));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new Word[0];
|
||||
}
|
||||
|
||||
return words.toArray(new Word[words.size()]);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,21 @@
|
|||
import processing.core.PApplet;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Simple application wrapper to run the TagCloudGenerator from command line.
|
||||
* Please provide a config.properties for configuration.
|
||||
*/
|
||||
public class TagCloud {
|
||||
|
||||
public static void main(String[] args){
|
||||
Configuration.getInstance().load();
|
||||
PApplet.main(new String[] { "--present", "Tree" });
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Configuration.getInstance().load(new FileInputStream("config.properties"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
PApplet.main(new String[]{"--present", "TagCloudGenerator"});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import wordcram.Word;
|
||||
import wordcram.WordColorer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Colors a tag cloud instance by using a random color per word, from a CSV list of
|
||||
* HEX string colors.
|
||||
*/
|
||||
public class TagCloudColorer implements WordColorer {
|
||||
|
||||
private ArrayList<Integer> colors = new ArrayList<Integer>();
|
||||
private Random randomGenerator = new Random();
|
||||
|
||||
public static final int FALLBACK_COLOR = ColorHelper.decodeHex("#000000");
|
||||
public static final String SEPARATOR = ",";
|
||||
|
||||
/**
|
||||
* Initializes a instance with CSV of HEX color strings.
|
||||
* Will use FALLBACK_COLOR as default, if no color could be parsed.
|
||||
*
|
||||
* @param colorString A CSV of HEX color string, e.g. "#000000,#111111,#222222"
|
||||
*/
|
||||
public TagCloudColorer(String colorString) {
|
||||
loadColorString(colorString);
|
||||
if (colors.isEmpty()) {
|
||||
colors.add(FALLBACK_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int colorFor(Word word) {
|
||||
return colors.get(randomGenerator.nextInt(colors.size()));
|
||||
}
|
||||
|
||||
private void loadColorString(String colorString) {
|
||||
for (String c : colorString.split(SEPARATOR)) {
|
||||
colors.add(ColorHelper.decodeHex(c));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
import processing.core.*;
|
||||
import wordcram.WordCram;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import wordcram.*;
|
||||
|
||||
/**
|
||||
* Generate a TagCloud image of a text file and a shape image.
|
||||
* <p/>
|
||||
* Uses WordsReader to parse the text file.
|
||||
* The shape image should have a white (#FFFFFF) background and a black (#000000) foreground.
|
||||
* <p/>
|
||||
* The draw method is called by the main Processing application. As this generator mustn't show more than one
|
||||
* frame, it save the image and exists the main application after the first drawing.
|
||||
* <p/>
|
||||
* Images are saved in TIFF, TARGA, JPEG, and PNG format depending on the extension within the config output file name.
|
||||
*/
|
||||
public class TagCloudGenerator extends PApplet {
|
||||
|
||||
private WordCram cram;
|
||||
|
||||
/**
|
||||
* Called before the first draw from the processing main application
|
||||
*/
|
||||
public void setup() {
|
||||
Configuration config = Configuration.getInstance();
|
||||
size(config.getWidth(), config.getHeight());
|
||||
background(ColorHelper.decodeHex(config.getBackgroundColor()));
|
||||
|
||||
TagCloudPlacer placer = TagCloudPlacer.fromFile(config.getShapeFile(), Color.black);
|
||||
WordsReader input = new WordsReader(config.getInputFile());
|
||||
Word[] words = input.getWords();
|
||||
TagCloudColorer colorer = new TagCloudColorer(config.getColors());
|
||||
TagCloudSizer sizer = new TagCloudSizer(config.getMinSize(), config.getMaxSize(), words);
|
||||
|
||||
cram = new WordCram(this)
|
||||
.fromWords(words)
|
||||
.withColorer(colorer)
|
||||
.withPlacer(placer)
|
||||
.withNudger(placer)
|
||||
.withSizer(sizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called repeatedly by the main processing application. As only one render run is needed
|
||||
* to generate the image, this function saves the generated image and
|
||||
* exists after the first frame.
|
||||
*/
|
||||
public void draw() {
|
||||
cram.drawAll();
|
||||
|
||||
if (Configuration.getInstance().isDebug()) {
|
||||
printDebug();
|
||||
}
|
||||
|
||||
save(Configuration.getInstance().getOutputFile());
|
||||
exit();
|
||||
}
|
||||
|
||||
private void printDebug() {
|
||||
int skippedBecauseOfNoSpace = 0;
|
||||
int skippedBecauseOfTooSmall = 0;
|
||||
Word[] skippedWords = cram.getSkippedWords();
|
||||
Word[] placedWords = cram.getWords();
|
||||
for (Word skipped : skippedWords) {
|
||||
if (skipped.wasSkippedBecause() == WordCram.NO_SPACE) {
|
||||
skippedBecauseOfNoSpace++;
|
||||
} else if (skipped.wasSkippedBecause() == WordCram.SHAPE_WAS_TOO_SMALL) {
|
||||
skippedBecauseOfTooSmall++;
|
||||
}
|
||||
}
|
||||
System.out.println("- STATISTICS ---------------------------------------");
|
||||
System.out.println("Total placed Words: " + placedWords.length);
|
||||
System.out.println("Total skipped Words: " + skippedWords.length);
|
||||
System.out.println("-> because of no space: " + skippedBecauseOfNoSpace);
|
||||
System.out.println("-> because of too small: " + skippedBecauseOfTooSmall);
|
||||
System.out.println("----------------------------------------------------");
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import processing.core.PVector;
|
|||
import wordcram.Word;
|
||||
import wordcram.WordNudger;
|
||||
import wordcram.WordPlacer;
|
||||
class ShapeBasedPlacer implements WordPlacer, WordNudger {
|
||||
class TagCloudPlacer implements WordPlacer, WordNudger {
|
||||
|
||||
public static int TOLERANCE = 5;
|
||||
public static boolean PRECISE = false;
|
||||
|
@ -36,7 +36,7 @@ class ShapeBasedPlacer implements WordPlacer, WordNudger {
|
|||
Random random;
|
||||
BufferedImage image = null;
|
||||
|
||||
public ShapeBasedPlacer(Shape shape) {
|
||||
public TagCloudPlacer(Shape shape) {
|
||||
this.area = new Area(shape);
|
||||
init();
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class ShapeBasedPlacer implements WordPlacer, WordNudger {
|
|||
this.maxY = (float) areaBounds.getMaxY();
|
||||
}
|
||||
|
||||
public static ShapeBasedPlacer fromTextGlyphs(String text, String fontName) {
|
||||
public static TagCloudPlacer fromTextGlyphs(String text, String fontName) {
|
||||
Font font = null;
|
||||
Graphics2D g2d;
|
||||
FontRenderContext frc;
|
||||
|
@ -60,21 +60,21 @@ class ShapeBasedPlacer implements WordPlacer, WordNudger {
|
|||
g2d = img.createGraphics();
|
||||
frc = g2d.getFontRenderContext();
|
||||
gv = font.createGlyphVector(frc, text);
|
||||
return new ShapeBasedPlacer(gv.getOutline(GLYPH_SIZE / 10,GLYPH_SIZE));
|
||||
return new TagCloudPlacer(gv.getOutline(GLYPH_SIZE / 10,GLYPH_SIZE));
|
||||
}
|
||||
|
||||
private ShapeBasedPlacer(BufferedImage image) {
|
||||
private TagCloudPlacer(BufferedImage image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public static ShapeBasedPlacer fromFile(String path, Color color) {
|
||||
public static TagCloudPlacer fromFile(String path, Color color) {
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
image = ImageIO.read(new File(path));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
ShapeBasedPlacer result = new ShapeBasedPlacer(image);
|
||||
TagCloudPlacer result = new TagCloudPlacer(image);
|
||||
if (PRECISE) {
|
||||
result.fromImagePrecise(color);
|
||||
} else {
|
|
@ -0,0 +1,63 @@
|
|||
import processing.core.PApplet;
|
||||
import wordcram.Word;
|
||||
|
||||
/**
|
||||
* Determines the size of words in a TagCloud instance.
|
||||
* The size will be determined as following:
|
||||
* A) All words have the same weight: use (maxSize - minSize) / 3
|
||||
* B) Words have different weights: use a linear interpolation between [minSize, maxSize] for [0,1]
|
||||
* <p/>
|
||||
* Hint: WordCramp normalizes after loading all word the word weight's to [0,1]
|
||||
*/
|
||||
public class TagCloudSizer implements wordcram.WordSizer {
|
||||
|
||||
private boolean allEqual = true;
|
||||
private float minSize;
|
||||
private float maxSize;
|
||||
|
||||
public static final float DEFAULT_TOLERANCE = 0.1f;
|
||||
|
||||
/**
|
||||
* Initialize an instance for minSize to maxSize for a given array of words.
|
||||
* Determines if all words have equal weight using the DEFAULT_TOLERANCE
|
||||
*
|
||||
* @param minSize minimum text size
|
||||
* @param maxSize maximum text size
|
||||
* @param words the list of words
|
||||
*/
|
||||
public TagCloudSizer(float minSize, float maxSize, Word[] words) {
|
||||
this(minSize, maxSize, words, DEFAULT_TOLERANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an instance for minSize to maxSize for a given array of words.
|
||||
* Determines if all words have equal weight using the tolerance
|
||||
*
|
||||
* @param minSize minimum text size
|
||||
* @param maxSize maximum text size
|
||||
* @param words the list of words
|
||||
* @param tolerance the maximum difference beween weight to be equal
|
||||
*/
|
||||
public TagCloudSizer(float minSize, float maxSize, Word[] words, float tolerance) {
|
||||
this.minSize = minSize;
|
||||
this.maxSize = maxSize;
|
||||
if (words.length > 0) {
|
||||
float initial = words[0].weight;
|
||||
for (Word w : words) {
|
||||
if (Math.abs(w.weight - initial) > tolerance) {
|
||||
allEqual = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float sizeFor(Word word, int wordRank, int wordCount) {
|
||||
if (allEqual) {
|
||||
return (maxSize - minSize) / 3.0f;
|
||||
} else {
|
||||
return PApplet.lerp(minSize, maxSize, word.weight);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
import processing.core.*;
|
||||
import wordcram.WordCram;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.PackedColorModel;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import wordcram.*;
|
||||
import wordcram.text.TextSource;
|
||||
|
||||
public class Tree extends PApplet {
|
||||
|
||||
private WordCram cram;
|
||||
private boolean draw = true;
|
||||
|
||||
public void setup(){
|
||||
Configuration config = Configuration.getInstance();
|
||||
size(config.getWidth(),config.getHeight());
|
||||
background(ColorHelper.decode(config.getBackgroundColor()));
|
||||
|
||||
ShapeBasedPlacer placer = ShapeBasedPlacer.fromFile(config.getShapeFile(), Color.black);
|
||||
InputWords input = new InputWords(config.getInputFile());
|
||||
Word[] words = input.getWords();
|
||||
TreeColorer colorer = new TreeColorer(config.getColors());
|
||||
WordSizer sizer = new WordSizer(config.getMinSize(), config.getMaxSize(), words);
|
||||
|
||||
cram = new WordCram(this)
|
||||
.fromWords(words)
|
||||
.withColorer(colorer)
|
||||
.withPlacer(placer)
|
||||
.withNudger(placer)
|
||||
.withSizer(sizer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void draw() {
|
||||
if(this.draw){
|
||||
System.out.println("Start drawing tag cloud...");
|
||||
cram.drawAll();
|
||||
this.draw = false;
|
||||
System.out.println("Finished drawing");
|
||||
|
||||
if(Configuration.getInstance().isDebug()){
|
||||
printDebug();
|
||||
}
|
||||
|
||||
save(Configuration.getInstance().getOutputFile());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
private void printDebug(){
|
||||
//tell me what didn’t get drawn
|
||||
int noSpace = 0;
|
||||
int tooSmall = 0;
|
||||
Word[] skippedWords = cram.getSkippedWords();
|
||||
Word[] placedWords = cram.getWords();
|
||||
for (Word skipped: skippedWords) {
|
||||
if (skipped.wasSkippedBecause() == WordCram.NO_SPACE) {
|
||||
noSpace++;
|
||||
} else if (skipped.wasSkippedBecause() == WordCram.SHAPE_WAS_TOO_SMALL) {
|
||||
tooSmall++;
|
||||
}
|
||||
}
|
||||
System.out.println("Total placed Words: " + placedWords.length);
|
||||
System.out.println("Total Skipped Words: " + skippedWords.length);
|
||||
System.out.println("Skipped because no Space: " + noSpace);
|
||||
System.out.println("Skipped because too small: " + tooSmall);
|
||||
System.out.println("Finished");
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import wordcram.Word;
|
||||
import wordcram.WordColorer;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
public class TreeColorer implements WordColorer {
|
||||
|
||||
private ArrayList<Integer> colors = new ArrayList<Integer>();
|
||||
private Random randomGenerator = new Random();
|
||||
|
||||
public TreeColorer(String colorString){
|
||||
for(String c : colorString.split(",")){
|
||||
colors.add(ColorHelper.decode(c));
|
||||
}
|
||||
if(colors.isEmpty()){
|
||||
colors.add(ColorHelper.decode("#000000"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int colorFor(Word word) {
|
||||
return colors.get(randomGenerator.nextInt(colors.size()));
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
import processing.core.PApplet;
|
||||
import wordcram.Word;
|
||||
|
||||
public class WordSizer implements wordcram.WordSizer{
|
||||
|
||||
private boolean allEqual = true;
|
||||
private float minSize = 4;
|
||||
private float maxSize = 38;
|
||||
|
||||
public WordSizer(float minSize, float maxSize, Word[] words){
|
||||
this.minSize = minSize;
|
||||
this.maxSize = maxSize;
|
||||
if(words.length > 0){
|
||||
float initial = words[0].weight;
|
||||
for(Word w : words){
|
||||
if(Math.abs(w.weight - initial) > 0.1){
|
||||
allEqual = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float sizeFor(Word word, int wordRank, int wordCount) {
|
||||
if(allEqual){
|
||||
return (maxSize - minSize) / 3.0f;
|
||||
}
|
||||
else{
|
||||
return PApplet.lerp(minSize, maxSize, word.weight);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
import wordcram.Word;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Helper to read list of Words with initial weights from a simple Textfile.
|
||||
* Supported text format:
|
||||
* WORD1,WEIGHT1
|
||||
* WORD2,WEIGHT2
|
||||
*
|
||||
* WORD must not contain a comma, but can include a space character.
|
||||
* WEIGHT will be parsed as a Float
|
||||
*/
|
||||
public class WordsReader {
|
||||
private String file;
|
||||
public static final String SEPARATOR = ",";
|
||||
|
||||
/**
|
||||
* Constructs a reader
|
||||
* @param file to be parsed
|
||||
*/
|
||||
public WordsReader(String file){
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the file and parse a list of words.
|
||||
* @return an array of weighted words.
|
||||
*/
|
||||
public Word[] getWords(){
|
||||
ArrayList<Word> words = new ArrayList<Word>();
|
||||
|
||||
BufferedReader reader;
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return new Word[0];
|
||||
}
|
||||
|
||||
String line;
|
||||
try {
|
||||
while((line = reader.readLine()) != null){
|
||||
Word word = parse(line);
|
||||
if(word != null)
|
||||
words.add(word);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new Word[0];
|
||||
}
|
||||
|
||||
return words.toArray(new Word[words.size()]);
|
||||
}
|
||||
|
||||
private Word parse(String line){
|
||||
String[] values = line.split(SEPARATOR);
|
||||
if(values.length == 2){
|
||||
return new Word(values[0].trim(), Float.parseFloat(values[1].trim()));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue