RhemModel.java [src/java/m/rhem/model] Revision: d198e6f0c36df918760aa96f5b88ad37bbbfdaa9  Date: Tue Oct 25 05:59:54 MDT 2022
package m.rhem.model;

import csip.api.server.ServiceException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.apache.commons.io.FileUtils;
import static rhem.utils.RHEMUtils.formatDouble;

/**
 *
 * @author rumpal
 */
public class RhemModel {

  String scenarioName;
  File workSpaceDir;

  String parameterFileName;
  String stormFileName;
  String runFileName;
  String summaryFileName;

  double avgSoilLoss;


  public RhemModel(String scenarioName, File workSpaceDir, String parameterFileName,
      String stormFileName, String runFileName, String summaryFileName) {
    this.scenarioName = scenarioName;
    this.workSpaceDir = workSpaceDir;
    this.parameterFileName = parameterFileName;
    this.stormFileName = stormFileName;
    this.runFileName = runFileName;
    this.summaryFileName = summaryFileName;
  }


  public void generateParamFile(Parameter param) throws ServiceException {
    try ( PrintWriter w = new PrintWriter(new File(workSpaceDir, parameterFileName))) {
      String now = new SimpleDateFormat("MMMM dd, YYYY, hh:mm a").format(new Date());

      w.println("! Parameter file for scenario: " + scenarioName);
      w.println("! Date built: " + now + " (Version 2.3)");
      w.println("! Parameter units: DIAMS(mm), DENSITY(g/cc),TEMP(deg C)");
      w.println("BEGIN GLOBAL");
      w.println(String.format("        %-8s=   %s", "CLEN", param.clen));
      w.println(String.format("        %-8s=   %s", "UNITS", "metric"));
      w.println(String.format("        %-8s=   %s", "DIAMS", param.diams));
      w.println(String.format("        %-8s=   %s", "DENSITY", param.density));
      w.println(String.format("        %-8s=   %s", "TEMP", 40));
      w.println(String.format("        %-8s=   %s", "NELE", 1));
      w.println("END GLOBAL");
      w.println("BEGIN PLANE");
      w.println(String.format("        %-8s=   %s", "ID", 1));
      w.println(String.format("        %-8s=   %s", "LEN", param.len));
      w.println(String.format("        %-8s=   %s", "WIDTH", 1.0));
      w.println(String.format("        %-8s=   %s", "CHEZY", param.chezy));
      w.println(String.format("        %-8s=   %s", "RCHEZY", param.rchezy));
      w.println(String.format("        %-8s=   %s", "SL", param.sl));
      w.println(String.format("        %-8s=   %s", "SX", param.sx));
      w.println(String.format("        %-8s=   %s", "CV", param.cv));
      w.println(String.format("        %-8s=   %s", "SAT", param.sat));
      w.println(String.format("        %-8s=   %s", "PR", 1));
      w.println(String.format("        %-8s=   %s", "KSS", param.kss));
      w.println(String.format("        %-8s=   %s", "KOMEGA", param.komega));
      w.println(String.format("        %-8s=   %s", "KCM", param.kcm));
      w.println(String.format("        %-8s=   %s", "CA", 1.0));
      w.println(String.format("        %-8s=   %s", "IN", 0.0));
      w.println(String.format("        %-8s=   %s", "KE", param.ke));
      w.println(String.format("        %-8s=   %s", "G", param.g));
      w.println(String.format("        %-8s=   %s", "DIST", param.dist));
      w.println(String.format("        %-8s=   %s", "POR", param.por));
      w.println(String.format("        %-8s=   %s", "ROCK", 0.00));
      w.println(String.format("        %-8s=   %s", "SMAX", param.smax));
      w.println(String.format("        %-8s=   %s", "ADF", param.adf));
      w.println(String.format("        %-8s=   %s", "ALF", param.alf));
      w.println(String.format("        %-8s=   %s", "BARE", param.bare));
      w.println(String.format("        %-8s=   %s", "RSP", 1.0));
      w.println(String.format("        %-8s=   %s", "SPACING", 1.0));
      w.println(String.format("        %-8s=   %s", "FRACT", param.fract));
      w.println("END PLANE");
    } catch (IOException E) {
      throw new ServiceException("Problem in generating the parameter file.", E);
    }
  }


