]> git.sesse.net Git - remoteglot/commitdiff
Add a very crude function for manual overrides.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 26 Dec 2023 13:50:54 +0000 (14:50 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 26 Dec 2023 13:50:54 +0000 (14:50 +0100)
Needed when the feed is hung but we have some other way of getting
the moves. No real undo yet (you can go back in history and do other
moves, but not delete anything), and it's pretty slow and sluggish.

config.pm
remoteglot.pl
www/js/remoteglot.js
www/manual-override.pl [new file with mode: 0755]

index f95d1f7e3eb8a1a777ff77ad7e1b608af9e8d2db..ec20c345264561fa0b3fb9b319bd44caf51ae461 100644 (file)
--- a/config.pm
+++ b/config.pm
@@ -78,6 +78,9 @@ our $dbistr = "dbi:Pg:dbname=remoteglot";
 our $dbiuser = undef;
 our $dbipass = undef;
 
+# For manual moves made from the web interface.
+our $adminpass = undef;
+
 eval {
        my $config_filename = $ENV{'REMOTEGLOT_CONFIG'} // 'config.local.pm';
        require $config_filename;
index a79239672116df2389bcdf68f0c9ba688fccdeee..8b3a0b776f40678ae3c6e58244580a5fd6e32c60 100755 (executable)
@@ -338,9 +338,12 @@ sub handle_pgn {
                        if ($pgn->result eq '1-0' || $pgn->result eq '1/2-1/2' || $pgn->result eq '0-1') {
                                $pos->{'result'} = $pgn->result;
                        }
-                       $pos->{'history'} = \@repretty_moves;
 
+                       my @extra_moves = ();
+                       $pos = extend_from_manual_override($pos, \@repretty_moves, \@extra_moves);
                        extract_clock($pgn, $pos);
+                       $pos->{'history'} = \@repretty_moves;
+                       $pos->{'extra_moves'} = \@extra_moves;
 
                        # Sometimes, PGNs lose a move or two for a short while,
                        # or people push out new ones non-atomically. 
@@ -771,6 +774,11 @@ sub output_screen {
        }
 
        return unless (exists($pos_calculating->{'board'}));
+
+       my $extra_moves = $pos_calculating->{'extra_moves'};
+       if (defined($extra_moves) && scalar @$extra_moves > 0) {
+               $text .= "  Manual move extensions: " . join(' ', @$extra_moves) . "\n";
+       }
                
        if (exists($info->{'pv1'}) && exists($info->{'pv2'})) {
                # multi-PV
@@ -1241,6 +1249,34 @@ sub plot_score {
        return undef;
 }
 
+sub extend_from_manual_override {
+       my ($pos, $moves, $extra_moves) = @_;
+
+       my $q = $dbh->prepare('SELECT next_move FROM game_extensions WHERE fen=? AND history=? AND player_w=? AND player_b=? AND (CURRENT_TIMESTAMP - ts) < INTERVAL \'1 hour\'');
+       while (1) {
+               my $player_w = $pos->{'player_w'};
+               my $player_b = $pos->{'player_b'};
+               if ($player_w =~ /^base64:(.*)$/) {
+                       $player_w = MIME::Base64::decode_base64($1);
+               }
+               if ($player_b =~ /^base64:(.*)$/) {
+                       $player_b = MIME::Base64::decode_base64($1);
+               }
+               #use Data::Dumper; print Dumper([$pos->fen(), JSON::XS::encode_json($moves), $player_w, $player_b]);
+               $q->execute($pos->fen(), JSON::XS::encode_json($moves), $player_w, $player_b);
+               my $ref = $q->fetchrow_hashref;
+               if (defined($ref)) {
+                       my $move = $ref->{'next_move'};
+                       ($pos) = $pos->make_pretty_move($move);
+                       push @$moves, $move;
+                       push @$extra_moves, $move;
+               } else {
+                       last;
+               }
+       }
+       return $pos;
+}
+
 sub extract_clock {
        my ($pgn, $pos) = @_;
 
index 54fc90b46afc5d5e818ddb87bd9a7cfaa41b33b6..51a470f502c59af3788255da7c719bab1694b336 100644 (file)
@@ -125,6 +125,9 @@ let reverse_dragging_from = null;
 /** @type {?number} @private */
 let unique = null;
 
+/** @type {?string} @private */
+let admin_password = null;
+
 /** @type {boolean} @private */
 let enable_sound = false;
 
@@ -1277,6 +1280,9 @@ function update_board() {
        } else {
                document.getElementById("searchstats").textContent = "";
        }
+       if (admin_password !== null) {
+               document.getElementById("searchstats").innerHTML += " | <span style=\"color: red;\">ADMIN MODE (if password is right)</span>";
+       }
 
        // Update the board itself.
        base_fen = data['position']['fen'];
@@ -2214,6 +2220,18 @@ function onSnapEnd(source, target) {
                promotion: 'q' // NOTE: always promote to a queen for example simplicity
        });
 
+       if (admin_password !== null) {
+               let url = '/manual-override.pl';
+               url += '?fen=' + encodeURIComponent(display_fen);
+               url += '&history=' + encodeURIComponent(JSON.stringify(current_analysis_data['position']['history']));
+               url += '&move=' + encodeURIComponent(move.san);
+               url += '&player_w=' + encodeURIComponent(current_analysis_data['position']['player_w']);
+               url += '&player_b=' + encodeURIComponent(current_analysis_data['position']['player_b']);
+               url += '&password=' + encodeURIComponent(admin_password);
+               fetch(url);
+               return;
+       }
+
        // Move ahead on the line we're on -- this includes history if we've
        // gone backwards.
        if (current_display_line &&
@@ -2459,6 +2477,11 @@ function init() {
                set_sound(false);
        }
 
+       let admin_match = window.location.href.match(/\?password=([a-zA-Z0-9_-]+)/);
+       if (admin_match !== null) {
+               admin_password = admin_match[1];
+       }
+
        // Create board.
        board = new window.ChessBoard('board', {
                onMoveEnd: function() { board_is_animating = false; },
diff --git a/www/manual-override.pl b/www/manual-override.pl
new file mode 100755 (executable)
index 0000000..616e5ea
--- /dev/null
@@ -0,0 +1,33 @@
+#! /usr/bin/perl
+use strict;
+use warnings;
+use DBI;
+use DBD::Pg;
+use CGI;
+use Encode;
+use lib qw(..);
+require 'config.pm';
+
+my $dbh = DBI->connect($remoteglotconf::dbistr, $remoteglotconf::dbiuser, $remoteglotconf::dbipass)
+        or die DBI->errstr;
+$dbh->{RaiseError} = 1;
+
+my $cgi = CGI->new;
+my $password = Encode::decode_utf8($cgi->param('password'));
+if (!defined($password) || $password ne $remoteglotconf::adminpass) {
+       print CGI->header(-type=>'text/plain; charset=utf-8', -status=>'403 Denied');
+       print "Nope.\n";
+       exit;
+}
+
+$dbh->do('INSERT INTO game_extensions ( fen, history, player_w, player_b, ts, next_move ) VALUES ( ?, ?, ?, ?, CURRENT_TIMESTAMP, ? )',
+       undef,
+       Encode::decode_utf8($cgi->param('fen')),
+       Encode::decode_utf8($cgi->param('history')),
+       Encode::decode_utf8($cgi->param('player_w')),
+       Encode::decode_utf8($cgi->param('player_b')),
+       Encode::decode_utf8($cgi->param('move')));
+system("touch", $remoteglotconf::json_output);
+
+print CGI->header(-type=>'text/plain; charset=utf-8');
+print "OK\n";