+}
+
+/**
+ * @param {string} move
+ * @param {Number} move_num
+ * @param {boolean} white_to_play
+ */
+var format_move_with_number = function(move, move_num, white_to_play) {
+ var ret;
+ if (white_to_play) {
+ ret = (move_num - 1) + '… ';
+ } else {
+ ret = move_num + '. ';
+ }
+ ret += move;
+ return ret;
+}
+
+/**
+ * @param {string} move
+ * @param {Number} halfmove_num
+ */
+var format_halfmove_with_number = function(move, halfmove_num) {
+ return format_move_with_number(
+ move,
+ Math.floor(halfmove_num / 2) + 1,
+ halfmove_num % 2 == 0);
+}
+
+/**
+ * @param {Object} data
+ * @param {Number} halfmove_num
+ */
+var format_tooltip = function(data, halfmove_num) {
+ if (data['score_history'][halfmove_num] ||
+ halfmove_num === data['position']['pretty_history'].length) {
+ var move;
+ var short_score;
+ if (halfmove_num === data['position']['pretty_history'].length) {
+ move = data['position']['last_move'];
+ short_score = data['short_score'];
+ } else {
+ move = data['position']['pretty_history'][halfmove_num];
+ short_score = data['score_history'][halfmove_num][1];
+ }
+ var move_with_number = format_halfmove_with_number(move, halfmove_num);
+
+ return "After " + move_with_number + ": " + short_score;
+ } else {
+ for (var i = halfmove_num; i --> 0; ) {
+ if (data['score_history'][i]) {
+ var move = data['position']['pretty_history'][i];
+ return "[Analysis kept from " + format_halfmove_with_number(move, i) + "]";
+ }
+ }
+ }
+}
+
+/**
+ * @param {boolean} sort_by_score
+ */
+var resort_refutation_lines = function(sort_by_score) {
+ sort_refutation_lines_by_score = sort_by_score;
+ if (supports_html5_storage()) {
+ localStorage['sort_refutation_lines_by_score'] = sort_by_score ? 1 : 0;
+ }
+ update_refutation_lines();
+}
+window['resort_refutation_lines'] = resort_refutation_lines;
+
+/**
+ * @param {boolean} truncate_history
+ */
+var set_truncate_history = function(truncate_history) {
+ truncate_display_history = truncate_history;
+ update_refutation_lines();
+}
+window['set_truncate_history'] = set_truncate_history;
+
+/**
+ * @param {number} line_num
+ * @param {number} move_num
+ */
+var show_line = function(line_num, move_num) {
+ if (line_num == -1) {
+ current_display_line = null;
+ current_display_move = null;
+ if (displayed_analysis_data) {
+ // TODO: Support exiting to history position if we are in an
+ // analysis line of a history position.
+ displayed_analysis_data = null;
+ update_board(current_analysis_data, displayed_analysis_data);
+ }
+ } else {
+ current_display_line = display_lines[line_num];
+ current_display_move = move_num;
+ }
+ current_display_line_is_history = (line_num == 0);
+
+ update_historic_analysis();
+ update_displayed_line();
+ update_highlight();
+ redraw_arrows();
+}
+window['show_line'] = show_line;
+
+var prev_move = function() {
+ if (current_display_move > -1) {
+ --current_display_move;
+ }
+ update_historic_analysis();
+ update_displayed_line();
+}
+window['prev_move'] = prev_move;
+
+var next_move = function() {
+ if (current_display_line && current_display_move < current_display_line.pretty_pv.length - 1) {
+ ++current_display_move;
+ }
+ update_historic_analysis();
+ update_displayed_line();
+}
+window['next_move'] = next_move;
+
+var update_historic_analysis = function() {
+ if (!current_display_line_is_history) {
+ return;
+ }
+ if (current_display_move == current_display_line.pretty_pv.length - 1) {
+ displayed_analysis_data = null;
+ update_board(current_analysis_data, displayed_analysis_data);
+ }
+
+ // Fetch old analysis for this line if it exists.
+ var hiddenboard = chess_from(null, current_display_line.pretty_pv, current_display_move);
+ var filename = "/history/move" + (current_display_move + 1) + "-" +
+ hiddenboard.fen().replace(/ /g, '_').replace(/\//g, '-') + ".json";