CSIP_NASS_LMOD_Matching.java [src/java/methods] Revision: default  Date:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package methods;

import lamps.metrics.JaroWinklerDistance;
import csip.SessionLogger;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import lamps.CSIP_Const;
import lamps.utils.Partition;
import methods.objects.ERU;
import methods.objects.Generic_Matching_Result;
import static methods.CSIP_NASS_LMOD.sortByValues;
import csip.utils.Numeric;

/**
 *
 * @author hokipka
 */
public class CSIP_NASS_LMOD_Matching {

    /**
     *
     * @param dataDir
     * @param unique_cmzs
     * @param LMOD_CMZ_Data
     * @param DB_LMOD_map
     * @throws Exception
     */
    public static void query_LAMPS_DB_Rotations_For_CMZ(File dataDir, List<String> unique_cmzs,
            List<ArrayList<String>> LMOD_CMZ_Data, HashMap<String, List<ArrayList<String>>> DB_LMOD_map, SessionLogger LOG) throws Exception {

        Class.forName("org.h2.Driver");
        try (Connection conn = DriverManager.getConnection("jdbc:h2:file:" + dataDir.getPath() + CSIP_Const.LocalDB, "sa", "");
                Statement state = conn.createStatement()) {

            for (String no_start_zero : unique_cmzs) {

                if (no_start_zero.equals("XX")) {
                    String queryString = "select max(KEY) as KEY, max(COVERCROPS) as COVERCROPS, max(TILOP_NR) as TILOP_NR, CROPSEQUENCE,cropseqacr,irrigated,years from LMOD_MGMTS_ACR_II group by CROPSEQUENCE,cropseqacr,irrigated,years order by years desc;";
                    ResultSet result = state.executeQuery(queryString);
                    int count = 0;
                    while (result.next()) {
                        if (!result.getString("CROPSEQACR").contains("?") && !result.getString("CROPSEQUENCE").contains("silage") && !result.getString("CROPSEQUENCE").contains("sweet") && !result.getString("CROPSEQUENCE").equals("Corn;")) { // for now "silage" & "sweet" out
                            ArrayList<String> LMOD_data_by_CMZ = new ArrayList<>();
                            List<ArrayList<String>> LMOD_data_by_CMZ_list = new ArrayList<>();
                            LMOD_data_by_CMZ.add(result.getString("KEY"));
                            LMOD_data_by_CMZ.add("" + no_start_zero + "");
                            LMOD_data_by_CMZ.add(result.getString("IRRIGATED"));
                            LMOD_data_by_CMZ.add(result.getString("COVERCROPS"));
                            LMOD_data_by_CMZ.add(result.getString("CROPSEQUENCE"));
                            LMOD_data_by_CMZ.add(result.getString("CROPSEQACR"));
                            LMOD_data_by_CMZ.add(result.getString("YEARS"));
                            LMOD_CMZ_Data.add(LMOD_data_by_CMZ);
                            LMOD_data_by_CMZ_list.add(LMOD_data_by_CMZ);
                            if (DB_LMOD_map.get(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED")) == null) {
                                DB_LMOD_map.put(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED"), LMOD_data_by_CMZ_list);
                            } else {
                                LMOD_data_by_CMZ_list = DB_LMOD_map.get(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED"));
                                LMOD_data_by_CMZ_list.add(LMOD_data_by_CMZ);
                                DB_LMOD_map.put(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED"), LMOD_data_by_CMZ_list);
                            }
                            count++;
                        }
                    }
                    LOG.info("Number of ALL Rotations " + no_start_zero + " size: " + count);

                } else {
                    //original String queryString = "select * from \"PUBLIC\".LMOD_MGMTS_ACR where CMZ='" + Integer.parseInt(unique_cmzs.get(i)) + "' order by years desc";
                    //String queryString = "select max(KEY),max(COVERCROPS),max(CROPSEQUENCE),max(TILOP_NR),cropseqacr,irrigated,years from LMOD_MGMTS_ACR group by cropseqacr,irrigated,years order by years desc;"; // ALL CMZs = ALL available CropRotations out of LMOD
                    //String queryString = "select max(KEY),max(COVERCROPS),max(TILOP_NR),CROPSEQUENCE,cropseqacr,irrigated,years from LMOD_MGMTS_ACR group by CROPSEQUENCE,cropseqacr,irrigated,years order by years desc;"; // ALL CMZs = ALL available CropRotations out of LMOD
                    // String queryString = "select max(KEY),max(COVERCROPS),max(CROPSEQUENCE),max(TILOP_NR),cropseqacr,irrigated,years from LMOD_MGMTS_ACR where CMZ='" + Integer.parseInt(unique_cmzs.get(i)) + "' or CMZ='3' or CMZ='4' group by cropseqacr,irrigated,years order by years desc;"; // ONLY specific CMZ CropRotations
                    //String queryString = "select max(KEY),max(COVERCROPS),max(TILOP_NR),CROPSEQUENCE,cropseqacr,irrigated,years from LMOD_MGMTS_ACR_II where CMZ='" + Integer.parseInt(unique_cmzs.get(i)) + "' or CMZ='3' or CMZ='4' group by CROPSEQUENCE,cropseqacr,irrigated,years order by years desc;";// ONLY specific CMZ CropRotations
                    if (no_start_zero.startsWith("0")) {
                        no_start_zero = no_start_zero.replace("0", "");
                    }
                    String queryString = "select max(STIR),CROPSEQUENCE,cropseqacr,irrigated,years,key,covercrops from LMOD_MGMTS_ACR_II where CMZ='" + no_start_zero + "' and covercrops='non-cover' group by CROPSEQUENCE,cropseqacr,irrigated,years,key,covercrops order by years desc;";
                    //select max(KEY),max(COVERCROPS),max(TILOP_NR),CROPSEQUENCE,cropseqacr,irrigated,years from LMOD_MGMTS_ACR where CMZ='4' group by CROPSEQUENCE,cropseqacr,irrigated,years order by years desc;
                    //w_log.println(" " + queryString);
                    ResultSet result = state.executeQuery(queryString);
                    int count = 0;
                    while (result.next()) {
                        if (!result.getString("CROPSEQACR").contains("?") && !result.getString("CROPSEQUENCE").contains("silage") && !result.getString("CROPSEQUENCE").contains("sweet") && !result.getString("CROPSEQUENCE").equals("Corn;")) { // for now "silage" & "sweet" out
                            ArrayList<String> LMOD_data_by_CMZ = new ArrayList<>();
                            List<ArrayList<String>> LMOD_data_by_CMZ_list = new ArrayList<>();
                            LMOD_data_by_CMZ.add(result.getString("KEY"));
                            LMOD_data_by_CMZ.add("" + no_start_zero + "");
                            LMOD_data_by_CMZ.add(result.getString("IRRIGATED"));
                            LMOD_data_by_CMZ.add(result.getString("COVERCROPS"));
                            LMOD_data_by_CMZ.add(result.getString("CROPSEQUENCE"));
                            LMOD_data_by_CMZ.add(result.getString("CROPSEQACR"));
                            LMOD_data_by_CMZ.add(result.getString("YEARS"));
                            LMOD_CMZ_Data.add(LMOD_data_by_CMZ);
                            LMOD_data_by_CMZ_list.add(LMOD_data_by_CMZ);
                            if (DB_LMOD_map.get(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED")) == null) {
                                DB_LMOD_map.put(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED"), LMOD_data_by_CMZ_list);
                            } else {
                                LMOD_data_by_CMZ_list = DB_LMOD_map.get(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED"));
                                LMOD_data_by_CMZ_list.add(LMOD_data_by_CMZ);
                                DB_LMOD_map.put(result.getString("CROPSEQACR") + "_" + "" + no_start_zero + "" + "_" + result.getString("IRRIGATED"), LMOD_data_by_CMZ_list);
//                            w_log.println("  double_seq_acr : " + result.getString("CROPSEQACR"));
//                            w_log.flush();
                            }

                            count++;
                        }
                    }
                    //w_log.println("Number of Rotations in CMZ " + no_start_zero + " size: " + count);
                    LOG.info("Number of Rotations in CMZ " + no_start_zero + " size: " + count);
                    //w_log.println(" ");
                }
            }
            state.close();
            conn.close();
        }

    }

    /**
     *
     * @param pattern
     * @param text
     * @return
     */
    public List<Integer> Match(String pattern, String text) {
        List<Integer> matches = new ArrayList<>();
        int m = text.length();
        int n = pattern.length();

        Map<Character, Integer> rightMostIndexes = preprocessForBadCharacterShift(pattern);
        int alignedAt = 0;
        while (alignedAt + (n - 1) < m) {
            for (int indexInPattern = n - 1; indexInPattern >= 0; indexInPattern--) {
                int indexInText = alignedAt + indexInPattern;
                char x = text.charAt(indexInText);
                char y = pattern.charAt(indexInPattern);
                if (indexInText >= m) {
                    break;
                }
                if (x != y) {
                    Integer r = rightMostIndexes.get(x);
                    if (r == null) {
                        alignedAt = indexInText + 1;
                    } else {
                        int shift = indexInText - (alignedAt + r);
                        alignedAt += shift > 0 ? shift : 1;
                    }
                    break;
                } else if (indexInPattern == 0) {
                    matches.add(alignedAt);
                    //alignedAt++; //org code
                    alignedAt = alignedAt + n;   // adjusted by H.Kipka
                }
            }
        }
        return matches;
    }

    /**
     *
     * @param pattern
     * @return
     */
    private Map<Character, Integer> preprocessForBadCharacterShift(String pattern) {
        Map<Character, Integer> map = new HashMap<>();
        for (int i = pattern.length() - 1; i >= 0; i--) {
            char c = pattern.charAt(i);
            if (!map.containsKey(c)) {
                map.put(c, i);
            }
        }
        return map;
    }

    public static abstract class yearComparator implements Comparator<String[]> {

        @Override
        public int compare(String[] o1, String[] o2) {
            return Integer.compare(Integer.parseInt(o1[1]), Integer.parseInt(o2[1]));
        }
    }

    /**
     *
     * @param dataDir
     * @param hrus
     * @param CDL_years
     * @param LMOD_CMZ_Data
     * @param DB_LMOD_map
     * @param start_year
     * @param end_year
     * @param LOG
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public static HashMap<Integer, ArrayList<String[]>> ConcurrentMatching(File dataDir, List<ERU> hrus, List<String> CDL_years, List<ArrayList<String>> LMOD_CMZ_Data, HashMap<String, List<ArrayList<String>>> DB_LMOD_map, Integer start_year, Integer end_year, SessionLogger LOG)
            throws InterruptedException, ExecutionException {

        final int threadNum = Partition.getThreadCount(hrus.size());
        final int first = 0;
        final int last = hrus.size() - 1;
        final List<String> years = CDL_years;
        final List<ERU> fhrus = hrus;
        final List<ArrayList<String>> fLMOD_CMZ_Data = LMOD_CMZ_Data;
        final HashMap<String, List<ArrayList<String>>> fDB_LMOD_map = DB_LMOD_map;
        final SessionLogger fSL = LOG;
        final File fdD = dataDir;
        final int st_year = start_year;
        final int en_year = end_year;

        final int p = (last + 1) / threadNum;
        int s = (last + 1) - p * threadNum;

        // Prepare to execute and store the Futures
        ExecutorService executor = Executors.newFixedThreadPool(threadNum);
        List<FutureTask<HashMap<Integer, ArrayList<String[]>>>> taskList = new ArrayList<>();
        for (int j = 0; j < threadNum; j++) {
            final int ii = j;
            FutureTask<HashMap<Integer, ArrayList<String[]>>> futureTask_1 = new FutureTask<>(new Callable<HashMap<Integer, ArrayList<String[]>>>() {
                int inlast = (ii == threadNum - 1 ? last : p + (ii * p));
                int infirst = (ii == 0 ? first : (p * ii) + 1);

                @Override
                public HashMap<Integer, ArrayList<String[]>> call() throws Exception {
                    return CSIP_NASS_LMOD_Matching.Matching(infirst, inlast, fdD, fhrus, fLMOD_CMZ_Data, fDB_LMOD_map, years, st_year, en_year, fSL);
                }
            });
            taskList.add(futureTask_1);
            executor.execute(futureTask_1);
        }

        HashMap<Integer, ArrayList<String[]>> result_map = new HashMap<>();

        // Wait until all results are available and combine them at the same time
        for (int j = 0; j < threadNum; j++) {
            FutureTask<HashMap<Integer, ArrayList<String[]>>> futureTask = taskList.get(j);
            Set<Integer> set = futureTask.get().keySet();
            for (int u : set) {
                if (result_map.get(u) == null) {
                    result_map.put(u, futureTask.get().get(u));
                }
            }
        }
        executor.shutdown();
        return result_map;
    }

    /**
     *
     * @param first
     * @param last
     * @param dataDir
     * @param hrus
     * @param LMOD_CMZ_Data
     * @param DB_LMOD_map
     * @param years
     * @param start_year
     * @param end_year
     * @param LOG
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static HashMap<Integer, ArrayList<String[]>> Matching(int first, int last, File dataDir, List<ERU> hrus, List<ArrayList<String>> LMOD_CMZ_Data, HashMap<String, List<ArrayList<String>>> DB_LMOD_map, List<String> years, Integer start_year, Integer end_year, SessionLogger LOG) throws ClassNotFoundException, SQLException {

        HashMap<Integer, ArrayList<String[]>> map = new HashMap<>();

        JaroWinklerDistance jaro = JaroWinklerDistance.JARO_DISTANCE;
        long start_time = System.currentTimeMillis();

        Class.forName("org.h2.Driver");
        try (Connection conn = DriverManager.getConnection("jdbc:h2:file:" + dataDir.getPath() + CSIP_Const.LocalDB, "sa", "")) {
            try (Statement state = conn.createStatement()) {

                for (int i = first; i <= last; i++) {

                    Generic_Matching_Result M_R = new Generic_Matching_Result();

                    ArrayList<String[]> Year_LMOD_Rot_Linkage = new ArrayList<>();

                    int String_count = 0;
                    int cmz_size = hrus.get(i).cmz.size();
                    String cmz_one = "";

                    if (hrus.get(i).cmz.get(0).startsWith("0")) {
                        cmz_one = hrus.get(i).cmz.get(0).replace("0", "");
                    } else {
                        cmz_one = hrus.get(i).cmz.get(0);
                    }

                    Map<String, Double> map_bigger_rot_jaro = new HashMap<>();

                    for (ArrayList<String> LMOD_CMZ_Data1 : LMOD_CMZ_Data) {
                        if (LMOD_CMZ_Data1.get(5).toCharArray().length > hrus.get(i).hru_seq_org.toCharArray().length) {
                            if (jaro.proximity(LMOD_CMZ_Data1.get(5), hrus.get(i).hru_seq_org) > 0.6) {
                                if (map_bigger_rot_jaro.get(LMOD_CMZ_Data1.get(5)) == null) {
                                    map_bigger_rot_jaro.put(LMOD_CMZ_Data1.get(5), jaro.proximity(LMOD_CMZ_Data1.get(5), hrus.get(i).hru_seq_org));
                                }
                            }
                        }
                        if (cmz_size < 2 && !Boolean.valueOf(LMOD_CMZ_Data1.get(3)) && (cmz_one).equals(LMOD_CMZ_Data1.get(1))) {
                            String[] matrix = {hrus.get(i).hru_seq_work, LMOD_CMZ_Data1.get(5)};
                            String s1 = matrix[0];
                            String s2 = matrix[1];
                            //String pattern, String text
                            List<Integer> matches = new CSIP_NASS_LMOD_Matching().Match(s2, s1);
                            //int boyer = 1;
                            char[] myNameChars = s1.toCharArray();
                            for (Integer integer : matches) {
                                for (int l = 0; l < s2.length(); l++) {
                                    myNameChars[integer + l] = '+';
                                    String_count++;
                                }
                                Year_LMOD_Rot_Linkage.add(new String[]{LMOD_CMZ_Data1.get(0), years.get(integer)});
                            }
                            hrus.get(i).hru_seq_work = String.valueOf(myNameChars);
                        }
                        if (cmz_size > 1 && Objects.equals(hrus.get(i).irrigated, Boolean.valueOf(LMOD_CMZ_Data1.get(2))) && !Boolean.valueOf(LMOD_CMZ_Data1.get(3))) {
                            String[] matrix = {hrus.get(i).hru_seq_work, LMOD_CMZ_Data1.get(5)};
                            String s1 = matrix[0];
                            String s2 = matrix[1];
                            //String pattern, String text
                            List<Integer> matches = new CSIP_NASS_LMOD_Matching().Match(s2, s1);
                            char[] myNameChars = s1.toCharArray();
                            for (Integer integer : matches) {
                                for (int l = 0; l < s2.length(); l++) {
                                    myNameChars[integer + l] = '+';
                                    String_count++;
                                }
                                Year_LMOD_Rot_Linkage.add(new String[]{LMOD_CMZ_Data1.get(0), years.get(integer)});
                            }
                            hrus.get(i).hru_seq_work = String.valueOf(myNameChars);
                        }
                    }

                    // generic matching here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    String pattern = "";
                    boolean match = false;
                    //w_log.println(i + " HRU ");
                    //w_log.println("  veg_seq : " + hrus.get(i).hru_veg_seq);
                    //w_log.println("  org_seq : " + hrus.get(i).hru_seq_org);
                    //w_log.flush();
                    String new_rebuilt = "";
                    int hash_pos = 0;

                    boolean right_irrigation_rotation = false;
                    boolean highest_opposite_irrigation_rotation = false;

                    if (hrus.get(i).sorted_adjusted_conf.size() > 1 && hrus.get(i).acc_crops_year_count > 0 && (hrus.get(i).non_field_crops_years / hrus.get(i).acc_crops_year_count) < 0.51) {
                        //LOG.info(" Verhaeltnis vegetation & fieldcrops: " + (hrus.get(i).non_field_crops_years / hrus.get(i).acc_crops_year_count) + "    non:" + hrus.get(i).non_field_crops_years + "     field:" + hrus.get(i).acc_crops_year_count);
                        //w_log.flush();

                        boolean rot_in_cmz = false;

                        for (String key : hrus.get(i).sorted_adjusted_conf.keySet()) {

                            //LOG.info(" key : " + key);
                            //LOG.info(" hrus.get(i).sorted_adjusted_conf.get(key) : " + hrus.get(i).sorted_adjusted_conf.get(key));
                            //LOG.info(" hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key) : " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)));
                            for (String cmz : hrus.get(i).cmz) {
                                //LOG.info("    " + hash_pos + ".in LIST  Seq : " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "  Adjusted avg. Conf: " + hrus.get(i).sorted_adjusted_conf.get(key) + "  for: " + key + "  CMZ: " + cmz);
                                //w_log.flush();
                                //int int_cmz = Integer.parseInt(cmz);
                                String irriation_boolean = "";
                                if (hrus.get(i).irrigated) {
                                    irriation_boolean = "FALSE";
                                } else {
                                    irriation_boolean = "TRUE";
                                }

                                if (!match && DB_LMOD_map.get(hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_" + cmz + "_" + (hrus.get(i).irrigated).toString().toUpperCase()) != null && !cmz.equals("XX")) {
                                    //LOG.info("  with cor irri   ");

                                    right_irrigation_rotation = true;

                                    List<ArrayList<String>> LMOD_data_by_CMZ = DB_LMOD_map.get(hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_" + cmz + "_" + (hrus.get(i).irrigated).toString().toUpperCase());
                                    //if (LMOD_data_by_CMZ.size() > 1) {
                                    //    LOG.info("    " + LMOD_data_by_CMZ.size() + ": Number of " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_" + cmz + "_" + (hrus.get(i).irrigated).toString().toUpperCase());
                                    //}
                                    pattern = hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key));
                                    //w_log.println("    " + hash_pos + ".in LIST  Seq : " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "  Adjusted avg. Conf: " + hrus.get(i).sorted_adjusted_conf.get(key) + "  for: " + key);
                                    //w_log.println("    LMOD    :  ==> " + pattern);
                                    //w_log.flush();
                                    M_R.LMOD_Key = LMOD_data_by_CMZ.get(0).get(0);
                                    M_R.Rotation = true;
                                    M_R.Rotation_Duration = Integer.parseInt(LMOD_data_by_CMZ.get(0).get(6));
                                    M_R.Acronym_Sequence = pattern;
                                    M_R.CropName_Sequence = LMOD_data_by_CMZ.get(0).get(4);
                                    M_R.Vegetation_Sequence = hrus.get(i).hru_veg_seq;
                                    M_R.Avg_Confidence_Value = hrus.get(i).sorted_adjusted_conf.get(key);
                                    M_R.Rot_Start_years = key;
                                    M_R.rotation_irrigation_correct = right_irrigation_rotation;

                                    //String pattern, String text
                                    List<Integer> inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, hrus.get(i).hru_seq_org);
                                    for (Integer inner_integer : inner_matches) {

                                        int ind = 0;
                                        for (Integer inner_int : inner_matches) {
                                            ind++;
                                        }
                                        int[] indexes = new int[ind];
                                        ind = 0;
                                        for (Integer inner_int : inner_matches) {
                                            indexes[ind] = inner_int;
                                            ind++;
                                        }

                                        String help = "";
                                        double jaro_loop_value = 0.0;
                                        int old_element = -20;

                                        for (int element : indexes) {
                                            if ((old_element + pattern.toCharArray().length - 1) + 1 != element) {

                                                char[] rebuilt = new char[hrus.get(i).hru_seq_org.toCharArray().length];
                                                String org_seq = hrus.get(i).hru_seq_org;

                                                for (int j = 0; j < pattern.toCharArray().length; j++) {
                                                    rebuilt[element + j] = pattern.toCharArray()[j];
                                                }

                                                int before = element;

                                                int after = (hrus.get(i).hru_seq_org.toCharArray().length - 1) - (element + pattern.toCharArray().length - 1);

                                                int width = pattern.toCharArray().length;

                                                //w_log.println(" rebuilt lenght:  " + rebuilt.length);
                                                //w_log.println(" before:   " + before + "   after:   " + after + " width: " + width);
                                                int b = 0;
                                                while (before > 0) {
                                                    rebuilt[(before - 1)] = pattern.toCharArray()[(width - 1) - b];
                                                    b++;
                                                    if (b > width - 1) {
                                                        b = 0;
                                                    }
                                                    before--;
                                                }

                                                width = pattern.toCharArray().length;

                                                int x = 0;
                                                b = 0;
                                                while (after > 0) {
                                                    rebuilt[(element + pattern.toCharArray().length) + x] = pattern.toCharArray()[b];
                                                    b++;
                                                    if (b > width - 1) {
                                                        b = 0;
                                                    }
                                                    x++;
                                                    after--;
                                                }

                                                new_rebuilt = String.valueOf(rebuilt);

                                                String help_inner = new_rebuilt;
                                                if (org_seq.startsWith("@")) {
                                                    x = 1;
                                                    while (org_seq.startsWith("@")) {
                                                        org_seq = hrus.get(i).hru_seq_org.substring(x, hrus.get(i).hru_seq_org.toCharArray().length);
                                                        new_rebuilt = help_inner.substring(x, rebuilt.length);
                                                        x++;
                                                    }
                                                }
                                                //w_log.println("        detected rotation :" + org_seq);
                                                //w_log.println("        rebuilt  rotation :" + new_rebuilt);
                                                //w_log.println("        JaroSimilarity    : " + jaro.proximity(org_seq, new_rebuilt) + " similar");
                                                if (jaro.proximity(org_seq, new_rebuilt) > jaro_loop_value) {
                                                    jaro_loop_value = jaro.proximity(org_seq, new_rebuilt);
                                                    help = help_inner;

                                                }
                                                if (pattern.toCharArray().length == 2) {// && pattern.toCharArray()[0] != pattern.toCharArray()[1]) {
                                                    String Char1 = String.valueOf(pattern.toCharArray()[0]);
                                                    String Char2 = String.valueOf(pattern.toCharArray()[1]);
                                                    if (Char1.equals(Char2)) {
                                                        break;
                                                    }
                                                }
                                                if (jaro_loop_value > 0.99 || pattern.toCharArray().length < 2) {
                                                    break;
                                                }
                                            }
                                            old_element = element;
                                        }
                                        //M_R.Jaro_Similarity_Value = "" + jaro_loop_value;
                                        M_R.Jaro_Similarity_Value = "" + jaro.proximity(hrus.get(i).hru_seq_org, help);
                                        boolean same = false;
                                        if (pattern.toCharArray().length > 1) {// && pattern.toCharArray()[0] != pattern.toCharArray()[1]) {
                                            String Char1 = String.valueOf(pattern.toCharArray()[0]);
                                            String Char2 = String.valueOf(pattern.toCharArray()[1]);
                                            if (!Char1.equals(Char2)) {
                                                same = true;
                                                //String pattern, String text
                                                inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, help);
                                                for (Integer in_integer : inner_matches) {
                                                    M_R.Rot_Start_years = years.get(in_integer);
                                                    break;
                                                }
                                            } else {
                                                inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, help);
                                                for (Integer in_integer : inner_matches) {
                                                    M_R.Rot_Start_years = years.get(in_integer);
                                                    break;
                                                }
                                            }
                                        } else if (pattern.toCharArray().length == 1) {
                                            M_R.Rot_Start_years = years.get(0);
                                        } else if (!same) {
                                            M_R.Rot_Start_years = key.split("\\,")[0];
                                        }
                                        M_R.Detected_Rebuilt_Rotation = hrus.get(i).hru_seq_org + " - " + help;
                                        //w_log.println(" detect rebuilt help : " + hrus.get(i).hru_seq_org + " - " + help);
                                        //w_log.println(" ");
                                        //w_log.flush();
                                        //if (jaro.proximity(org_seq, new_rebuilt) > 0.2) {
                                        match = true;
                                        rot_in_cmz = true;
                                        break;
                                        //}
                                    }
                                } else if (!match && !highest_opposite_irrigation_rotation && DB_LMOD_map.get(hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_" + cmz + "_" + irriation_boolean) != null && !cmz.equals("XX")) {
                                    //LOG.info("  without cor irri   ");

                                    highest_opposite_irrigation_rotation = true;
                                    List<ArrayList<String>> LMOD_data_by_CMZ = DB_LMOD_map.get(hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_" + cmz + "_" + irriation_boolean);
                                    //w_log.println("  hhru " + hrus.get(i).ID + " " + LMOD_data_by_CMZ.get(0).get(4) + " change irrigation flag.");
                                    //w_log.flush();
                                    pattern = hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key));
                                    //w_log.println("   hh " + hash_pos + ".in LIST  Seq : " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "  Adjusted avg. Conf: " + hrus.get(i).sorted_adjusted_conf.get(key) + "  for: " + key);
                                    //w_log.println("   hh LMOD    :  ==> " + pattern);
                                    //w_log.flush();
                                    M_R.LMOD_Key = LMOD_data_by_CMZ.get(0).get(0);
                                    M_R.Rotation = true;
                                    M_R.Rotation_Duration = Integer.parseInt(LMOD_data_by_CMZ.get(0).get(6));
                                    M_R.Acronym_Sequence = pattern;
                                    M_R.CropName_Sequence = LMOD_data_by_CMZ.get(0).get(4);
                                    M_R.Vegetation_Sequence = hrus.get(i).hru_veg_seq;
                                    M_R.Avg_Confidence_Value = hrus.get(i).sorted_adjusted_conf.get(key);
                                    M_R.Rot_Start_years = key;
                                    M_R.rotation_irrigation_correct = right_irrigation_rotation;

                                    //String pattern, String text
                                    List<Integer> inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, hrus.get(i).hru_seq_org);
                                    for (Integer inner_integer : inner_matches) {

                                        int ind = 0;
                                        for (Integer inner_int : inner_matches) {
                                            ind++;
                                        }
                                        int[] indexes = new int[ind];
                                        ind = 0;
                                        for (Integer inner_int : inner_matches) {
                                            indexes[ind] = inner_int;
                                            ind++;
                                        }

                                        String help = "";
                                        double jaro_loop_value = 0.0;
                                        int old_element = -20;

                                        for (int element : indexes) {
                                            if ((old_element + pattern.toCharArray().length - 1) + 1 != element) {

                                                char[] rebuilt = new char[hrus.get(i).hru_seq_org.toCharArray().length];
                                                String org_seq = hrus.get(i).hru_seq_org;

                                                for (int j = 0; j < pattern.toCharArray().length; j++) {
                                                    rebuilt[element + j] = pattern.toCharArray()[j];
                                                }

                                                int before = element;

                                                int after = (hrus.get(i).hru_seq_org.toCharArray().length - 1) - (element + pattern.toCharArray().length - 1);

                                                int width = pattern.toCharArray().length;

//                                    w_log.println(" rebuilt lenght:  " + rebuilt.length);
//                                    w_log.println(" before:   " + before + "   after:   " + after + " width: " + width);
                                                int b = 0;
                                                while (before > 0) {
                                                    rebuilt[(before - 1)] = pattern.toCharArray()[(width - 1) - b];
                                                    b++;
                                                    if (b > width - 1) {
                                                        b = 0;
                                                    }
                                                    before--;
                                                }

                                                width = pattern.toCharArray().length;

                                                int x = 0;
                                                b = 0;
                                                while (after > 0) {
                                                    rebuilt[(element + pattern.toCharArray().length) + x] = pattern.toCharArray()[b];
                                                    b++;
                                                    if (b > width - 1) {
                                                        b = 0;
                                                    }
                                                    x++;
                                                    after--;
                                                }

                                                new_rebuilt = String.valueOf(rebuilt);

                                                String help_inner = new_rebuilt;
                                                if (org_seq.startsWith("@")) {
                                                    x = 1;
                                                    while (org_seq.startsWith("@")) {
                                                        org_seq = hrus.get(i).hru_seq_org.substring(x, hrus.get(i).hru_seq_org.toCharArray().length);
                                                        new_rebuilt = help_inner.substring(x, rebuilt.length);
                                                        x++;
                                                    }
                                                }
                                                //w_log.println("        detected rotation :" + org_seq);
                                                //w_log.println("        rebuilt  rotation :" + new_rebuilt);
                                                //w_log.println("        JaroSimilarity    : " + jaro.proximity(org_seq, new_rebuilt) + " similar");
                                                if (jaro.proximity(org_seq, new_rebuilt) > jaro_loop_value) {
                                                    jaro_loop_value = jaro.proximity(org_seq, new_rebuilt);
                                                    help = help_inner;

                                                }
                                                if (pattern.toCharArray().length == 2) {// && pattern.toCharArray()[0] != pattern.toCharArray()[1]) {
                                                    String Char1 = String.valueOf(pattern.toCharArray()[0]);
                                                    String Char2 = String.valueOf(pattern.toCharArray()[1]);
                                                    if (Char1.equals(Char2)) {
                                                        break;
                                                    }
                                                }
                                                if (jaro_loop_value > 0.99 || pattern.toCharArray().length < 2) {
                                                    break;
                                                }
                                            }
                                            old_element = element;
                                        }
                                        //M_R.Jaro_Similarity_Value = "" + jaro_loop_value;
                                        M_R.Jaro_Similarity_Value = "" + jaro.proximity(hrus.get(i).hru_seq_org, help);
                                        boolean same = false;
                                        if (pattern.toCharArray().length > 1) {// && pattern.toCharArray()[0] != pattern.toCharArray()[1]) {
                                            String Char1 = String.valueOf(pattern.toCharArray()[0]);
                                            String Char2 = String.valueOf(pattern.toCharArray()[1]);
                                            if (!Char1.equals(Char2)) {
                                                same = true;
                                                //String pattern, String text
                                                inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, help);
                                                for (Integer in_integer : inner_matches) {
                                                    M_R.Rot_Start_years = years.get(in_integer);
                                                    break;
                                                }
                                            } else {
                                                inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, help);
                                                for (Integer in_integer : inner_matches) {
                                                    M_R.Rot_Start_years = years.get(in_integer);
                                                    break;
                                                }
                                            }
                                        } else if (pattern.toCharArray().length == 1) {
                                            M_R.Rot_Start_years = years.get(0);
                                        } else if (!same) {
                                            M_R.Rot_Start_years = key.split("\\,")[0];
                                        }
                                        M_R.Detected_Rebuilt_Rotation = hrus.get(i).hru_seq_org + " - " + help;
//                                w_log.println(" ");
//                                w_log.flush();
                                        //if (jaro.proximity(org_seq, new_rebuilt) > 0.2) {
                                        match = true;
                                        rot_in_cmz = true;
                                        break;
                                        //}
                                    }

                                }
                            }//end fitting CMZ
                            if (match) {
                                rot_in_cmz = true;
                                break;
                            }
                            hash_pos++;
                        }
                        //case for NO fitting rotation in CMZ!!!!! Here:
                        /*


                         */
                        if (!match && !rot_in_cmz) {
                            //LOG.info(i + " HRU in new XXXXX match: ");
                            //LOG.info("  veg_seq : " + hrus.get(i).hru_veg_seq);
                            //LOG.info("  org_seq : " + hrus.get(i).hru_seq_org);
                            //w_log.flush();
                            for (String key : hrus.get(i).sorted_adjusted_conf.keySet()) {
                                //LOG.info(" key : " + key);
                                //LOG.info(" hrus.get(i).sorted_adjusted_conf.get(key) : " + hrus.get(i).sorted_adjusted_conf.get(key));
                                //LOG.info(" hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key) : " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)));

                                if (!match && DB_LMOD_map.get(hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_XX_" + (hrus.get(i).irrigated).toString().toUpperCase()) != null) {

                                    right_irrigation_rotation = true;

                                    List<ArrayList<String>> LMOD_data_by_CMZ = DB_LMOD_map.get(hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_XX_" + (hrus.get(i).irrigated).toString().toUpperCase());
//                            if (LMOD_data_by_CMZ.size() > 1) {
                                    //w_log.println("    " + LMOD_data_by_CMZ.size() + ": Number of " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "_XX_" + (hrus.get(i).irrigated).toString().toUpperCase());
                                    //w_log.flush();
//                            }
                                    pattern = hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key));

                                    //w_log.println("    " + hash_pos + ".in LIST  Seq : " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)) + "  Adjusted avg. Conf: " + hrus.get(i).sorted_adjusted_conf.get(key) + "  for: " + key);
                                    //w_log.println("    LMOD    :  ==> " + pattern);
                                    //w_log.flush();
                                    M_R.LMOD_Key = LMOD_data_by_CMZ.get(0).get(0);
                                    M_R.Rotation = true;
                                    M_R.Rotation_Duration = Integer.parseInt(LMOD_data_by_CMZ.get(0).get(6));
                                    M_R.Acronym_Sequence = pattern;
                                    M_R.CropName_Sequence = LMOD_data_by_CMZ.get(0).get(4);
                                    M_R.Vegetation_Sequence = hrus.get(i).hru_veg_seq;
                                    M_R.Avg_Confidence_Value = hrus.get(i).sorted_adjusted_conf.get(key);
                                    M_R.Rot_Start_years = key;
                                    M_R.rotation_irrigation_correct = right_irrigation_rotation;

                                    //String pattern, String text
                                    List<Integer> inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, hrus.get(i).hru_seq_org);
                                    for (Integer inner_integer : inner_matches) {

                                        int ind = 0;
                                        for (Integer inner_int : inner_matches) {
                                            ind++;
                                        }
                                        int[] indexes = new int[ind];
                                        ind = 0;
                                        for (Integer inner_int : inner_matches) {
                                            indexes[ind] = inner_int;
                                            ind++;
                                        }

                                        String help = "";
                                        double jaro_loop_value = 0.0;
                                        int old_element = -20;

                                        for (int element : indexes) {
                                            if ((old_element + pattern.toCharArray().length - 1) + 1 != element) {

                                                char[] rebuilt = new char[hrus.get(i).hru_seq_org.toCharArray().length];
                                                String org_seq = hrus.get(i).hru_seq_org;

                                                for (int j = 0; j < pattern.toCharArray().length; j++) {
                                                    rebuilt[element + j] = pattern.toCharArray()[j];
                                                }

                                                int before = element;

                                                int after = (hrus.get(i).hru_seq_org.toCharArray().length - 1) - (element + pattern.toCharArray().length - 1);

                                                int width = pattern.toCharArray().length;

                                                //w_log.println(" rebuilt lenght:  " + rebuilt.length);
                                                //w_log.println(" before:   " + before + "   after:   " + after + " width: " + width);
                                                int b = 0;
                                                while (before > 0) {
                                                    rebuilt[(before - 1)] = pattern.toCharArray()[(width - 1) - b];
                                                    b++;
                                                    if (b > width - 1) {
                                                        b = 0;
                                                    }
                                                    before--;
                                                }

                                                width = pattern.toCharArray().length;

                                                int x = 0;
                                                b = 0;
                                                while (after > 0) {
                                                    rebuilt[(element + pattern.toCharArray().length) + x] = pattern.toCharArray()[b];
                                                    b++;
                                                    if (b > width - 1) {
                                                        b = 0;
                                                    }
                                                    x++;
                                                    after--;
                                                }

                                                new_rebuilt = String.valueOf(rebuilt);

                                                String help_inner = new_rebuilt;
                                                if (org_seq.startsWith("@")) {
                                                    x = 1;
                                                    while (org_seq.startsWith("@")) {
                                                        org_seq = hrus.get(i).hru_seq_org.substring(x, hrus.get(i).hru_seq_org.toCharArray().length);
                                                        new_rebuilt = help_inner.substring(x, rebuilt.length);
                                                        x++;
                                                    }
                                                }
                                                //w_log.println("        detected rotation :" + org_seq);
                                                //w_log.println("        rebuilt  rotation :" + new_rebuilt);
                                                //w_log.println("        JaroSimilarity    : " + jaro.proximity(org_seq, new_rebuilt) + " similar");
                                                if (jaro.proximity(org_seq, new_rebuilt) > jaro_loop_value) {
                                                    jaro_loop_value = jaro.proximity(org_seq, new_rebuilt);
                                                    help = help_inner;

                                                }
                                                if (pattern.toCharArray().length == 2) {// && pattern.toCharArray()[0] != pattern.toCharArray()[1]) {
                                                    String Char1 = String.valueOf(pattern.toCharArray()[0]);
                                                    String Char2 = String.valueOf(pattern.toCharArray()[1]);
                                                    if (Char1.equals(Char2)) {
                                                        break;
                                                    }
                                                }
                                                if (jaro_loop_value > 0.99 || pattern.toCharArray().length < 2) {
                                                    break;
                                                }
                                            }
                                            old_element = element;
                                        }
                                        //M_R.Jaro_Similarity_Value = "" + jaro_loop_value;
                                        M_R.Jaro_Similarity_Value = "" + jaro.proximity(hrus.get(i).hru_seq_org, help);
                                        boolean same = false;
                                        if (pattern.toCharArray().length > 1) {// && pattern.toCharArray()[0] != pattern.toCharArray()[1]) {
                                            String Char1 = String.valueOf(pattern.toCharArray()[0]);
                                            String Char2 = String.valueOf(pattern.toCharArray()[1]);
                                            if (!Char1.equals(Char2)) {
                                                same = true;
                                                //String pattern, String text
                                                inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, help);
                                                for (Integer in_integer : inner_matches) {
                                                    M_R.Rot_Start_years = years.get(in_integer);
                                                    break;
                                                }
                                            } else {
                                                inner_matches = new CSIP_NASS_LMOD_Matching().Match(pattern, help);
                                                for (Integer in_integer : inner_matches) {
                                                    M_R.Rot_Start_years = years.get(in_integer);
                                                    break;
                                                }
                                            }
                                        } else if (pattern.toCharArray().length == 1) {
                                            M_R.Rot_Start_years = years.get(0);
                                        } else if (!same) {
                                            M_R.Rot_Start_years = key.split("\\,")[0];
                                        }
                                        M_R.Detected_Rebuilt_Rotation = hrus.get(i).hru_seq_org + " - " + help;
                                        //w_log.println(" detect rebuilt help : " + hrus.get(i).hru_seq_org + " - " + help);
                                        //w_log.println(" ");
                                        //w_log.flush();
                                        //if (jaro.proximity(org_seq, new_rebuilt) > 0.2) {
                                        match = true;
                                        //LOG.info(" Match !!! : " + hrus.get(i).seq_map.get(hrus.get(i).sorted_adjusted_conf.get(key)));

                                        break;
                                        //}
                                    }
                                    if (match) {
                                        break;
                                    }
                                }
                                if (match) {
                                    break;
                                }
                            }
                        }
                    }

                    // non field crop handling
                    if (!match || new_rebuilt.toCharArray().length < 2) {
                        Map<String, Integer> majority_veg = new HashMap<>();
                        String[] each_veg = hrus.get(i).hru_veg_seq.split(";");
                        for (int j = each_veg.length - 1; j >= ((each_veg.length) - each_veg.length); j--) {
                            if (!each_veg[j].equals("NODATA")) {
                                if (majority_veg.get(each_veg[j]) == null) {
                                    majority_veg.put(each_veg[j], 1);
                                } else {
                                    int count = majority_veg.get(each_veg[j]);
                                    majority_veg.put(each_veg[j], count + 1);
                                }
                            }
                        }
                        majority_veg = sortByValues(majority_veg);
                        if (majority_veg.isEmpty()) {
                            majority_veg.put("NODATA", 1);
                        }

                        for (String key : majority_veg.keySet()) {
                            //w_log.println("        =====>>>> Majority vegetation: " + key + "  , count = " + majority_veg.get(key));
                            M_R.Rotation = false;
                            M_R.Rotation_Duration = 1;
                            M_R.Vegetation_Sequence = key;
                            M_R.Avg_Confidence_Value = 0.0;
                            M_R.Rot_Start_years = hrus.get(i).nass_list_data.get(0).getyear();
                            if (CSIP_Const.NonFieldCropClasses.contains(key)) {
                                break;
                            }
                        }
                    }

                    if (!map_bigger_rot_jaro.isEmpty()) {
                        Map<String, Double> sorted = sortByValues(map_bigger_rot_jaro);
                        double old_value = 0;
                        for (String key : sorted.keySet()) {
                            //if (old_value == 0 || old_value == sorted.get(key)) {
                            //w_log.println(i + " ====>>>> Bigger rotation     JaroWinkler simi: " + key + "  = " + sorted.get(key));
                            //w_log.flush();
                            old_value = sorted.get(key);
                            // } else {
                            //    break;
                            // }
                        }
                    }
                    Map<Integer, String[]> YearRotGen = new HashMap<>();

                    if (M_R.Rotation) {
                        int compl_1st_start_year = 0;
                        int compl_last_start_year = 0;
                        int before = Integer.parseInt(M_R.Rot_Start_years) - 1;
                        int after_gen = (2100 + 1) - (Integer.parseInt(M_R.Rot_Start_years) + M_R.Acronym_Sequence.toCharArray().length);
                        int width = M_R.Acronym_Sequence.toCharArray().length;

                        //System.out.println(" before:   " + before + "   after:   " + (Integer.parseInt(M_R.Rot_Start_years) + M_R.Acronym_Sequence.toCharArray().length) + " width: " + width + "  " + M_R.Acronym_Sequence + "  " + M_R.Rot_Start_years);
                        String[] generic_years = new String[2];

                        int b = 0;
                        while (before > (1900 - 1)) {
                            generic_years = new String[]{Character.toString(M_R.Acronym_Sequence.toCharArray()[(width - 1) - b]), "" + ((width - 1) - b)};
                            YearRotGen.put(before, generic_years);
                            b++;
                            if (b > width - 1) {
                                b = 0;
                            }
                            before--;
                        }

                        int gh = 0;
                        for (int j = Integer.parseInt(M_R.Rot_Start_years); j < (Integer.parseInt(M_R.Rot_Start_years) + M_R.Acronym_Sequence.toCharArray().length); j++) {
                            generic_years = new String[]{Character.toString(M_R.Acronym_Sequence.toCharArray()[gh]), "" + gh};
                            YearRotGen.put((Integer.parseInt(M_R.Rot_Start_years) + gh), generic_years);
                            gh++;
                        }

                        before = Integer.parseInt(M_R.Rot_Start_years) - 1;

                        int x = 0;
                        while (after_gen > 0) {
                            generic_years = new String[]{Character.toString(M_R.Acronym_Sequence.toCharArray()[b]), "" + b};
                            YearRotGen.put((before + 1 + M_R.Acronym_Sequence.toCharArray().length + x), generic_years);
                            b++;
                            if (b > width - 1) {
                                b = 0;
                            }
                            x++;
                            after_gen--;
                        }

                        if (!YearRotGen.isEmpty()) {
                            Map<Integer, String[]> treeMap = new TreeMap<>(YearRotGen);

                            boolean first_zero = false;

                            int preparts = -99;
                            int afterparts = -99;
                            boolean prefit = false;
                            boolean aftfit = false;

                            for (int j = start_year; j < end_year + 1; j++) {
                                int rot_pos = Integer.parseInt(treeMap.get(j)[1]);
                                if (rot_pos == 0 && !first_zero) {
                                    compl_1st_start_year = j;
                                    first_zero = true;
                                }
                                if (preparts == -99) {
                                    preparts = rot_pos;
                                }
                                if (rot_pos == M_R.Acronym_Sequence.toCharArray().length - 1) {
                                    compl_last_start_year = j;
                                }
                                afterparts = rot_pos;
                            }

                            if (compl_1st_start_year != start_year) {
                                for (int j = compl_1st_start_year; j > start_year - 1; j--) {
                                    int rot_pos = Integer.parseInt(treeMap.get(j)[1]);
                                    preparts = rot_pos;
                                }
                            } else {
                                prefit = true;
                            }

                            if (compl_last_start_year != end_year) {
                                for (int j = compl_last_start_year + 1; j < end_year + 1; j++) {
                                    int rot_pos = Integer.parseInt(treeMap.get(j)[1]);
                                    afterparts = rot_pos;
                                }
                            } else {
                                aftfit = true;
                            }

                            Map<Boolean, Integer[]> result_start_end = new HashMap<>();

                            if (prefit && aftfit) {
                                result_start_end.put(true, new Integer[]{start_year, end_year, -99, -99, -99, -99});
                            } else {
                                result_start_end.put(false, new Integer[]{start_year, end_year, compl_1st_start_year, preparts, compl_last_start_year, afterparts});
                            }
                            M_R.custom_start_end = result_start_end;
                        }
                    }

                    hrus.get(i).Matching_Result = M_R;

                    if (hrus.get(i).hru_seq_work.length() != String_count) {

                        for (int j = 0; j < hrus.get(i).hru_seq_work.toCharArray().length; j++) {
                            if (hrus.get(i).hru_seq_work.toCharArray()[j] != '@' && hrus.get(i).hru_seq_work.toCharArray()[j] != '+') {

                                ArrayList<ArrayList<String>> LMOD_Global_Data = new ArrayList<>();
                                String queryString = "select * from \"PUBLIC\".LMOD_MGMTS_ACR_II where CROPSEQACR='" + hrus.get(i).hru_seq_work.toCharArray()[j] + "' AND IRRIGATED='" + hrus.get(i).irrigated.toString().toUpperCase() + "'";

                                ResultSet result = state.executeQuery(queryString);
                                ArrayList<String> LMOD_data = new ArrayList<>();
                                boolean empty = true;
                                while (result.next()) {
                                    LMOD_data.add(result.getString("KEY"));
                                    LMOD_data.add(result.getString("CMZ"));
                                    LMOD_data.add(result.getString("IRRIGATED"));
                                    LMOD_data.add(result.getString("COVERCROPS"));
                                    LMOD_data.add(result.getString("CROPSEQUENCE"));
                                    LMOD_data.add(result.getString("CROPSEQACR"));
                                    LMOD_Global_Data.add(LMOD_data);
                                    empty = false;
                                }
                                if (empty) {
                                    queryString = "select * from \"PUBLIC\".LMOD_MGMTS_ACR_II where CROPSEQACR='" + hrus.get(i).hru_seq_work.toCharArray()[j] + "'";

                                    result = state.executeQuery(queryString);
                                    while (result.next()) {
                                        LMOD_data.add(result.getString("KEY"));
                                        LMOD_data.add(result.getString("CMZ"));
                                        LMOD_data.add(result.getString("IRRIGATED"));
                                        LMOD_data.add(result.getString("COVERCROPS"));
                                        LMOD_data.add(result.getString("CROPSEQUENCE"));
                                        LMOD_data.add(result.getString("CROPSEQACR"));
                                        LMOD_Global_Data.add(LMOD_data);
                                        empty = false;
                                    }
                                }

                                if (empty) {
                                    // NASS acronym but NO LMOD acronym

                                    /*
                                    LOG.info(" BIIGG ERROR with Geometry: " + hrus.get(i).ID + "  and sequence: " + hrus.get(i).hru_seq_work);
                                    HAVE To do something here !!!!!!!!!!!!!!!! Holm Kipka June issue
                                    -saw the asparagus example +++C+++
                                    there is now single year Asperagus in LMOD ????????????                                   
                                    
                                     */
                                    char[] myNameChars = hrus.get(i).hru_seq_work.toCharArray();
                                    myNameChars[j] = '@';
                                    hrus.get(i).hru_seq_work = String.valueOf(myNameChars);
                                } else {

                                    Year_LMOD_Rot_Linkage.add(new String[]{LMOD_Global_Data.get(0).get(0), (years.get(j))});
                                    char[] myNameChars = hrus.get(i).hru_seq_work.toCharArray();
                                    myNameChars[j] = '+';
                                    hrus.get(i).hru_seq_work = String.valueOf(myNameChars);

                                }

                            }
                            if (hrus.get(i).hru_seq_work.toCharArray()[j] == '@') {
                                Year_LMOD_Rot_Linkage.add(new String[]{hrus.get(i).hru_veg_seq.split(";")[j], (years.get(j))});
                            }
                        }//end for

                    }
                    Collections.sort(Year_LMOD_Rot_Linkage, new yearComparator() {
                    });
                    map.put(i, Year_LMOD_Rot_Linkage);
                }
                state.close();
            }//try state
            conn.close();//end db connection
        }//try conn

        long end_time = System.currentTimeMillis();
        double difference = (end_time - start_time) / 1000;
        //LOG.info(" Done  first : " + first + "   last : " + last + "    time : " + difference + " s");

        return map;
    }

