Started code review + some fixes (unfinished)
[vchess.git] / client / src / utils / gameStorage.js
CommitLineData
967a2686
BA
1// Game object: {
2// // Static informations:
11667c79 3// id: string
967a2686
BA
4// vname: string,
5// fenStart: string,
6// players: array of sid+id+name,
71468011 7// cadence: string,
967a2686
BA
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,
809ba2aa 15// initime: array of integers (when clock start running),
967a2686
BA
16// score: string (several options; '*' == running),
17// }
18
fd7aea36 19import { ajax } from "@/utils/ajax";
602d6bef 20import { store } from "@/store";
fd7aea36 21
6808d7a1 22function dbOperation(callback) {
967a2686
BA
23 let db = null;
24 let DBOpenRequest = window.indexedDB.open("vchess", 4);
25
26 DBOpenRequest.onerror = function(event) {
602d6bef 27 alert(store.state.tr["Database error:"] + " " + event.target.errorCode);
967a2686
BA
28 };
29
6808d7a1 30 DBOpenRequest.onsuccess = function() {
967a2686
BA
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) {
6808d7a1
BA
39 alert(
40 store.state.tr["Error while loading database:"] +
41 " " +
42 event.target.errorCode
43 );
967a2686
BA
44 };
45 // Create objectStore for vchess->games
11667c79 46 let objectStore = db.createObjectStore("games", { keyPath: "id" });
42c15a75 47 objectStore.createIndex("score", "score"); //to search by game result
6808d7a1 48 };
967a2686
BA
49}
50
6808d7a1 51export const GameStorage = {
967a2686 52 // Optional callback to get error status
6808d7a1
BA
53 add: function(game, callback) {
54 dbOperation(db => {
967a2686 55 let transaction = db.transaction("games", "readwrite");
6808d7a1 56 if (callback) {
967a2686
BA
57 transaction.oncomplete = function() {
58 callback({}); //everything's fine
6808d7a1 59 };
967a2686 60 transaction.onerror = function() {
6808d7a1
BA
61 callback({
62 errmsg:
63 store.state.tr["Game retrieval failed:"] + " " + transaction.error
64 });
967a2686
BA
65 };
66 }
67 let objectStore = transaction.objectStore("games");
68 objectStore.add(game);
69 });
70 },
71
72 // TODO: also option to takeback a move ?
dcd68c41 73 // obj: chat, move, fen, clocks, score[Msg], initime, ...
6808d7a1
BA
74 update: function(gameId, obj) {
75 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
3d55deea 76 // corr: only move, fen and score
6808d7a1
BA
77 ajax("/games", "PUT", {
78 gid: gameId,
79 newObj: {
80 // Some fields may be undefined:
81 chat: obj.chat,
82 move: obj.move,
83 fen: obj.fen,
84 score: obj.score,
85 scoreMsg: obj.scoreMsg,
86 drawOffer: obj.drawOffer
3d55deea 87 }
6808d7a1
BA
88 });
89 } else {
3d55deea 90 // live
6808d7a1
BA
91 dbOperation(db => {
92 let objectStore = db
93 .transaction("games", "readwrite")
94 .objectStore("games");
3d55deea
BA
95 objectStore.get(gameId).onsuccess = function(event) {
96 const game = event.target.result;
97 Object.keys(obj).forEach(k => {
6808d7a1
BA
98 if (k == "move") game.moves.push(obj[k]);
99 else game[k] = obj[k];
3d55deea
BA
100 });
101 objectStore.put(game); //save updated data
6808d7a1 102 };
3d55deea
BA
103 });
104 }
967a2686
BA
105 },
106
fd7aea36 107 // Retrieve all local games (running, completed, imported...)
6808d7a1
BA
108 getAll: function(callback) {
109 dbOperation(db => {
110 let objectStore = db.transaction("games").objectStore("games");
fd7aea36
BA
111 let games = [];
112 objectStore.openCursor().onsuccess = function(event) {
113 let cursor = event.target.result;
114 // if there is still another cursor to go, keep running this code
6808d7a1 115 if (cursor) {
fd7aea36
BA
116 games.push(cursor.value);
117 cursor.continue();
6808d7a1
BA
118 } else callback(games);
119 };
fd7aea36
BA
120 });
121 },
122
123 // Retrieve any game from its identifiers (locally or on server)
124 // NOTE: need callback because result is obtained asynchronously
6808d7a1 125 get: function(gameId, callback) {
fd7aea36 126 // corr games identifiers are integers
6808d7a1
BA
127 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
128 ajax("/games", "GET", { gid: gameId }, res => {
92b82def
BA
129 let game = res.game;
130 game.moves.forEach(m => {
131 m.squares = JSON.parse(m.squares);
132 });
133 callback(game);
fd7aea36 134 });
6808d7a1
BA
135 } //local game
136 else {
137 dbOperation(db => {
138 let objectStore = db.transaction("games").objectStore("games");
967a2686
BA
139 objectStore.get(gameId).onsuccess = function(event) {
140 callback(event.target.result);
6808d7a1 141 };
fd7aea36
BA
142 });
143 }
967a2686
BA
144 },
145
6808d7a1
BA
146 getCurrent: function(callback) {
147 dbOperation(db => {
148 let objectStore = db.transaction("games").objectStore("games");
42c15a75
BA
149 objectStore.get("*").onsuccess = function(event) {
150 callback(event.target.result);
151 };
152 });
153 },
154
967a2686 155 // Delete a game in indexedDB
6808d7a1
BA
156 remove: function(gameId, callback) {
157 dbOperation(db => {
967a2686 158 let transaction = db.transaction(["games"], "readwrite");
6808d7a1 159 if (callback) {
967a2686
BA
160 transaction.oncomplete = function() {
161 callback({}); //everything's fine
6808d7a1 162 };
967a2686 163 transaction.onerror = function() {
6808d7a1
BA
164 callback({
165 errmsg:
166 store.state.tr["Game removal failed:"] + " " + transaction.error
167 });
967a2686
BA
168 };
169 }
170 transaction.objectStore("games").delete(gameId);
171 });
6808d7a1 172 }
967a2686 173};