Dear users, Please note that, from Monday, August 16, 2019, RSA keys shorter than 2048bit will no longer be accepted for security reasons. Please update your keys as needed before this date. If you need assistance with regard to this process, please contact sia@list.lu

Thank you for your understanding.

Commit 728e74b1 authored by Nico Mack's avatar Nico Mack

Implemented concept of colour scales

parent 3a175449
......@@ -2,6 +2,7 @@ ABOVE_ELEMENT=above
BELOW_ELEMENT=below
BLINK_ON_OUT_OF_RANGE_NODE=blinkOnOutOfRange
CAPPED_DISPLAY_NODE=cappedDisplay
COLOUR_SCALE_NODE=colourScale
FACE_IS_TOUCHABLE_NODE=faceIsTouchable
ITEMS_VARIABLE_NODE=itemsVariable
HTML_TEMPLATE_NODE=htmlTemplate
......@@ -9,13 +10,14 @@ LABEL_NODE=label
LOWER_BOUND_RADIUS_NODE=lowerBoundRadius
LOWER_BOUND_VARIABLE_NODE=lowerBoundVariable
LOWER_STOP_ANGLE_NODE=lowerStopAngle
MAPPING_NODE=mapping
MAXIMUM_VALUE_NODE=maximumValue
MINIMUM_VALUE_NODE=minimumValue
MODIFY_VALUE_ON_ROTATION_NODE=modifyValueOnRotation
MULTITURN_NODE=multiTurn
RADIAL_LAYOUT_NODE=radialLayout
REFERENCE_NODE=reference
RELATIVE_NODE=relative
SCALES_NODE=scales
SELECTED_ITEMS_VARIABLE_NODE=selectedItemsVariable
SELECTED_RADIUS_NODE=selectedRadius
STEP_SIZE_NODE=stepSize
......
......@@ -31,6 +31,7 @@ public class CpsNamespace extends NLS {
public static String BLINK_ON_OUT_OF_RANGE_NODE;
public static String CAPPED_DISPLAY_NODE;
public static String COLOUR_SCALE_NODE;
public static String FACE_IS_TOUCHABLE_NODE;
public static String HTML_TEMPLATE_NODE;
......@@ -43,16 +44,19 @@ public class CpsNamespace extends NLS {
public static String LOWER_BOUND_VARIABLE_NODE;
public static String LOWER_STOP_ANGLE_NODE;
public static String MAPPING_NODE;
public static String MAXIMUM_VALUE_NODE;
public static String MINIMUM_VALUE_NODE;
public static String MODIFY_VALUE_ON_ROTATION_NODE;
public static String MULTITURN_NODE;
public static String RADIAL_LAYOUT_NODE;
public static String REFERENCE_NODE;
public static String RELATIVE_NODE;
public static String SCALES_NODE;
public static String SELECTED_ITEMS_VARIABLE_NODE;
public static String SELECTED_RADIUS_NODE;
public static String STEP_SIZE_NODE;
......
......@@ -23,7 +23,7 @@ package lu.list.itis.dkd.tui.utility;
// * Class Definition and Members *
// ***************************************************************************
public class ValueRange<T> {
public class ValueRange<T extends Comparable<T>> implements Comparable<T> {
private T lowerValue;
private T upperValue;
......@@ -42,6 +42,13 @@ public class ValueRange<T> {
// ***************************************************************************
// * Class Body
// ***************************************************************************
// ---------------------------------------------------------------------------
@SuppressWarnings("unchecked")
public Class<T> getClassOfValues() {
return (Class<T>) this.lowerValue.getClass();
}
// ---------------------------------------------------------------------------
/**
* Simple getter method for lowerValue.
......@@ -92,4 +99,37 @@ public class ValueRange<T> {
this.upperValue = upperValue;
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
// ---------------------------------------------------------------------------
@Override
public int compareTo(T candidate) {
int comparison = candidate.compareTo(lowerValue);
if (comparison >= 0) {
comparison = candidate.compareTo(upperValue);
if (comparison <= 0) {
comparison = 0;
}
}
return comparison;
}
// ---------------------------------------------------------------------------
@Override
public String toString() {
StringBuilder builder = new StringBuilder("[");
builder.append((lowerValue != null) ? lowerValue : "null");
builder.append(" <=> ");
builder.append((upperValue != null) ? upperValue : "null");
builder.append("]");
return builder.toString();
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved. If you wish
* to use this code for any purpose, please contact the author(s).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lu.list.itis.dkd.tui.utility.scales;
import lu.list.itis.dkd.tui.utility.ValueRange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 2.5.0
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class ColourMapping<T extends Comparable<T>> {
private Color colour;
private ValueRange<T> range;
// ***************************************************************************
// * Constants *
// ***************************************************************************
private static final Logger LOGGER = LoggerFactory.getLogger(ColourMapping.class.getSimpleName());
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
public ColourMapping(ValueRange<T> range, Color colour) {
this.range = range;
this.colour = colour;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
public Class<T> getMappedClass() {
return this.range.getClassOfValues();
}
// ---------------------------------------------------------------------------
/**
* Simple getter method for colour.
*
* @return The value of colour.
*/
// ---------------------------------------------------------------------------
public Color getColour() {
return colour;
}
// ---------------------------------------------------------------------------
/**
* Simple setter method for colour.
*
* @param colour
* The value to set colour to.
*/
// ---------------------------------------------------------------------------
public void setColour(Color colour) {
this.colour = colour;
}
// ---------------------------------------------------------------------------
/**
* Simple getter method for range.
*
* @return The value of range.
*/
// ---------------------------------------------------------------------------
public ValueRange<T> getRange() {
return range;
}
// ---------------------------------------------------------------------------
/**
* Simple setter method for range.
*
* @param range
* The value to set range to.
*/
// ---------------------------------------------------------------------------
public void setRange(ValueRange<T> range) {
this.range = range;
}
// ---------------------------------------------------------------------------
/**
* Checks whether the specified value is inside this mappings' range.
*
* @param value
* specifies the value to be checked.
* @return <code>true</code> if specified value falls within this mappings' value range,
* <code>false</code> otherwise
*/
// ---------------------------------------------------------------------------
public boolean inRange(T value) {
boolean inRange = (range.compareTo(value) == 0);
if (LOGGER.isTraceEnabled() && inRange) {
LOGGER.trace("{} in range of {}", value, range);
}
return inRange;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved. If you wish
* to use this code for any purpose, please contact the author(s).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lu.list.itis.dkd.tui.utility.scales;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.bootstrapping.BootstrappingUtils;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.ColorFactory;
import lu.list.itis.dkd.tui.utility.CpsNamespace;
import lu.list.itis.dkd.tui.utility.Externalization;
import lu.list.itis.dkd.tui.utility.StringUtils;
import lu.list.itis.dkd.tui.utility.ValueRange;
import org.jdom2.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 2.5.0
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class ColourScale<T extends Comparable<T>> {
private String name;
private List<ColourMapping<T>> mappings;
private Color defaultColour;
// ***************************************************************************
// * Constants *
// ***************************************************************************
private static final String AUTO = "auto"; //$NON-NLS-1$
private static final Logger LOGGER = LoggerFactory.getLogger(ColourScale.class.getSimpleName());
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
public ColourScale() {
this.mappings = new ArrayList<>();
this.defaultColour = Color.WHITE;
}
// ---------------------------------------------------------------------------
public ColourScale(Element rootElement) throws BuildException {
this.mappings = new ArrayList<>();
this.buildFromBootstrap(rootElement);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitives *
// ***************************************************************************
// ---------------------------------------------------------------------------
private void buildFromBootstrap(@Nullable Element rootElement) throws BuildException {
name = BootstrappingUtils.getAttributeAsString(rootElement, Externalization.NAME_NODE, BootstrappingUtils.MANDATORY, null);
defaultColour = new Color(StringUtils.getIntegerValue(BootstrappingUtils.getAttributeAsString(rootElement, Externalization.DEFAULT_NODE, BootstrappingUtils.OPTIONAL, "0xFFFFFF")));
List<Element> mappingElements = rootElement.getChildren(CpsNamespace.MAPPING_NODE);
if ((mappingElements != null) && !mappingElements.isEmpty()) {
List<Color> automaticColours = ColorFactory.makeRainbowColours(mappingElements.size());
Iterator<Color> colourIterator = automaticColours.iterator();
for (Element mapping : mappingElements) {
this.mappings.add(this.buildValueRange(mapping, colourIterator.next()));
}
}
}
// ---------------------------------------------------------------------------
@SuppressWarnings("unchecked")
private ColourMapping<T> buildValueRange(@Nullable Element rootElement, Color automaticColour) throws BuildException {
ColourMapping<T> mapping;
double lowerBound = BootstrappingUtils.getAttributeAsDouble(rootElement, Externalization.LOWER_BOUND_NODE, BootstrappingUtils.MANDATORY, null);
double upperBound = BootstrappingUtils.getAttributeAsDouble(rootElement, Externalization.UPPER_BOUND_NODE, BootstrappingUtils.MANDATORY, null);
String colourNode = BootstrappingUtils.getAttributeAsString(rootElement, Externalization.COLOUR_NODE, BootstrappingUtils.MANDATORY, null);
Color colour;
if (AUTO.equals(colourNode)) {
colour = automaticColour;
} else {
colour = new Color(StringUtils.getIntegerValue(colourNode));
}
ValueRange<Double> range = new ValueRange<>(lowerBound, upperBound);
mapping = (ColourMapping<T>) new ColourMapping<>(range, colour);
return mapping;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
public String getName() {
return this.name;
}
// ---------------------------------------------------------------------------
public boolean addMapping(ColourMapping<T> mapping) {
return this.mappings.add(mapping);
}
// ---------------------------------------------------------------------------
/**
* Returns the matching colour for the specified value if a corresponding colour mapping is
* available for this scale. If no such mapping is found, then this scales' default colour is
* returned.
*
* @param value
* specifies the value to get matching colour for.
* @return the colour defined by this scale for the specified value.
*/
// ---------------------------------------------------------------------------
public Color getColourFor(T value) {
for (ColourMapping<T> mapping : mappings) {
if (mapping.inRange(value)) {
return mapping.getColour();
}
}
return this.defaultColour;
}
// ---------------------------------------------------------------------------
/**
* Returns the matching colour for the specified value if a corresponding colour mapping is
* available for this scale. If no such mapping is found, then this scales' default colour is
* returned.
*
* @param value
* specifies the value to get matching colour for.
* @return the colour defined by this scale for the specified value.
*/
// ---------------------------------------------------------------------------
@SuppressWarnings("unchecked")
public Color getColourFor(Object value) {
for (ColourMapping<T> mapping : mappings) {
if (mapping.getMappedClass().isAssignableFrom(value.getClass())) {
if (mapping.inRange((T) value)) {
return mapping.getColour();
}
}
}
return this.defaultColour;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved. If you wish
* to use this code for any purpose, please contact the author(s).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lu.list.itis.dkd.tui.utility.scales;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.CpsNamespace;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 1.0
* @version 1.0.0
* @param <T>
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class ScaleSystemBuilder {
private Document scenarioDocument;
private Map<String, ColourScale<?>> scales = new HashMap<>();
// ***************************************************************************
// * Constants *
// ***************************************************************************
private static final Logger LOGGER = LoggerFactory.getLogger(ScaleSystemBuilder.class.getSimpleName());
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s)
// ***************************************************************************
// ---------------------------------------------------------------------------
public ScaleSystemBuilder(File scenario) throws ScaleSystemException {
SAXBuilder builder = new SAXBuilder();
try {
scenarioDocument = builder.build(scenario);
} catch (IOException | JDOMException e) {
LOGGER.error("Error occured while trying to process the object bootstrapping file!", e); //$NON-NLS-1$
throw new ScaleSystemException("The document containing the bootstrapping information could not be processed!"); //$NON-NLS-1$
}
Element rootNode = this.scenarioDocument.getRootElement();
try {
this.buildFromElement(rootNode.getChild(CpsNamespace.SCALES_NODE));
} catch (BuildException exception) {
LOGGER.error("Error occured while building scale system!", exception); //$NON-NLS-1$
throw new ScaleSystemException("Failed to build scale system!"); //$NON-NLS-1$
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitives
// ***************************************************************************
// ---------------------------------------------------------------------------
private void buildFromElement(Element scalesNode) throws BuildException {
if ((scalesNode != null) && scalesNode.getName().equalsIgnoreCase(CpsNamespace.SCALES_NODE)) {
List<Element> colourScales = scalesNode.getChildren(CpsNamespace.COLOUR_SCALE_NODE);
if ((colourScales != null) && !colourScales.isEmpty()) {
for (Element scaleElement : colourScales) {
ColourScale<?> scale = new ColourScale<>(scaleElement);
this.scales.put(scale.getName(), scale);
}
}
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body
// ***************************************************************************
// ---------------------------------------------------------------------------
public ColourScale<?> getScale(String scaleName) {
return this.scales.get(scaleName);
}
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2016.
*
* This file is part of TULIP.
*
* TULIP is licensed under a dual-licensing scheme. For non-commercial purposes, the LGPL version 3,
* as stated below, is applicable. For all commercial purposes TULIP is licensed under a LIST
* proprietary license. Please contact LIST at tto@list.lu to obtain a commercial license.
*
* For all non-commercial purposes, TULIP is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, version 3 of the License.
*
* TULIP 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 Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.utility.scales;
/**
*
* @author Nico Mack [nico.mack@list.lu]
* @since 1.1
* @version 1.3.0
*/
public class ScaleSystemException extends Exception {
/**
*
*/
private static final long serialVersionUID = 7422560120940501724L;
/**
*
* @param reason
*/
public ScaleSystemException(String reason) {
super(reason);
}
}
\ No newline at end of file
......@@ -126,7 +126,7 @@ public abstract class BaseCoxcombSliceBuilder<B extends BaseCoxcombSliceBuilder<
label = BootstrappingUtils.getContentAsString(rootElement, CpsNamespace.LABEL_NODE, BootstrappingUtils.OPTIONAL, Externalization.EMPTY_STRING, context);
radialLayout = BootstrappingUtils.getContentAsBoolean(rootElement, CpsNamespace.RADIAL_LAYOUT_NODE, BootstrappingUtils.OPTIONAL, Boolean.FALSE, context);
radialLayout = BootstrappingUtils.getContentAsBoolean(rootElement, Externalization.RADIAL_LAYOUT_NODE, BootstrappingUtils.OPTIONAL, Boolean.FALSE, context);
cappedDisplay = BootstrappingUtils.getContentAsBoolean(rootElement, CpsNamespace.CAPPED_DISPLAY_NODE, BootstrappingUtils.OPTIONAL, Boolean.FALSE, context);
blinkOnOutOfRange = BootstrappingUtils.getContentAsBoolean(rootElement, CpsNamespace.BLINK_ON_OUT_OF_RANGE_NODE, BootstrappingUtils.OPTIONAL, Boolean.FALSE, context);
faceIsTouchable = BootstrappingUtils.getContentAsBoolean(rootElement, CpsNamespace.FACE_IS_TOUCHABLE_NODE, BootstrappingUtils.OPTIONAL, Boolean.FALSE, context);
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved. If you wish
* to use this code for any purpose, please contact the author(s).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lu.list.itis.dkd.tui.utility;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
*/
public class ValueRangeTest {
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {}
@Test
public void testCompareTo() {
ValueRange<Double> range = new ValueRange<>(0.25d, 0.75d);
assertTrue(range.compareTo(0.15) < 0);
assertTrue(range.compareTo(0.25) == 0);
assertTrue(range.compareTo(0.56) == 0);
assertTrue(range.compareTo(0.75) == 0);
assertTrue(range.compareTo(0.76) > 0);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment