From 7d17d48232fce74150d7a2802cbd330dc4e9493c Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 20 Nov 2014 23:15:55 +0100 Subject: [PATCH 1/1] Support displaying historic analysis. Not perfect still, though. --- www/js/remoteglot.js | 165 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 132 insertions(+), 33 deletions(-) diff --git a/www/js/remoteglot.js b/www/js/remoteglot.js index 52e4c4a..37c6b87 100644 --- a/www/js/remoteglot.js +++ b/www/js/remoteglot.js @@ -3,6 +3,23 @@ /** @type {window.ChessBoard} @private */ var board = null; +/** + * The most recent analysis data we have from the server + * (about the most recent position). + * + * @type {?Object} + * @private */ +var current_analysis_data = null; + +/** + * If we are displaying previous analysis, this is non-null, + * and will override most of current_analysis_data. + * + * @type {?Object} + * @private + */ +var displayed_analysis_data = null; + /** @type {Array.<{ * from_col: number, * from_row: number, @@ -70,6 +87,9 @@ var display_lines = []; /** @type {?DisplayLine} @private */ var current_display_line = null; +/** @type {boolean} @private */ +var current_display_line_is_history = false; + /** @type {?number} @private */ var current_display_move = null; @@ -101,7 +121,8 @@ var request_update = function() { }).done(function(data, textstatus, xhr) { ims = xhr.getResponseHeader('X-Remoteglot-Last-Modified'); var num_viewers = xhr.getResponseHeader('X-Remoteglot-Num-Viewers'); - update_board(data); + current_analysis_data = data; + update_board(current_analysis_data, displayed_analysis_data); update_num_viewers(num_viewers); // Next update. @@ -565,44 +586,55 @@ var update_refutation_lines = function() { /** * @param {Object} data + * @param {?Object} display_data */ -var update_board = function(data) { +var update_board = function(current_data, display_data) { + var data = display_data || current_data; + display_lines = []; - // The headline. + // Print the history. This is pretty much the only thing that's + // unconditionally taken from current_data (we're not interested in + // historic history). + if (current_data['position']['history']) { + add_pv('start', current_data['position']['history'], 1, 'W', 8, true); + } else { + display_lines.push(null); + } + update_history(); + + // The headline. Names are always fetched from current_data; + // the rest can depend a bit. var headline; - if (data['position']['player_w'] && data['position']['player_b']) { - headline = data['position']['player_w'] + '–' + - data['position']['player_b'] + ', analysis'; + if (current_data && + current_data['position']['player_w'] && current_data['position']['player_b']) { + headline = current_data['position']['player_w'] + '–' + + current_data['position']['player_b'] + ', analysis'; } else { headline = 'Analysis'; } - var last_move; - if (data['position']['last_move'] !== 'none') { - if (data['position']['toplay'] == 'W') { - last_move = (data['position']['move_num']-1) + '… '; - } else { - last_move = data['position']['move_num'] + '. '; - } - last_move += data['position']['last_move']; + var last_move; + if (display_data) { + // Displaying some non-current position, pick out the last move + // from the history. This will work even if the fetch failed. + last_move = format_move_with_number( + current_display_line.pretty_pv[current_display_move], + Math.floor((current_display_move + 1) / 2) + 1, + (current_display_move % 2 == 1)); + headline += ' after ' + last_move; + } else if (data['position']['last_move'] !== 'none') { + last_move = format_move_with_number( + data['position']['last_move'], + data['position']['move_num'], + data['position']['toplay'] == 'W'); headline += ' after ' + last_move; } else { last_move = null; } - $("#headline").text(headline); - // The engine id. - if (data['id'] && data['id']['name'] !== null) { - $("#engineid").text(data['id']['name']); - } - - // The score. - if (data['score'] !== null) { - $("#score").text(data['score']); - } - + // The contains a very brief headline. var title_elems = []; if (data['short_score'] !== undefined && data['short_score'] !== null) { title_elems.push(data['short_score']); @@ -617,6 +649,26 @@ var update_board = function(data) { document.title = 'analysis.sesse.net'; } + if (data['failed']) { + $("#score").text("No analysis for this move"); + $("#pv").empty(); + $("#searchstats").html(" "); + $("#refutationlines").empty(); + refutation_lines = []; + update_refutation_lines(); + return; + } + + // The engine id. + if (data['id'] && data['id']['name'] !== null) { + $("#engineid").text(data['id']['name']); + } + + // The score. + if (data['score'] !== null) { + $("#score").text(data['score']); + } + // The search stats. if (data['tablebase'] == 1) { $("#searchstats").text("Tablebase result"); @@ -650,14 +702,6 @@ var update_board = function(data) { } update_highlight(); - // Print the history. - if (data['position']['history']) { - add_pv('start', data['position']['history'], 1, 'W', 8, true); - } else { - display_lines.push(null); - } - update_history(); - // Print the PV. $("#pv").html(add_pv(data['position']['fen'], data['pv_uci'], data['position']['move_num'], data['position']['toplay'])); @@ -734,6 +778,22 @@ var update_num_viewers = function(num_viewers) { } } +/** + * @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 {boolean} sort_by_score */ @@ -760,10 +820,19 @@ 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(); @@ -774,6 +843,7 @@ var prev_move = function() { if (current_display_move > -1) { --current_display_move; } + update_historic_analysis(); update_displayed_line(); } window['prev_move'] = prev_move; @@ -782,10 +852,39 @@ 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 = new Chess(); + for (var i = 0; i <= current_display_move; ++i) { + hiddenboard.move(ucimove_to_chessjs_move(current_display_line.uci_pv[i])); + } + var filename = "/history/move" + (current_display_move + 1) + "-" + + hiddenboard.fen().replace(/ /g, '_').replace(/\//g, '-') + ".json"; + + $.ajax({ + url: filename + }).done(function(data, textstatus, xhr) { + displayed_analysis_data = data; + update_board(current_analysis_data, displayed_analysis_data); + }).fail(function() { + displayed_analysis_data = {'failed': true}; + update_board(current_analysis_data, displayed_analysis_data); + }); +} + var update_displayed_line = function() { if (highlighted_move !== null) { highlighted_move.removeClass('highlight'); -- 2.39.2