    /**
     *
     * @param workspace
     * @param hrus
     * @param irrigation_map
     * @param delta
     * @param LOG
     * @throws IOException
     */
    public static void AOI_NASS_LMOD_generic_match_data_writer(File workspace, List<ERU> hrus, HashMap<Integer, ArrayList<HashMap<Integer, Double>>> irrigation_map, double delta, SessionLogger LOG) throws IOException {
        //try (PrintWriter w = new PrintWriter(new FileWriter(new File(workspace, CSIP_Const.AOI_NASS_LMOD_generic_result)))) {

        LOG.info("===>      AOI_NASS_LMOD_generic_result");

        List<String> records = new ArrayList<>();

        records.add("# delta-factor for adjusted average confidence value: " + delta);
        records.add("# Shown sequences are for the NASS CropScape provided time period ");

        records.add(" ");
        records.add(" ");
        records.add("FieldID / HRU,Generic LMOD Rotation (GLR) Best Match,LMOD Found Rotation Duration (Year(s)),LMOD Rotation Acronym, Adjusted Average Confidence Value (AACV),Detected NASS Sequence,Rebuilt from LMOD Crop Rotation Sequence,GLR Start Year,Jaro Similarity,Field-Crop,Irrigated Area (%) 2002,Irrigated Area(%) 2007,Irrigated Area (%) 2012,Irrigated Area (%) 2017,State,County,CMZ,Area");

        for (int i = 0; i < hrus.size(); i++) {
            int HRUID = hrus.get(i).ID;
            String hru_state = "";
            for (String st : hrus.get(i).state) {
                hru_state = hru_state + " -" + st;
            }
            String hru_cmz = "";
            for (String cm : hrus.get(i).cmz) {
                hru_cmz = hru_cmz + " -" + cm;
            }
            String hru_county = "";
            for (String counties : hrus.get(i).county) {
                hru_county = hru_county + " -" + counties;
            }
            if (hrus.get(i).Matching_Result.Rotation) {
                double irri02 = 0;
                double irri07 = 0;
                double irri12 = 0;
                double irri17 = 0;
                if (irrigation_map.get(HRUID) != null) {
                    for (int j = 0; j < irrigation_map.get(HRUID).size(); j++) {
                        for (Integer keys : irrigation_map.get(HRUID).get(j).keySet()) {
                            if (2002 == keys) {
                                irri02 = Math.round((irrigation_map.get(HRUID).get(j).get(2002) * 100) / 100) > 100 ? 100 : Math.round(irrigation_map.get(HRUID).get(j).get(2002) * 100) / 100;
                            }
                            if (2007 == keys) {
                                irri07 = Math.round((irrigation_map.get(HRUID).get(j).get(2007) * 100) / 100) > 100 ? 100 : Math.round(irrigation_map.get(HRUID).get(j).get(2007) * 100) / 100;
                            }
                            if (2012 == keys) {
                                irri12 = Math.round((irrigation_map.get(HRUID).get(j).get(2012) * 100) / 100) > 100 ? 100 : Math.round(irrigation_map.get(HRUID).get(j).get(2012) * 100) / 100;
                            }
                            if (2017 == keys) {
                                irri17 = Math.round((irrigation_map.get(HRUID).get(j).get(2017) * 100) / 100) > 100 ? 100 : Math.round(irrigation_map.get(HRUID).get(j).get(2017) * 100) / 100;
                            }
                        }
                    }
                }
                records.add(HRUID + "," + hrus.get(i).Matching_Result.CropName_Sequence + "," + hrus.get(i).Matching_Result.Rotation_Duration + "," + hrus.get(i).Matching_Result.Acronym_Sequence + "," + Double.toString(Numeric.round(hrus.get(i).Matching_Result.Avg_Confidence_Value, 3)) + "," + hrus.get(i).Matching_Result.Detected_Rebuilt_Rotation.split("-")[0].trim() + "," + hrus.get(i).Matching_Result.Detected_Rebuilt_Rotation.split("-")[1].trim() + "," + hrus.get(i).Matching_Result.Rot_Start_years + "," + Double.toString(Numeric.round(Double.parseDouble(hrus.get(i).Matching_Result.Jaro_Similarity_Value), 3)) + ",TRUE," + irri02 + "," + irri07 + "," + irri12 + "," + irri17 + "," + hru_state + "," + hru_county + "," + hru_cmz + "," + Math.round(hrus.get(i).geom.getArea() * 100) / 100);
            } else { // just majority vegetation detected
                records.add(HRUID + "," + hrus.get(i).Matching_Result.Vegetation_Sequence + ",-,-" + ",-" + "," + hrus.get(i).hru_seq_org + ",-," + hrus.get(i).nass_list_data.get(0).getyear() + ",-,FALSE,-,-,-,-," + hru_state + "," + hru_county + "," + hru_cmz + "," + Math.round(hrus.get(i).geom.getArea() * 100) / 100);
            }
        }
        try (FileWriter writer = new FileWriter(new File(workspace, CSIP_Const.AOI_NASS_LMOD_generic_result))) {
            BufferedWriter buffWriter = new BufferedWriter(writer);
            for (String record : records) {
                buffWriter.write(record + "\r\n");
                //writer.write(record);
            }
            //writer.flush();
            buffWriter.close();
        }
    }

