Almost fixed clocks update (incoherent FEN state)
[vchess.git] / client / src / utils / gameStorage.js
1 // Game object: {
2 // // Static informations:
3 // gameId: string
4 // vname: string,
5 // fenStart: string,
6 // players: array of sid+id+name,
7 // timeControl: string,
8 // increment: integer (seconds),
9 // mode: string ("live" or "corr")
10 // imported: boolean (optional, default false)
11 // // Game (dynamic) state:
12 // fen: string,
13 // moves: array of Move objects,
14 // clocks: array of integers,
15 // initime: array of integers (when clock start running),
16 // score: string (several options; '*' == running),
17 // }
18
19 function dbOperation(callback)
20 {
21 let db = null;
22 let DBOpenRequest = window.indexedDB.open("vchess", 4);
23
24 DBOpenRequest.onerror = function(event) {
25 alert("Database error: " + event.target.errorCode);
26 };
27
28 DBOpenRequest.onsuccess = function(event) {
29 db = DBOpenRequest.result;
30 callback(db);
31 db.close();
32 };
33
34 DBOpenRequest.onupgradeneeded = function(event) {
35 let db = event.target.result;
36 db.onerror = function(event) {
37 alert("Error while loading database: " + event.target.errorCode);
38 };
39 // Create objectStore for vchess->games
40 db.createObjectStore("games", { keyPath: "gameId" });
41 }
42 }
43
44 export const GameStorage =
45 {
46 // Optional callback to get error status
47 add: function(game, callback)
48 {
49 dbOperation((db) => {
50 let transaction = db.transaction("games", "readwrite");
51 if (callback)
52 {
53 transaction.oncomplete = function() {
54 callback({}); //everything's fine
55 }
56 transaction.onerror = function() {
57 callback({errmsg: "addGame failed: " + transaction.error});
58 };
59 }
60 let objectStore = transaction.objectStore("games");
61 objectStore.add(game);
62 });
63 },
64
65 // TODO: also option to takeback a move ?
66 // NOTE: for live games only (all on server for corr)
67 update: function(gameId, obj) //colorIdx, nextIdx, move, fen, addTime, score
68 {
69 dbOperation((db) => {
70 let objectStore = db.transaction("games", "readwrite").objectStore("games");
71 objectStore.get(gameId).onsuccess = function(event) {
72 const game = event.target.result;
73 if (!!obj.move)
74 {
75 game.moves.push(obj.move);
76 game.fen = obj.fen;
77 if (!!obj.addTime) //NaN if first move in game
78 game.clocks[obj.colorIdx] += obj.addTime;
79 game.initime[obj.nextIdx] = Date.now();
80 }
81 if (!!obj.score)
82 game.score = obj.score;
83 objectStore.put(game); //save updated data
84 }
85 });
86 },
87
88 // Retrieve any live game from its identifiers (locally, running or not)
89 // NOTE: need callback because result is obtained asynchronously
90 get: function(gameId, callback)
91 {
92 dbOperation((db) => {
93 let objectStore = db.transaction('games').objectStore('games');
94 if (!gameId) //retrieve all
95 {
96 let games = [];
97 objectStore.openCursor().onsuccess = function(event) {
98 let cursor = event.target.result;
99 // if there is still another cursor to go, keep running this code
100 if (cursor)
101 {
102 games.push(cursor.value);
103 cursor.continue();
104 }
105 else
106 callback(games);
107 }
108 }
109 else //just one game
110 {
111 objectStore.get(gameId).onsuccess = function(event) {
112 callback(event.target.result);
113 }
114 }
115 });
116 },
117
118 // Delete a game in indexedDB
119 remove: function(gameId, callback)
120 {
121 dbOperation((db) => {
122 let transaction = db.transaction(["games"], "readwrite");
123 if (callback)
124 {
125 transaction.oncomplete = function() {
126 callback({}); //everything's fine
127 }
128 transaction.onerror = function() {
129 callback({errmsg: "removeGame failed: " + transaction.error});
130 };
131 }
132 transaction.objectStore("games").delete(gameId);
133 });
134 },
135 };