+ my $q = $dbh->prepare('SELECT * FROM current_games ORDER BY priority DESC, id');
+ $q->execute;
+ while (my $ref = $q->fetchrow_hashref) {
+ eval {
+ my $other_game_contents = File::Slurp::read_file($ref->{'json_path'});
+ my $other_game_json = JSON::XS::decode_json($other_game_contents);
+
+ die "Missing position" if (!exists($other_game_json->{'position'}));
+ my $white = $other_game_json->{'position'}{'player_w'} // die 'Missing white';
+ my $black = $other_game_json->{'position'}{'player_b'} // die 'Missing black';
+
+ my $game = {
+ id => $ref->{'id'},
+ name => "$white–$black",
+ url => $ref->{'url'},
+ hashurl => $ref->{'hash_url'},
+ };
+ if (defined($other_game_json->{'position'}{'result'})) {
+ $game->{'result'} = $other_game_json->{'position'}{'result'};
+ } else {
+ $game->{'score'} = $other_game_json->{'score'};
+ }
+ push @games, $game;
+ };
+ if ($@) {
+ warn "Could not add external game " . $ref->{'json_path'} . ": $@";
+ }
+ }
+
+ if (scalar @games > 0) {
+ $json->{'games'} = \@games;
+ }
+ }
+
+ my $json_enc = JSON::XS->new;
+ $json_enc->canonical(1);
+ my $encoded = $json_enc->encode($json);
+ unless ($historic_json_only || !defined($remoteglotconf::json_output) ||
+ (defined($last_written_json) && $last_written_json eq $encoded)) {
+ atomic_set_contents($remoteglotconf::json_output, $encoded);
+ $last_written_json = $encoded;
+ }
+
+ if (exists($pos_calculating->{'history'}) &&
+ defined($remoteglotconf::json_history_dir) && defined($json->{'engine'}{name})) {
+ my $id = id_for_pos($pos_calculating);
+ my $filename = $remoteglotconf::json_history_dir . "/" . $id . ".json";
+
+ # Overwrite old analysis (assuming it exists at all) if we're
+ # using a different engine, or if we've calculated deeper.
+ # nodes is used as a tiebreaker. Don't bother about Multi-PV
+ # data; it's not that important.
+ my ($old_engine, $old_depth, $old_nodes) = get_json_analysis_stats($id);
+ my $new_depth = $json->{'depth'} // 0;
+ my $new_nodes = $json->{'nodes'} // 0;
+ if (!defined($old_engine) ||
+ $old_engine ne $json->{'engine'}{'name'} ||
+ $new_depth > $old_depth ||
+ ($new_depth == $old_depth && $new_nodes >= $old_nodes)) {
+ atomic_set_contents($filename, $encoded);
+ if (defined($json->{'score'})) {
+ $dbh->do('INSERT INTO scores (id, score_type, score_value, engine, depth, nodes) VALUES (?,?,?,?,?,?) ' .
+ ' ON CONFLICT (id) DO UPDATE SET ' .
+ ' score_type=EXCLUDED.score_type, ' .
+ ' score_value=EXCLUDED.score_value, ' .
+ ' engine=EXCLUDED.engine, ' .
+ ' depth=EXCLUDED.depth, ' .
+ ' nodes=EXCLUDED.nodes',
+ undef,
+ $id, $json->{'score'}[0], $json->{'score'}[1],
+ $json->{'engine'}{'name'}, $new_depth, $new_nodes);
+ }
+ }