mirror of
https://bitbucket.org/grumdrig/pq-web.git
synced 2026-09-29 00:34: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);
|
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() {
|
function CookieStorage() {
|
||||||
this.getItem = function(key) {
|
this.getItem = function(key, callback) {
|
||||||
try {
|
|
||||||
var result;
|
var result;
|
||||||
$.each(document.cookie.split(";"), function (i,cook) {
|
$.each(document.cookie.split(";"), function (i,cook) {
|
||||||
if (cook.split("=")[0] === key)
|
if (cook.split("=")[0] === key)
|
||||||
result = unescape(cook.split("=")[1]);
|
result = unescape(cook.split("=")[1]);
|
||||||
});
|
});
|
||||||
|
if (callback)
|
||||||
|
setTimeout(function () { callback(result); }, 0);
|
||||||
return result;
|
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);
|
document.cookie = key + "=" + escape(value);
|
||||||
|
if (callback)
|
||||||
|
setTimeout(callback, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.removeItem = function (key) {
|
this.removeItem = function (key) {
|
||||||
@@ -181,49 +199,99 @@ function CookieStorage() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SqlStorage() {
|
||||||
|
this.async = true;
|
||||||
|
|
||||||
var storage = window.localStorage;
|
this.db = window.openDatabase("pq", "", "Progress Quest", 2500);
|
||||||
if (!storage)
|
|
||||||
storage = new CookieStorage();
|
|
||||||
|
|
||||||
function loadRoster() {
|
this.db.transaction(function(tx) {
|
||||||
if (storage) {
|
tx.executeSql("CREATE TABLE IF NOT EXISTS Storage(key TEXT UNIQUE, value TEXT)");
|
||||||
var r = storage.getItem("roster");
|
});
|
||||||
if (r) {
|
|
||||||
|
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 {
|
try {
|
||||||
return JSON.parse(r);
|
value = JSON.parse(value);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// aight
|
// aight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
storage.games = value || {};
|
||||||
|
callback(storage.games);
|
||||||
}
|
}
|
||||||
return {};
|
this.getItem("roster", gotItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSheet(name) {
|
storage.loadSheet = function (name, callback) {
|
||||||
return loadRoster()[name];
|
return this.loadRoster(function (games) {
|
||||||
|
if (callback)
|
||||||
|
callback(games[name]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function storeRoster(roster) {
|
|
||||||
if (storage) {
|
storage.storeRoster = function (roster, callback) {
|
||||||
|
this.games = roster;
|
||||||
try {
|
try {
|
||||||
storage.setItem("roster", JSON.stringify(roster));
|
this.setItem("roster", JSON.stringify(roster), callback);
|
||||||
return true;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.toString().indexOf("QUOTA_EXCEEDED_ERR") != -1) {
|
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?)");
|
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;
|
this.storeRoster = function (roster, callback) {
|
||||||
return false;
|
setTimeout(callback, 0);
|
||||||
}
|
};
|
||||||
|
setTimeout(callback, 0);
|
||||||
|
} else {
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addToRoster(newguy) {
|
storage.addToRoster = function (newguy, callback) {
|
||||||
if (storage) {
|
if (this.games) {
|
||||||
var r = loadRoster();
|
this.games[newguy.Traits.Name] = newguy;
|
||||||
r[newguy.Traits.Name] = newguy;
|
this.storeRoster(this.games, callback);
|
||||||
storeRoster(r);
|
} else {
|
||||||
|
this.loadRoster(function () {
|
||||||
|
if (storage.games) // should always be true
|
||||||
|
storage.addToRoster(newguy, callback);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-9
@@ -28,6 +28,13 @@ p {
|
|||||||
#go {
|
#go {
|
||||||
font-size: 30pt;
|
font-size: 30pt;
|
||||||
}
|
}
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
th { text-align: left; padding-right: 2em; }
|
||||||
|
.good { color: #2a2; }
|
||||||
|
.bad { color: #a22; }
|
||||||
|
.ugly { color: #c82; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -62,16 +69,16 @@ coolant, and ported ProgrOS to that.
|
|||||||
Between you, me, and that talking pony over there, this is pretty much
|
Between you, me, and that talking pony over there, this is pretty much
|
||||||
beta software at this point. Browser support breakdown:
|
beta software at this point. Browser support breakdown:
|
||||||
<center>
|
<center>
|
||||||
<style>
|
|
||||||
th { text-align: left; padding-right: 2em; }
|
|
||||||
.good { color: #2a2; }
|
|
||||||
.bad { color: #a22; }
|
|
||||||
.ugly { color: #c82; }
|
|
||||||
</style>
|
|
||||||
<table>
|
<table>
|
||||||
<tr><th class=good>Chrome, Firefox, Safari <td>Aces! Works great! We think!
|
<tr>
|
||||||
<tr><th class=ugly>Internet Explorer, Mobile Safari <td>Visual problems. Can't save games.
|
<th class=good>Chrome, Firefox, Safari
|
||||||
<tr><th class=bad>Opera <td>Crashes quite a bit.
|
<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>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
|||||||
@@ -118,3 +118,7 @@ tr { height: 15px; }
|
|||||||
#Quests td, #Plots td {
|
#Quests td, #Plots td {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.iOS div.hint {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,9 +12,8 @@
|
|||||||
maximum-scale=1.0;
|
maximum-scale=1.0;
|
||||||
minimum-scale=1.0;
|
minimum-scale=1.0;
|
||||||
user-scalable=0;" />
|
user-scalable=0;" />
|
||||||
<meta names="apple-mobile-web-app-status-bar-style"
|
<meta names="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
content="black" />
|
<link rel="apple-touch-icon" href="touch-icon.png" />
|
||||||
<link rel="apple-touch-icon" href="swords.gif" />
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -157,7 +156,7 @@
|
|||||||
|
|
||||||
<div class="progress-container" id="PlotBar">
|
<div class="progress-container" id="PlotBar">
|
||||||
<div class="hint"></div>
|
<div class="hint"></div>
|
||||||
<div class="bar" style="width: 50%"></div>
|
<div class="bar"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="label head">Quests</span>
|
<span class="label head">Quests</span>
|
||||||
@@ -170,7 +169,7 @@
|
|||||||
|
|
||||||
<div class="progress-container" id="QuestBar">
|
<div class="progress-container" id="QuestBar">
|
||||||
<div class="hint"></div>
|
<div class="hint"></div>
|
||||||
<div class="bar" style="width: 50%"></div>
|
<div class="bar"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -180,7 +179,7 @@
|
|||||||
|
|
||||||
<div class="progress-container" id="TaskBar">
|
<div class="progress-container" id="TaskBar">
|
||||||
<div class="hint"></div>
|
<div class="hint"></div>
|
||||||
<div class="bar" style="width: 50%"></div>
|
<div class="bar"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -965,39 +965,37 @@ function FormCreate() {
|
|||||||
$(window).unload(function (event) {
|
$(window).unload(function (event) {
|
||||||
StopTimer();
|
StopTimer();
|
||||||
SaveGame();
|
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() {
|
function quit() {
|
||||||
SaveGame();
|
$(window).unbind('unload');
|
||||||
window.location = "roster.html";
|
SaveGame(function () { 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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1026,17 +1024,40 @@ function HotOrNot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function SaveGame() {
|
function SaveGame(callback) {
|
||||||
Log('Saving game: ' + GameSaveName());
|
Log('Saving game: ' + GameSaveName());
|
||||||
HotOrNot();
|
HotOrNot();
|
||||||
game.date = ''+new Date();
|
game.date = ''+new Date();
|
||||||
game.stamp = +new Date();
|
game.stamp = +new Date();
|
||||||
game.seed = randseed();
|
game.seed = randseed();
|
||||||
return addToRoster(game);
|
storage.addToRoster(game, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LoadGame(sheet) {
|
function LoadGame(sheet) {
|
||||||
|
if (!sheet) {
|
||||||
|
alert("Error loading game");
|
||||||
|
window.location = "roster.html";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
game = sheet;
|
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);
|
randseed(game.seed);
|
||||||
$.each(AllBars.concat(AllLists), function (i, e) { e.load(game); });
|
$.each(AllBars.concat(AllLists), function (i, e) { e.load(game); });
|
||||||
if (Kill)
|
if (Kill)
|
||||||
@@ -1121,6 +1142,11 @@ function FormKeyDown(e) {
|
|||||||
quit();
|
quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.which == 19) { // ^S
|
||||||
|
SaveGame();
|
||||||
|
alert(JSON.stringify(game).length);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (e.which == 20) { // ^T
|
if (e.which == 20) { // ^T
|
||||||
TaskBar.reposition(TaskBar.Max());
|
TaskBar.reposition(TaskBar.Max());
|
||||||
|
|||||||
@@ -205,9 +205,10 @@ function sold() {
|
|||||||
newguy.Equips.Weapon = newguy.bestequip;
|
newguy.Equips.Weapon = newguy.bestequip;
|
||||||
newguy.Equips.Hauberk = "-3 Burlap";
|
newguy.Equips.Hauberk = "-3 Burlap";
|
||||||
|
|
||||||
addToRoster(newguy);
|
storage.addToRoster(newguy, function () {
|
||||||
|
|
||||||
window.location.href = "main.html#" + escape(newguy.Traits.Name);
|
window.location.href = "main.html#" + escape(newguy.Traits.Name);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancel() {
|
function cancel() {
|
||||||
|
|||||||
+3
-1
@@ -64,7 +64,9 @@ a.x, a.sheet {
|
|||||||
.banter {
|
.banter {
|
||||||
font-size: 11pt;
|
font-size: 11pt;
|
||||||
}
|
}
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
var games;
|
|
||||||
|
|
||||||
function load() {
|
function load() {
|
||||||
var roster = $("#roster");
|
|
||||||
roster.empty();
|
|
||||||
|
|
||||||
if (!window.localStorage) {
|
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.");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
storage.loadRoster(loadGames);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadGames(games) {
|
||||||
|
var roster = $("#roster");
|
||||||
|
roster.empty();
|
||||||
|
|
||||||
var newone = window.location.href.split('#')[1];
|
var newone = window.location.href.split('#')[1];
|
||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
games = loadRoster();
|
|
||||||
$.each(games, function (key, c) {
|
$.each(games, function (key, c) {
|
||||||
var name = c.Traits.Name;
|
var name = c.Traits.Name;
|
||||||
|
|
||||||
@@ -24,7 +28,7 @@ function load() {
|
|||||||
if (confirm("Terminate " + Pick(["faithful","noble","loyal","brave"])+
|
if (confirm("Terminate " + Pick(["faithful","noble","loyal","brave"])+
|
||||||
" " + name + "?")) {
|
" " + name + "?")) {
|
||||||
delete games[name];
|
delete games[name];
|
||||||
storeRoster(games);
|
storage.storeRoster(games);
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -58,8 +62,7 @@ function brag(sheet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clearRoster() {
|
function clearRoster() {
|
||||||
storeRoster({});
|
storage.storeRoster({}, load);
|
||||||
load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ var window = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var navigator = { userAgent: "v8" };
|
||||||
|
|
||||||
var location = window.location;
|
var location = window.location;
|
||||||
|
|
||||||
@@ -94,13 +95,13 @@ var timers = [{}];
|
|||||||
var setInterval = global.setInterval = function (callback, interval) {
|
var setInterval = global.setInterval = function (callback, interval) {
|
||||||
timers.push({callback:callback, interval:interval});
|
timers.push({callback:callback, interval:interval});
|
||||||
return timers.length-1;
|
return timers.length-1;
|
||||||
}
|
};
|
||||||
|
var setTimeout = setInterval; // TODO: distinguish!
|
||||||
|
|
||||||
load("config.js");
|
load("config.js");
|
||||||
|
|
||||||
var cs = 0;
|
var cs = 0;
|
||||||
for (var c in loadRoster())
|
storage.loadRoster(function (cs) { for (var c in cs) cs++; });
|
||||||
cs++;
|
|
||||||
print(cs, "characters");
|
print(cs, "characters");
|
||||||
|
|
||||||
load("newguy.js");
|
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
|
// It takes 18 sec to simulate 18 hours of play when I just checked (to
|
||||||
// level 10)
|
// level 10)
|
||||||
|
|
||||||
for (var j = 1, t = 0; j < 11; ++j) {
|
for (var j = 1, t = 0; j < 1001; ++j) {
|
||||||
t += LevelUpTime(j);
|
t += LevelUpTime(j);
|
||||||
//if (j % 100 == 0)
|
if (j % 100 == 0)
|
||||||
print(j, RoughTime(LevelUpTime(j))+",", RoughTime(t));
|
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;
|
var l = 0;
|
||||||
for (var i = 0; i < 100000000; ++i) {
|
for (var i = 0; i < 1000000000; ++i) {
|
||||||
if (game.Traits.Level != l) {
|
if (game.Traits.Level != l) {
|
||||||
SaveGame();
|
SaveGame();
|
||||||
charsheet(game);
|
charsheet(game);
|
||||||
@@ -147,4 +153,5 @@ for (var i = 0; i < 100000000; ++i) {
|
|||||||
now += timers[1].interval;
|
now += timers[1].interval;
|
||||||
timers[1].callback();
|
timers[1].callback();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user