Package naturalLanguage

Source Code of naturalLanguage.Units

package naturalLanguage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import lipstone.joshua.customStructures.lists.SortedList;
import lipstone.joshua.parser.Parser;
import lipstone.joshua.parser.exceptions.ParserException;
import lipstone.joshua.parser.types.BigDec;
import lipstone.joshua.parser.util.ConsCell;
import lipstone.joshua.parser.util.ConsType;
import lipstone.joshua.parser.util.LengthComparison;

public class Units {
  private HashMap<String, Unit> units;
  private static final String[] SI = {"meter", "second", "gram", "ampere", "kelvin", "mole", "candela", "byte"};
  private HashMap<String, BigDec> prefixes;
  private HashMap<String, String> abbreviatedPrefixes;
  private TreeMap<String, String> unitAbbreviations;
  private final NaturalLanguage nl;
  private static final String prefixAbbreviations = "(y|z|a|f|p|n|m|c|d|da|h|k|M|G|T|P|E|Y)";
  private static final String[] alphabet = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
  private SortedList<String> allUnits;
  private static final BigDec TEN = new BigDec(10);
  private Parser parser;
 
  public Units(Parser parser, NaturalLanguage nl) {
    this.parser = parser;
    this.nl = nl;
    units = new HashMap<String, Unit>();
    prefixes = new HashMap<String, BigDec>();
    abbreviatedPrefixes = new HashMap<String, String>();
    unitAbbreviations = new TreeMap<String, String>(new LengthComparison());
    allUnits = new SortedList<String>(new LengthComparison());
   
    //I know, but it is slightly faster than using an array and iterating through while converting to BigDec
    prefixes.put("yocto", new BigDec(-8));
    prefixes.put("zepto", new BigDec(-7));
    prefixes.put("atto", new BigDec(-6));
    prefixes.put("femto", new BigDec(-5));
    prefixes.put("pico", new BigDec(-4));
    prefixes.put("nano", new BigDec(-3));
    prefixes.put("micro", new BigDec(-2));
    prefixes.put("milli", new BigDec(-1));
    prefixes.put("mili", new BigDec(-1));
    prefixes.put("centi", new BigDec(-2.0 / 3.0));
    prefixes.put("deci", new BigDec(-1.0 / 3.0));
    prefixes.put("deca", new BigDec(1.0 / 3.0));
    prefixes.put("hecto", new BigDec(2.0 / 3.0));
    prefixes.put("milli", BigDec.ONE);
    prefixes.put("kilo", BigDec.ONE);
    prefixes.put("mega", new BigDec(2));
    prefixes.put("giga", new BigDec(3));
    prefixes.put("tera", new BigDec(4));
    prefixes.put("peta", new BigDec(5));
    prefixes.put("exa", new BigDec(6));
    prefixes.put("zetta", new BigDec(7));
    prefixes.put("yotta", new BigDec(8));
   
    abbreviatedPrefixes.put("y", "yocto");
    abbreviatedPrefixes.put("z", "zepto");
    abbreviatedPrefixes.put("a", "atto");
    abbreviatedPrefixes.put("f", "femto");
    abbreviatedPrefixes.put("p", "pico");
    abbreviatedPrefixes.put("n", "nano");
    abbreviatedPrefixes.put("m", "milli");
    abbreviatedPrefixes.put("c", "centi");
    abbreviatedPrefixes.put("d", "deci");
    abbreviatedPrefixes.put("da", "deca");
    abbreviatedPrefixes.put("h", "hecto");
    abbreviatedPrefixes.put("k", "kilo");
    abbreviatedPrefixes.put("M", "mega");
    abbreviatedPrefixes.put("G", "giga");
    abbreviatedPrefixes.put("T", "tera");
    abbreviatedPrefixes.put("P", "peta");
    abbreviatedPrefixes.put("E", "exa");
    abbreviatedPrefixes.put("Y", "yotta");
   
    loadUnits();
  }
 
  /**
   * Run a unit conversion
   *
   * @param input
   *            the unit conversion
   * @param parser
   *            the parser that precipitated this method call
   * @return the units converted from the input units to the output units
   * @throws ParserException
   */
  public BigDec convertUnits(ConsCell leftUnits, ConsCell rightUnits) throws ParserException {
    return getFactor(leftUnits).divide(getFactor(rightUnits));
  }
 
  private BigDec getFactor(ConsCell units) throws ParserException {
    ConsCell current = units;
    BigDec factor = BigDec.ONE;
    do {
      boolean divide = current.getPreviousConsCell().getCarType() == ConsType.OPERATOR && (char) current.getPreviousConsCell().getCar() == '/';
      BigDec partial;
      if (current.getCarType() == ConsType.IDENTIFIER) {
        String[] unit = stripPrefix((String) current.getCar());
        partial = this.units.get(unit[1]).getFactor();
        if (partial == null)
          throw new InvalidUnitException(current.getCar() + " is not a valid unit.", nl);
        if (unit[0].length() > 0)
          partial = partial.multiply(prefixes.get(unit[0]));
      }
      else if (current.getCarType() == ConsType.CONS_CELL) {
        ConsCell fact = parser.run(parser.preProcess((ConsCell) current.getCar()));
        if (fact.getCarType() != ConsType.NUMBER || fact.length() != 1)
          throw new InvalidUnitException(current.getCar() + " is not a valid unit set.", nl);
        partial = (BigDec) fact.getCar();
      }
      else
        continue;
      if (current.getNextConsCell().getCarType() == ConsType.OPERATOR && (char) current.getNextConsCell().getCar() == '^') {
        current.getNextConsCell().remove();
        ConsCell power = current.getNextConsCell().singular();
        if (power.getCarType() == ConsType.OPERATOR)
          power.append(current.getNextConsCell().remove().singular());
        else if (power.getCarType() == ConsType.CONS_CELL)
          power = (ConsCell) power.getCar();
        current.getNextConsCell().remove();
        power = parser.run(parser.preProcess(power));
        if (power.getCarType() != ConsType.NUMBER || power.length() != 1)
          throw new InvalidUnitException(current.getCar() + " is raised to an invalid power.", nl);
        partial = partial.pow((BigDec) power.getCar());
      }
      factor = divide ? factor.divide(partial) : factor.multiply(partial);
    } while (!(current = current.getNextConsCell()).isNull());
    return factor;
  }
 
  private String[] stripPrefix(String unit) throws InvalidUnitException {
    Matcher m = nl.getPrefixPattern().matcher(unit);
    if (m.find() && m.start() == 0 && units.containsKey(unit.substring(m.end())))
      return new String[]{nl.getAbbreviationPrefixes().get(m.group()), unit.substring(m.end())};
    for (String prefix : nl.getAbbreviationPrefixes().values())
      if ((m = Pattern.compile(prefix).matcher(unit)).find() && m.start() == 0 && units.containsKey(unit.substring(m.end())))
        return new String[]{m.group(), unit.substring(m.end())};
    return new String[]{"", unit};
  }
 
  /*String convertUnits(String input, Parser parser) throws NumberFormatException, ParserException {
    String output = "";
    input = NaturalLanguage.parse(input, parser);
    //Split the input string into its three subcomponents: quantity, initial units, final units
    ArrayList<String> parts = parser.fromCommaList(input);
    parts.set(0, temperatureUnits(parts, parser));
    parts.set(1, expandAbbreviations(parts.get(1)));
    parts.set(2, expandAbbreviations(parts.get(2)));
    for (int i = 1; i < parts.size(); i++) {
      parts.set(i, parts.get(i).replaceAll("[/\\\\]", " per "));
      parts.set(i, parts.get(i).replaceAll("\\Q*\\E", " "));
      //In case the other replacements cause multiple spaces
      while (parts.get(i).contains("  "))
        parts.set(i, parts.get(i).replaceAll("  ", " "));
    }
    //Determine the conversion factor
    BigDec factors[] = {BigDec.ONE, BigDec.ONE};
    for (int i = 0; i < 2; i++)
      factors[i] = getFactor(parts.get(i + 1), parser);
    //Convert the units
    output = parser.run(parser.preProcess(parts.get(0) + "*" + factors[0] + "/" + factors[1]));
    return output;
  }
 
  String expandAbbreviations(String input) {
    for (String abbreviation : unitAbbreviations.keySet())
      input = input.replaceAll("\\b" + abbreviation + "\\b", unitAbbreviations.get(abbreviation));
   
    for (Unit unit : units) {
      Pattern p = Pattern.compile("\\b" + prefixAbbreviations + "(" + unit.getName() + ")\\b");
      Matcher m = p.matcher(input);
      while (m.find()) {
        input = input.substring(0, m.start(1)) + abbreviatedPrefixes.get(m.group(1)) + input.substring(m.start(2));
        m = p.matcher(input);
      }
      p = Pattern.compile("\\b" + prefixAbbreviations + "(" + unit.getAbbreviations() + ")\\b");
      m = p.matcher(input);
      while (m.find()) {
        input = input.substring(0, m.start(1)) + abbreviatedPrefixes.get(m.group(1)) + unitAbbreviations.get(m.group(2)) + input.substring(m.end(2));
        m = p.matcher(input);
      }
    }
    return input;
  }
 
  private BigDec getFactor(String unit, Parser parser) throws UndefinedResultException, UnbalancedParenthesesException {
    BigDec factor = BigDec.ONE;
    //Get the units
    ArrayList<String> Units = new ArrayList<String>();
    for (String str : unit.trim().split(" "))
      Units.add(str);
    Units = exponents(Units);
    int per = 0;
    boolean perParen = false, hasEnd = false;
    for (int a = 0; a < Units.size(); a++) {
      String u = Units.get(a);
      BigDec tempFactor = BigDec.ZERO;
      if (u.equalsIgnoreCase("per")) {
        if (a < Units.size() - 1 && Units.get(a + 1).charAt(0) == '(')
          perParen = !perParen;
        per++;
        a++;
        u = Units.get(a);
      }
      for (int b = 0; b < units.size(); b++) {
        Matcher m = Pattern.compile(units.get(b).getName(), Pattern.CASE_INSENSITIVE).matcher(u);
        while (m.find()) {
          BigDec power = BigDec.ONE, prefix = BigDec.ZERO;
          int end = 0;
          String tempKey = u.substring(0, m.start()).trim().toLowerCase();
          if (prefixes.containsKey(tempKey))
            prefix = prefix.add(prefixes.get(tempKey));
         
          if (m.end() < u.length() - 1 && u.charAt(m.end()) == '^') {
            if (u.charAt(m.end() + 1) == '(') {
              end = parser.getEndIndex(u, m.end() + 1);
              hasEnd = true;
            }
            else if (u.indexOf(')', m.end()) == -1)
              end = u.length();
            else
              end = u.length() - 1;
            power = power.multiply(new BigDec(u.substring(m.end() + 1, end)));
          }
          else if (m.end() < u.length() - 2 && u.charAt(m.end()) == 's' && u.charAt(m.end() + 1) == '^') {
            if (u.charAt(m.end() + 2) == '(') {
              end = parser.getEndIndex(u, m.end() + 2);
              hasEnd = true;
            }
            else if (u.indexOf(')', m.end()) == -1)
              end = u.length();
            else
              end = u.length() - 1;
            power = power.multiply(new BigDec(u.substring(m.end() + 2, end)));
          }
          if (!isSI(units.get(b).getName()))
            tempFactor = getFactor(units.get(b).getSI(), parser).multiply(new BigDec(units.get(b).getFactor())).multiply(new BigDec(1000).pow(new BigDec(prefix))).pow(power);
          else
            tempFactor = new BigDec(units.get(b).getFactor()).multiply(new BigDec(1000).pow(new BigDec(prefix))).pow(power);
        }
      }
      if (per >= 1 || perParen) {
        tempFactor = tempFactor.pow(BigDec.MINUSONE);
        if (!perParen)
          per--;
      }
      if (hasEnd && per >= 1) {
        perParen = !perParen;
        per--;
      }
      if (tempFactor.neq(BigDec.ZERO))
        factor = factor.multiply(tempFactor);
    }
    return factor;
  }
 
  private String temperatureUnits(ArrayList<String> parts, Parser parser) throws ParserException {
    BigDec temperature = new BigDec(parser.run(parts.get(0)));
    //Convert to Kelvin
    if (parts.size() < 3)
      return parts.get(0);
    for (int i = 0; i < parts.size(); i++)
      if (!(parts.get(i) == null) && parts.get(i).length() < 1)
        return parts.get(0);
    if (parts.get(1).contains("fahrenheit") || parts.get(1).contains("farenheit") || parts.get(1).contains("Fahrenheit") || parts.get(1).contains("Farenheit"))
      temperature = new BigDec(parser.run("5/9*(" + temperature + "+459.67)"));
    if (parts.get(1).contains("Celcius") || parts.get(1).contains("celcius"))
      temperature = temperature.add(new BigDec(273.15));
    //Now convert to the end scale
    if (parts.get(2).contains("fahrenheit") || parts.get(2).contains("farenheit") || parts.get(2).contains("Fahrenheit") || parts.get(2).contains("Farenheit"))
      temperature = new BigDec(parser.run(temperature.toString() + "*9/5-459.67"));
    if (parts.get(2).contains("Celcius") || parts.get(2).contains("celcius"))
      temperature = temperature.subtract(new BigDec(273.15));
    return temperature.toString();
  }
 
  public String DecimaltoIEEE754(String input, Parser parser) throws ParserException {
    ArrayList<String> parts = parser.fromCommaList(input);
    int exp = parser.IEEE754exp, sig = parser.IEEE754sig;
    if (parts.size() == 3) {
      try {
        exp = Integer.parseInt(parts.get(1));
        sig = Integer.parseInt(parts.get(2));
      }
      catch (NumberFormatException nfe) {}
    }
    return DecimaltoIEEE754(input, exp, sig, parser);
  }
 
  public String DecimaltoIEEE754(String input, int exp, int sig, Parser parser) throws ParserException {
    input = parser.run(parser.preProcess(input));
    BigDec number;
    try {
      number = new BigDec(input);
    }
    catch (NumberFormatException e) {
      return input;
    }
    String[] parts = new String[]{"0", "", "1"};
    if (number.lt(BigDec.ZERO)) //if number is negative, set the sign bit to 1
      parts[0] = "1";
    parts[2] = convertBases(input, TEN, new BigDec(2));
    String[] baseExp = scientificNotation(parts[2], true, parser);
    parts[1] = convertBases(parser.run(baseExp[1] + "+" + new Double((Math.pow(2, exp - 1) - 1)).toString()), TEN, new BigDec(2));
    parts[2] = baseExp[0].replaceAll("\\Q.\\E", "");
    if (parts[2].length() > 0)
      parts[2] = parts[2].substring(1);
    while (parts[1].length() < exp)
      parts[1] = "0" + parts[1];
    while (parts[2].length() < sig)
      parts[2] = parts[2] + "0";
   
    return parts[0] + parts[1] + parts[2];
  }
 
  public String IEEE754toDecimal(String input, Parser parser) throws ParserException {
    ArrayList<String> parts = parser.fromCommaList(input);
    int exp = parser.IEEE754exp, sig = parser.IEEE754sig;
    if (parts.size() == 3) {
      try {
        exp = Integer.parseInt(parts.get(1));
        sig = Integer.parseInt(parts.get(2));
      }
      catch (NumberFormatException nfe) {}
    }
    return IEEE754toDecimal(input, exp, sig, parser);
  }
 
  public String IEEE754toDecimal(String input, int exp, int sig, Parser parser) throws ParserException {
    String output = "";
    input = parser.run(parser.preProcess(input));
    System.out.println("in: " + input);
    input = fromScientificNotation(input);
    System.out.println("in: " + input);
    if (input.length() != (1 + exp + sig) || !parser.isNumber(input))
      return input;
    String[] parts = new String[3];
    parts[0] = input.substring(0, 1);
    parts[1] = input.substring(1, exp + 1);
    parts[2] = input.substring(exp + 2);
    if (parts[0].charAt(0) == '1')
      output = "-";
    parts[1] = parser.run(convertBases(parts[1], new BigDec(2), TEN) + "-" + (Math.pow(2, exp - 1) - 1));
    parts[2] = "1" + parts[2].substring(0, new Double(parts[1]).intValue()) + "." + parts[2].substring(new Double(parts[1]).intValue());
    output = output + parts[2];
    return output;
  }
 
  public String convertBases(String input, Parser parser) throws ParserException {
    String number = "";
    BigDec initialBase = BigDec.ZERO, finalBase = TEN;
    ArrayList<String> parts = parser.fromCommaList(input);
    try {
      initialBase = new BigDec(parser.run(parser.preProcess(parts.get(1))));
    }
    catch (NumberFormatException e) {
      if (parts.get(1).equalsIgnoreCase("IEEE754")) {
        parts.set(0, IEEE754toDecimal(parts.get(0), parser));
        initialBase = TEN;
      }
    };
    if (parts.size() > 2)
      try {
        finalBase = new BigDec(parser.run(parser.preProcess(parts.get(2))));
      }
      catch (NumberFormatException e) {
        if (parts.get(2).equalsIgnoreCase("IEEE754")) {
          parts.set(0, IEEE754toDecimal(parts.get(0), parser));
          initialBase = TEN;
        }
      }
    if (initialBase.eq(TEN))
      number = parser.run(parser.preProcess(parts.get(0)));
    else
      number = parts.get(0);
    System.out.println(number);
    return convertBases(number, initialBase, finalBase);
  }
 
  public String convertBases(String number, BigDec initialBase, BigDec finalBase) throws UndefinedResultException {
    if (number.length() < 1 || initialBase.lt(BigDec.ONE) || finalBase.lt(BigDec.ONE))
      return "0.0";
    if (initialBase.neq(TEN))
      number = NtoDecimal(number, initialBase);
    if (finalBase.neq(TEN))
      number = DecimaltoN(number, finalBase);
    if (number.length() > 1 && number.charAt(number.length() - 1) == '.')
      number = number.substring(0, number.length() - 1);
    return number;
  }
 
  public String NtoDecimal(String number, BigDec initialBase) throws UndefinedResultException {
    BigDec output = BigDec.ZERO;
    if (!number.contains("."))
      number = number + ".";
    int power = number.indexOf(".");
    number = number.replaceAll("\\Q.\\E", "");
    for (int i = 0; i < number.length(); i++) {
      try {
        output = output.add(new BigDec(number.substring(i, i + 1)).multiply(initialBase.pow(new BigDec(power - i - 1))));
      }
      catch (NumberFormatException e) {
        if (betNum(number.charAt(i)) >= 0)
          output = output.add(TEN.add(new BigDec(betNum(number.charAt(i)))).multiply(initialBase.pow(new BigDec(power - i - 1))));
      }
    }
    return output.toString();
  }
 
  public String DecimaltoN(String number, BigDec finalBase) throws UndefinedResultException {
    String output = "";
    BigDec input = BigDec.ZERO;
    try {
      input = new BigDec(number);
    }
    catch (NumberFormatException e) {
      return "0.0";
    }
    while (input.neq(BigDec.ZERO)) {
      int temp = input.mod(finalBase).intValue();
      if (temp > 9)
        output = alphabet[temp - 10] + output;
      else
        output = temp + output;
      input = new BigDec(input.divide(finalBase).toBigInt());
    }
    if (output.length() > 1 && output.charAt(0) == '0')
      output = output.substring(1);
    if (number.contains(".")) {
      String decimal = fromScientificNotation(number), decOut = "";
      decimal = decimal.substring(decimal.indexOf("."));
      int max = (int) (decimal.length() * 1.5), i = 0;
      BigDec dec = BigDec.ZERO;
      do {
        try {
          dec = new BigDec(decimal).multiply(finalBase);
        }
        catch (NumberFormatException e) {
          break;
        }
        if (dec.eq(BigDec.ZERO)) {
          output = output + "." + decOut;
        }
        else {
          int temp = dec.intValue();
          if (temp > 9)
            decOut = decOut + alphabet[temp - 10];
          else
            decOut = decOut + temp;
          decimal = dec.toString();
          decimal = decimal.substring(decimal.indexOf("."));
        }
        i++;
      } while (dec.neq(BigDec.ZERO) && i < max);
      if (i >= max)
        output = output + "." + decOut;
    }
    return output;
  }
 
  private int betNum(Character num) {
    for (int i = 0; i < alphabet.length; i++)
      if (alphabet[i].equalsIgnoreCase(num.toString()))
        return i;
    return 0;
  }*/
 
