From 44cc541f8346f0fc778c7539fa5d921feb658080 Mon Sep 17 00:00:00 2001 From: hama Date: Thu, 7 Jul 2016 00:13:40 +0200 Subject: [PATCH] Diagram, PairData... --- src/main/java/de/republib/gui/Diagram.java | 153 +++++++++++++++++ src/main/java/de/republib/pinet/Client.java | 17 +- .../de/republib/pinet/gui/ControlCenter.java | 59 +++++++ .../java/de/republib/util/BytePairData.java | 122 ++++++++++++++ src/main/java/de/republib/util/DynBytes.java | 12 +- .../de/republib/util/FunctionPairData.java | 158 ++++++++++++++++++ src/main/java/de/republib/util/I18N.java | 23 +++ src/main/java/de/republib/util/IPairData.java | 38 +++++ .../java/de/republib/util/MathFunction.java | 12 ++ src/main/java/de/republib/util/PairData.java | 32 ++++ .../de/republib/util/BytePairDataTest.java | 90 ++++++++++ .../java/de/republib/util/DynBytesTest.java | 34 +++- .../republib/util/FunctionPairDataTest.java | 131 +++++++++++++++ 13 files changed, 874 insertions(+), 7 deletions(-) create mode 100644 src/main/java/de/republib/gui/Diagram.java create mode 100644 src/main/java/de/republib/pinet/gui/ControlCenter.java create mode 100644 src/main/java/de/republib/util/BytePairData.java create mode 100644 src/main/java/de/republib/util/FunctionPairData.java create mode 100644 src/main/java/de/republib/util/I18N.java create mode 100644 src/main/java/de/republib/util/IPairData.java create mode 100644 src/main/java/de/republib/util/MathFunction.java create mode 100644 src/main/java/de/republib/util/PairData.java create mode 100644 src/test/java/de/republib/util/BytePairDataTest.java create mode 100644 src/test/java/de/republib/util/FunctionPairDataTest.java diff --git a/src/main/java/de/republib/gui/Diagram.java b/src/main/java/de/republib/gui/Diagram.java new file mode 100644 index 0000000..9e2f0f2 --- /dev/null +++ b/src/main/java/de/republib/gui/Diagram.java @@ -0,0 +1,153 @@ +/** + * + */ +package de.republib.gui; + +import java.awt.Color; +import java.awt.Graphics; +import java.util.LinkedList; +import java.util.List; + +import javax.swing.JPanel; + +import de.republib.util.IPairData; + +/** + * A diagram sheet. + * + *
+ * ----------------------------
+ * |<-- vertic. scale
+ * |
+ * |
+ * |
+ * |          v-- horiz. scale
+ * |__________________________
+ * -----------------------------
+ * 
+ * + * @author hm + * + */ +public class Diagram extends JPanel { + private double realX0 = 0.0; + private double realY0 = 0.0; + private double realWidth = 1.0; + private double realHeight = 1.0; + /// 0.0: no fix ration. Otherwise: width / height + private final double ratio = 800.0 / 600.0; + /// distance horizontal scale to left border + private final int hScaleDistance = 5; + /// distance vertical scale to bottom + private final int vScaleDistance = 5; + private final int scaleWidth = 1; + private final Color colorScale = Color.DARK_GRAY; + private final Color colorScaleFont = Color.BLACK; + private final Color colorSheet = Color.WHITE; + private final List data = new LinkedList(); + + /** + * Appends a data package for drawing one line. + * + * @param data + * the pair data for one line + * @return the instance (for chaining) + */ + Diagram addData(IPairData data) { + this.data.add(data); + return this; + } + + @Override + protected void paintComponent(Graphics graphics) { + super.paintComponent(graphics); + paintScale(graphics); + paintData(graphics); + } + + /** + * Paints the data as lines in the sheet. + * + * @param graphics + * the graphic environment + */ + protected void paintData(Graphics graphics) { + final double x0 = this.realX0; + final double realWidth = this.realWidth; + final double y0 = this.realY0; + final double realHeight = this.realHeight; + for (final IPairData data : this.data) { + this.realX0 = data.getX(0); + this.realWidth = data.getX(data.getSteps() - 1) - this.realX0; + int lastX = 0, lastY = 0; + for (int ix = 0; ix < data.getSteps(); ix++) { + final int x = transformX(data.getX(ix)); + final int y = transformY(data.getY(ix)); + if (ix > 0) { + graphics.drawLine(lastX, lastY, x, y); + } + lastX = x; + lastY = y; + } + } + this.realX0 = x0; + this.realWidth = realWidth; + this.realY0 = y0; + this.realHeight = realHeight; + } + + /** + * Paints the scales. + * + * @param graphics + * the graphic environment + */ + protected void paintScale(Graphics graphics) { + graphics.setColor(this.colorScale); + graphics.drawLine(this.hScaleDistance, this.vScaleDistance, this.getWidth() - this.hScaleDistance, + this.vScaleDistance); + graphics.drawLine(this.hScaleDistance, this.vScaleDistance, this.hScaleDistance, + this.getHeight() - this.vScaleDistance); + + } + + /** + * Calculates the x position in pixel from a real x coordinate. + * + * @param x + * the x coordinate in the real world + * @return the x value in pixel coordinate + */ + public int transformX(double x) { + final double xPixel = (x - this.realX0) * (getWidth() - 2 * this.hScaleDistance); + int rc; + if (xPixel < 0) { + rc = 0; + } else if (xPixel > getWidth()) { + rc = getWidth(); + } else { + rc = (int) Math.round(xPixel); + } + return rc; + } + + /** + * Calculates the y position in pixel from a real y coordinate. + * + * @param y + * the y coordinate in the real world + * @return the y value in pixel coordinate + */ + public int transformY(double y) { + final double yPixel = (y - this.realY0) * (getHeight() - 2 * this.vScaleDistance); + int rc; + if (yPixel < 0) { + rc = -1; + } else if (yPixel > getHeight()) { + rc = getHeight(); + } else { + rc = (int) Math.round(yPixel); + } + return rc; + } +} diff --git a/src/main/java/de/republib/pinet/Client.java b/src/main/java/de/republib/pinet/Client.java index 12456d1..0dbfea7 100644 --- a/src/main/java/de/republib/pinet/Client.java +++ b/src/main/java/de/republib/pinet/Client.java @@ -3,12 +3,25 @@ package de.republib.pinet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import de.republib.pinet.gui.ControlCenter; + /** * A TCP client to use services from a GPIO server. */ public class Client { static Logger logger = LoggerFactory.getLogger(Client.class); + public static void client(String host, int port) { + final GpioClient client = new GpioClient(host, port); + client.blink(PinNumber.PIN_RPi2_12, 10, 500, 500); + } + + public static void gui() { + final ControlCenter center = new ControlCenter(); + center.populate(); + center.run(); + } + /** * Evaluates the options and start the program. * @@ -27,7 +40,7 @@ public class Client { port = Integer.parseInt(arg); } } - final GpioClient client = new GpioClient(host, port); - client.blink(PinNumber.PIN_RPi2_12, 10, 500, 500); + Client.gui(); + // Client.client(host, port); } } diff --git a/src/main/java/de/republib/pinet/gui/ControlCenter.java b/src/main/java/de/republib/pinet/gui/ControlCenter.java new file mode 100644 index 0000000..18dfd5b --- /dev/null +++ b/src/main/java/de/republib/pinet/gui/ControlCenter.java @@ -0,0 +1,59 @@ +package de.republib.pinet.gui; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridLayout; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; + +import de.republib.gui.Diagram; +import de.republib.util.I18N; + +/** + * Created by hm on 03.07.16. + */ +public class ControlCenter { + private JFrame frame; + private JPanel panelCenter; + private JPanel panelOutput; + private JPanel panelLog; + private JLabel labelStatusLine; + private JPanel panelData; + private JPanel panelHead; + private JTextField textFieldServer; + private JTextField textFieldPort; + private JTabbedPane tabbedPane; + + public void populate() { + this.frame = new JFrame(I18N.tr("Pinet Control Center")); + this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + this.frame.setMinimumSize(new Dimension(800, 600)); + + // Add content to the window. + this.frame.add(this.panelCenter = new JPanel(new GridLayout(1, 1)), BorderLayout.CENTER); + this.frame.add(this.panelHead = new JPanel(new FlowLayout()), BorderLayout.NORTH); + this.frame.add(this.labelStatusLine = new JLabel(I18N.tr("welcome")), BorderLayout.SOUTH); + + this.panelHead.add(new JLabel(I18N.tr("Server:"))); + this.panelHead.add(this.textFieldServer = new JTextField("localhost")); + this.panelHead.add(new JLabel(I18N.tr("Port:"))); + this.panelHead.add(this.textFieldPort = new JTextField("15000")); + + this.panelCenter.add(this.tabbedPane = new JTabbedPane()); + this.tabbedPane.addTab(I18N.tr("Output"), this.panelOutput = new JPanel()); + this.tabbedPane.addTab(I18N.tr("Diagram"), this.panelData = new Diagram()); + this.tabbedPane.addTab(I18N.tr("Log"), this.panelLog = new JPanel()); + } + + public void run() { + // Display the window. + this.frame.pack(); + this.frame.setVisible(true); + } +} diff --git a/src/main/java/de/republib/util/BytePairData.java b/src/main/java/de/republib/util/BytePairData.java new file mode 100644 index 0000000..06c10e6 --- /dev/null +++ b/src/main/java/de/republib/util/BytePairData.java @@ -0,0 +1,122 @@ +/** + * + */ +package de.republib.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author hm + * + */ +public class BytePairData extends DynBytes implements IPairData { + static Logger logger = LoggerFactory.getLogger(BytePairData.class); + private final double minX; + + private final double maxX; + + private final int dataWidth; + + /** + * Constructor. + * + * @param capacity + * @param blocksize + * @param minX + * @param maxX + * @param dataWidth + */ + public BytePairData(int capacity, int blocksize, double minX, double maxX, int dataWidth) { + super(capacity, blocksize); + if (dataWidth < 0 || dataWidth > 8) { + BytePairData.logger.error("getY(): illegal data width: {:d}", dataWidth); + dataWidth = 1; + } + this.minX = minX; + this.maxX = maxX; + this.dataWidth = dataWidth; + } + + /** + * @return the dataWidth + */ + public int getDataWidth() { + return this.dataWidth; + } + + /** + * @return the maxX + */ + public double getMaxX() { + return this.maxX; + } + + /** + * @return the minX + */ + public double getMinX() { + return this.minX; + } + + /* + * (non-Javadoc) + * + * @see de.republib.util.IData2D#getSteps() + */ + @Override + public int getSteps() { + return this.length / this.dataWidth; + } + + /* + * (non-Javadoc) + * + * @see de.republib.util.IData2D#getX(int) + */ + @Override + public double getX(int index) { + double x = this.minX; + if (index < 0 || index >= this.length / this.dataWidth) { + BytePairData.logger.error("getX(): wrong index: {:d} / {:d}", index, this.length / this.dataWidth); + } else { + x = this.minX + index * (this.maxX - this.minX) / (this.length / this.dataWidth); + } + return x; + } + + /* + * (non-Javadoc) + * + * @see de.republib.util.IData2D#getY(int) + */ + @Override + public double getY(int index) { + double y = 0.0; + if (index < 0 || index >= this.length / this.dataWidth) { + BytePairData.logger.error("getY(): wrong index: {:d} / {:d}", index, this.length / this.dataWidth); + } else { + switch (this.dataWidth) { + case 1: + y = this.buffer[index]; + break; + case 2: + case 3: + case 4: + y = this.intAsLittleEndian(index * this.dataWidth, this.dataWidth, 0); + break; + case 5: + case 6: + case 7: + case 8: + y = this.longAsLittleEndian(index * this.dataWidth, this.dataWidth, 0); + break; + default: + BytePairData.logger.error("getY(): illegal data width: {:d}", index, this.dataWidth); + break; + } + } + return y; + } + +} diff --git a/src/main/java/de/republib/util/DynBytes.java b/src/main/java/de/republib/util/DynBytes.java index 2ab43a5..d01cfaa 100644 --- a/src/main/java/de/republib/util/DynBytes.java +++ b/src/main/java/de/republib/util/DynBytes.java @@ -163,7 +163,9 @@ public class DynBytes { * @return the instance (for chaining) */ public DynBytes appendLittleEndian(int number, int width) { - if (width >= 1 && width <= 4) { + if (width < 1 || width > 4) { + DynBytes.logger.debug("appendLitleEndian(%d, %d); wrong width", number, width); + } else { ensureSize(this.length + width); for (int ix = 0; ix < width; ix++) { this.buffer[this.length++] = (byte) (number & 0xff); @@ -301,6 +303,10 @@ public class DynBytes { for (int ii = width - 1; ii >= 0; ii--) { rc = (rc << 8) | ((this.buffer[index + ii]) & 0xff); } + // first bit == 1? + if (width < 4 && rc >> (width * 8 - 1) != 0) { + rc = rc - (1 << width * 8); + } } return rc; } @@ -321,6 +327,10 @@ public class DynBytes { for (int ii = width - 1; ii >= 0; ii--) { rc = (rc << 8) | ((this.buffer[index + ii]) & 0xff); } + // first bit == 1? + if (width < 8 && rc >> (width * 8 - 1) != 0) { + rc = rc - (1L << width * 8); + } } return rc; } diff --git a/src/main/java/de/republib/util/FunctionPairData.java b/src/main/java/de/republib/util/FunctionPairData.java new file mode 100644 index 0000000..a4cf5d1 --- /dev/null +++ b/src/main/java/de/republib/util/FunctionPairData.java @@ -0,0 +1,158 @@ +/** + * + */ +package de.republib.util; + +/** + * Generate mathematical functions as (x, y) pairs. + * + * @author hm + * + */ +public class FunctionPairData implements IPairData { + private final MathFunction function; + + private final double xMin; + + private final double xMax; + + private double factor = 1.0; + + private double factor2 = 1.0; + + private double offset = 0.0; + + private final int steps; + + public FunctionPairData(MathFunction function, double xMin, double xMax, int steps) { + this.function = function; + this.xMax = xMax; + this.xMin = xMin; + this.steps = steps; + } + + /** + * @return the factor + */ + public double getFactor() { + return this.factor; + } + + /** + * @return the factor2 + */ + public double getFactor2() { + return this.factor2; + } + + /** + * @return the function + */ + public MathFunction getFunction() { + return this.function; + } + + /** + * @return the offset + */ + public double getOffset() { + return this.offset; + } + + /* + * (non-Javadoc) + * + * @see de.republib.util.IPairData#getCount() + */ + @Override + public int getSteps() { + return this.steps; + } + + /* + * (non-Javadoc) + * + * @see de.republib.util.IPairData#getX(int) + */ + @Override + public double getX(int index) { + return this.xMin + (this.xMax - this.xMin) * index / this.steps; + } + + /** + * @return the xMax + */ + public double getxMax() { + return this.xMax; + } + + /** + * @return the xMin + */ + public double getxMin() { + return this.xMin; + } + + /* + * (non-Javadoc) + * + * @see de.republib.util.IPairData#getY(int) + */ + @Override + public double getY(int index) { + double y = 0.0; + final double x = getX(index); + switch (this.function) { + case COS: + y = Math.cos(x); + break; + case SIN: + y = Math.sin(x); + break; + case TAN: + y = Math.tan(x); + break; + case EXP: + y = Math.exp(x); + break; + case X: + y = x; + break; + case LOG: + if (x > 0) { + y = Math.log(x); + } + break; + case X2: + y = x * x + this.factor2 / this.factor * x; + break; + default: + break; + } + return y * this.factor + this.offset; + } + + /** + * @param factor + * the factor to set + */ + public void setFactor(double factor) { + this.factor = factor; + } + + /** + * @param factor2 + * the factor2 to set + */ + public void setFactor2(double factor2) { + this.factor2 = factor2; + } + + /** + * @param offset + * the offset to set + */ + public void setOffset(double offset) { + this.offset = offset; + } +} diff --git a/src/main/java/de/republib/util/I18N.java b/src/main/java/de/republib/util/I18N.java new file mode 100644 index 0000000..b8932ae --- /dev/null +++ b/src/main/java/de/republib/util/I18N.java @@ -0,0 +1,23 @@ +/** + * + */ +package de.republib.util; + +/** + * Internationalization. + * + * @author hm + * + */ +public class I18N { + /** + * Translate a string. + * + * @param text + * text to translate + * @return the translated text + */ + public static String tr(final String key) { + return key; + } +} diff --git a/src/main/java/de/republib/util/IPairData.java b/src/main/java/de/republib/util/IPairData.java new file mode 100644 index 0000000..257abca --- /dev/null +++ b/src/main/java/de/republib/util/IPairData.java @@ -0,0 +1,38 @@ +/** + * + */ +package de.republib.util; + +/** + * Interface of a data storage for (x, y) pairs. + * + * @author hm + * + */ +public interface IPairData { + + /** + * Returns the number of (x, y) pairs. + * + * @return the number of pairs. + */ + int getSteps(); + + /** + * Returns the n-th x value. + * + * @param index + * index of the x value: 0..getCount() - 1 + * @return the index-th x value + */ + double getX(int index); + + /** + * Returns the n-th y value. + * + * @param index + * index of the x value: 0..getCount() - 1 + * @return the index-th x value + */ + double getY(int index); +} diff --git a/src/main/java/de/republib/util/MathFunction.java b/src/main/java/de/republib/util/MathFunction.java new file mode 100644 index 0000000..af8a1ce --- /dev/null +++ b/src/main/java/de/republib/util/MathFunction.java @@ -0,0 +1,12 @@ +/** + * + */ +package de.republib.util; + +/** + * @author hm + * + */ +public enum MathFunction { + UNDEF, SIN, COS, TAN, X, X2, EXP, LOG +} diff --git a/src/main/java/de/republib/util/PairData.java b/src/main/java/de/republib/util/PairData.java new file mode 100644 index 0000000..6d3c517 --- /dev/null +++ b/src/main/java/de/republib/util/PairData.java @@ -0,0 +1,32 @@ +/** + * + */ +package de.republib.util; + +/** + * @author hm + * + */ +public class PairData { + public static double maxY(IPairData data) { + double rc = data.getY(0); + for (int ix = data.getSteps() - 1; ix > 0; ix--) { + final double current = data.getY(ix); + if (current > rc) { + rc = current; + } + } + return rc; + } + + public static double minY(IPairData data) { + double rc = data.getY(0); + for (int ix = data.getSteps() - 1; ix > 0; ix--) { + final double current = data.getY(ix); + if (current > rc) { + rc = current; + } + } + return rc; + } +} diff --git a/src/test/java/de/republib/util/BytePairDataTest.java b/src/test/java/de/republib/util/BytePairDataTest.java new file mode 100644 index 0000000..b547273 --- /dev/null +++ b/src/test/java/de/republib/util/BytePairDataTest.java @@ -0,0 +1,90 @@ +package de.republib.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Tests the class BytePairData. + * + * @author hm + * + */ +public class BytePairDataTest { + static Logger logger = LoggerFactory.getLogger(BytePairDataTest.class); + + @Test + public void BytePairData() { + for (int width = 1; width <= 8; width++) { + for (int count = 256; count < width * 256; count++) { + testOne(count, width); + } + } + } + + @Test + public void getSteps() { + testOne(1024, 3); + testOne(1024 * 64, 5); + testOne(1024 * 128, 8); + final BytePairData data = new BytePairData(133, 16, -44.0, 2.55, 2); + Assert.assertEquals(data.getLength(), 0); + + Assert.assertEquals(data.getSteps(), 0); + Assert.assertEquals(data.getMinX(), -44.0); + Assert.assertEquals(data.getMaxX(), 2.55); + } + + @Test + public void getX() { + final BytePairData data = new BytePairData(133, 16, -1000.0, 1000.0, 4); + Assert.assertEquals(data.getLength(), 0); + for (int ix = 0; ix < 1000; ix++) { + data.appendLittleEndian(ix * 314, 4); + } + Assert.assertEquals(data.getSteps(), 1000); + for (int ix = 0; ix < 1000; ix++) { + Assert.assertEquals(data.getX(ix), (-1000.0 + ix * 2)); + Assert.assertEquals(data.getY(ix), 314.0 * ix); + } + } + + @Test + public void getY() { + final BytePairData data = new BytePairData(133, 16, -50.0, 50, 8); + Assert.assertEquals(data.getLength(), 0); + for (int ix = 0; ix < 1000; ix++) { + data.appendLittleEndian((long) ix * ix, 8); + } + Assert.assertEquals(data.getSteps(), 1000); + for (int ix = 0; ix < 1000; ix++) { + Assert.assertEquals(data.getX(ix), (-50.0 + ix / 10.0)); + Assert.assertEquals(data.getY(ix), (double) ix * ix); + } + } + + private void testOne(int count, int dataWidth) { + // BytePairDataTest.logger.info(String.format("count: %d width: %d", + // count, dataWidth)); + // capacity should be incremented: + final BytePairData data = new BytePairData(count * dataWidth - 16, 16, 0.0, count, dataWidth); + for (int ix = 0; ix < count; ix++) { + data.appendLittleEndian((long) (ix % 128 - 128), dataWidth); + } + if (data.getCapacity() < count * dataWidth) { + Assert.assertTrue(data.getCapacity() >= count * dataWidth); + } + Assert.assertEquals(data.getBlocksize(), 16); + Assert.assertEquals(data.getLength(), count * dataWidth); + + Assert.assertEquals(data.getSteps(), count); + Assert.assertEquals(data.getMinX(), 0.0); + Assert.assertEquals(data.getMaxX(), (double) count); + Assert.assertEquals(data.getSteps(), count); + for (int ix = 0; ix < count; ix++) { + Assert.assertEquals(data.getX(ix), (double) ix); + Assert.assertEquals(data.getY(ix), (double) (ix % 128 - 128)); + } + } +} diff --git a/src/test/java/de/republib/util/DynBytesTest.java b/src/test/java/de/republib/util/DynBytesTest.java index 194ccfb..4e6e3f8 100644 --- a/src/test/java/de/republib/util/DynBytesTest.java +++ b/src/test/java/de/republib/util/DynBytesTest.java @@ -137,8 +137,8 @@ public class DynBytesTest { public void testIntAsLittleEndian() { final DynBytes buffer = new DynBytes(16, 2); buffer.appendLittleEndian(0x1234567890abcdefL, 8); - Assert.assertEquals(buffer.intAsLittleEndian(0, 1, -1), 0xef); - Assert.assertEquals(buffer.intAsLittleEndian(0, 3, -1), 0xabcdef); + Assert.assertEquals(buffer.intAsLittleEndian(0, 1, -1), -17 /* 0xef */); + Assert.assertEquals(buffer.intAsLittleEndian(0, 3, -1), -5517841 /* 0xabcdef */); Assert.assertEquals(buffer.intAsLittleEndian(1, 4, -1), 0x7890abcd); Assert.assertEquals(buffer.intAsLittleEndian(6, 2, -1), 0x1234); @@ -150,14 +150,24 @@ public class DynBytesTest { // wrong width: Assert.assertEquals(buffer.intAsLittleEndian(0, 0, -5), -5); Assert.assertEquals(buffer.intAsLittleEndian(0, 5, -6), -6); + + // negative values: + buffer.setLength(0).appendLittleEndian(-128, 1); + Assert.assertEquals(buffer.intAsLittleEndian(0, 1, -5), -128); + buffer.setLength(0).appendLittleEndian(-32000, 2); + Assert.assertEquals(buffer.intAsLittleEndian(0, 2, -5), -32000); + buffer.setLength(0).appendLittleEndian(-1, 3); + Assert.assertEquals(buffer.intAsLittleEndian(0, 3, -5), -1); + buffer.setLength(0).appendLittleEndian(-1, 4); + Assert.assertEquals(buffer.intAsLittleEndian(0, 4, -5), -1); } @org.testng.annotations.Test public void testLongAsLittleEndian() { final DynBytes buffer = new DynBytes(16, 2); buffer.appendLittleEndian(0x1234567890abcdefL, 8); - Assert.assertEquals(buffer.longAsLittleEndian(0, 1, -1), 0xefL); - Assert.assertEquals(buffer.longAsLittleEndian(0, 3, -1), 0xabcdefL); + Assert.assertEquals(buffer.longAsLittleEndian(0, 1, -1), -17L /* 0xef */); + Assert.assertEquals(buffer.longAsLittleEndian(0, 3, -1), -5517841L /* 0xabcdef */); Assert.assertEquals(buffer.longAsLittleEndian(1, 4, -1), 0x7890abcdL); Assert.assertEquals(buffer.longAsLittleEndian(6, 2, -1), 0x1234L); @@ -169,6 +179,22 @@ public class DynBytesTest { // wrong width: Assert.assertEquals(buffer.intAsLittleEndian(0, 0, -5), -5); Assert.assertEquals(buffer.intAsLittleEndian(0, 5, -6), -6); + + // negative values: + for (int width = 1; width <= 8; width++) { + buffer.setLength(0).appendLittleEndian(-1L, width); + Assert.assertEquals(buffer.longAsLittleEndian(0, width, -5), -1); + buffer.setLength(0).appendLittleEndian(-128L, width); + Assert.assertEquals(buffer.longAsLittleEndian(0, width, -5), -128L); + } + buffer.setLength(0).appendLittleEndian(-128, 1); + Assert.assertEquals(buffer.longAsLittleEndian(0, 1, -5), -128); + buffer.setLength(0).appendLittleEndian(-32000, 2); + Assert.assertEquals(buffer.longAsLittleEndian(0, 2, -5), -32000); + buffer.setLength(0).appendLittleEndian(-1, 3); + Assert.assertEquals(buffer.longAsLittleEndian(0, 3, -5), -1); + buffer.setLength(0).appendLittleEndian(-1, 4); + Assert.assertEquals(buffer.longAsLittleEndian(0, 4, -5), -1); } @org.testng.annotations.Test diff --git a/src/test/java/de/republib/util/FunctionPairDataTest.java b/src/test/java/de/republib/util/FunctionPairDataTest.java new file mode 100644 index 0000000..3fc2b2c --- /dev/null +++ b/src/test/java/de/republib/util/FunctionPairDataTest.java @@ -0,0 +1,131 @@ +package de.republib.util; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class FunctionPairDataTest { + + void checkFunctionCos() { + final FunctionPairData data = new FunctionPairData(MathFunction.COS, 0.0, 4 * Math.PI / 4, 4); + data.setFactor(2); + data.setOffset(-15); + Assert.assertEquals(data.getSteps(), 4); + Assert.assertEquals(data.getY(0), -15.0 + 2 * Math.cos(0.0)); + Assert.assertEquals(data.getY(1), -15 + 2 * Math.cos(Math.PI / 4)); + Assert.assertEquals(data.getY(2), -15 + 2 * Math.cos(Math.PI / 2)); + Assert.assertEquals(data.getY(3), -15 + 2 * Math.cos(3 * Math.PI / 4)); + } + + void checkFunctionExp() { + final FunctionPairData data = new FunctionPairData(MathFunction.EXP, 0.0, 4.0, 4); + data.setFactor(10); + data.setOffset(3); + Assert.assertEquals(data.getSteps(), 4); + Assert.assertEquals(data.getY(0), 13.0); + Assert.assertEquals(data.getY(1), 3 + 10 * Math.exp(1.0)); + Assert.assertEquals(data.getY(2), 3 + 10 * Math.exp(2.0)); + Assert.assertEquals(data.getY(3), 3 + 10 * Math.exp(3.0)); + } + + void checkFunctionLog() { + final FunctionPairData data = new FunctionPairData(MathFunction.LOG, 1.0, 5.0, 4); + data.setFactor(7); + data.setOffset(5); + Assert.assertEquals(data.getSteps(), 4); + Assert.assertEquals(data.getY(0), 5.0 + 7 * Math.log(1)); + Assert.assertEquals(data.getY(1), 5.0 + 7 * Math.log(2.0)); + Assert.assertEquals(data.getY(2), 5.0 + 7 * Math.log(3.0)); + Assert.assertEquals(data.getY(3), 5.0 + 7 * Math.log(4.0)); + } + + void checkFunctionSin() { + final FunctionPairData data = new FunctionPairData(MathFunction.SIN, 0.0, 4 * Math.PI / 4, 4); + data.setFactor(2); + data.setOffset(-15); + Assert.assertEquals(data.getSteps(), 4); + Assert.assertEquals(data.getY(0), -15.0); + Assert.assertEquals(data.getY(1), -15 + 2 * Math.sin(Math.PI / 4)); + Assert.assertEquals(data.getY(2), -15 + 2 * Math.sin(Math.PI / 2)); + Assert.assertEquals(data.getY(3), -15 + 2 * Math.sin(3 * Math.PI / 4)); + } + + void checkFunctionTan() { + final FunctionPairData data = new FunctionPairData(MathFunction.TAN, 0.0, 4 * Math.PI / 4, 4); + data.setFactor(2); + data.setOffset(-3); + Assert.assertEquals(data.getSteps(), 4); + Assert.assertEquals(data.getY(0), -3.0); + Assert.assertEquals(data.getY(1), -3 + 2 * Math.tan(Math.PI / 4)); + Assert.assertEquals(data.getY(2), -3 + 2 * Math.tan(Math.PI / 2)); + Assert.assertEquals(data.getY(3), -3 + 2 * Math.tan(3 * Math.PI / 4)); + } + + void checkFunctionX() { + final FunctionPairData data = new FunctionPairData(MathFunction.X, 0.0, 100.0, 10); + data.setFactor(2.0); + data.setOffset(-5.0); + Assert.assertEquals(data.getSteps(), 10); + Assert.assertEquals(data.getY(0), -5.0); + Assert.assertEquals(data.getY(9), -5.0 + (100.0 - 10) * 2); + } + + void checkFunctionX2() { + final FunctionPairData data = new FunctionPairData(MathFunction.X2, 0.0, 2.0, 2); + data.setFactor(0.5); + data.setFactor2(3.0); + data.setOffset(-10.0); + Assert.assertEquals(data.getSteps(), 2); + Assert.assertEquals(data.getY(0), -10.0); + Assert.assertEquals(data.getY(2), -10.0 + 0.5 * 2.0 * 2.0 + 2.0 * 3); + } + + @Test + public void FunctionPairData() { + final FunctionPairData data = new FunctionPairData(MathFunction.X, 0.0, 100.0, 10); + Assert.assertEquals(data.getSteps(), 10); + } + + @Test + public void getSteps() { + final FunctionPairData data = new FunctionPairData(MathFunction.X2, 0.0, 100.0, 432); + Assert.assertEquals(data.getSteps(), 432); + } + + @Test + public void getX() { + final FunctionPairData data = new FunctionPairData(MathFunction.SIN, 0.0, 100.0, 432); + Assert.assertEquals(data.getSteps(), 432); + } + + @Test + public void getY() { + checkFunctionX(); + checkFunctionX2(); + checkFunctionSin(); + checkFunctionCos(); + checkFunctionTan(); + checkFunctionExp(); + checkFunctionLog(); + } + + @Test + public void setFactor() { + final FunctionPairData data = new FunctionPairData(MathFunction.SIN, 0.0, 100.0, 432); + data.setFactor(44.33); + Assert.assertEquals(data.getFactor(), 44.33); + } + + @Test + public void setFactor2() { + final FunctionPairData data = new FunctionPairData(MathFunction.SIN, 0.0, 100.0, 432); + data.setFactor2(88.33); + Assert.assertEquals(data.getFactor2(), 88.33); + } + + @Test + public void setOffset() { + final FunctionPairData data = new FunctionPairData(MathFunction.SIN, 0.0, 100.0, 432); + data.setOffset(-32.44); + Assert.assertEquals(data.getOffset(), -32.44); + } +} -- 2.39.5