]> git.sesse.net Git - remoteglot/blob - www/js/hash-lookup.js
Fix JS serving crash with promotions in the hash PV.
[remoteglot] / www / js / hash-lookup.js
1 var grpc = require('grpc');
2 var Chess = require(__dirname + '/chess.min.js').Chess;
3
4 var PROTO_PATH = __dirname + '/hashprobe.proto';
5 var hashprobe_proto = grpc.load(PROTO_PATH).hashprobe;
6
7 // TODO: Make destination configurable.
8 var client = new hashprobe_proto.HashProbe('localhost:50051', grpc.credentials.createInsecure());
9
10 var board = new Chess();
11
12 var handle_request = function(fen, response) {
13         if (!board.validate_fen(fen).valid) {
14                 response.writeHead(400, {});
15                 response.end();
16                 return;
17         }
18         client.probe({fen: fen}, function(err, probe_response) {
19                 if (err) {
20                         response.writeHead(500, {});
21                         response.end();
22                 } else {
23                         handle_response(fen, response, probe_response);
24                 }
25         });
26 }
27 exports.handle_request = handle_request;
28
29 var handle_response = function(fen, response, probe_response) {
30         var lines = {};
31
32         var root = translate_line(board, fen, probe_response['root'], true);
33         for (var i = 0; i < probe_response['line'].length; ++i) {
34                 var line = probe_response['line'][i];
35                 var uci_move = line['move']['from_sq'] + line['move']['to_sq'] + line['move']['promotion'];
36                 lines[uci_move] = translate_line(board, fen, line, false);
37         }
38
39         var text = JSON.stringify({
40                 root: root,
41                 lines: lines
42         });
43         var headers = {
44                 'Content-Type': 'text/json; charset=utf-8'
45                 //'Content-Length': text.length
46         };
47         response.writeHead(200, headers);
48         response.write(text);
49         response.end();
50 }
51
52 var translate_line = function(board, fen, line, pretty_score) {
53         var r = {};
54         board.load(fen);
55         var toplay = board.turn();
56
57         if (line['move'] && line['move']['from_sq']) {
58                 var promo = line['move']['promotion'];
59                 if (promo) {
60                         r['pretty_move'] = board.move({ from: line['move']['from_sq'], to: line['move']['to_sq'], promotion: promo.toLowerCase() }).san;
61                 } else {
62                         r['pretty_move'] = board.move({ from: line['move']['from_sq'], to: line['move']['to_sq'] }).san;
63                 }
64         } else {
65                 r['pretty_move'] = '';
66         }
67         r['sort_key'] = r['pretty_move'];
68         if (!line['found']) {
69                 r['pv_pretty'] = [];
70                 r['score_sort_key'] = -100000000;
71                 return r;
72         }
73         r['depth'] = line['depth'];
74
75         // Convert the PV.
76         var pv = [];
77         if (r['pretty_move']) {
78                 pv.push(r['pretty_move']);
79         }
80         for (var j = 0; j < line['pv'].length; ++j) {
81                 var move = line['pv'][j];
82                 var decoded = board.move({ from: move['from_sq'], to: move['to_sq'], promotion: move['promotion'] });
83                 if (decoded === null) {
84                         break;
85                 }
86                 pv.push(decoded.san);
87         }
88         r['pv_pretty'] = pv;
89
90         // Write out the pretty score.
91         // TODO: mates!
92         var score = pretty_score ? 'Score: ' : '';
93
94         if (line['bound'] === 'BOUND_UPPER') {
95                 score += '≤\u00a0';
96         } else if (line['bound'] === 'BOUND_LOWER') {
97                 score += '≥\u00a0';
98         }
99
100         var value = line['value']['score_cp'];
101         if (value > 0) {
102                 score += '+' + (value / 100.0).toFixed(2);
103         } else if (value < 0) {
104                 score += (value / 100.0).toFixed(2);
105         } else if (value == 0) {
106                 score += '0.00';
107         } else {
108                 score += '';
109         }
110         r['pretty_score'] = score;
111         r['score_sort_key'] = score_sort_key(line['value'], toplay === 'b') * 200 + r['depth'];
112
113         return r;
114 }
115
116 var score_sort_key = function(score, invert) {
117         if (score['score_type'] === 'SCORE_MATE') {
118                 var mate = score['score_mate'];
119                 var score;
120                 if (mate > 0) {
121                         // Side to move mates
122                         score = 99999 - mate;
123                 } else {
124                         // Side to move is getting mated (note the double negative for mate)
125                         score = -99999 - mate;
126                 }
127                 if (invert) {
128                         score = -score;
129                 }
130                 return score;
131         } else if (score['score_type'] === 'SCORE_CP') {
132                 var score = score['score_cp'];
133                 if (invert) {
134                         score = -score;
135                 }
136                 return score;
137         }
138
139         return null;
140 }