  private void loadUnits() {
    //base units
    addUnit("meter", "meter", BigDec.ONE, "m");
    addUnit("second", "second", BigDec.ONE, "s");
    addUnit("gram", "gram", BigDec.ONE, "g");
    addUnit("ampere", "ampere", BigDec.ONE, "A");
    addUnit("kelvin", "kelvin", BigDec.ONE, "K");
    addUnit("mole", "mole", BigDec.ONE, "mol");
    addUnit("candela", "candela", BigDec.ONE, "cd");
    addUnit("byte", "byte", BigDec.ONE, "b");
    addUnit("radian", "radian", BigDec.ONE, "rad");
   
    //SI abbreviations
    addUnit("amp", "ampere", BigDec.ONE);
   
    //angle
    addUnit("degree", "radian", new BigDec(Math.PI / 180));
    addUnit("grad", "radian", new BigDec(Math.PI / 200));
   
    //distance
    addUnit("mile", "meter", new BigDec(1609.34), "mi");
    addUnit("f(o|e)\\1t", "meter", new BigDec(0.3048), "ft");
    addUnit("inch", "meter", new BigDec(0.0254), "in");
    addUnit("yard", "meter", new BigDec(0.9144), "yd");
    //compensates for plural
    addUnit("inche", "meter", new BigDec(0.0254));
   
    //volume
    addUnit("liter", "centimeter^3", new BigDec(1000), "L");
    addUnit("litre", "centimeter^3", new BigDec(1000));
   
    //time
    addUnit("minute", "second", new BigDec(60));
    addUnit("hour", "minute", new BigDec(60), "hr");
    addUnit("day", "hour", new BigDec(24));
    addUnit("week", "day", new BigDec(7));
    addUnit("month", "day", new BigDec(30));
    addUnit("year", "day", new BigDec(365), "yr");
   
    //mass
    addUnit("slug", "gram", new BigDec(14593.9029));
   
    //temperature
    addUnit("rankine", "kelvin", new BigDec(1.8));
    //frequency
    addUnit("hertz", "second^(-1)", BigDec.ONE, "Hz");
    //force
    addUnit("newton", "kilogram meter per (second^2)", BigDec.ONE, "N");
    //pressure, stress
    addUnit("pascal", "newton per (meter^2)", BigDec.ONE, "Pa");
    addUnit("psi", "pascal", new BigDec(6894.75729));
   
    //energy, work, heat
    addUnit("joule", "newton meter", BigDec.ONE, "J");
    addUnit("calorie", "joule", new BigDec(4.184), "cal");
    addUnit("Calorie", "calorie", new BigDec(1000), "Cal");
   
    //power, radiant flux
    addUnit("watt", "joule per (second)", BigDec.ONE, "W");
    //electric charge, quantity of electricity
    addUnit("coulomb", "second ampere", BigDec.ONE, "C");
    //voltage, electrical potential difference, electromotive force
    addUnit("volt", "joule per (coulomb)", BigDec.ONE, "V");
    //electric capacitance
    addUnit("farad", "coulomb per (volt)", BigDec.ONE, "F");
    //electric resistance, impedance, reactance
    addUnit("ohm", "volt per (ampere)", BigDec.ONE);
    //electrical conductance
    addUnit("siemens", "ohm^(-1)", BigDec.ONE, "S");
    //magnetic flux
    addUnit("weber", "joule per (ampere)", BigDec.ONE, "Wb");
    //magnetic field strength, magnetic flux density
    addUnit("tesla", "volt second per (meter^2)", BigDec.ONE, "T");
    //inductance
    addUnit("henry", "volt second per (ampere)", BigDec.ONE, "H");
    //luminous flux
    addUnit("lumen", "candela", BigDec.ONE, "lm");
    //illuminance
    addUnit("lux", "lumen per (meter^2)", BigDec.ONE, "lx");
    //radioactivity (decays per unit time)
    addUnit("becquerel", "second^(-1)", BigDec.ONE, "Bq");
    //absorbed dose (of ionizing radiation)
    addUnit("gray", "joule per (kilogram)", BigDec.ONE, "Gy");
    //equivalent dose (of ionizing radiation)
    addUnit("sievert", "coulomb per (volt)", BigDec.ONE, "Sv");
    //catalytic activity
    addUnit("katal", "mole per (second)", BigDec.ONE, "kat");
   
    //data
    addUnit("bit", "byte", new BigDec(0.125));
    addUnit("nibble", "byte", new BigDec(0.5));
  }
 
