* hw7_3.dat
Item Available
Laptops 1
Desktops 50
Printers 76
Disc Drives 27
Network cards 124
* index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=9;IE=8;IE=7;ie=edge">
<title>hw7_3</title>
</head>
<body>
<div class="container">
<table>
<thead>
<tr>
<th>Item</th><th>Available</th><th>Order amount</th>
</tr>
</thead>
<tbody id="items">
<!--<tr><td>Laptops</td><td>1</td></tr>-->
</tbody>
</table>
<br />
<p><button onclick="vm.orderNow()">Order Now</button></p>
<br />
<div id="orderList"></div>
<div id="errMsg"></div>
</div>
<script>
var $ = (function() {
function _xhr() {
var xmlHttp = null;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return new XMLHttpRequest();
}
function param(data) {
return Object.keys(data).map(function(key) {
return key + '=' + data[key];
}).join('&');
}
function ajax(o) {
var request = _xhr(),
type = o.type ? o.type : 'GET',
url = o.url,
success = o.success,
dataType = o.dataType ? o.dataType : "text/html",
data = o.data ? o.data : {};
request.withCredentials = true;
request.open(type, url, true);
request.onload = function() {
if (200 <= request.status && request.status < 400) {
var resp = request.responseText;
if (dataType === "json") {
success(JSON.parse(resp))
} else {
success(resp);
}
} else {
typeof o.fail === "function" && o.fail();
}
};
request.onerror = function() {
typeof o.error === "function" && o.error();
};
if (type === "POST") {
// request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
// request.send(param(data));
request.send(data);
} else {
request.send();
}
}
return {
ajax: ajax,
param: param
}
})();
var vm = {
data: {
inventory: []
},
setData: function(name, value) {
this.data[name] = value;
this.render();
},
render: function() {
var t = document.getElementById("items");
t.innerHTML = "";
this.data.inventory.forEach(function(ent, index) {
var tr = document.createElement("tr");
var td1 = document.createElement("td");
td1.innerHTML = ent.item;
var td2 = document.createElement("td");
td2.innerHTML = ent.available;
var td3 = document.createElement("td");
var select = document.createElement("select");
[0, 1, 5, 10, 50, 100].forEach(function(n) {
var option = document.createElement("option");
option.value = n;
option.innerText = n;
select.appendChild(option);
});
select.onchange = function(e) {
vm.data.inventory[index].amount = parseInt(e.currentTarget.value, 10);
console.log(vm.data);
};
td3.appendChild(select);
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
t.appendChild(tr);
});
},
orderNow: function() {
var d = this.data.inventory.filter(function(el) {
return el.amount > 0
}).map(function(el) {
return {
"item": el.item,
"amount": el.amount
}
});
var s = JSON.stringify(d);
$.ajax({
type: 'POST',
url: "hw7_3.php?action=order",
data: "{\"s\":"+s+"}",
dataType: 'json',
success: function(resp) {
console.log(resp);
// vm.setData("inventory", resp.data);
var orderWrap = document.getElementById("orderList");
var errorWrap = document.getElementById("errMsg");
orderWrap.innerHTML = errorWrap.innerHTML = "";
if (resp.code == 200) {
if (resp.data.stock) {
vm.setData("inventory", resp.data.stock);
}
orderWrap.innerHTML =
"Your order as below: <br />" +
resp.data.order.map(function(o) {
return o.item + " × " + o.amount;
}).join("<br />");
} else {
errorWrap.innerHTML = resp.msg + ": <br />" + JSON.stringify(resp.data.exceeds);
}
},
error: function() {
onsole.error("There was a connection error of some sort");
},
fail: function() {
console.error("We reached our target server, but it returned an error");
}
});
}
};
window.onload = function() {
// load items
$.ajax({
type: 'GET',
url: "hw7_3.php?action=index",
dataType: 'json',
success: function(resp) {
console.log(resp.data);
// order amount = 0;
resp.data.forEach(function(it) {
it['amount'] = 0;
});
vm.setData("inventory", resp.data);
},
error: function() {
onsole.error("There was a connection error of some sort");
},
fail: function() {
console.error("We reached our target server, but it returned an error");
}
});
}
</script>
</body>
</html>
* hw7_3.php
<?php
/**
* Created by PhpStorm.
* User: mzh
* Date: 4/30/2020
* Time: 09:59
*/
function items() {
$m = _loadItems();
$a = array();
$seq = 0;
foreach ($m as $item => $available) {
$seq += 1;
array_push($a, [
'id' => $seq,
'item' => $item,
'available'=>$available
]);
}
_success($a);
}
function order() {
$input = file_get_contents('php://input');
// save orders
if (!is_dir("./orders")) {
$ret = @mkdir("./orders", 0777);
if (!$ret) {
_xhrReturn([
"code" => 500,
"data" => null,
"msg" => "mkdir orders failed"
]);
}
}
$dat = fopen(sprintf("orders/order%s.dat", date("Ymd", time())), "a");
if (!is_resource($dat)) {
_xhrReturn([
"code" => 500,
"data" => null,
"msg" => "open order file failed, check server permission"
]);
}
$s = sprintf("%s%s\t%s\r\n", date("YmdHis", time()), rand(1000,9999), $input);
fwrite($dat, $s);
fclose($dat);
// order items
$o = json_decode($input);
$a = $o->s;
/**
* array(2) {
* [0]=>object(stdClass)#1 (2) {["item"]=>string(8) "Desktops"["amount"]=>int(10)}
* [1]=>object(stdClass)#2 (2) {["item"]=>string(8) "Printers"["amount"]=>int(100)}
* }
*/
$exceeds = [];
$stockMap = _loadItems();
foreach($a as $it) {
$productName = $it->item;
$orderAmount = $it->amount;
if ($stockMap[ $productName ] < $orderAmount) {
array_push($exceeds, $productName);
} else {
$stockMap[$productName] -= $orderAmount;
}
}
// return items, transform from assoc to index
$trans = function($map) {
$retItems = [];
$seq = 0;
foreach ($map as $item => $available) {
$seq += 1;
array_push($retItems, [
'id' => $seq,
'item' => $item,
'available'=>$available
]);
}
return $retItems;
};
// Invalid order
if (!empty($exceeds)) {
_xhrReturn([
"code" => 403,
"data" => [
"exceeds" => $exceeds,
"order" => [],
"stock" => call_user_func($trans, $stockMap)
],
"msg" => "Items to be ordered exceeds the number available"
]);
}
// update hw7_3.dat
_saveItems($stockMap);
_xhrReturn([
"code" => 200,
"data" => [
"exceeds" => [],
"order" => $a,
"stock" => call_user_func($trans, _loadItems())
]
]);
}
// item_name => available
function _loadItems() {
defined("BUFSIZE") || define("BUFSIZE", 256);
$db = fopen("hw7_3.dat", "r");
// jump over header
fgets($db, BUFSIZE);
$entries = array();
while (($line = fgets($db, BUFSIZE))) {
$line = rtrim($line, "\r\n ");
$a = explode("\t", $line);
$entries[ $a[0] ] = intval($a[1]);
}
return $entries;
}
function _saveItems($map) {
$db = fopen("hw7_3.dat", "w");
if (is_resource($db)) {
fwrite($db, "Item\tAvailable\r\n");
foreach ($map as $item => $available) {
fwrite($db, sprintf("%s\t%s\r\n", $item, $available));
}
fclose($db);
}
}
/**
* @param $a array
*/
function _xhrReturn($a) {
header("content-type: application/json;charset=utf-8");
echo json_encode($a);
exit(0);
}
function _success($data) {
_xhrReturn(array('code'=>200, 'data'=>$data, 'msg' => 'success'));
}
$action = $_GET['action'];
if ($action === "order") {
order();
} else {
// list items
items();
}