pgn method

String pgn([
  1. Map? options
])

Return the PGN representation of the game thus far

Implementation

String pgn([Map? options]) {
  /* using the specification from http://www.chessclub.com/help/PGN-spec
     * example for html usage: .pgn({ max_width: 72, newline_char: "<br />" })
     */
  final newline = (options != null &&
          options.containsKey('newline_char') &&
          options['newline_char'] != null)
      ? options['newline_char']
      : '\n';
  final max_width = (options != null &&
          options.containsKey('max_width') &&
          options['max_width'] != null)
      ? options['max_width']
      : 0;
  final result = [];
  var header_exists = false;

  /* add the PGN header headerrmation */
  for (var i in header.keys) {
    /* TODO: order of enumerated properties in header object is not
       * guaranteed, see ECMA-262 spec (section 12.6.4)
       */
    result.add(
        '[' + i.toString() + ' \"' + header[i].toString() + '\"]' + newline);
    header_exists = true;
  }

  if (header_exists && (history.isNotEmpty)) {
    result.add(newline);
  }

  final moves = san_moves();

  if (max_width == 0) {
    return result.join('') + moves.join(' ');
  }

  /* wrap the PGN output at max_width */
  var current_width = 0;
  for (var i = 0; i < moves.length; i++) {
    /* if the current move will push past max_width */
    if (current_width + moves[i]!.length > max_width && i != 0) {
      /* don't end the line with whitespace */
      if (result[result.length - 1] == ' ') {
        result.removeLast();
      }

      result.add(newline);
      current_width = 0;
    } else if (i != 0) {
      result.add(' ');
      current_width++;
    }
    result.add(moves[i]);
    current_width += moves[i]!.length;
  }

  return result.join('');
}