  public void addUnit(String name, String SI, BigDec SIfactor) {
    addUnit(name, SI, SIfactor, new String[]{});
  }
 
  public void addUnit(String name, String SI, BigDec SIfactor, String... abbreviations) {
    units.put(name, new Unit(name, SI, SIfactor, abbreviations));
    for (String abbreviation : abbreviations)
      unitAbbreviations.put(abbreviation, name);
    for (String prefix : prefixes.keySet())
      allUnits.add(prefix + name);
  }
 
  public boolean containsUnit(String input) {
    for (int i = 0; i < units.size(); i++)
      if (input.contains(units.get(i).getName()))
        return true;
    return false;
  }
 
  private boolean isSI(String unit) {
    for (String str : SI)
      if (unit.trim().equalsIgnoreCase(str))
        return true;
    return false;
  }
 
  private ArrayList<String> exponents(ArrayList<String> units) {
    for (int i = 0; i < units.size(); i++) {
      String u = units.get(i);
      if ((u.equalsIgnoreCase("square") || u.equalsIgnoreCase("cubic")) && i < units.size() - 1) {
        if (units.get(i + 1).charAt(units.get(i + 1).length()) == ')') {
          if (u.equalsIgnoreCase("square"))
            units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length() - 1) + "^2)");
          else if (u.equalsIgnoreCase("cubic"))
            units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length() - 1) + "^3)");
        }
        else {
          if (u.equalsIgnoreCase("square"))
            units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length()) + "^2");
          else if (u.equalsIgnoreCase("cubic"))
            units.set(i + 1, units.get(i + 1).substring(0, units.get(i + 1).length()) + "^3");
        }
        units.remove(i);
        u = units.get(i);
      }
      if ((u.equalsIgnoreCase("squared") || u.equalsIgnoreCase("cubed")) && i >= 1) {
        if (units.get(i - 1).charAt(units.get(i - 1).length()) == ')') {
          if (u.equalsIgnoreCase("squared"))
            units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length() - 1) + "^2)");
          else if (u.equalsIgnoreCase("cubed"))
            units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length() - 1) + "^3)");
        }
        else {
          if (u.equalsIgnoreCase("squared"))
            units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length()) + "^2");
          else if (u.equalsIgnoreCase("cubed"))
            units.set(i - 1, units.get(i - 1).substring(0, units.get(i - 1).length()) + "^3");
        }
        units.remove(i);
      }
    }
    return units;
  }
 
  private String[] scientificNotation(String num, boolean array, Parser parser) {
    String parts[] = new String[]{"", ""};//base, order
    if (!num.contains("."))
      num = num + ".0";
    while (num.charAt(0) == '0' && num.charAt(1) != '.')
      num = num.substring(1);
    if (num.length() > 1) {
      for (int i = 0; i < num.length(); i++)
        if (parser.isNumber(num.charAt(i)) && num.charAt(i) != '0' && num.charAt(i) != '.') {
          parts[1] = new BigDec(num.indexOf('.') - i - 1).toString();
          break;
        }
      parts[0] = num.substring(0, 1) + "." + num.substring(1).replaceAll("\\Q.\\E", "");
    }
    else
      return new String[]{num, "0"};
    return parts;
  }
 
  private String fromScientificNotation(String num) {
    String exp = "0";
    if (num.contains("E")) {
      exp = num.substring(num.indexOf("E") + 1);
      num = num.substring(0, num.indexOf("E"));
    }
    if (num.contains("10^")) {
      exp = num.substring(num.indexOf("*10^") + 4);
      num = num.substring(0, num.indexOf("*10^"));
    }
    if (num.contains(".")) {
      int index = num.indexOf("."), expo = new Double(exp).intValue();
      while (num.length() < expo + index + 1)
        num = num + "0";
      num = num.substring(0, index) + num.substring(index + 1, index + 1 + expo) + "." + num.substring(index + 1 + expo);
    }
    return num;
  }
 
  /**
   * Add a unit from a unit's data string
   *
   * @param data
   *            a <tt>String</tt> of the form <code>name : SI : factor : abbreviation</code> or
   *            <code>name : SI : factor</code> if there is no abbreviation
   */
  public void addUnit(String data) {
    String[] parts = data.split(" : ");
    if (parts.length == 4)
      addUnit(parts[0], parts[1], parts[2], parts[3]);
    else
      addUnit(parts[0], parts[1], parts[2], "");
  }
 
  /**
   * Convenience method - calls {@link #addUnit(String, String, String, String)} with no abbreviation
   *
   * @param name
   *            the of the unit
   * @param SI
   *            an equivalent unit (preferably in the SI system)
   * @param factor
   *            the conversion factor between this unit and the unit in SI
   */
  public void addUnit(String name, String SI, String factor) {
    addUnit(name, SI, new BigDec(factor.trim()));
  }
 
  /**
   * Adds a unit
   *
   * @param name
   *            the of the unit
   * @param SI
   *            an equivalent unit (preferably in the SI system)
   * @param factor
   *            the conversion factor between this unit and the unit in SI
   * @param abbriviation
   *            the abbreviation for this unit
   */
  public void addUnit(String name, String SI, String factor, String... abbriviation) {
    addUnit(name, SI, new BigDec(factor.trim()), abbriviation);
  }
 
  public void removeUnit(String name) {
    unitAbbreviations.clear();
    for (int i = 0; i < units.size(); i++) {
      if (units.get(i).getName().equals(name)) {
        units.remove(i--);
        continue;
      }
      for (String abbreviation : units.get(i).getAbbreviations())
        unitAbbreviations.put(abbreviation, units.get(i).getName());
    }
   
  }
 
  public HashMap<String, Unit> getUnits() {
    return units;
  }
 
  public ArrayList<String> getUnitNames() {
    return allUnits;
  }
}
TOP

Related Classes of naturalLanguage.Units

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.