public static Integer pickWinner(ArrayList<PitchCandidate> pitch_candidates) {
    // pick highest ranking pitch candidate -> return_me[i]
    ArrayList<PitchCandidate> pitch_winners = new ArrayList();
    for (PitchCandidate myPC : pitch_candidates) {
      System.out.println(
          "pitch candidate pitch: " + myPC.getPitch() + " and rank: " + myPC.getRank());
      if (pitch_winners.isEmpty()) {
        pitch_winners.add(myPC);
        System.out.println(
            "pitch_winners is empty. adding " + myPC.getPitch() + " with rank" + myPC.getRank());
      } else if (myPC.getRank() > pitch_winners.get(0).getRank()) {
        pitch_winners.clear();
        pitch_winners.add(myPC);
        System.out.println(
            "after emptying pitch_winners adding "
                + myPC.getPitch()
                + " with rank "
                + myPC.getRank());
      } else if (Objects.equals(myPC.getRank(), pitch_winners.get(0).getRank())) {
        pitch_winners.add(myPC);
        System.out.println(
            "adding " + myPC.getPitch() + " to pitch_winners with rank " + myPC.getRank());
      }
    }
    int cp_winner = pitch_winners.get(0).getPitch();

    if (pitch_winners.size() > 1)
      cp_winner = pitch_winners.get(roll.nextInt(pitch_winners.size())).getPitch();
    pitch_winners.clear();
    return cp_winner;
  }
  public static ArrayList<PitchCandidate> harmonicChecksSuperBasic(
      ArrayList<PitchCandidate> pitch_candidates,
      MelodicNote CF_note,
      Boolean CFnoteRoot,
      MelodicNote CP_note) {
    // begin Harmonic checks
    // Will need to evaluate each CP pitch candidate against the counterpoint notes
    // in each previously built voice

    // Evaluate Pitch Candidates Against these checke
    for (PitchCandidate myPC : pitch_candidates) {
      int this_interval = abs(myPC.getPitch() - CF_note.getPitch()) % 12;
      System.out.println("this interval  = " + this_interval);

      // compute interval whether consonant
      boolean this_interval_consonant = false;
      boolean root_interval_consonant = false;
      for (Integer consonance : consonances) {
        if (this_interval == consonance) this_interval_consonant = true;
      }
      if (this_interval_consonant) {
        System.out.println("this interval consonant");
      } else {
        if (CP_note.getAccent()) {
          // if (CP_note.getAccent() && CP_note.getStartTime() <= CF_note.getStartTime()) {
          myPC.decrementRank(Decrements.accented_dissonance);
          System.out.println("dissonant accent2");
        }
      }
    }
    return pitch_candidates;
  }
  public static ArrayList<PitchCandidate> harmonicChecks(
      ArrayList<PitchCandidate> pitch_candidates,
      MelodicNote CF_note,
      Boolean CFnoteRoot,
      Integer previous_cf_pitch,
      Integer previous_cp_pitch,
      MelodicNote CP_note,
      int voice_pitch_count,
      int cf_voice_index) {
    // begin Harmonic checks
    boolean cand_prev_cf_diss = true;
    // Will need to evaluate each CP pitch candidate against the counterpoint notes
    // in each previously built voice

    // Evaluate Pitch Candidates Against these checke
    for (PitchCandidate myPC : pitch_candidates) {
      Integer cand_pitch = myPC.getPitch();
      Integer cf_pitch = CF_note.getPitch();
      if (previous_cp_pitch == 9999)
        previous_cp_pitch = cand_pitch; // 9999 means the CP is held over to multiple cfs
      Integer melody_motion_to_cand = cand_pitch - previous_cp_pitch;
      int this_interval = abs(myPC.getPitch() - CF_note.getPitch()) % 12;
      // if (myPC.getLatestInterval(cf_voice_index) != null) previous_cf_pitch =
      // myPC.getLatestInterval(cf_voice_index); //NEW
      System.out.println("this interval  = " + this_interval);
      Integer melodic_motion_to_ = cf_pitch - previous_cf_pitch;
      Integer previous_interval = abs(previous_cp_pitch - previous_cf_pitch) % 12;
      System.out.println("previous interval  = " + previous_interval);
      Double cp_start_time = CP_note.getStartTime();
      Double cf_start_time = CF_note.getStartTime();

      // compute interval whether consonant
      boolean this_interval_consonant = false;
      for (Integer consonance : consonances) {
        if (this_interval == consonance) {
          this_interval_consonant = true;
          System.out.println(
              "this_interval == "
                  + consonance
                  + " means this_interval_consonant == "
                  + this_interval_consonant);
          break;
        }
      }

      if (this_interval_consonant) {
        System.out.println("this interval consonant");
        if (this_interval == 0) {
          myPC.decrementRank(Decrements.octave);
          System.out.println("octave");
        }
      } else {
        if (this_interval == 1
            && (abs(myPC.getPitch() - CF_note.getPitch()) < 14 || large_dissonance_bad)) {
          myPC.decrementRank(Decrements.minor_9th);
          System.out.println("minor 9th");
        }
        if (CP_note.getAccent()
            && (abs(myPC.getPitch() - CF_note.getPitch()) < 36 || large_dissonance_bad)) {
          // if (CP_note.getAccent() && CP_note.getStartTime()<= CF_note.getStartTime() ) {
          myPC.decrementRank(Decrements.accented_dissonance);
          System.out.println("dissonant accent");
        }
      }

      // compute previous_interval consonant
      boolean previous_interval_consonant = false;
      for (Integer consonance : consonances) {
        if (previous_interval == consonance) previous_interval_consonant = true;
      }
      if (previous_interval_consonant) System.out.println("previous interval consonant");

      if (cp_start_time > cf_start_time) {
        System.out.println("CP starts after CF");
        if (melody_motion_to_cand == 0) {
          myPC.decrementRank(Decrements.seq_of_same_cons);
        }
        if (previous_interval_consonant) {
          if (!this_interval_consonant && abs(melody_motion_to_cand) > 2) {
            myPC.decrementRank(Decrements.bad_diss_approach_from_cons);
          }
        } else if (this_interval_consonant) {
          if (abs(melody_motion_to_cand) > 2) {
            myPC.decrementRank(Decrements.bad_cons_approach_from_diss);
          }

        } else {
          if (abs(melody_motion_to_cand) > 4) { // New_Interval is dissonant
            myPC.decrementRank(Decrements.bad_diss_approach_from_diss);
          }
        }
      } else if (cp_start_time < cf_start_time) {
        System.out.println("CP starts before CF");
        if (previous_interval_consonant) {
          if (previous_interval == this_interval) {
            myPC.decrementRank(Decrements.seq_same_type_cons);
          }
        } else { // ie Previous_Interval is dissonant
          if (this_interval_consonant) {
            if (abs(melodic_motion_to_) > 2)
              myPC.decrementRank(Decrements.bad_cons_approach_from_diss);
          } else // New_Interval is dissonant
          if (abs(melodic_motion_to_) > 4)
            myPC.decrementRank(Decrements.bad_diss_approach_from_diss);
        }
      } else {
        System.out.println("CP and CF start at the same time");
        if (previous_interval_consonant) {
          if (this_interval_consonant) {
            for (Integer consonance : consonances) {
              if ((cand_pitch - previous_cf_pitch) % 12 == consonance) {
                cand_prev_cf_diss = false;
              }
            }

            if (cand_prev_cf_diss == true) myPC.decrementRank(Decrements.diss_cp_previous_cf);

            if (previous_interval == this_interval) {
              same_consonant_count++;
              if (same_consonant_count > same_consonant_threshold)
                myPC.decrementRank(Decrements.seq_of_same_cons);
            }
            // Too many of same type of interval
            for (Integer perfect_consonance : perfect_consonances) {
              if (this_interval == perfect_consonance) {
                if (this_interval == previous_interval) {
                  myPC.decrementRank(Decrements.seq_same_type_cons);
                  if (melody_motion_to_cand > 0)
                    if (melodic_motion_to_ > 0)
                      myPC.decrementRank(Decrements.parallel_perf_consonance);
                  if (melody_motion_to_cand < 0)
                    if (melodic_motion_to_ < 0)
                      myPC.decrementRank(Decrements.parallel_perf_consonance);
                }
              } else {
                if (melody_motion_to_cand > 0)
                  if (melodic_motion_to_ > 0)
                    myPC.decrementRank(Decrements.direct_motion_perf_cons);
                if (melody_motion_to_cand < 0)
                  if (melodic_motion_to_ < 0)
                    myPC.decrementRank(Decrements.direct_motion_perf_cons);
              }
            }
            // If dissonance between CP1 and CF2 is this resolved?
          } else // New_Interval is dissonant
          myPC.decrementRank(Decrements.motion_into_diss_both_voices_change);
        } else // ie Previous_Interval is dissonant
        if (this_interval_consonant) {

          for (Integer consonance : consonances) {
            if ((cand_pitch - previous_cp_pitch) % 12 == consonance) {
              cand_prev_cf_diss = false;
            }
          }

          if (cand_prev_cf_diss == true) myPC.decrementRank(Decrements.diss_cp_previous_cf);
          if (melody_motion_to_cand > 0)
            if (melodic_motion_to_ > 0) myPC.decrementRank(Decrements.direct_motion_perf_cons);
          if (melody_motion_to_cand < 0)
            if (melodic_motion_to_ < 0) myPC.decrementRank(Decrements.direct_motion_perf_cons);
        } else { // this interval is dissonant
          myPC.decrementRank(Decrements.motion_into_diss_both_voices_change);
          myPC.decrementRank(Decrements.seq_of_diss);
          if (this_interval == previous_interval) {
            myPC.decrementRank(Decrements.seq_same_type_diss);
            if (melody_motion_to_cand > 0)
              if (melodic_motion_to_ > 0) myPC.decrementRank(Decrements.direct_motion_into_diss);
            if (melody_motion_to_cand < 0)
              if (melodic_motion_to_ < 0) myPC.decrementRank(Decrements.direct_motion_into_diss);
          }
        }
      }
      myPC.setLatestInterval(cf_pitch, cf_voice_index);
    }
    return pitch_candidates;
  }
  public static ArrayList<PitchCandidate> melodicCheck(
      ArrayList<PitchCandidate> pitch_candidates,
      ModeModule my_mode_module,
      MelodicVoice alter_me,
      Integer pitch_center,
      int voice_pitch_count,
      Integer previous_cp_pitch,
      Integer previous_melodic_interval,
      Boolean is_accent) {
    // Melodic Checks
    // Evaluate each pitch candidate
    for (PitchCandidate myPC : pitch_candidates) {
      int cand_pitch = myPC.getPitch();
      int melody_motion_to_cand = 0;

      System.out.println("melodicCheck evaluating pitch candidate " + cand_pitch);

      // Check if Dissonant with Root
      boolean root_interval_consonant = false;
      int root_interval = abs(cand_pitch - root_key) % 12;
      for (Integer consonance : root_consonances) {
        if (root_interval == consonance) root_interval_consonant = true;
      }
      if (root_interval_consonant) {
        System.out.println(cand_pitch + " root interval consonant");
      } else {
        if (is_accent) {
          myPC.decrementRank(Decrements.dissonant_with_root);
          System.out.println(cand_pitch + " dissonant accent with root");
        } else System.out.println("dissonant with root but note accent = " + is_accent);
      }

      // randomly decrement non-tonics
      if (cand_pitch % 12 != my_mode_module.getTonic() && roll.nextInt(2) == 1) {
        myPC.decrementRank(Decrements.is_not_tonic);
        System.out.println(cand_pitch + " is not tonic");
      }

      // decrement illegal notes
      if (cand_pitch < 0 || cand_pitch > 127) {
        myPC.decrementRank(Decrements.illegal_note);
        System.out.println(cand_pitch + " is illegal note");
      }

      // decrement motion outside of voice range
      if (cand_pitch < alter_me.getRangeMin() || cand_pitch > alter_me.getRangeMax()) {
        myPC.decrementRank(Decrements.outside_range);
        System.out.println(
            cand_pitch + " outside range " + alter_me.getRangeMin() + "-" + alter_me.getRangeMax());
      }

      // decrement too far from pitch center
      if (abs(cand_pitch - pitch_center) > 16) {
        myPC.decrementRank(Decrements.remote_from_pitchcenter);
        System.out.println(cand_pitch + " too far from pitch center" + pitch_center);
      }

      if (voice_pitch_count > 0) {
        melody_motion_to_cand = cand_pitch - previous_cp_pitch;

        // The candidate has already followed the preceding note too often. (method created)
        // look for previous_cp_pitch in PitchCount
        // if it's there get_count
        // if the count is greater than samplesize
        // check if previous_cp_pitch and pitch_candidate in MOtion Counts
        // if so get count - then divide motion count by pitch count
        // get the percentage from mode module
        // if actual count is greater than mode module percentage decrement
        for (PitchCount my_pitch_count : pitch_counts) {
          if (my_pitch_count.getPitch() == previous_cp_pitch % 12)
            if (my_pitch_count.getCount() > sample_size)
              for (MotionCount my_motion_count : motion_counts) {
                // logger.log(Level.INFO, "Entering Motion Counts");
                // System.out.println("pitch_count for " + previous_cp_pitch %12 + " = " +
                // my_pitch_count.getCount());
                // System.out.println("motion count " + my_motion_count.getCount());
                if (my_motion_count.getPreviousPitch() == previous_cp_pitch % 12
                    && my_motion_count.getSucceedingPitch() == cand_pitch % 12) {
                  double actual =
                      (double) my_motion_count.getCount() / (double) my_pitch_count.getCount();
                  System.out.println("actual = " + actual);
                  double thresh = 0.20;
                  if (my_mode_module.getMelodicMotionProbability(
                          cand_pitch, previous_cp_pitch, key_transpose)
                      != null) {
                    thresh =
                        my_mode_module.getMelodicMotionProbability(
                            cand_pitch, previous_cp_pitch, key_transpose);
                    System.out.println(
                        "motion probability of "
                            + previous_cp_pitch
                            + " to "
                            + cand_pitch
                            + " = "
                            + thresh);
                  } else
                    System.out.println(
                        "motion probability of "
                            + previous_cp_pitch
                            + " to "
                            + cand_pitch
                            + " is NULL");

                  if (actual >= thresh) {
                    myPC.decrementRank(Decrements.melodic_motion_quota_exceed);
                    System.out.println(
                        cand_pitch + " is approached too often from " + previous_cp_pitch);
                  }
                }
              }
        }
      }
      if (voice_pitch_count > 1) {
        // Peak/Trough check
        // a melodic phrase should have no more than two peaks and two troughs
        // a peak is defined as a change in melodic direction
        // so when a candidate pitch wants to go in the opposite direction of
        // the previous melodic interval we want to increment the peak or trough count accordingly
        // and determine whether we have more than two peaks or more than two troughs
        // note that the melody can always go higher or lower than the previous peak or trough

        if (previous_melodic_interval < 0
            && melody_motion_to_cand
                > 0) { // will there be a change in direction from - to +  ie trough?
          if (previous_cp_pitch == trough)
            trough_count++; // will this trough = previous trough? then increment
        }
        if (previous_melodic_interval > 0 && melody_motion_to_cand < 0) { // will there be a trough?
          if (previous_cp_pitch == peak)
            peak_count++; // will this trough = previous trough? then increment
        }
        if (peak_count > 1 || trough_count > 1) {
          peak_count--; // remember to decrement these counts since we won't actually use this pitch
          trough_count--;
          myPC.decrementRank(Decrements.peak_trough_quota_exceed);
          System.out.println(cand_pitch + " duplicates previous peak or trough");
        }
        // Motion after Leaps checks
        // First check if the melody does not go in opposite direction of leap
        // then check if there are two successive leaps in the same direction
        if (previous_melodic_interval > 4 && melody_motion_to_cand > 0) {
          myPC.decrementRank(Decrements.bad_motion_after_leap);
          System.out.println(
              melody_motion_to_cand + " to " + cand_pitch + " is bad motion after leap");
          if (melody_motion_to_cand > 4) {
            myPC.decrementRank(Decrements.successive_leaps);
            System.out.println(cand_pitch + " is successive leap");
          }
        }
        if (previous_melodic_interval < -4 && melody_motion_to_cand < 0) {
          myPC.decrementRank(Decrements.bad_motion_after_leap);
          System.out.println(
              melody_motion_to_cand + " to " + cand_pitch + " is bad motion after leap");
          if (melody_motion_to_cand < -4) {
            myPC.decrementRank(Decrements.successive_leaps);
            System.out.println(cand_pitch + " is successive leap");
          }
        }
      }
      // end melody checks
    } // next pitch candidate
    return pitch_candidates;
  }