    /**
     *
     * @param dataDir
     * @param hrus
     * @param DB_map_managements
     * @param Unique_LMOD_OPKEYs
     * @param Unique_LMOD_ManKEYs
     * @param managements
     * @param OP_map
     * @param DB_map_managements_acr
     * @param OP_map_tillage
     * @param LMOD_AGES_CID_map
     * @param only_veg_map
     * @param only_landuse_map
     * @param LOG
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static void AOI_NASS_DETECTED_LMODDATA_PREPARATION(File dataDir, List<ERU> hrus, HashMap<String, ArrayList<String[]>> DB_map_managements, ArrayList<String> Unique_LMOD_OPKEYs, ArrayList<String> Unique_LMOD_ManKEYs, HashMap<String, HashMap<Integer, ArrayList<String[]>>> managements, HashMap<String, String> OP_map, HashMap<String, String[]> DB_map_managements_acr, HashMap<String, String[]> OP_map_tillage, HashMap<String, String> LMOD_AGES_CID_map, HashMap<String, String> only_veg_map, HashMap<String, String> only_landuse_map, SessionLogger LOG) throws IOException, ClassNotFoundException, SQLException {

        LOG.info("===>      AOI_NASS_DETECTED_LMODDATA_PREPARATION");

        ArrayList<String[]> custom_line = new ArrayList<>();
        HashMap<Integer, ArrayList<String[]>> man_yearparts_map = new HashMap<>();

        Class.forName("org.h2.Driver");
        try (Connection conn = DriverManager.getConnection("jdbc:h2:file:" + dataDir.getPath() + CSIP_Const.LocalDB, "sa", ""); Statement state = conn.createStatement()) {
            String queryString = "select NASSNAME,AGES_MID,AgES_landuse from PUBLIC.DICTIONARY where AGES_MID is not null;";
            ResultSet result = state.executeQuery(queryString);
            while (result.next()) {
                only_veg_map.put(result.getString("NASSNAME"), result.getString("AGES_MID"));
                only_landuse_map.put(result.getString("NASSNAME"), result.getString("AgES_landuse"));
            }

            queryString = "select LAMS_LMOD_H2,AGES_CID from PUBLIC.DICTIONARY where LAMS_LMOD_H2 is not null and AGES_CID is not null;";
            result = state.executeQuery(queryString);
            while (result.next()) {
                String[] LMOD_names = result.getString("LAMS_LMOD_H2").trim().split(";");
                for (String LMOD_name : LMOD_names) {
                    if (LMOD_AGES_CID_map.get(LMOD_name) == null) {
                        LMOD_AGES_CID_map.put(LMOD_name, result.getString("AGES_CID").trim().split(";")[0]);
                    }
                }
            }

            LOG.info("===>        PREPARATION: query each HRU-management");

            for (int i = 0; i < hrus.size(); i++) {
                //System.out.println("ID " + hrus.get(i).ID);
                if (hrus.get(i).Matching_Result.Rotation) {
                    //System.out.println(" " + hrus.get(i).Matching_Result.LMOD_Key);
                    queryString = "select distinct * from PUBLIC.LMOD_MANAGEMENTS_II where MANKEY='" + hrus.get(i).Matching_Result.LMOD_Key + "' order by date";
                    result = state.executeQuery(queryString);
                    ArrayList<String[]> Management_data = new ArrayList<>();
                    man_yearparts_map = new HashMap<>();
                    int rot_year = -1;
                    int old_year = -1;
                    int year_count = 0;
                    int xx = 0;
                    custom_line = new ArrayList<>();
                    while (result.next()) {
                        String[] DBrow = new String[7];
                        DBrow[0] = result.getString("OPKEY").trim();
                        if (!Unique_LMOD_OPKEYs.contains(result.getString("OPKEY").trim())) {
                            Unique_LMOD_OPKEYs.add(result.getString("OPKEY").trim());
                        }
                        if (!Unique_LMOD_ManKEYs.contains(hrus.get(i).Matching_Result.LMOD_Key)) {
                            Unique_LMOD_ManKEYs.add(hrus.get(i).Matching_Result.LMOD_Key);
                        }
                        DBrow[1] = result.getString("DATE").trim();
                        //System.out.println(" " + result.getString("DATE").trim());
                        DBrow[2] = result.getString("OPERATION").replaceAll(",", ":").replace("\\", "").trim();
                        DBrow[3] = result.getString("VEGETATIONINFO").replaceAll(",", ":").trim();
                        DBrow[4] = "" + (result.getString("SEED_HARV") == null ? "" : result.getString("SEED_HARV"));
                        DBrow[5] = "" + (result.getString("VEGETATION") == null ? "" : result.getString("VEGETATION"));
                        DBrow[6] = "" + (result.getString("HARV_FRAC") == null ? "" : result.getString("HARV_FRAC"));
                        Management_data.add(DBrow);
                        //----------------------------
                        rot_year = Integer.parseInt(result.getString("DATE").trim().split("\\.")[0]) + 1;

                        if (rot_year != old_year) {
                            if (man_yearparts_map.put(year_count, custom_line) != null) {
                                throw new IllegalArgumentException("Duplicate MID: " + old_year);
                            }
                            custom_line = new ArrayList<>();
                            old_year = rot_year;
                            year_count++;
                        }
                        DBrow = new String[4];
                        DBrow[0] = result.getString("DATE").trim().split("\\.")[1] + "/" + result.getString("DATE").trim().split("\\.")[2];
                        DBrow[1] = result.getString("OPERATION").replaceAll(",", ":").replace("\\", "").trim();
                        DBrow[2] = result.getString("VEGETATIONINFO").replaceAll(",", ":").trim();
                        DBrow[3] = result.getString("OPKEY").trim();
                        custom_line.add(DBrow);
                        xx++;
                    }
                    if (man_yearparts_map.put(year_count, custom_line) != null) {
                        throw new IllegalArgumentException("Duplicate MID: " + rot_year);
                    }
                    DB_map_managements.put(hrus.get(i).Matching_Result.LMOD_Key, Management_data);
                    managements.put(hrus.get(i).Matching_Result.LMOD_Key, man_yearparts_map);
                }
            }

            //w_log.println("===>        PREPARATION: query unique OPKeys");
            LOG.info("===>        PREPARATION: query unique OPKeys");
            //w_log.flush();

            for (String OPKey : Unique_LMOD_OPKEYs) {
                queryString = "select distinct * from \"PUBLIC\".LMOD_OPERATIONS where OPKEY='" + OPKey + "'";
                result = state.executeQuery(queryString);
                while (result.next()) {
                    String[] till = new String[4];
                    String intens = "" + result.getString("TILL_INTENSITY");
                    String tilldepthmax = "" + result.getString("TILL_DEPTH_MAX");
                    String tillmin = "" + result.getString("TILL_DEPTH_MIN");
                    String tilldeptunit = "" + result.getString("DEPTH_UNIT");
                    String name = "" + result.getString("DESCRIPTION").replaceAll(",", ":");
                    name = "" + name.replaceAll("\\\\n", "");
                    if (!tilldeptunit.equals("null")) {
                        till[0] = name;
                        till[1] = name;
                        till[2] = intens;
                        double depth = (Double.parseDouble(tillmin) + Double.parseDouble(tilldepthmax) / 2) * 25.4;
                        till[3] = "" + Numeric.round(depth, 0);
                        OP_map_tillage.put(OPKey, till);
                    }
                    String result_line = (intens.equals("null") ? "NA" : intens) + "," + (tilldepthmax.equals("null") ? "NA" : tilldepthmax) + "," + (tillmin.equals("null") ? "NA" : tillmin) + "," + (tilldeptunit.equals("null") ? "NA" : tilldeptunit) + "," + (name.equals("null") ? "NA" : name);
                    OP_map.put(OPKey, result_line);

                }

            }

            //w_log.println("===>        PREPARATION: query unique ManKeys");
            LOG.info("===>        PREPARATION: query unique ManKeys");
            //w_log.flush();

            for (String ManKey : Unique_LMOD_ManKEYs) {
                queryString = "select distinct * from \"PUBLIC\".LMOD_MGMTS_ACR_II where KEY='" + ManKey + "'";
                result = state.executeQuery(queryString);
                while (result.next()) {
                    DB_map_managements_acr.put(ManKey, new String[]{result.getString("START_DATE"), result.getString("FIRST_SEED"), result.getString("LAST_HARV"), result.getString("END_DATE"), result.getString("CAL_YEARS"), result.getString("YEARS"), result.getString("CROPSEQUENCE")});
                }
            }
            state.close();
            conn.close();//end db connection
        }
    }

    /**
     *
     * @param workspace
     * @param hrus
     * @param DB_map_managements
     * @param managements
     * @param OP_map
     * @param DB_map_managements_acr
     * @param LMOD_AGES_MID_map
     * @param only_veg_map
     * @param start_year
     * @param end_year
     * @param LOG
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws SQLException
     * @throws java.lang.InterruptedException
     * @throws java.util.concurrent.ExecutionException
     */
    public static void AOI_NASS_LMODDATA_costum_generic_writer(File workspace, List<ERU> hrus, HashMap<String, ArrayList<String[]>> DB_map_managements, HashMap<String, HashMap<Integer, ArrayList<String[]>>> managements, HashMap<String, String> OP_map, HashMap<String, String[]> DB_map_managements_acr, HashMap<String, String> LMOD_AGES_MID_map, HashMap<String, String> only_veg_map, Integer start_year, Integer end_year, SessionLogger LOG) throws IOException, ClassNotFoundException, SQLException, InterruptedException, ExecutionException {

        //w_log.println("===>      AOI_NASS_LMOD_result_custom");
        LOG.info("===>      AOI_NASS_LMOD_result_custom");
        //w_log.flush();

        List<String> records = new ArrayList<>();

        records.add("FieldID / HRU, Date,Operation,Vegetation,Tillage-Intensity,Tillage-Depth-Max,Tillage-Depth-Min,Depth-Unit,Description \r\n");

        final int threadNum = Partition.getThreadCount(hrus.size());
        final int first = 0;
        final int last = hrus.size() - 1;
        final List<ERU> fhrus = hrus;
        final HashMap<String, ArrayList<String[]>> DB_map_managements_fin = DB_map_managements;
        final HashMap<String, HashMap<Integer, ArrayList<String[]>>> managements_fin = managements;
        final HashMap<String, String> OP_map_fin = OP_map;
        final HashMap<String, String[]> DB_map_managements_acr_fin = DB_map_managements_acr;
        final HashMap<String, String> LMOD_AGES_MID_map_fin = LMOD_AGES_MID_map;
        final HashMap<String, String> only_veg_map_fin = only_veg_map;
        final Integer start_year_fin = start_year;
        final Integer end_year_fin = end_year;

        final int p = (last + 1) / threadNum;
        int s = (last + 1) - p * threadNum;

        // Prepare to execute and store the Futures
        ExecutorService executor = Executors.newFixedThreadPool(threadNum);
        List<FutureTask<List<String>>> taskList = new ArrayList<>();
        for (int j = 0; j < threadNum; j++) {
            final int ii = j;
            FutureTask<List<String>> futureTask_1 = new FutureTask<>(new Callable<List<String>>() {
                int inlast = (ii == threadNum - 1 ? last : p + (ii * p));
                int infirst = (ii == 0 ? first : (p * ii) + 1);

                @Override
                public List<String> call() throws Exception {
                    return CSIP_NASS_LMOD_Matching.AOI_NASS_LMODDATA_costum_generic_concurrent(infirst, inlast, fhrus, DB_map_managements_fin, managements_fin, OP_map_fin, DB_map_managements_acr_fin, LMOD_AGES_MID_map_fin, only_veg_map_fin, start_year_fin, end_year_fin);
                }
            });
            taskList.add(futureTask_1);
            executor.execute(futureTask_1);
        }

        // Wait until all results are available and combine them at the same time
        for (int j = 0; j < threadNum; j++) {
            FutureTask<List<String>> futureTask = taskList.get(j);
            for (int i = 0; i < futureTask.get().size(); i++) {
                records.add(futureTask.get().get(i));
            }
        }
        executor.shutdown();

        //w.close();
        try (FileWriter writer = new FileWriter(new File(workspace, CSIP_Const.AOI_NASS_LMOD_result_custom))) {
            BufferedWriter buffWriter = new BufferedWriter(writer);
            for (String record : records) {
                buffWriter.write(record);
                //writer.write(record);
            }
            //writer.flush();
            buffWriter.close();
        }

    }

