mirror of
https://bitbucket.org/grumdrig/pq-web.git
synced 2026-09-29 08:44:00 -06:00
Use Web SQL if available. Works nicely on iPad now.
This commit is contained in:
@@ -157,23 +157,41 @@ function GenerateName() {
|
||||
return result.charAt(0).toUpperCase() + result.slice(1);
|
||||
}
|
||||
|
||||
function LocalStorage() {
|
||||
this.getItem = function (key, callback) {
|
||||
var result = window.localStorage.getItem(key);
|
||||
if (callback)
|
||||
callback(result);
|
||||
};
|
||||
|
||||
this.setItem = function (key, value, callback) {
|
||||
window.localStorage.setItem(key, value);
|
||||
if (callback)
|
||||
callback();
|
||||
};
|
||||
|
||||
this.removeItem = function (key) {
|
||||
window.localStorage.removeItem(key);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function CookieStorage() {
|
||||
this.getItem = function(key) {
|
||||
try {
|
||||
this.getItem = function(key, callback) {
|
||||
var result;
|
||||
$.each(document.cookie.split(";"), function (i,cook) {
|
||||
if (cook.split("=")[0] === key)
|
||||
result = unescape(cook.split("=")[1]);
|
||||
});
|
||||
if (callback)
|
||||
setTimeout(function () { callback(result); }, 0);
|
||||
return result;
|
||||
} catch (err) {
|
||||
// Probably a JSON parse error
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
this.setItem = function (key, value) {
|
||||
this.setItem = function (key, value, callback) {
|
||||
document.cookie = key + "=" + escape(value);
|
||||
if (callback)
|
||||
setTimeout(callback, 0);
|
||||
};
|
||||
|
||||
this.removeItem = function (key) {
|
||||
@@ -181,49 +199,99 @@ function CookieStorage() {
|
||||
};
|
||||
}
|
||||
|
||||
function SqlStorage() {
|
||||
this.async = true;
|
||||
|
||||
var storage = window.localStorage;
|
||||
if (!storage)
|
||||
storage = new CookieStorage();
|
||||
this.db = window.openDatabase("pq", "", "Progress Quest", 2500);
|
||||
|
||||
function loadRoster() {
|
||||
if (storage) {
|
||||
var r = storage.getItem("roster");
|
||||
if (r) {
|
||||
this.db.transaction(function(tx) {
|
||||
tx.executeSql("CREATE TABLE IF NOT EXISTS Storage(key TEXT UNIQUE, value TEXT)");
|
||||
});
|
||||
|
||||
this.getItem = function(key, callback) {
|
||||
this.db.transaction(function (tx) {
|
||||
tx.executeSql("SELECT value FROM Storage WHERE key=?", [key], function(tx, rs) {
|
||||
if (rs.rows.length)
|
||||
callback(rs.rows.item(0).value);
|
||||
else
|
||||
callback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
this.setItem = function (key, value, callback) {
|
||||
this.db.transaction(function (tx) {
|
||||
tx.executeSql("INSERT OR REPLACE INTO Storage (key,value) VALUES (?,?)",
|
||||
[key, value],
|
||||
callback);
|
||||
});
|
||||
};
|
||||
|
||||
this.removeItem = function (key) {
|
||||
this.db.transaction(function (tx) {
|
||||
tx.executeSql("DELETE FROM Storage WHERE key=?", [key]);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
var iPad = navigator.userAgent.match(/iPad/);
|
||||
var iPod = navigator.userAgent.match(/iPod/);
|
||||
var iPhone = navigator.userAgent.match(/iPhone/);
|
||||
var iOS = iPad || iPod || iPhone;
|
||||
|
||||
var storage = ((window.localStorage && !iOS) ? new LocalStorage() :
|
||||
window.openDatabase ? new SqlStorage() :
|
||||
new CookieStorage());
|
||||
|
||||
storage.loadRoster = function (callback) {
|
||||
function gotItem(value) {
|
||||
if (value) {
|
||||
try {
|
||||
return JSON.parse(r);
|
||||
value = JSON.parse(value);
|
||||
} catch (err) {
|
||||
// aight
|
||||
}
|
||||
}
|
||||
storage.games = value || {};
|
||||
callback(storage.games);
|
||||
}
|
||||
return {};
|
||||
this.getItem("roster", gotItem);
|
||||
}
|
||||
|
||||
function loadSheet(name) {
|
||||
return loadRoster()[name];
|
||||
storage.loadSheet = function (name, callback) {
|
||||
return this.loadRoster(function (games) {
|
||||
if (callback)
|
||||
callback(games[name]);
|
||||
});
|
||||
}
|
||||
|
||||
function storeRoster(roster) {
|
||||
if (storage) {
|
||||
|
||||
storage.storeRoster = function (roster, callback) {
|
||||
this.games = roster;
|
||||
try {
|
||||
storage.setItem("roster", JSON.stringify(roster));
|
||||
return true;
|
||||
this.setItem("roster", JSON.stringify(roster), callback);
|
||||
} catch (err) {
|
||||
if (err.toString().indexOf("QUOTA_EXCEEDED_ERR") != -1) {
|
||||
alert("This browser lacks storage capacity to save this game. This game can continue but cannot be saved. (Mobile Safari, I'll wager?)");
|
||||
storage = null;
|
||||
return false;
|
||||
}
|
||||
this.storeRoster = function (roster, callback) {
|
||||
setTimeout(callback, 0);
|
||||
};
|
||||
setTimeout(callback, 0);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addToRoster(newguy) {
|
||||
if (storage) {
|
||||
var r = loadRoster();
|
||||
r[newguy.Traits.Name] = newguy;
|
||||
storeRoster(r);
|
||||
storage.addToRoster = function (newguy, callback) {
|
||||
if (this.games) {
|
||||
this.games[newguy.Traits.Name] = newguy;
|
||||
this.storeRoster(this.games, callback);
|
||||
} else {
|
||||
this.loadRoster(function () {
|
||||
if (storage.games) // should always be true
|
||||
storage.addToRoster(newguy, callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-9
@@ -28,6 +28,13 @@ p {
|
||||
#go {
|
||||
font-size: 30pt;
|
||||
}
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
th { text-align: left; padding-right: 2em; }
|
||||
.good { color: #2a2; }
|
||||
.bad { color: #a22; }
|
||||
.ugly { color: #c82; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@@ -62,16 +69,16 @@ coolant, and ported ProgrOS to that.
|
||||
Between you, me, and that talking pony over there, this is pretty much
|
||||
beta software at this point. Browser support breakdown:
|
||||
<center>
|
||||
<style>
|
||||
th { text-align: left; padding-right: 2em; }
|
||||
.good { color: #2a2; }
|
||||
.bad { color: #a22; }
|
||||
.ugly { color: #c82; }
|
||||
</style>
|
||||
<table>
|
||||
<tr><th class=good>Chrome, Firefox, Safari <td>Aces! Works great! We think!
|
||||
<tr><th class=ugly>Internet Explorer, Mobile Safari <td>Visual problems. Can't save games.
|
||||
<tr><th class=bad>Opera <td>Crashes quite a bit.
|
||||
<tr>
|
||||
<th class=good>Chrome, Firefox, Safari
|
||||
<td>Aces! Works great! We think!
|
||||
<tr>
|
||||
<th class=ugly>Opera, Mobile Safari
|
||||
<td>Visual glitches.
|
||||
<tr>
|
||||
<th class=bad>Internet Explorer
|
||||
<td>Visual glitches. Can't save games.
|
||||
</table>
|
||||
</center>
|
||||
|
||||
|
||||
@@ -118,3 +118,7 @@ tr { height: 15px; }
|
||||
#Quests td, #Plots td {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
body.iOS div.hint {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@
|
||||
maximum-scale=1.0;
|
||||
minimum-scale=1.0;
|
||||
user-scalable=0;" />
|
||||
<meta names="apple-mobile-web-app-status-bar-style"
|
||||
content="black" />
|
||||
<link rel="apple-touch-icon" href="swords.gif" />
|
||||
<meta names="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<link rel="apple-touch-icon" href="touch-icon.png" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -157,7 +156,7 @@
|
||||
|
||||
<div class="progress-container" id="PlotBar">
|
||||
<div class="hint"></div>
|
||||
<div class="bar" style="width: 50%"></div>
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
|
||||
<span class="label head">Quests</span>
|
||||
@@ -170,7 +169,7 @@
|
||||
|
||||
<div class="progress-container" id="QuestBar">
|
||||
<div class="hint"></div>
|
||||
<div class="bar" style="width: 50%"></div>
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -180,7 +179,7 @@
|
||||
|
||||
<div class="progress-container" id="TaskBar">
|
||||
<div class="hint"></div>
|
||||
<div class="bar" style="width: 50%"></div>
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -965,39 +965,37 @@ function FormCreate() {
|
||||
$(window).unload(function (event) {
|
||||
StopTimer();
|
||||
SaveGame();
|
||||
if (storage.async) {
|
||||
// Have to give SQL transaction a chance to complete
|
||||
if (window.showModalDialog)
|
||||
pause(100);
|
||||
|
||||
// Just accept some data loss - alert is too ugly. Maybe increase save
|
||||
// frequency.
|
||||
// else alert("Game saved");
|
||||
}
|
||||
});
|
||||
|
||||
if (iOS) $("body").addClass("iOS");
|
||||
}
|
||||
|
||||
LoadCharacter();
|
||||
var name = unescape(window.location.href.split('#')[1]);
|
||||
storage.loadSheet(name, LoadGame);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function pause(msec) {
|
||||
window.showModalDialog("javascript:document.writeln ('<script>window.setTimeout(" +
|
||||
"function () { window.close(); }," + msec + ");</script>')",
|
||||
null,
|
||||
"dialogWidth:0;dialogHeight:0;dialogHide:yes;unadorned:yes;"+
|
||||
"status:no;scroll:no;center:no;dialogTop:-10000;dialogLeft:-10000");
|
||||
}
|
||||
|
||||
function quit() {
|
||||
SaveGame();
|
||||
window.location = "roster.html";
|
||||
}
|
||||
|
||||
function LoadCharacter() {
|
||||
var result = true;
|
||||
var name = unescape(window.location.href.split('#')[1]);
|
||||
var sheet = loadSheet(name);
|
||||
|
||||
if (!sheet) {
|
||||
alert("Error loading " + name);
|
||||
window.location = "roster.html";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window.localStorage) {
|
||||
// Cookies can't hold a whole game save
|
||||
storage.removeItem("roster");
|
||||
storage = null;
|
||||
}
|
||||
|
||||
LoadGame(sheet);
|
||||
|
||||
if (document)
|
||||
$("#title").text("Progress Quest - " + GameSaveName());
|
||||
$(window).unbind('unload');
|
||||
SaveGame(function () { window.location = "roster.html"; });
|
||||
}
|
||||
|
||||
|
||||
@@ -1026,17 +1024,40 @@ function HotOrNot() {
|
||||
}
|
||||
|
||||
|
||||
function SaveGame() {
|
||||
function SaveGame(callback) {
|
||||
Log('Saving game: ' + GameSaveName());
|
||||
HotOrNot();
|
||||
game.date = ''+new Date();
|
||||
game.stamp = +new Date();
|
||||
game.seed = randseed();
|
||||
return addToRoster(game);
|
||||
storage.addToRoster(game, callback);
|
||||
}
|
||||
|
||||
function LoadGame(sheet) {
|
||||
if (!sheet) {
|
||||
alert("Error loading game");
|
||||
window.location = "roster.html";
|
||||
return;
|
||||
}
|
||||
|
||||
game = sheet;
|
||||
|
||||
/*
|
||||
if (!window.localStorage) {
|
||||
// Cookies can't hold a whole game save
|
||||
storage.removeItem("roster");
|
||||
storage = null;
|
||||
}
|
||||
*/
|
||||
|
||||
if (document) {
|
||||
var title = "Progress Quest - " + GameSaveName();
|
||||
$("#title").text(title);
|
||||
if (iOS) title = GameSaveName();
|
||||
$("title").text(title);
|
||||
}
|
||||
|
||||
|
||||
randseed(game.seed);
|
||||
$.each(AllBars.concat(AllLists), function (i, e) { e.load(game); });
|
||||
if (Kill)
|
||||
@@ -1121,6 +1142,11 @@ function FormKeyDown(e) {
|
||||
quit();
|
||||
}
|
||||
|
||||
if (e.which == 19) { // ^S
|
||||
SaveGame();
|
||||
alert(JSON.stringify(game).length);
|
||||
}
|
||||
|
||||
/*
|
||||
if (e.which == 20) { // ^T
|
||||
TaskBar.reposition(TaskBar.Max());
|
||||
|
||||
@@ -205,9 +205,10 @@ function sold() {
|
||||
newguy.Equips.Weapon = newguy.bestequip;
|
||||
newguy.Equips.Hauberk = "-3 Burlap";
|
||||
|
||||
addToRoster(newguy);
|
||||
|
||||
storage.addToRoster(newguy, function () {
|
||||
window.location.href = "main.html#" + escape(newguy.Traits.Name);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
|
||||
+3
-1
@@ -64,7 +64,9 @@ a.x, a.sheet {
|
||||
.banter {
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
var games;
|
||||
|
||||
function load() {
|
||||
var roster = $("#roster");
|
||||
roster.empty();
|
||||
|
||||
if (!window.localStorage) {
|
||||
roster.html("<b>Hrumph:</b> This browser does not support local storage. You can still play fast and loose: your character will live only as long as the game stays running in your browser.");
|
||||
return;
|
||||
}
|
||||
|
||||
storage.loadRoster(loadGames);
|
||||
}
|
||||
|
||||
function loadGames(games) {
|
||||
var roster = $("#roster");
|
||||
roster.empty();
|
||||
|
||||
var newone = window.location.href.split('#')[1];
|
||||
|
||||
var count = 0;
|
||||
games = loadRoster();
|
||||
|
||||
$.each(games, function (key, c) {
|
||||
var name = c.Traits.Name;
|
||||
|
||||
@@ -24,7 +28,7 @@ function load() {
|
||||
if (confirm("Terminate " + Pick(["faithful","noble","loyal","brave"])+
|
||||
" " + name + "?")) {
|
||||
delete games[name];
|
||||
storeRoster(games);
|
||||
storage.storeRoster(games);
|
||||
load();
|
||||
}
|
||||
});
|
||||
@@ -58,8 +62,7 @@ function brag(sheet) {
|
||||
}
|
||||
|
||||
function clearRoster() {
|
||||
storeRoster({});
|
||||
load();
|
||||
storage.storeRoster({}, load);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
@@ -30,6 +30,7 @@ var window = {
|
||||
},
|
||||
};
|
||||
|
||||
var navigator = { userAgent: "v8" };
|
||||
|
||||
var location = window.location;
|
||||
|
||||
@@ -94,13 +95,13 @@ var timers = [{}];
|
||||
var setInterval = global.setInterval = function (callback, interval) {
|
||||
timers.push({callback:callback, interval:interval});
|
||||
return timers.length-1;
|
||||
}
|
||||
};
|
||||
var setTimeout = setInterval; // TODO: distinguish!
|
||||
|
||||
load("config.js");
|
||||
|
||||
var cs = 0;
|
||||
for (var c in loadRoster())
|
||||
cs++;
|
||||
storage.loadRoster(function (cs) { for (var c in cs) cs++; });
|
||||
print(cs, "characters");
|
||||
|
||||
load("newguy.js");
|
||||
@@ -129,14 +130,19 @@ function charsheet(game) {
|
||||
// It takes 18 sec to simulate 18 hours of play when I just checked (to
|
||||
// level 10)
|
||||
|
||||
for (var j = 1, t = 0; j < 11; ++j) {
|
||||
for (var j = 1, t = 0; j < 1001; ++j) {
|
||||
t += LevelUpTime(j);
|
||||
//if (j % 100 == 0)
|
||||
if (j % 100 == 0)
|
||||
print(j, RoughTime(LevelUpTime(j))+",", RoughTime(t));
|
||||
}
|
||||
|
||||
var tmpl = read("charsheet.txt");
|
||||
storage.loadSheet("Shienzid", function (sheet) {
|
||||
game = sheet;
|
||||
print(template(tmpl, sheet));
|
||||
|
||||
var l = 0;
|
||||
for (var i = 0; i < 100000000; ++i) {
|
||||
for (var i = 0; i < 1000000000; ++i) {
|
||||
if (game.Traits.Level != l) {
|
||||
SaveGame();
|
||||
charsheet(game);
|
||||
@@ -147,4 +153,5 @@ for (var i = 0; i < 100000000; ++i) {
|
||||
now += timers[1].interval;
|
||||
timers[1].callback();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user