From 4e8b4c364bdab0af78bf72f9b7c9bdbfeabac0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20F=C3=BCrderer?= Date: Sat, 8 Jun 2019 15:39:50 +0200 Subject: [PATCH] Add java program to create test data --- testdata/.gitignore | 2 + testdata/create.sh | 22 +++ testdata/src/creation/Creator.java | 184 +++++++++++++++++++++++++ testdata/src/creation/Dictionary.java | 16 +++ testdata/src/creation/MyDate.java | 66 +++++++++ testdata/src/creation/NameCreator.java | 35 +++++ testdata/src/creation/NamedColor.java | 13 ++ 7 files changed, 338 insertions(+) create mode 100644 testdata/.gitignore create mode 100755 testdata/create.sh create mode 100644 testdata/src/creation/Creator.java create mode 100644 testdata/src/creation/Dictionary.java create mode 100644 testdata/src/creation/MyDate.java create mode 100644 testdata/src/creation/NameCreator.java create mode 100644 testdata/src/creation/NamedColor.java diff --git a/testdata/.gitignore b/testdata/.gitignore new file mode 100644 index 0000000..342e2f4 --- /dev/null +++ b/testdata/.gitignore @@ -0,0 +1,2 @@ +bin +outputdir diff --git a/testdata/create.sh b/testdata/create.sh new file mode 100755 index 0000000..931c62e --- /dev/null +++ b/testdata/create.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# use the correct working directory +cd $(dirname "$0") + +# compile java code +mkdir -p bin +javac -sourcepath src -d bin src/creation/Creator.java + +# recreate output dir +rm -rf outputdir +mkdir -p outputdir/data/textures + +# create textures +java -classpath bin creation.Creator + +# place a server binary in the output directory +( + cd ../server/texture-sync-server + cargo build --release +) +cp ../server/texture-sync-server/target/release/texture-sync-server ./outputdir/ diff --git a/testdata/src/creation/Creator.java b/testdata/src/creation/Creator.java new file mode 100644 index 0000000..2e3f926 --- /dev/null +++ b/testdata/src/creation/Creator.java @@ -0,0 +1,184 @@ +package creation; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Random; +import java.util.UUID; + +import javax.imageio.ImageIO; + +public class Creator { + public static void main(String[] args) { + Random r = new Random(1); + + String basedir = "outputdir/data"; + String[] names = NameCreator.generateNames(r); + + try { + FileOutputStream collectionOutput = new FileOutputStream(basedir + "/collection.json"); + PrintWriter collectionWriter = new PrintWriter(collectionOutput); + collectionWriter.write("{\n \"textures\": [\n "); + boolean first = true; + int i=1; + for (String name : names) { + if (first) { + first = false; + } else { + collectionWriter.write(",\n "); + } + System.out.println("Creating " + name + " (texture " + i + " of " + names.length + ")"); + storeImage(name, basedir, r, collectionWriter); + i++; + } + collectionWriter.write("\n ]\n}\n"); + collectionWriter.close(); + collectionOutput.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static boolean randBool(Random r, double probability) { + return r.nextDouble() < probability; + } + + private static void storeImage(String name, String outputdir, Random r, PrintWriter collectionWriter) + throws IOException { + int size = 256 * (1 << r.nextInt(6)); + NamedColor[] shuffling = Dictionary.colors.clone(); + NamedColor[] mycolors = new NamedColor[3]; + for (int i = 0; i < 3; i++) { + int otherPos = r.nextInt(7 - i) + i; + mycolors[i] = shuffling[otherPos]; + shuffling[otherPos] = shuffling[i]; + } + MyDate date = randomDate(r); + + boolean grey = randBool(r, 0.01); + boolean border = randBool(r, 0.1); + boolean bold = randBool(r, 0.03); + boolean italic = randBool(r, 0.07); + BufferedImage img = createImage(size, name, mycolors, date, grey, border, bold, italic); + + File tmpLocation = new File(outputdir + "/tempimage"); + ImageIO.write(img, name.substring(name.length() - 3), tmpLocation); + String hash = hashFile(tmpLocation); + String ending = name.substring(name.length() - 3); + if (ending.equals("jpg")) { + ending = "jpeg"; + } + tmpLocation.renameTo(new File(outputdir + "/textures/" + hash)); + String tags = mycolors[0].name + "\", \"" + mycolors[1].name + "\", \"" + mycolors[2].name; + if (grey) { + tags += "\", \"grey"; + } + if (border) { + tags += "\", \"border"; + } + if (bold) { + tags += "\", \"bold"; + } + if (italic) { + tags += "\", \"italic"; + } + collectionWriter.write("{\n"); + collectionWriter.write(" \"id\": \"" + UUID.randomUUID() + "\",\n"); + collectionWriter.write(" \"name\": \"" + name + "\",\n"); + collectionWriter.write(" \"tags\": [\"" + tags + "\"],\n"); + collectionWriter.write(" \"format\": \"" + ending + "\",\n"); + collectionWriter.write(" \"resolution\": [" + size + ", " + size + "],\n"); + collectionWriter.write(" \"added_on\": " + date.asJsonArray() + ",\n"); + collectionWriter.write(" \"texture_hash\": \"" + hash + "\"\n"); + collectionWriter.write(" }"); + } + + private static MyDate randomDate(Random r) { + int back = (int) (-300 * Math.log(r.nextDouble())); + return new MyDate(3, 6, 2019).ago(back); + } + + private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); + + public static String bytesToHex(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + private static String hashFile(File f) throws IOException { + byte[] data = Files.readAllBytes(f.toPath()); + try { + MessageDigest hash = MessageDigest.getInstance("SHA-256"); + byte[] hashval = hash.digest(data); + return bytesToHex(hashval); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + + private static BufferedImage createImage(int size, String name, NamedColor[] colors, MyDate date, boolean grey, + boolean border, boolean bold, boolean italic) { + BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + + // background + if (grey) { + g.setColor(Color.LIGHT_GRAY); + } else { + g.setColor(Color.WHITE); + } + g.fillRect(0, 0, size, size); + + // border + if (border) { + int w = size / 40; + int l = size - 2*w; + g.setColor(Color.BLACK); + g.fillRect(w, w, l, w); + g.fillRect(w, w, w, l); + g.fillRect(w, l, l, w); + g.fillRect(l, w, w, l); + } + + // text + int fontstyle = Font.PLAIN; + if (bold) { + fontstyle |= Font.BOLD; + } + if (italic) { + fontstyle |= Font.ITALIC; + } + Font f = new Font("Arial", fontstyle, size / 10); + g.setFont(f); + g.setColor(Color.BLACK); + int width = g.getFontMetrics().stringWidth(name); + int basey = size / 2 + g.getFontMetrics().getAscent(); + int textheight = g.getFontMetrics().getHeight(); + g.drawString(name, (size - width) / 2, basey); + g.drawString(size + " x " + size, (size - width) / 2, basey + textheight); + g.drawString(date.asReadableString(), (size - width) / 2, basey + 2 * textheight); + + // color dots + for (int i = 0; i < 3; i++) { + NamedColor current = colors[i]; + g.setColor(current.color); + g.fillOval((1 + 3 * i) * size / 10, size * 3 / 10, size / 5, size / 5); + } + + return img; + } +} diff --git a/testdata/src/creation/Dictionary.java b/testdata/src/creation/Dictionary.java new file mode 100644 index 0000000..f6b8ebb --- /dev/null +++ b/testdata/src/creation/Dictionary.java @@ -0,0 +1,16 @@ +package creation; + +import java.awt.Color; + +public class Dictionary { + public static final String[] adjectives = { "fast", "slow", "long", "short", "fat", "big", "small", "angry", + "awful", "calm", "clever", "crazy", "dirty", "excited", "evil", "kind", "lucky", "poor", "shy", "soft", + "tall", }; + public static final String[] animals = { "bat", "bee", "camel", "cat", "chicken", "cod", "deer", "dog", "duck", + "fly", "fox", "frog", "horse", "koala", "lion", "mouse", "owl", "pig", "rabbit", "rat", "tiger", "turtle", + "wolf", "zebra" }; + public static final NamedColor[] colors = { new NamedColor("red", Color.RED), + new NamedColor("orange", Color.ORANGE), new NamedColor("yellow", Color.YELLOW), + new NamedColor("green", Color.GREEN), new NamedColor("blue", Color.BLUE), + new NamedColor("magenta", Color.MAGENTA), new NamedColor("black", Color.BLACK), }; +} diff --git a/testdata/src/creation/MyDate.java b/testdata/src/creation/MyDate.java new file mode 100644 index 0000000..979791b --- /dev/null +++ b/testdata/src/creation/MyDate.java @@ -0,0 +1,66 @@ +package creation; + +public class MyDate { + public final int day, month, year; + + public MyDate(int day, int month, int year) { + if (!isValid(day, month, year)) { + throw new IllegalArgumentException("Invalid date"); + } + this.day = day; + this.month = month; + this.year = year; + } + + public String asJsonArray() { + return "[" + year + ", " + month + ", " + day + "]"; + } + + public String asReadableString() { + return twoDigit(day) + "." + twoDigit(month) + "." + twoDigit(year); + } + + public MyDate previous() { + if (isValid(day - 1, month, year)) { + return new MyDate(day - 1, month, year); + } + for (int possibleDay = 31; possibleDay >= 28; possibleDay--) { + if (isValid(possibleDay, month - 1, year)) { + return new MyDate(possibleDay, month - 1, year); + } + } + return new MyDate(31, 12, year - 1); + } + + public MyDate ago(int number) { + MyDate d = this; + for (int i=0; i 12) { + return false; + } + int length = monthLengths[month - 1]; + if (day < 1 || day > length) { + return false; + } + return true; + } + + private boolean isLeapYear(int year) { + return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0); + } +} diff --git a/testdata/src/creation/NameCreator.java b/testdata/src/creation/NameCreator.java new file mode 100644 index 0000000..12e141a --- /dev/null +++ b/testdata/src/creation/NameCreator.java @@ -0,0 +1,35 @@ +package creation; + +import java.util.ArrayList; +import java.util.Random; + +public class NameCreator { + private static void shuffle(ArrayList list, Random r) { + for (int low=0; low names = new ArrayList<>(); + for (String ending : new String[] {"jpg", "png"}) { + for (String animal : Dictionary.animals) { + for (String adjective : Dictionary.adjectives) { + String name = adjective + "-" + animal + "." + ending; + names.add(name); + } + } + } + shuffle(names, r); + while (names.size() > 1000) { + names.remove(names.size() - 1); + } + return names.toArray(new String[1000]); + } +} diff --git a/testdata/src/creation/NamedColor.java b/testdata/src/creation/NamedColor.java new file mode 100644 index 0000000..9474ee7 --- /dev/null +++ b/testdata/src/creation/NamedColor.java @@ -0,0 +1,13 @@ +package creation; + +import java.awt.Color; + +public class NamedColor { + public final String name; + public final Color color; + + public NamedColor(String name, Color color) { + this.name = name; + this.color = color; + } +}