frettable function

bool frettable(
  1. List<int> frets
)

Implementation

bool frettable(List<int> frets) {
  const totalFingers = 4;
  List<List<Map<String, int>>> usedFingers = [];

  for (int string = 0; string < frets.length; string++) {
    int fret = frets[string];
    List<Map<String, int>> newGroup = [];
    Map<String, int> note = {'fret': fret, 'string': string};

    if (fret > 0) {
      bool needNewGroup = true;

      // first try to add note to one of current finger groups
      for (var fingerGroup in usedFingers) {
        int groupFret = fingerGroup[0]['fret']!;
        int groupString = fingerGroup[0]['string']!;

        // barre if fret number matches where finger is fretted on a previous note
        // but dont barre when:
        // * on top 5 strings and next note in sequence is a lower fret
        // * on 5th note and third group, and last note would create fourth group
        if (fret == groupFret &&
            !(string < 5 && fret >= frets[string + 1]) &&
            !(string == 4 && frets[5] != fret && usedFingers.length == 3)) {
          // if the in between notes are on higher frets
          List<int> diff = frets.sublist(groupString + 1, string);
          if (diff.where((i) => (i >= fret)).length == diff.length) {
            // then barre this note with the rest of this finger group
            fingerGroup.add(note);
            needNewGroup = false;
          }
        }
      }

      // otherwise create new group
      if (needNewGroup) {
        newGroup.add(note);
        usedFingers.add(newGroup);
      }
    }
  }

  return usedFingers.length <= totalFingers;
}