aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--craftmine.php9
-rw-r--r--css/craftmine.css9
-rw-r--r--inc/Inventory.inc41
-rw-r--r--inc/Item.inc17
-rw-r--r--inc/account.inc18
-rw-r--r--inc/craftmine.inc14
-rw-r--r--inc/messages.inc15
-rw-r--r--inc/mine.inc4
-rw-r--r--inc/shop.inc59
-rw-r--r--index.xhtml78
-rw-r--r--js/craftmine.js22
-rw-r--r--js/gui.js42
-rw-r--r--js/shop.js57
13 files changed, 370 insertions, 15 deletions
diff --git a/craftmine.php b/craftmine.php
index 5df926f..869c83a 100644
--- a/craftmine.php
+++ b/craftmine.php
@@ -1,7 +1,10 @@
<?php
-session_start();
require_once("inc/mine.inc");
+require_once("inc/shop.inc");
+
+session_start(); // Must be placed *BEFORE* $_SESSION is actually used and *AFTER* all classes are imported
+
/**
* Indique au client une message requete.
*/
@@ -32,7 +35,9 @@ if (!isset($_POST["op"])) {
$op = $_POST["op"];
switch($op) {
case "withdrawMine": withdrawMine(); break;
- case "getCraftMine": sendMine(); break;
+ case "getCraftMine": sendCraftMine(); break;
+ case "buildShop": buildShop(); break;
+ case "buyItem": buyItem(); break;
default: reportBadRequest();
}
diff --git a/css/craftmine.css b/css/craftmine.css
new file mode 100644
index 0000000..2a51ff7
--- /dev/null
+++ b/css/craftmine.css
@@ -0,0 +1,9 @@
+.tab-pane {
+ display: none;
+}
+.tab-pane:target {
+ display: block;
+}
+.item-icon {
+ font-size: 3em;
+}
diff --git a/inc/Inventory.inc b/inc/Inventory.inc
new file mode 100644
index 0000000..efe54f2
--- /dev/null
+++ b/inc/Inventory.inc
@@ -0,0 +1,41 @@
+<?php
+
+class Inventory {
+
+ public $items = array();
+
+ public static function created() {
+ return !empty($_SESSION["inventory"]);
+ }
+
+ public static function sendContent() {
+ return self::get()->items;
+ }
+
+ public static function get() {
+ if(!self::created()) {
+ $_SESSION["inventory"] = new Inventory();
+ }
+ return $_SESSION["inventory"];
+ }
+
+ private function _addItem($item) {
+ $this->items[] = $item;
+ }
+
+ public static function addItem($item) {
+ $inv = self::get();
+ $inv->_addItem($item);
+ }
+
+ private function _removeItem($item) {
+ unset($this->items[array_search($item, $this->items)]);
+ }
+
+ public static function removeItem($item) {
+ $inv = self::get();
+ $inv->_removeItem($item);
+ }
+}
+
+?>
diff --git a/inc/Item.inc b/inc/Item.inc
new file mode 100644
index 0000000..bf77818
--- /dev/null
+++ b/inc/Item.inc
@@ -0,0 +1,17 @@
+<?php
+
+class Item {
+ public $name = "";
+ public $cost = 0;
+ public $icon = "";
+ public $desc = "";
+
+ function __construct($name, $cost, $icon, $desc) {
+ $this->name = $name;
+ $this->cost = $cost;
+ $this->icon = $icon;
+ $this->desc = $desc;
+ }
+}
+
+?>
diff --git a/inc/account.inc b/inc/account.inc
new file mode 100644
index 0000000..19f311d
--- /dev/null
+++ b/inc/account.inc
@@ -0,0 +1,18 @@
+<?php
+require_once("messages.inc");
+
+function debitAccount($amount) {
+ if($_SESSION["mine"]["gold"] <= $amount) {
+ sendError("gold_insufficient");
+ return false;
+ }
+ $_SESSION["mine"]["gold"] -= $amount;
+ return true;
+}
+
+function creditAccount($amount) {
+ $_SESSION["mine"]["gold"] += $amount;
+}
+
+
+?>
diff --git a/inc/craftmine.inc b/inc/craftmine.inc
new file mode 100644
index 0000000..a30538c
--- /dev/null
+++ b/inc/craftmine.inc
@@ -0,0 +1,14 @@
+<?php
+
+require_once("mine.inc");
+require_once("shop.inc");
+
+function sendCraftMine() {
+ $data = array("gold" => sendMine(),
+ "shop" => sendShop(),
+ "inventory" => Inventory::sendContent(),
+ );
+ echo json_encode($data);
+}
+
+?>
diff --git a/inc/messages.inc b/inc/messages.inc
new file mode 100644
index 0000000..f1ca8b3
--- /dev/null
+++ b/inc/messages.inc
@@ -0,0 +1,15 @@
+<?php
+
+$messages = array(
+ "shop_already_built" => "You have already built a shop.",
+ "gold_insufficient" => "You don't have enough gold.",
+ "shop_missing_item" => "This item does not exist.",
+);
+
+function sendError($msg) {
+ global $messages;
+ $text = $messages[$msg];
+ echo json_encode(array("error" => $text));
+}
+
+?>
diff --git a/inc/mine.inc b/inc/mine.inc
index aea04ad..6a04cc4 100644
--- a/inc/mine.inc
+++ b/inc/mine.inc
@@ -8,13 +8,13 @@ function withdrawMine() {
$amount = intval($_POST["amount"]);
if($amount == 0) return;
$_SESSION["mine"]["gold"] += $amount;
- echo $_SESSION["mine"]["gold"];
+ echo json_encode($_SESSION["mine"]["gold"]);
}
function sendMine() {
if(empty($_SESSION["mine"])) initCraftMine();
$mine = $_SESSION["mine"];
- echo $mine["gold"];
+ return $mine["gold"];
}
diff --git a/inc/shop.inc b/inc/shop.inc
new file mode 100644
index 0000000..11cf97b
--- /dev/null
+++ b/inc/shop.inc
@@ -0,0 +1,59 @@
+<?php
+
+require_once("messages.inc");
+require_once("account.inc");
+require_once("Item.inc");
+require_once("Inventory.inc");
+
+$shop = array(
+ "cost" => 3,
+ "items" => array(
+ new Item("cat", 6, "🐈", "Nyan!"),
+ new Item("torch", 3, "🔦", "Electric torch"),
+ ),
+);
+
+function getItem($name) {
+ global $shop;
+ foreach($shop["items"] as $item) {
+ if($name == $item->name) {
+ return $item;
+ }
+ }
+ sendError("shop_missing_item");
+ return false;
+}
+
+function initShop() {
+ $_SESSION["shop"] = true;
+}
+
+function sendShop() {
+ global $shop;
+ if(!empty($_SESSION["shop"]))
+ return $shop;
+ else return false;
+}
+
+function buildShop() {
+ global $shop;
+ if(!empty($_SESSION["shop"])) {
+ sendError("shop_already_built");
+ }
+ elseif(debitAccount($shop["cost"])) {
+ initShop();
+ $_SESSION["mine"]["gold"] -= $shop["cost"];
+ echo json_encode(sendShop());
+ }
+}
+
+function buyItem() {
+ $item = getItem($_POST["item"]);
+ if($item && debitAccount($item->cost)) {
+ Inventory::addItem($item);
+ echo json_encode($item);
+ }
+}
+
+
+?>
diff --git a/index.xhtml b/index.xhtml
index 5b38b69..6ec45ef 100644
--- a/index.xhtml
+++ b/index.xhtml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="css/bootstrap.min.css"?>
+<?xml-stylesheet type="text/css" href="css/craftmine.css"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
@@ -11,13 +12,78 @@
<meta name="author" content="Alexandre Renoux,Pierre-Emmanuel Novac"/>
<title>CraftMine</title>
<script type="text/javascript" charset="utf-8" src="js/craftmine.js"></script>
+ <script type="text/javascript" charset="utf-8" src="js/shop.js"></script>
+ <script type="text/javascript" charset="utf-8" src="js/gui.js"></script>
</head>
-<body onload="init()">
+<body onload="init()" onhashchange="changeTab()">
+<div class="container-fluid">
+<div class="row">
<h1>CraftMine</h1>
- <span id="gold">0</span>
- <span id="mine">0</span>
- <form class="form-horizontal" method="post" action="craftmine.php">
- <button type="button" name="withdraw" onclick="withdrawMine()">Withdraw</button>
- </form>
+</div>
+<div class="row">
+ <div class="col-md-4">
+ <div class="row">
+ <div class="col-md-10">
+ <span id="gold">0</span>
+ <span id="mine">0</span>
+ <form class="form-horizontal" method="post" action="craftmine.php">
+ <button class="btn btn-default" type="button" name="withdraw" onclick="withdrawMine()">Withdraw</button>
+ </form>
+ </div>
+ </div>
+ <div id="error-box" class="row" style="margin-top:1em;display:none">
+ <div class="col-md-10">
+ <div class="alert alert-danger">
+ <ul>
+ </ul>
+ </div>
+ </div>
+ </div>
+ <div id="info-box" class="row" style="margin-top:1em;display:none">
+ <div class="col-md-10">
+ <div class="alert alert-success">
+ <ul>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <div class="col-md-8">
+ <div class="row">
+
+ <div id="tabs-panel" class="tabbable">
+ <ul class="nav nav-tabs">
+ <li role="presentation"><a href="#tab1" data-toggle="tab">Build</a></li>
+ <li role="presentation"><a href="#tab2" data-toggle="tab">Shop</a></li>
+ <li role="presentation"><a href="#tab3" data-toggle="tab">Inventory</a></li>
+ <li role="presentation"><a href="#tab4" data-toggle="tab">Dungeon</a></li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane" id="tab1">
+ <h4>Select a building to build:</h4>
+ <ul class="list-inline">
+ <li><button class="btn btn-default" type="button" onclick="">Miner's guild</button></li>
+ <li><button class="btn btn-default" type="button" onclick="buildShop()">Shop</button></li>
+ </ul>
+ </div>
+ <div class="tab-pane" id="tab2">
+ <h4>There's no shop in this city.</h4>
+ </div>
+ <div class="tab-pane" id="tab3">
+ <h4>Your inventory is empty.</h4>
+ </div>
+ <div class="tab-pane" id="tab4">
+ <h4>Look at how poor you are! You can't access the dungeon, it is only for the elite.</h4>
+ </div>
+ </div>
+ </div>
+
+
+
+ </div>
+ </div>
+</div>
+</div>
</body>
</html>
diff --git a/js/craftmine.js b/js/craftmine.js
index bbb1074..66c35fc 100644
--- a/js/craftmine.js
+++ b/js/craftmine.js
@@ -11,7 +11,12 @@ function sendRequest(url, params, callback) {
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == "200") {
- callback(xhr);
+ var data = JSON.parse(xhr.responseText);
+ if(data.error) {
+ showError(data.error);
+ return;
+ }
+ if(callback) callback(data);
}
}
xhr.send(params);
@@ -24,9 +29,14 @@ function updateData() {
}
}
+function debitAccount(amount) {
+ data.gold -= amount;
+ updateData("gold");
+}
+
function withdrawMine() {
sendRequest("craftmine.php", "op=withdrawMine&amount="+data.mine, function(xhr) {
- var gold = parseInt(xhr.responseText); // Server's response is a string
+ var gold = parseInt(xhr); // Server's response is a string
if(isNaN(gold)) return;
data.gold = gold;
data.mine = 0;
@@ -35,9 +45,10 @@ function withdrawMine() {
}
function initCraftMine() {
- sendRequest("craftmine.php", "op=getCraftMine", function(xhr) {
- var ret = xhr.responseText;
- data.gold = parseInt(ret); // Server's response is a string
+ sendRequest("craftmine.php", "op=getCraftMine", function(ret) {
+ data.gold = parseInt(ret.gold); // Server's response is a string
+ if(ret.shop) displayShop(ret.shop);
+ displayInventory(ret.inventory);
updateData("gold");
})
}
@@ -50,5 +61,6 @@ function updateMine() {
function init() {
initCraftMine();
+ changeTab();
window.setInterval(updateMine, 1000);
}
diff --git a/js/gui.js b/js/gui.js
new file mode 100644
index 0000000..bdf1710
--- /dev/null
+++ b/js/gui.js
@@ -0,0 +1,42 @@
+var MESSAGE_TIMEOUT = 4000;
+
+function changeTab() {
+ var hashtype = window.location.hash.substr(1,3);
+ if(hashtype != "tab") return;
+ var id = window.location.hash.substr(4);
+ var tabs = document.querySelectorAll("#tabs-panel > ul > li");
+ for(var i=0; i < tabs.length; i++) {
+ if(i == id-1)
+ tabs[i].className = "active";
+ else
+ tabs[i].className = "";
+ }
+
+}
+
+function showMessage(type, msg) {
+ var msg_box = document.getElementById(type+"-box");
+ msg_box.style.display = "initial";
+ var msg_list = msg_box.firstElementChild.firstElementChild.firstElementChild;
+ msg_list.innerHTML = "<li>" + msg + "</li>\n" + msg_list.innerHTML;
+
+ window.setTimeout(hideMessage.bind(null, type), MESSAGE_TIMEOUT);
+}
+
+function hideMessage(type) {
+ var msg_box = document.getElementById(type+"-box");
+ var msg_list = msg_box.firstElementChild.firstElementChild.firstElementChild;
+ var item = msg_list.lastElementChild;
+ msg_list.removeChild(item);
+
+ if(msg_list.children.length <= 0)
+ msg_box.style.display = "none";
+}
+
+function showError(msg) {
+ showMessage("error", msg);
+}
+
+function showInfo(msg) {
+ showMessage("info", msg);
+}
diff --git a/js/shop.js b/js/shop.js
new file mode 100644
index 0000000..00636e1
--- /dev/null
+++ b/js/shop.js
@@ -0,0 +1,57 @@
+function displayShop(ret) {
+ var tmphtml = "<h4> Select an item to buy it:</h4>";
+ tmphtml += "<ul class=\"list-inline\">";
+ for(var i=0; i < ret.items.length; i++) {
+ tmphtml += "<li>";
+ tmphtml += "<button type=\"submit\" class=\"btn btn-primary\" onclick=\"buyItem('" + ret.items[i].name + "')\"><span class=\"item-icon\">" + ret.items[i].icon + "</span><br />" + ret.items[i].name + "</button>";
+ tmphtml += "</li>";
+ }
+ tmphtml += "</ul>"
+ document.getElementById("tab2").innerHTML = tmphtml;
+}
+
+function displayInventory(items) {
+ for(var i=0; i < items.length; i++) {
+ addItem(items[i]);
+ }
+}
+
+function buildShop() {
+ sendRequest("craftmine.php", "op=buildShop", function(ret) {
+ displayShop(ret);
+ debitAccount(ret.cost);
+ });
+}
+
+function addItem(ret) {
+ var itemhtml = "<li>";
+ itemhtml += "<button type=\"submit\" class=\"btn btn-primary\" onclick=\"useItem('" + ret.name + "')\"><span class=\"item-icon\">" + ret.icon + "</span><br />" + ret.name + "</button>";
+ itemhtml += "</li>";
+
+ var invcontent = document.getElementById("tab3");
+
+ if(invcontent.children.length <= 1)
+ {
+ var tmphtml = "<h4>Your bag contains the following items:</h4>";
+ tmphtml += "<ul class=\"list-inline\">";
+ tmphtml += itemhtml;
+ tmphtml += "</ul>"
+ invcontent.innerHTML = tmphtml;
+ } else
+ invcontent.getElementsByTagName('ul')[0].innerHTML += itemhtml;
+
+ showInfo(ret.desc);
+}
+
+function buyItem(name) {
+ sendRequest("craftmine.php", "op=buyItem&item="+name, function(ret) {
+ addItem(ret);
+ debitAccount(ret.cost);
+ });
+}
+
+function useItem(name) {
+ sendRequest("craftmine.php", "op=useItem&item="+name, function(ret) {
+ });
+}
+