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