/*
* Copyright (C) 2011 Laurent Caillette
*
* This program 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, 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/>.
*/
package org.novelang.novelist;
import java.util.Random;
import com.google.common.base.Preconditions;
/**
* Various manipulation primitives for bounded values.
*
* @author Laurent Caillette
*/
public class Bounded {
private Bounded() { }
// ==========
// Percentage
// ==========
public static Percentage newPercentage( final float value ) {
return new Percentage( value ) ;
}
public static Percentage newPercentage( final Random random ) {
return newPercentage( percentage( random ) ) ;
}
private static float percentage( final Random random ) {
return ( float ) ( 100.0 * Math.abs( random.nextDouble() ) ) ;
}
/**
* A fractional value between 0 and 100.
*
* @author Laurent Caillette
*/
public static class Percentage {
private final float value ;
private Percentage( final float value ) {
Preconditions.checkArgument( isValid( value ) ) ;
this.value = value ;
}
public static boolean isValid( final Float value ) {
return ( value != null ) && ( value >= 0.0f ) && ( value <= 100.0f ) ;
}
public boolean hit( final Random random ) {
return percentage( random ) < value;
}
public boolean isStrictlySmallerThan( final float other ) {
return value < other ;
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + value + "]" ;
}
}
// =====
// Range
// =====
public static IntegerInclusiveExclusive newInclusiveRange(
final int lowerBoundInclusive,
final int upperBoundInclusive
) {
return new IntegerInclusiveExclusive( lowerBoundInclusive, upperBoundInclusive + 1 ) ;
}
/**
* Range defined by two positive integers.
*
* @author Laurent Caillette
*/
public static class IntegerInclusiveExclusive {
private final int lowerBoundInclusive ;
private final int upperBoundExclusive;
private IntegerInclusiveExclusive(
final int lowerBoundInclusive,
final int upperBoundExclusive
) {
Preconditions.checkArgument( lowerBoundInclusive >= 0 ) ;
// This is required by Random.nextInt( int ).
Preconditions.checkArgument( upperBoundExclusive > lowerBoundInclusive ) ;
this.lowerBoundInclusive = lowerBoundInclusive ;
this.upperBoundExclusive = upperBoundExclusive;
}
public int boundInteger( final Random random ) {
return
lowerBoundInclusive +
random.nextInt( upperBoundExclusive - lowerBoundInclusive )
;
}
}
}