ce609af09ad8fdcc1fe93e1fa88d47930490d979
[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 // cadence: string,
8 // increment: integer (seconds),
9 // type: string ("live" or "corr")
10 // // Game (dynamic) state:
11 // fen: string,
12 // moves: array of Move objects,
13 // clocks: array of integers,
14 // initime: array of integers (when clock start running),
15 // score: string (several options; '*' == running),
16 // }
17
18 import { ajax } from "@/utils/ajax";
19 import { store } from "@/store";
20
21 function dbOperation(callback) {
22 let db = null;
23 let DBOpenRequest = window.indexedDB.open("vchess", 4);
24
25 DBOpenRequest.onerror = function(event) {
26 alert(store.state.tr["Database error: stop private browsing, or update your browser"]);
27 callback("error",null);
28 };
29
30 DBOpenRequest.onsuccess = function() {
31 db = DBOpenRequest.result;
32 callback(null,db);
33 db.close();
34 };
35
36 DBOpenRequest.onupgradeneeded = function(event) {
37 let db = event.target.result;
38 let objectStore = db.createObjectStore("games", { keyPath: "id" });
39 objectStore.createIndex("score", "score"); //to search by game result
40 };
41 }
42
43 export const GameStorage = {
44 // Optional callback to get error status
45 add: function(game, callback) {
46 dbOperation((err,db) => {
47 if (err) {
48 callback("error");
49 return;
50 }
51 let transaction = db.transaction("games", "readwrite");
52 transaction.oncomplete = function() {
53 callback(); //everything's fine
54 };
55 let objectStore = transaction.objectStore("games");
56 objectStore.add(game);
57 });
58 },
59
60 // TODO: also option to takeback a move ?
61 // obj: chat, move, fen, clocks, score[Msg], initime, ...
62 update: function(gameId, obj) {
63 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
64 // corr: only move, fen and score
65 ajax("/games", "PUT", {
66 gid: gameId,
67 newObj: {
68 // Some fields may be undefined:
69 chat: obj.chat,
70 move: obj.move,
71 fen: obj.fen,
72 score: obj.score,
73 scoreMsg: obj.scoreMsg,
74 drawOffer: obj.drawOffer
75 }
76 });
77 } else {
78 // live
79 dbOperation((err,db) => {
80 let objectStore = db
81 .transaction("games", "readwrite")
82 .objectStore("games");
83 objectStore.get(gameId).onsuccess = function(event) {
84 // Ignoring error silently: shouldn't happen now. TODO?
85 if (event.target.result) {
86 const game = event.target.result;
87 Object.keys(obj).forEach(k => {
88 if (k == "move") game.moves.push(obj[k]);
89 else game[k] = obj[k];
90 });
91 objectStore.put(game); //save updated data
92 }
93 };
94 });
95 }
96 },
97
98 // Retrieve all local games (running, completed, imported...)
99 getAll: function(callback) {
100 dbOperation((err,db) => {
101 let objectStore = db.transaction("games").objectStore("games");
102 let games = [];
103 objectStore.openCursor().onsuccess = function(event) {
104 let cursor = event.target.result;
105 // if there is still another cursor to go, keep running this code
106 if (cursor) {
107 games.push(cursor.value);
108 cursor.continue();
109 } else callback(games);
110 };
111 });
112 },
113
114 // Retrieve any game from its identifiers (locally or on server)
115 // NOTE: need callback because result is obtained asynchronously
116 get: function(gameId, callback) {
117 // corr games identifiers are integers
118 if (Number.isInteger(gameId) || !isNaN(parseInt(gameId))) {
119 ajax("/games", "GET", { gid: gameId }, res => {
120 let game = res.game;
121 game.moves.forEach(m => {
122 m.squares = JSON.parse(m.squares);
123 });
124 callback(game);
125 });
126 }
127 else {
128 // Local game
129 dbOperation((err,db) => {
130 let objectStore = db.transaction("games").objectStore("games");
131 objectStore.get(gameId).onsuccess = function(event) {
132 if (event.target.result)
133 callback(event.target.result);
134 };
135 });
136 }
137 },
138
139 // Delete a game in indexedDB
140 remove: function(gameId, callback) {
141 dbOperation((err,db) => {
142 if (!err) {
143 let transaction = db.transaction(["games"], "readwrite");
144 transaction.oncomplete = function() {
145 callback({}); //everything's fine
146 };
147 transaction.objectStore("games").delete(gameId);
148 }
149 });
150 }
151 };