RoboTweaker/Props.java

From Robowiki
< RoboTweaker
Revision as of 17:57, 13 May 2016 by RobertWalker (talk | contribs) (Moved source for Props.java to its own page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
import java.lang.reflect.Method;

/**
 * Reads values from system properties and coerces them to various types. If a property is null, the
 * indicated default value will be returned instead. This is useful for allowing your robot's
 * constants to be overridden, and this mechanism is used in RoboTweaker for automated testing of a
 * range of values. This object is intended to be stored statically for use throughout your robot.
 * 
 * All keys provided to get() methods will have a prefix applied to them. This prefix is specified
 * in the constructor, and it is suggested that you use your robot's name as the prefix.
 * 
 * Example: Say your robot named me.MyRobot has the following constant:
 * 
 * private static final double FIRE_POWER = 3.0;
 * 
 * After reading the Selecting Fire Power article on RoboWiki, you begin to wonder whether it might
 * not be a good idea to experiment with the amount of energy you pour into each shot. To allow you
 * to modify this constant without having to change your code each time, you can change it to look
 * like this:
 * 
 * private static final Props PROPS = new Props("me.MyRobot");
 * private static final double FIRE_POWER = PROPS.get("firePower", 3.0);
 * 
 * This will cause your robot to check for a system property named "me.MyRobot.firePower". If it
 * exists, it will be coerced to a double, and FIRE_POWER will be set to that value. If it doesn't
 * exist, it will fall back to the specified default value, 3.0.
 * 
 * You can now use an automated tool such as RoboTweaker to test various values for FIRE_POWER and
 * find out what works best for your robot.
 */
public class Props {
	private String prefix;

	public Props(String prefix) {
		this.prefix = prefix + ".";
	}

	public boolean get(String key, boolean def) {
		String value = get(key);
		return value != null ? Boolean.parseBoolean(value) : def;
	}

	public int get(String key, int def) {
		String value = get(key);
		return value != null ? Integer.parseInt(value) : def;
	}

	public long get(String key, long def) {
		String value = get(key);
		return value != null ? Long.parseLong(value) : def;
	}

	public float get(String key, float def) {
		String value = get(key);
		return value != null ? Float.parseFloat(value) : def;
	}

	public double get(String key, double def) {
		String value = get(key);
		return value != null ? Double.parseDouble(value) : def;
	}

	@SuppressWarnings("unchecked")
	public <T extends Enum<?>> T get(String key, Class<T> enumClass, T def) {
		String value = get(key);

		if (value != null) {
			try {
				Method method = enumClass.getMethod("name", String.class);
				return (T) method.invoke(null, key);
			} catch (ReflectiveOperationException ex) {
				throw new RuntimeException(ex);
			}
		}

		return def;
	}

	public String get(String key, String def) {
		return System.getProperty(prefix + key, def);
	}

	private String get(String key) {
		return System.getProperty(prefix + key);
	}
}