a9ebf33ae234b5aa49052dd39aad1d599f50d0d5
[vchess.git] / client / src / utils / gameStorage.js
1 // Game object: {
2 // // Static informations:
3 // id: 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 import { ajax } from "@/utils/ajax";
20
21 function dbOperation(callback)
22 {
23 let db = null;
24 let DBOpenRequest = window.indexedDB.open("vchess", 4);
25
26 DBOpenRequest.onerror = function(event) {
27 alert("Database error: " + event.target.errorCode);
28 };
29
30 DBOpenRequest.onsuccess = function(event) {
31 db = DBOpenRequest.result;
32 callback(db);
33 db.close();
34 };
35
36 DBOpenRequest.onupgradeneeded = function(event) {
37 let db = event.target.result;
38 db.onerror = function(event) {
39 alert("Error while loading database: " + event.target.errorCode);
40 };
41 // Create objectStore for vchess->games
42 let objectStore = db.createObjectStore("games", { keyPath: "id" });
43 objectStore.createIndex("score", "score"); //to search by game result
44 }
45 }
46
47 export const GameStorage =
48 {
49 // Optional callback to get error status
50 // TODO: this func called from Hall seems to not work now...
51 add: function(game, callback)
52 {
53 dbOperation((db) => {
54 let transaction = db.transaction("games", "readwrite");
55 if (callback)
56 {
57 transaction.oncomplete = function() {
58 callback({}); //everything's fine
59 }
60 transaction.onerror = function() {
61 callback({errmsg: "addGame failed: " + transaction.error});
62 };
63 }
64 let objectStore = transaction.objectStore("games");
65 objectStore.add(game);
66 });
67 },
68
69 // TODO: also option to takeback a move ?
70 update: function(gameId, obj) //chat, move, fen, clocks, score, initime, ...
71 {
72 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId)))
73 {
74 // corr: only move, fen and score
75 ajax(
76 "/games",
77 "PUT",
78 {
79 gid: gameId,
80 newObj:
81 {
82 chat: obj.chat,
83 move: obj.move, //may be undefined...
84 fen: obj.fen,
85 score: obj.score,
86 drawOffer: obj.drawOffer,
87 }
88 }
89 );
90 }
91 else
92 {
93 // live
94 dbOperation((db) => {
95 let objectStore = db.transaction("games", "readwrite").objectStore("games");
96 objectStore.get(gameId).onsuccess = function(event) {
97 const game = event.target.result;
98 Object.keys(obj).forEach(k => {
99 if (k == "move")
100 game.moves.push(obj[k]);
101 else
102 game[k] = obj[k];
103 });
104 objectStore.put(game); //save updated data
105 }
106 });
107 }
108 },
109
110 // Retrieve all local games (running, completed, imported...)
111 getAll: function(callback)
112 {
113 dbOperation((db) => {
114 let objectStore = db.transaction('games').objectStore('games');
115 let games = [];
116 objectStore.openCursor().onsuccess = function(event) {
117 let cursor = event.target.result;
118 // if there is still another cursor to go, keep running this code
119 if (cursor)
120 {
121 games.push(cursor.value);
122 cursor.continue();
123 }
124 else
125 callback(games);
126 }
127 });
128 },
129
130 // Retrieve any game from its identifiers (locally or on server)
131 // NOTE: need callback because result is obtained asynchronously
132 get: function(gameId, callback)
133 {
134 // corr games identifiers are integers
135 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId)))
136 {
137 ajax("/games", "GET", {gid:gameId}, res => {
138 let game = res.game;
139 game.moves.forEach(m => {
140 m.squares = JSON.parse(m.squares);
141 });
142 callback(game);
143 });
144 }
145 else //local game
146 {
147 dbOperation((db) => {
148 let objectStore = db.transaction('games').objectStore('games');
149 objectStore.get(gameId).onsuccess = function(event) {
150 callback(event.target.result);
151 }
152 });
153 }
154 },
155
156 getCurrent: function(callback)
157 {
158 dbOperation((db) => {
159 let objectStore = db.transaction('games').objectStore('games');
160 objectStore.get("*").onsuccess = function(event) {
161 callback(event.target.result);
162 };
163 });
164 },
165
166 // Delete a game in indexedDB
167 remove: function(gameId, callback)
168 {
169 dbOperation((db) => {
170 let transaction = db.transaction(["games"], "readwrite");
171 if (callback)
172 {
173 transaction.oncomplete = function() {
174 callback({}); //everything's fine
175 }
176 transaction.onerror = function() {
177 callback({errmsg: "removeGame failed: " + transaction.error});
178 };
179 }
180 transaction.objectStore("games").delete(gameId);
181 });
182 },
183 };