    public static List<String> AOI_NASS_LMODDATA_costum_generic_concurrent(int first, int last, List<ERU> hrus, HashMap<String, ArrayList<String[]>> DB_map_managements, HashMap<String, HashMap<Integer, ArrayList<String[]>>> managements, HashMap<String, String> OP_map, HashMap<String, String[]> DB_map_managements_acr, HashMap<String, String> LMOD_AGES_MID_map, HashMap<String, String> only_veg_map, Integer start_year, Integer end_year) throws IOException, ClassNotFoundException, SQLException {

        List<String> records = new ArrayList<>();

        for (int i = first; i <= last; i++) {
            if (hrus.get(i).Matching_Result.Rotation) {
                Map<Boolean, Integer[]> result_start_end = hrus.get(i).Matching_Result.custom_start_end;
                boolean fit_boolean = false;
                for (Boolean key : result_start_end.keySet()) {
                    fit_boolean = key;
                    break;
                }

                ArrayList<String[]> Management_data = DB_map_managements.get(hrus.get(i).Matching_Result.LMOD_Key);

                int rot_year = -1;
                int old_year = -1;
                int test_year = 0;
                int lines_count = 0;
                int first_month = 0;
                int last_month = 0;
                for (String[] line : Management_data) {
                    if (lines_count == 0) {
                        first_month = Integer.parseInt(line[1].trim().split("\\.")[1]);
                    }
                    //System.out.println(" check  " + line[1].trim());
                    rot_year = Integer.parseInt(line[1].trim().split("\\.")[0]);
                    if (rot_year > old_year) {
                        old_year = rot_year;
                        test_year++;
                    }
                    last_month = Integer.parseInt(line[1].trim().split("\\.")[1]);
                    lines_count++;
                }
                //System.out.println(" ");
                //System.out.println(" perfect fit " + hrus.get(i).ID + "    test_year count: " + test_year + " lines: " + lines_count + "  key: " + hrus.get(i).Matching_Result.LMOD_Key + " 1st mo: " + first_month + "  last_mo: " + last_month);

                int year_count = start_year;

                if (fit_boolean) {

                    rot_year = -1;
                    old_year = -1;
                    int xxx = 0;
                    while (year_count < end_year + 1) {
                        String veggy = "";
                        //last month first month in same year!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        if (test_year == 1 && year_count <= end_year) {
                            for (String[] line : Management_data) {
                                if (!line[3].isEmpty()) {
                                    veggy = line[3];
                                }
                                records.add(hrus.get(i).ID + "," + line[1].split("\\.")[1] + "/" + line[1].split("\\.")[2] + "/" + year_count + "," + line[2] + "," + veggy + "," + OP_map.get(line[0]) + " \r\n");
                                if (line[2].contains("arvest") || line[2].contains("kill")) {
                                    veggy = "";
                                }
                            }
                            year_count++;
                        } else {
                            for (String[] line : Management_data) {
                                if (!line[3].isEmpty()) {
                                    veggy = line[3];
                                }
                                //System.out.println(" " + line[1].trim());
                                rot_year = Integer.parseInt(line[1].trim().split("\\.")[0]);
                                if (rot_year != old_year) {
                                    old_year = rot_year;
                                    if (xxx > 0) {
                                        year_count++;
                                    }
                                }
                                if (year_count <= end_year) {
                                    records.add(hrus.get(i).ID + "," + line[1].split("\\.")[1] + "/" + line[1].split("\\.")[2] + "/" + year_count + "," + line[2] + "," + veggy + "," + OP_map.get(line[0]) + " \r\n");
                                }
                                if (line[2].contains("arvest") || line[2].contains("kill")) {
                                    veggy = "";
                                }
                                xxx++;
                            }
                            // + " 1st mo: " + first_month + "  last_mo: " + last_month
                            if (first_month < last_month) {
                                year_count++;
                            }
                            rot_year = -1;
                            old_year = -1;
                            xxx = 0;
                        }
                    }
                } else {
                    //result_start_end.put(false, new Integer[]{start_year, end_year, compl_1st_start_year, preparts, compl_last_start_year, afterparts})
                    // ID1 2008 2014 2009 1 2013 0
                    // ID2 2008 2014 2008 0 2013 0
                    Integer[] rotation_parts = result_start_end.get(false);
                    //System.out.println(hrus.get(i).ID + " " + rotation_parts[0] + " " + rotation_parts[1] + " " + rotation_parts[2] + " " + rotation_parts[3] + " " + rotation_parts[4] + " " + rotation_parts[5]);
                    HashMap<Integer, ArrayList<String[]>> man_yearparts_mapII = managements.get(hrus.get(i).Matching_Result.LMOD_Key);
                    if (rotation_parts[0] > rotation_parts[2] || rotation_parts[0] < rotation_parts[2]) {
                        //System.out.println(rotation_parts[0] + "  pre part to adjust  " + rotation_parts[2]);
                        int part_years = rotation_parts[2] - rotation_parts[0];
                        int x = 0;
//                        for (Integer keys : man_yearparts_mapII.keySet()) {
//                            System.out.println(" " + keys);
//                            for (int j = 0; j < man_yearparts_mapII.get(keys).size(); j++) {
//                                for (int k = 0; k < man_yearparts_mapII.get(keys).get(j).length; k++) {
//                                    System.out.print(" " + man_yearparts_mapII.get(keys).get(j)[k]);
//                                }
//                                System.out.println(" ");
//                            }
//                        }
                        int list_position = 0;
                        if (Integer.parseInt(DB_map_managements_acr.get(hrus.get(i).Matching_Result.LMOD_Key)[4]) > Integer.parseInt(DB_map_managements_acr.get(hrus.get(i).Matching_Result.LMOD_Key)[5])) {
                            list_position = rotation_parts[3] + 1 + 1;
                        } else {
                            list_position = rotation_parts[3] + 1;
                        }
                        while (x < part_years) {
                            ArrayList<String[]> custom_lineII = man_yearparts_mapII.get(list_position);
                            for (int j = 0; j < custom_lineII.size(); j++) {
                                String veg = "";
                                if (!custom_lineII.get(j)[2].isEmpty()) {
                                    veg = custom_lineII.get(j)[2];
                                }
                                records.add(hrus.get(i).ID + "," + custom_lineII.get(j)[0] + "/" + (rotation_parts[2] - (part_years - x)) + "," + custom_lineII.get(j)[1] + "," + veg + "," + OP_map.get(custom_lineII.get(j)[3]) + " \r\n");
                            }
                            x++;
                        }
                    }
                    // fitting years !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    rot_year = -1;
                    old_year = -1;
                    int xxx = 0;
                    year_count = rotation_parts[2];
                    while (year_count < rotation_parts[4] + 1) {
                        String veggy = "";
                        //last manth first month in same year!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        if (test_year == 1 && year_count <= rotation_parts[4]) {
                            for (String[] line : Management_data) {
                                if (!line[3].isEmpty()) {
                                    veggy = line[3];
                                }
                                records.add(hrus.get(i).ID + "," + line[1].split("\\.")[1] + "/" + line[1].split("\\.")[2] + "/" + year_count + "," + line[2] + "," + veggy + "," + OP_map.get(line[0]) + " \r\n");
                                if (line[2].contains("arvest") || line[2].contains("kill")) {
                                    veggy = "";
                                }
                            }
                            year_count++;
                        } else {
                            for (String[] line : Management_data) {
                                if (!line[3].isEmpty()) {
                                    veggy = line[3];
                                }
                                //System.out.println(" " + line[1].trim());
                                rot_year = Integer.parseInt(line[1].trim().split("\\.")[0]);
                                if (rot_year != old_year) {
                                    old_year = rot_year;
                                    if (xxx > 0) {
                                        year_count++;
                                    }
                                }
                                if (year_count <= rotation_parts[4]) {
                                    records.add(hrus.get(i).ID + "," + line[1].split("\\.")[1] + "/" + line[1].split("\\.")[2] + "/" + year_count + "," + line[2] + "," + veggy + "," + OP_map.get(line[0]) + " \r\n");
                                }
                                if (line[2].contains("arvest") || line[2].contains("kill")) {
                                    veggy = "";
                                }
                                xxx++;
                            }
                            if (first_month < last_month) {
                                year_count++;
                            }
                            rot_year = -1;
                            old_year = -1;
                            xxx = 0;
                        }
                    }
                    // ID1 2008 2014 2009 1 2013 0
                    // ID2 2008 2014 2008 0 2013 0
                    if (rotation_parts[1] > rotation_parts[4] || rotation_parts[1] < rotation_parts[4]) {
                        //System.out.println(rotation_parts[1] + "  after part to adjust  " + rotation_parts[4]);
                        int part_years = rotation_parts[1] - rotation_parts[4];
                        int x = 0;
                        int list_position = 0;
                        if (Integer.parseInt(DB_map_managements_acr.get(hrus.get(i).Matching_Result.LMOD_Key)[4]) > Integer.parseInt(DB_map_managements_acr.get(hrus.get(i).Matching_Result.LMOD_Key)[5])) {
                            list_position = rotation_parts[5] + 1 + 1;
                        } else {
                            list_position = rotation_parts[5] + 1;
                        }
                        while (x < part_years) {
                            ArrayList<String[]> custom_lineII = man_yearparts_mapII.get(list_position);
                            for (int j = 0; j < custom_lineII.size(); j++) {
                                records.add(hrus.get(i).ID + "," + custom_lineII.get(j)[0] + "/" + (rotation_parts[4] + (1 + x)) + "," + custom_lineII.get(j)[1] + "," + custom_lineII.get(j)[2] + "," + OP_map.get(custom_lineII.get(j)[3]) + " \r\n");
                            }
                            x++;
                        }
                    }
                }
            } else { // just detected majority vegetation = non-field-crops; e.g. forest, grassland
                if (LMOD_AGES_MID_map.get(only_veg_map.get(hrus.get(i).Matching_Result.Vegetation_Sequence)) == null) {
                    LMOD_AGES_MID_map.put(only_veg_map.get(hrus.get(i).Matching_Result.Vegetation_Sequence), only_veg_map.get(hrus.get(i).Matching_Result.Vegetation_Sequence));
                }
                if (only_veg_map.get(hrus.get(i).Matching_Result.Vegetation_Sequence) == null) {
                    System.out.println(hrus.get(i).ID + " !!!!!  only veg with -NULL- " + hrus.get(i).Matching_Result.Vegetation_Sequence);

                }
                for (int j = start_year; j < end_year + 1; j++) {
                    records.add(hrus.get(i).ID + ",01/01/" + j + ",NA," + hrus.get(i).Matching_Result.Vegetation_Sequence + ",NA,NA,NA,NA,NA \r\n");
                    records.add(hrus.get(i).ID + ",12/31/" + j + ",NA," + hrus.get(i).Matching_Result.Vegetation_Sequence + ",NA,NA,NA,NA,NA \r\n");
                }
            }
        }
        return records;
    }
}