  public void generateStormFile(String cligen_db, double Ke, String stateId, String climatestationId)
      throws ServiceException, URISyntaxException {
    stateId = stateId.toUpperCase();
    try {
      if (isIntl(stateId)) {
        try {
          File cs = new File(cligen_db + "/" + stateId + "/" + climatestationId + ".txt");
          if (!cs.exists())
            throw new ServiceException("Climate station not found: " + climatestationId + ".txt for " + stateId);

//          URL u = new URL(cligen_db + "/international/" + climatestationId + ".txt");
          Files.createSymbolicLink(Paths.get(workSpaceDir.toString(), stormFileName), Paths.get(cs.toURI()));
        } catch (IOException E) {
          throw new ServiceException("Climate station not found: " + climatestationId + ".txt for " + stateId);
        }
        return;
      }

      String cligenFileName = "/" + stateId + "/300yr/" + stateId + "_" + climatestationId + "_300yr.out";
      URL u = new URL(cligen_db + cligenFileName);
      long counter = 0;
      try ( BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(u.openStream()))) {
        File tempFile = new File(workSpaceDir, "tempSummaryFile.pre");
        try ( PrintWriter writer = new PrintWriter(tempFile)) {
          for (int i = 0; i <= 17; i++) {
            bufferedReader.readLine();
          }
          String line;
          while ((line = bufferedReader.readLine()) != null) {
            String[] test = line.split("\\s+");
            double keComparison = Double.parseDouble(test[8]) * (Double.parseDouble(test[5]) / Double.parseDouble(test[6]));
            if (Ke < keComparison && test.length > 8) {
              counter++;
              writer.println(String.format("    %-5s %-5s %-5s %-5s %-5s %-6s %-6s %-6s",
                  counter, test[2], test[3], test[4], test[5], test[6], test[7], test[8]));
            }
          }
        }
        appendInfo(tempFile, counter, stateId, climatestationId);
        tempFile.delete();
      }
    } catch (IOException E) {
      throw new ServiceException("Problem in generating the storm file.", E);
    }
  }


  void appendInfo(File tempFile, long counter, String stateId, String climatestationId) throws ServiceException {
    try ( PrintWriter writer = new PrintWriter(new File(workSpaceDir, stormFileName))) {
      String now = new SimpleDateFormat("MMMM dd, YYYY, hh:mm a").format(new Date());
      writer.println("# Storm file for scenario: " + scenarioName);
      writer.println("# Date built: " + now + " (Version 2.3)");
      writer.println("# State: " + stateId);
      writer.println("# Climate Station: " + climatestationId);
      writer.println(counter + " # The number of rain events");
      writer.println("0 # Breakpoint data? (0 for no, 1 for yes)");
      writer.println("#  id     day  month  year  Rain   Dur    Tp     Ip");
      writer.println("#                           (mm)   (h)");
      try ( BufferedReader bufferedReader = new BufferedReader(new FileReader(tempFile))) {
        String line;
        while ((line = bufferedReader.readLine()) != null) {
          writer.println(line);
        }
      }
    } catch (IOException E) {
      throw new ServiceException("Problem in generating the storm file.", E);
    }
  }


  public void generateRunFile() throws ServiceException, IOException {
    FileUtils.writeStringToFile(new File(workSpaceDir, runFileName),
        parameterFileName + ", " + stormFileName + ", "
        + summaryFileName + ", \"" + scenarioName + "\", 0, 2, y, y, n, n, y");
  }


  public void appendToSumFile(double avgYearlyPrecip) throws ServiceException {
    DecimalFormat df = new DecimalFormat("#.#####");
    File summaryFile = new File(workSpaceDir, summaryFileName);
    File tempSummaryFile = new File(workSpaceDir, "temp_" + summaryFileName);
    try ( PrintWriter writer = new PrintWriter(tempSummaryFile)) {
      writer.println("     -ANNUAL-AVERAGES-");
      writer.println();
      writer.println("  Avg. Precipitation(mm/year)=   " + df.format(avgYearlyPrecip));
      try ( BufferedReader bufferedReader = new BufferedReader(new FileReader(summaryFile))) {
        for (int i = 0; i < 3; i++) {
          bufferedReader.readLine();
        }
        String line;
        while ((line = bufferedReader.readLine()) != null) {
          if (line.toLowerCase().contains("variable")) {
            int c = 0;
            while (c < 6) {
              if (c != 0) {
                line = bufferedReader.readLine();
              }
              String[] test = line.split("\\s+");
              if (c == 2) {
                writer.print(String.format("%-25s", test[1] + test[2]));
                for (int i = 3; i < test.length; i++) {
                  writer.print(String.format("%-25s", test[i]));
                }
              } else {
                for (int i = 1; i < test.length; i++) {
                  writer.print(String.format("%-25s", test[i]));
                }
              }
              writer.println();
              c++;
            }
          } else {
            if (line.contains("Avg-Soil-Loss")) {
              String asl = line.substring(line.indexOf('=') + 1);
              avgSoilLoss = Double.parseDouble(asl.trim());
            }
            writer.print(line);
            writer.println();
          }
        }
      }
    } catch (IOException E) {
      throw new ServiceException("Problem in editing the summary file.", E);
    }
    summaryFile.delete();
    tempSummaryFile.renameTo(summaryFile);
  }


  public String getTDS() {
    return formatDouble((2.36 * (avgSoilLoss * 1000) + 0.99) / 1000.0);
  }


  public String getTDS(double asl) {
    return formatDouble((2.36 * (asl * 1000) + 0.99) / 1000.0);
  }

  static final List<String> intl = Arrays.asList("INTL_", "INTL_AF", "INTL_SA");


  public boolean isIntl(String stateId) {
    return intl.contains(stateId.toUpperCase());
    //return stateId.toLowerCase().startsWith("intl_");
  }

}