<commit_before>function TeoriaChord(root, name) {
  if (!(root instanceof TeoriaNote)) {
    return null;
  }

  name = name || '';
  this.name = root.name.toUpperCase() + root.accidental.sign + name;
  this.symbol = name;
  this.root = root;
  this.intervals = [];
  this._voicing = [];

  var i, length, c, strQuality, parsing = 'quality', additionals = [],
      notes = ['P1', 'M3', 'P5', 'm7', 'M9', 'P11', 'M13'],
      chordLength = 2, bass, symbol;

  function setChord(intervals) {
    for (var n = 0, chordl = intervals.length; n < chordl; n++) {
      notes[n + 1] = intervals[n];
    }

    chordLength = intervals.length;
  }

  // Remove whitespace, commas and parentheses
  name = name.replace(/[,\s\(\)]/g, '');
  bass = name.split('/');
  if (bass.length === 2) {
    name = bass[0];
    bass = bass[1];
  } else {
    bass = null;
  }

  for (i = 0, length = name.length; i < length; i++) {
    if (!(c = name[i])) {
      break;
    }

    switch (parsing) {
      // Parses for the "base" chord, either a triad or a seventh chord
      case 'quality':
        strQuality = ((i + 3) <= length) ? name.substr(i, 3) : null;
        symbol = (strQuality in kSymbols) ?
          strQuality : (c in kSymbols) ? c : '';

        setChord(kSymbols[symbol]);

        i += symbol.length - 1;
        parsing = 'extension';
        break;

      // Parses for the top interval or a pure sixth
      case 'extension':
        c = (c === '1' && name[i + 1]) ?
          parseFloat(name.substr(i, 2)) : parseFloat(c);

        if (!isNaN(c) && c !== 6) {
          chordLength = (c - 1) / 2;

          if (chordLength !== Math.round(chordLength)) {
            throw new Error('Invalid interval extension: ' + c.toString(10));
          }

          // Special care for diminished chords
          if (symbol === 'o' || symbol === 'dim') {
            notes[3] = 'd7';
          }

          i += String(c).length - 1;
        } else if (c === 6) {
          notes[3] = 'M6';
          chordLength = (chordLength < 3) ? 3 : chordLength;
        } else {
          i -= 1;
        }

        parsing = 'alterations';
        break;

      // Parses for possible alterations of intervals (#5, b9, etc.)
      case 'alterations':
        var alterations = name.substr(i).split(/(#|b|add|maj|sus|M)/),
            next, flat = false, sharp = false;

        if (alterations.length === 1) {
          throw new Error('Invalid alterations');
        } else if (alterations[0].length !== 0) {
          throw new Error('Invalid token: \'' + alterations[0] + '\'');
        }

        for (var a = 1, aLength = alterations.length; a < aLength; a++) {
          next = alterations[a + 1];

          switch (alterations[a]) {
          case 'M':
          case 'maj':
            chordLength = (chordLength < 3) ? 3 : chordLength;

            if (next === '7') { // Ignore the seventh, that is already implied
              a++;
            }

            notes[3] = 'M7';
            break;

          case 'sus':
            var type = 'P4';
            if (next === '2' || next === '4') {
              a++;

              if (next === '2') {
                type = 'M2';
              }
            }

            notes[1] = type; // Replace third with M2 or P4
            break;

          case 'add':
            if (next && !isNaN(parseInt(next, 10))) {
              if (next === '9') {
                additionals.push('M9');
              } else if (next === '11') {
                additionals.push('P11');
              } else if (next === '13') {
                additionals.push('M13');
              }

              a += next.length;
            }
            break;

          case 'b':
            flat = true;
            break;

          case '#':
            sharp = true;
            break;

          default:
            if (alterations[a].length === 0) {
              break;
            }

            var token = parseInt(alterations[a], 10), quality,
                interval = parseInt(alterations[a], 10), intPos;
            if (isNaN(token) ||
                String(token).length !== alterations[a].length) {
              throw new Error('Invalid token: \'' + alterations[a] + '\'');
            }

            if (token === 6) {
              if (sharp) {
                notes[3] = 'A6';
              } else if (flat) {
                notes[3] = 'm6';
              } else {
                notes[3] = 'M6';
              }

              chordLength = (chordLength < 3) ? 3 : chordLength;
              continue;
            }

            // Calculate the position in the 'note' array
            intPos = (interval - 1) / 2;
            if (chordLength < intPos) {
              chordLength = intPos;
            }

            if (interval < 5 || interval === 7 ||
                intPos !== Math.round(intPos)) {
              throw new Error('Invalid interval alteration: ' +
                  interval.toString(10));
            }

            quality = notes[intPos][0];

            // Alterate the quality of the interval according the accidentals
            if (sharp) {
              if (quality === 'd') {
                quality = 'm';
              } else if (quality === 'm') {
                quality = 'M';
              } else if (quality === 'M' || quality === 'P') {
                quality = 'A';
              }
            } else if (flat) {
              if (quality === 'A') {
                quality = 'M';
              } else if (quality === 'M') {
                quality = 'm';
              } else if (quality === 'm' || quality === 'P') {
                quality = 'd';
              }
            }

            notes[intPos] = quality + interval;
            break;
          }
        }

        parsing = 'ended';
        break;
    }

    if (parsing === 'ended') {
      break;
    }
  }

  this.intervals = notes
    .slice(0, chordLength + 1)
    .concat(additionals)
    .map(function(i) { return teoria.interval(i); });

  for (i = 0, length = this.intervals.length; i < length; i++) {
    this._voicing[i] = this.intervals[i];
  }

  if (bass) {
    var intervals = this.intervals, bassInterval, inserted = 0, note;
    // Make sure the bass is atop of the root note
    note = teoria.note(bass + (root.octave + 1));

    bassInterval = teoria.interval.between(root, note);
    bass = bassInterval.simpleInterval;

    if (bassInterval.direction === 'up') {
      bassInterval = bassInterval.invert();
      bassInterval.direction = 'down';
    }

    this._voicing = [bassInterval];
    for (i = 0; i < length; i++) {
      if (intervals[i].interval === bass) {
        continue;
      }

      inserted++;
      this._voicing[inserted] = intervals[i];
    }
  }
}

TeoriaChord.prototype = {
  notes: function() {
    var voicing = this.voicing(), notes = [];

    for (var i = 0, length = voicing.length; i < length; i++) {
      notes.push(teoria.interval.from(this.root, voicing[i]));
    }

    return notes;
  },

  voicing: function(voicing) {
    // Get the voicing
    if (!voicing) {
      return this._voicing;
    }

    // Set the voicing
    this._voicing = [];
    for (var i = 0, length = voicing.length; i < length; i++) {
      this._voicing[i] = teoria.interval(voicing[i]);
    }

    return this;
  },

  resetVoicing: function() {
    this._voicing = this.intervals;
  },

  dominant: function(additional) {
    additional = additional || '';
    return new TeoriaChord(this.root.interval('P5'), additional);
  },

  subdominant: function(additional) {
    additional = additional || '';
    return new TeoriaChord(this.root.interval('P4'), additional);
  },

  parallel: function(additional) {
    additional = additional || '';
    var quality = this.quality();

    if (this.chordType() !== 'triad' || quality === 'diminished' ||
        quality === 'augmented') {
      throw new Error('Only major/minor triads have parallel chords');
    }

    if (quality === 'major') {
      return new TeoriaChord(this.root.interval('m3', 'down'), 'm');
    } else {
      return new TeoriaChord(this.root.interval('m3', 'up'));
    }
  },

  quality: function() {
    var third, fifth, seventh, intervals = this.intervals;

    for (var i = 0, length = intervals.length; i < length; i++) {
      if (intervals[i].interval === 3) {
        third = intervals[i];
      } else if (intervals[i].interval === 5) {
        fifth = intervals[i];
      } else if (intervals[i].interval === 7) {
        seventh = intervals[i];
      }
    }

    if (!third) {
      return;
    }

    third = (third.direction === 'down') ? third.invert() : third;
    third = third.simple();

    if (fifth) {
      fifth = (fifth.direction === 'down') ? fifth.invert() : fifth;
      fifth = fifth.simple();
    }

    if (seventh) {
      seventh = (seventh.direction === 'down') ? seventh.invert() : seventh;
      seventh = seventh.simple();
    }

    if (third === 'M3') {
      if (fifth === 'A5') {
        return 'augmented';
      } else if (fifth === 'P5') {
        return (seventh === 'm7') ? 'dominant' : 'major';
      }

      return 'major';
    } else if (third === 'm3') {
      if (fifth === 'P5') {
        return 'minor';
      } else if (fifth === 'd5') {
        return (seventh === 'm7') ? 'half-diminished' : 'diminished';
      }

      return 'minor';
    }
  },

  chordType: function() { // In need of better name
    var length = this.intervals.length, interval, has, invert, i, name;

    if (length === 2) {
      return 'dyad';
    } else if (length === 3) {
      has = {first: false, third: false, fifth: false};
      for (i = 0; i < length; i++) {
        interval = this.intervals[i];
        invert = interval.invert();
        if (interval.simpleIntervalType.name in has) {
          has[interval.simpleIntervalType.name] = true;
        } else if (invert.simpleIntervalType.name in has) {
          has[invert.simpleIntervalType.name] = true;
        }
      }

      name = (has.first && has.third && has.fifth) ? 'triad' : 'trichord';
    } else if (length === 4) {
      has = {first: false, third: false, fifth: false, seventh: false};
      for (i = 0; i < length; i++) {
        interval = this.intervals[i];
        invert = interval.invert();
        if (interval.simpleIntervalType.name in has) {
          has[interval.simpleIntervalType.name] = true;
        } else if (invert.simpleIntervalType.name in has) {
          has[invert.simpleIntervalType.name] = true;
        }
      }

      if (has.first && has.third && has.fifth && has.seventh) {
        name = 'tetrad';
      }
    }

    return name || 'unknown';
  },

  get: function(interval) {
    if (typeof interval === 'string' && interval in kStepNumber) {
      var intervals = this.intervals, i, length;

      interval = kStepNumber[interval];
      for (i = 0, length = intervals.length; i < length; i++) {
        if (intervals[i].interval === +interval) {
          return teoria.interval.from(this.root, intervals[i]);
        }
      }

      return null;
    } else {
      throw new Error('Invalid interval name');
    }
  },

  interval: function(interval, direction) {
    return new TeoriaChord(this.root.interval(interval, direction),
                           this.symbol);
  },

  transpose: function(interval, direction) {
    this.root.transpose(interval, direction);

    return this;
  },

  toString: function() {
    return this.name;
  }
};
<commit_msg>Change name, when transpose chord<commit_after>function TeoriaChord(root, name) {
  if (!(root instanceof TeoriaNote)) {
    return null;
  }

  name = name || '';
  this.name = root.name.toUpperCase() + root.accidental.sign + name;
  this.symbol = name;
  this.root = root;
  this.intervals = [];
  this._voicing = [];

  var i, length, c, strQuality, parsing = 'quality', additionals = [],
      notes = ['P1', 'M3', 'P5', 'm7', 'M9', 'P11', 'M13'],
      chordLength = 2, bass, symbol;

  function setChord(intervals) {
    for (var n = 0, chordl = intervals.length; n < chordl; n++) {
      notes[n + 1] = intervals[n];
    }

    chordLength = intervals.length;
  }

  // Remove whitespace, commas and parentheses
  name = name.replace(/[,\s\(\)]/g, '');
  bass = name.split('/');
  if (bass.length === 2) {
    name = bass[0];
    bass = bass[1];
  } else {
    bass = null;
  }

  for (i = 0, length = name.length; i < length; i++) {
    if (!(c = name[i])) {
      break;
    }

    switch (parsing) {
      // Parses for the "base" chord, either a triad or a seventh chord
      case 'quality':
        strQuality = ((i + 3) <= length) ? name.substr(i, 3) : null;
        symbol = (strQuality in kSymbols) ?
          strQuality : (c in kSymbols) ? c : '';

        setChord(kSymbols[symbol]);

        i += symbol.length - 1;
        parsing = 'extension';
        break;

      // Parses for the top interval or a pure sixth
      case 'extension':
        c = (c === '1' && name[i + 1]) ?
          parseFloat(name.substr(i, 2)) : parseFloat(c);

        if (!isNaN(c) && c !== 6) {
          chordLength = (c - 1) / 2;

          if (chordLength !== Math.round(chordLength)) {
            throw new Error('Invalid interval extension: ' + c.toString(10));
          }

          // Special care for diminished chords
          if (symbol === 'o' || symbol === 'dim') {
            notes[3] = 'd7';
          }

          i += String(c).length - 1;
        } else if (c === 6) {
          notes[3] = 'M6';
          chordLength = (chordLength < 3) ? 3 : chordLength;
        } else {
          i -= 1;
        }

        parsing = 'alterations';
        break;

      // Parses for possible alterations of intervals (#5, b9, etc.)
      case 'alterations':
        var alterations = name.substr(i).split(/(#|b|add|maj|sus|M)/),
            next, flat = false, sharp = false;

        if (alterations.length === 1) {
          throw new Error('Invalid alterations');
        } else if (alterations[0].length !== 0) {
          throw new Error('Invalid token: \'' + alterations[0] + '\'');
        }

        for (var a = 1, aLength = alterations.length; a < aLength; a++) {
          next = alterations[a + 1];

          switch (alterations[a]) {
          case 'M':
          case 'maj':
            chordLength = (chordLength < 3) ? 3 : chordLength;

            if (next === '7') { // Ignore the seventh, that is already implied
              a++;
            }

            notes[3] = 'M7';
            break;

          case 'sus':
            var type = 'P4';
            if (next === '2' || next === '4') {
              a++;

              if (next === '2') {
                type = 'M2';
              }
            }

            notes[1] = type; // Replace third with M2 or P4
            break;

          case 'add':
            if (next && !isNaN(parseInt(next, 10))) {
              if (next === '9') {
                additionals.push('M9');
              } else if (next === '11') {
                additionals.push('P11');
              } else if (next === '13') {
                additionals.push('M13');
              }

              a += next.length;
            }
            break;

          case 'b':
            flat = true;
            break;

          case '#':
            sharp = true;
            break;

          default:
            if (alterations[a].length === 0) {
              break;
            }

            var token = parseInt(alterations[a], 10), quality,
                interval = parseInt(alterations[a], 10), intPos;
            if (isNaN(token) ||
                String(token).length !== alterations[a].length) {
              throw new Error('Invalid token: \'' + alterations[a] + '\'');
            }

            if (token === 6) {
              if (sharp) {
                notes[3] = 'A6';
              } else if (flat) {
                notes[3] = 'm6';
              } else {
                notes[3] = 'M6';
              }

              chordLength = (chordLength < 3) ? 3 : chordLength;
              continue;
            }

            // Calculate the position in the 'note' array
            intPos = (interval - 1) / 2;
            if (chordLength < intPos) {
              chordLength = intPos;
            }

            if (interval < 5 || interval === 7 ||
                intPos !== Math.round(intPos)) {
              throw new Error('Invalid interval alteration: ' +
                  interval.toString(10));
            }

            quality = notes[intPos][0];

            // Alterate the quality of the interval according the accidentals
            if (sharp) {
              if (quality === 'd') {
                quality = 'm';
              } else if (quality === 'm') {
                quality = 'M';
              } else if (quality === 'M' || quality === 'P') {
                quality = 'A';
              }
            } else if (flat) {
              if (quality === 'A') {
                quality = 'M';
              } else if (quality === 'M') {
                quality = 'm';
              } else if (quality === 'm' || quality === 'P') {
                quality = 'd';
              }
            }

            notes[intPos] = quality + interval;
            break;
          }
        }

        parsing = 'ended';
        break;
    }

    if (parsing === 'ended') {
      break;
    }
  }

  this.intervals = notes
    .slice(0, chordLength + 1)
    .concat(additionals)
    .map(function(i) { return teoria.interval(i); });

  for (i = 0, length = this.intervals.length; i < length; i++) {
    this._voicing[i] = this.intervals[i];
  }

  if (bass) {
    var intervals = this.intervals, bassInterval, inserted = 0, note;
    // Make sure the bass is atop of the root note
    note = teoria.note(bass + (root.octave + 1));

    bassInterval = teoria.interval.between(root, note);
    bass = bassInterval.simpleInterval;

    if (bassInterval.direction === 'up') {
      bassInterval = bassInterval.invert();
      bassInterval.direction = 'down';
    }

    this._voicing = [bassInterval];
    for (i = 0; i < length; i++) {
      if (intervals[i].interval === bass) {
        continue;
      }

      inserted++;
      this._voicing[inserted] = intervals[i];
    }
  }
}

TeoriaChord.prototype = {
  notes: function() {
    var voicing = this.voicing(), notes = [];

    for (var i = 0, length = voicing.length; i < length; i++) {
      notes.push(teoria.interval.from(this.root, voicing[i]));
    }

    return notes;
  },

  voicing: function(voicing) {
    // Get the voicing
    if (!voicing) {
      return this._voicing;
    }

    // Set the voicing
    this._voicing = [];
    for (var i = 0, length = voicing.length; i < length; i++) {
      this._voicing[i] = teoria.interval(voicing[i]);
    }

    return this;
  },

  resetVoicing: function() {
    this._voicing = this.intervals;
  },

  dominant: function(additional) {
    additional = additional || '';
    return new TeoriaChord(this.root.interval('P5'), additional);
  },

  subdominant: function(additional) {
    additional = additional || '';
    return new TeoriaChord(this.root.interval('P4'), additional);
  },

  parallel: function(additional) {
    additional = additional || '';
    var quality = this.quality();

    if (this.chordType() !== 'triad' || quality === 'diminished' ||
        quality === 'augmented') {
      throw new Error('Only major/minor triads have parallel chords');
    }

    if (quality === 'major') {
      return new TeoriaChord(this.root.interval('m3', 'down'), 'm');
    } else {
      return new TeoriaChord(this.root.interval('m3', 'up'));
    }
  },

  quality: function() {
    var third, fifth, seventh, intervals = this.intervals;

    for (var i = 0, length = intervals.length; i < length; i++) {
      if (intervals[i].interval === 3) {
        third = intervals[i];
      } else if (intervals[i].interval === 5) {
        fifth = intervals[i];
      } else if (intervals[i].interval === 7) {
        seventh = intervals[i];
      }
    }

    if (!third) {
      return;
    }

    third = (third.direction === 'down') ? third.invert() : third;
    third = third.simple();

    if (fifth) {
      fifth = (fifth.direction === 'down') ? fifth.invert() : fifth;
      fifth = fifth.simple();
    }

    if (seventh) {
      seventh = (seventh.direction === 'down') ? seventh.invert() : seventh;
      seventh = seventh.simple();
    }

    if (third === 'M3') {
      if (fifth === 'A5') {
        return 'augmented';
      } else if (fifth === 'P5') {
        return (seventh === 'm7') ? 'dominant' : 'major';
      }

      return 'major';
    } else if (third === 'm3') {
      if (fifth === 'P5') {
        return 'minor';
      } else if (fifth === 'd5') {
        return (seventh === 'm7') ? 'half-diminished' : 'diminished';
      }

      return 'minor';
    }
  },

  chordType: function() { // In need of better name
    var length = this.intervals.length, interval, has, invert, i, name;

    if (length === 2) {
      return 'dyad';
    } else if (length === 3) {
      has = {first: false, third: false, fifth: false};
      for (i = 0; i < length; i++) {
        interval = this.intervals[i];
        invert = interval.invert();
        if (interval.simpleIntervalType.name in has) {
          has[interval.simpleIntervalType.name] = true;
        } else if (invert.simpleIntervalType.name in has) {
          has[invert.simpleIntervalType.name] = true;
        }
      }

      name = (has.first && has.third && has.fifth) ? 'triad' : 'trichord';
    } else if (length === 4) {
      has = {first: false, third: false, fifth: false, seventh: false};
      for (i = 0; i < length; i++) {
        interval = this.intervals[i];
        invert = interval.invert();
        if (interval.simpleIntervalType.name in has) {
          has[interval.simpleIntervalType.name] = true;
        } else if (invert.simpleIntervalType.name in has) {
          has[invert.simpleIntervalType.name] = true;
        }
      }

      if (has.first && has.third && has.fifth && has.seventh) {
        name = 'tetrad';
      }
    }

    return name || 'unknown';
  },

  get: function(interval) {
    if (typeof interval === 'string' && interval in kStepNumber) {
      var intervals = this.intervals, i, length;

      interval = kStepNumber[interval];
      for (i = 0, length = intervals.length; i < length; i++) {
        if (intervals[i].interval === +interval) {
          return teoria.interval.from(this.root, intervals[i]);
        }
      }

      return null;
    } else {
      throw new Error('Invalid interval name');
    }
  },

  interval: function(interval, direction) {
    return new TeoriaChord(this.root.interval(interval, direction),
                           this.symbol);
  },

  transpose: function(interval, direction) {
    this.root.transpose(interval, direction);
    this.name = this.root.name.toUpperCase() +
                this.root.accidental.sign + this.symbol;

    return this;
  },

  toString: function() {
    return this.name;
  }
};

{'fraction_non_alphanumeric': 0.15683808863064783, 'fraction_numerical': 0.010406729685196427, 'mean_word_length': 1.7449416805522495, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4172907', 'n_tokens_mistral': 7387, 'n_tokens_neox': 7000, 'n_words': 1800}