mirror of
https://gitee.com/BDWare/agent-backend
synced 2025-01-10 09:54:11 +00:00
359 lines
12 KiB
Plaintext
359 lines
12 KiB
Plaintext
|
import "loadResource.yjs"
|
|||
|
@LogType("Arg")
|
|||
|
contract Incentives{
|
|||
|
|
|||
|
export function getMainFrame(arg){
|
|||
|
return "/html/main.html";
|
|||
|
}
|
|||
|
|
|||
|
function onCreate(arg) {
|
|||
|
Global.owner = requester;
|
|||
|
Global.bids = [];
|
|||
|
Global.asks = [];
|
|||
|
Global.listFinal = [];
|
|||
|
Global.status = "Bidding";
|
|||
|
}
|
|||
|
|
|||
|
export function getOwner(arg) {
|
|||
|
return Global.owner;
|
|||
|
}
|
|||
|
|
|||
|
export function isOwner(arg) {
|
|||
|
return requester==Global.owner;
|
|||
|
}
|
|||
|
|
|||
|
export function getStatus(arg) {
|
|||
|
return Global.status;
|
|||
|
}
|
|||
|
|
|||
|
export function getAskListRW(arg) {
|
|||
|
var retList = [];
|
|||
|
for (var i = 0; i < Global.asks.length; i++) {
|
|||
|
var ask = {};
|
|||
|
ask["item"] = Global.asks[i]["item"];
|
|||
|
if (Global.asks[i]["seller"] == requester) {
|
|||
|
ask["seller"] = Global.asks[i]["seller"];
|
|||
|
ask["price"] = Global.asks[i]["price"];
|
|||
|
} else {
|
|||
|
ask["seller"] = "Anonymous";
|
|||
|
ask["price"] = "Unknown";
|
|||
|
}
|
|||
|
retList.push(ask);
|
|||
|
}
|
|||
|
return JSON.stringify(retList);
|
|||
|
}
|
|||
|
|
|||
|
export function getAskListRO(arg) {
|
|||
|
if (requester != Global.owner) {
|
|||
|
return "Access Denied";
|
|||
|
}
|
|||
|
return JSON.stringify(Global.asks);
|
|||
|
}
|
|||
|
|
|||
|
export function getBidListAll(arg) {
|
|||
|
if (requester != Global.owner) {
|
|||
|
return "Access Denied";
|
|||
|
}
|
|||
|
return JSON.stringify(Global.bids);
|
|||
|
}
|
|||
|
|
|||
|
export function getBidListPrivate(arg) {
|
|||
|
var retList = [];
|
|||
|
for (var i = 0; i < Global.bids.length; i++) {
|
|||
|
if (Global.bids[i]["bidder"]==requester) {
|
|||
|
retList.push(Global.bids[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
return JSON.stringify(retList);
|
|||
|
}
|
|||
|
|
|||
|
export function bid(arg) {//每个args的格式是:{"bidder":"","item":""} item资源编号,bidder买方
|
|||
|
var args = JSON.parse(arg);
|
|||
|
args["bidder"] = requester; //从外界引入bidder的编号
|
|||
|
return bidHelper(args);
|
|||
|
}
|
|||
|
|
|||
|
function bidHelper(args){
|
|||
|
if (Global.status != "Bidding") {
|
|||
|
return "Not in bidding status!";
|
|||
|
}
|
|||
|
var asks = findAllElements(Global.asks, "item", args["item"]);
|
|||
|
if (asks.length == 0) {
|
|||
|
return "No such item exists!";
|
|||
|
}
|
|||
|
for (var i = 0; i< Global.bids.length; i++) {
|
|||
|
if (Global.bids[i]["bidder"]==args["bidder"] && Global.bids[i]["item"]==args["item"]) {
|
|||
|
return "A valid bid already exists"; //这个已经存在买方购买该资源的信息
|
|||
|
}
|
|||
|
}
|
|||
|
Global.bids.push(args); //没有已存在,就可以将这个信息加入global.bids
|
|||
|
return "Success";
|
|||
|
}
|
|||
|
|
|||
|
export function ask(arg) { //每个args的格式是:{"seller":"","item":""} item资源编号,seller卖方
|
|||
|
var args = JSON.parse(arg);
|
|||
|
args["seller"] = requester;
|
|||
|
return askHelper(args);
|
|||
|
}
|
|||
|
|
|||
|
function askHelper(args){
|
|||
|
if (Global.status != "Bidding") {
|
|||
|
return "Not in bidding status";
|
|||
|
}
|
|||
|
for (var i = 0; i< Global.asks.length; i++) {
|
|||
|
if (Global.asks[i]["item"]==args["item"]) {
|
|||
|
return "A valid ask already exists"; //已经存在卖方提供该资源的信息
|
|||
|
}
|
|||
|
}
|
|||
|
Global.asks.push(args); //没有已存在,就可以将这个信息加入Global.asks
|
|||
|
return "Success";
|
|||
|
}
|
|||
|
|
|||
|
export function match(arg) {
|
|||
|
if (Global.status != "Bidding") {
|
|||
|
return "Not in bidding status";
|
|||
|
}
|
|||
|
if (requester != Global.owner) {
|
|||
|
return "Access Denied";
|
|||
|
}
|
|||
|
if (Global.bids.length == 0 || Global.asks.length == 0) {
|
|||
|
return "Must have at least 1 resource and 1 bid!";
|
|||
|
}
|
|||
|
|
|||
|
// Algorithm 2 winning candidates determination
|
|||
|
// sort bids and asks
|
|||
|
sortObjectArray(Global.bids,"price",false); //买方按照价格降序跑列
|
|||
|
sortObjectArray(Global.asks,"price",true); //卖方升序排列
|
|||
|
// calculate threshold value
|
|||
|
var thrPos = Math.ceil((Global.asks.length+1.0)/2.0); //取中位数beta
|
|||
|
var askThrValue = Global.asks[thrPos-1]["price"]; //卖方的阈值
|
|||
|
// get candidates according to the threshold value
|
|||
|
var candidateBidsTmp = [];
|
|||
|
for (var i = 0; i < Global.bids.length; i++) {
|
|||
|
if (Global.bids[i]["price"] >= askThrValue) { //取大于等于卖方阈值的所有买方价格
|
|||
|
candidateBidsTmp.push(Global.bids[i]); //candidateBidsTmp:大于等于卖方阈值价格的买方价格
|
|||
|
} else {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
var bidThrValue = candidateBidsTmp[candidateBidsTmp.length-1]["price"]; //取买方的阈值最低价
|
|||
|
// get rid of impossible candidates踢出不可能的candidates
|
|||
|
var candidateAsks = [];
|
|||
|
var candidateBids = [];
|
|||
|
for (var i=0; i<candidateBidsTmp.length; i++) {
|
|||
|
var askList = findAllElements(Global.asks, "item", candidateBidsTmp[i]["item"]);
|
|||
|
//在global.asks中的找到提供该资源的所有卖方
|
|||
|
if (askList.length == 1 && askList[0]["price"] < askThrValue) {
|
|||
|
//如果只有一个卖方提供该资源且卖方提供的资源价格小于卖方阈值
|
|||
|
candidateBids.push(candidateBidsTmp[i]); //那么这个买方就可能可以拥有这个资源(匹配),加入candidateBids(插入顺序也是按照价格降序排列的)
|
|||
|
var cAskList = findAllElements(candidateAsks, "item", candidateBidsTmp[i]["item"]);
|
|||
|
//在candidateAsks中找到提供这个资源的所有卖方
|
|||
|
if (cAskList.length == 0) {
|
|||
|
//如果还没有加入提供该资源的卖方,那么就加入candidateAsks,就是说这个卖方可能可以卖出这个资源
|
|||
|
candidateAsks.push(askList[0]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Algorithm 3 assignment and pricing
|
|||
|
var matchedList = [];
|
|||
|
for (var i=0; i<candidateAsks.length; i++) {
|
|||
|
var record = {};
|
|||
|
record["used"] = false;
|
|||
|
record["result"] = "N/A";
|
|||
|
record["item"] = candidateAsks[i]["item"];
|
|||
|
record["seller"] = candidateAsks[i]["seller"];
|
|||
|
record["sellerPrice"] = askThrValue;
|
|||
|
var bids = findAllElements(candidateBids, "item", candidateAsks[i]["item"]);
|
|||
|
//在匹配的买方中找到给该资源报价的所有买方
|
|||
|
record["bidder"] = bids[0]["bidder"];
|
|||
|
if (bids.length == 1) {
|
|||
|
//如果只有一个买方报价
|
|||
|
record["bidderPrice"] = bidThrValue;
|
|||
|
//将成交价格设定为买方的阈值价格
|
|||
|
} else {
|
|||
|
record["bidderPrice"] = bids[1]["price"];
|
|||
|
//如果有至少两个报价,那么按照次价格设定成交价
|
|||
|
}
|
|||
|
matchedList.push(record);
|
|||
|
}
|
|||
|
|
|||
|
// Algorithm 4 winner elimination
|
|||
|
var listFinal = [];
|
|||
|
for (var i=0; i<matchedList.length; i++) {
|
|||
|
var finalRecordList = findAllElements(listFinal, "bidder", matchedList[i]["bidder"]);
|
|||
|
|
|||
|
if (finalRecordList.length != 0) {
|
|||
|
break; //如果listFinal中已经存在这个买方了,就break
|
|||
|
}
|
|||
|
var matches = findAllElements(matchedList, "bidder", matchedList[i]["bidder"]);
|
|||
|
//找到和同个买方的所有情况
|
|||
|
if (matches.length == 1) { //没有同个买方多个匹配结果,直接加入listFinal
|
|||
|
listFinal.push(matches[0]);
|
|||
|
} else {
|
|||
|
//如果有同个买方多个匹配结果
|
|||
|
var utilities = [];
|
|||
|
for (var j = 0; j < matches.length; j++) {
|
|||
|
var bidPrice = findAllElements(
|
|||
|
findAllElements(Global.bids, "bidder", matches[j]["bidder"]),
|
|||
|
"item", matches[j]["item"])[0]["price"];
|
|||
|
//同个买方同个资源的最初报价
|
|||
|
var finalPrice = matches[j]["bidderPrice"]; //成交报价
|
|||
|
utilities.push(bidPrice-finalPrice); //效用
|
|||
|
}
|
|||
|
var maxU = Number.MIN_VALUE;
|
|||
|
var maxUIndex = -1;
|
|||
|
for (var j = 0; j < utilities.length; j++) {
|
|||
|
if (utilities[j] > maxU) {
|
|||
|
maxU = utilities[j];
|
|||
|
maxUIndex = j;
|
|||
|
}
|
|||
|
}
|
|||
|
listFinal.push(matches[maxUIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
Global.listFinal = listFinal;
|
|||
|
Global.status = "Finalized";
|
|||
|
return "Success";
|
|||
|
}
|
|||
|
|
|||
|
@Cost({"countGas":true,"extraGas":"getFinalPrice"})
|
|||
|
export function execute(arg) {
|
|||
|
if (Global.status != "Finalized") {
|
|||
|
return "Bidding has not been finalized!"
|
|||
|
}
|
|||
|
var args = JSON.parse(arg);
|
|||
|
var winningBid = false;
|
|||
|
for (var i=0; i < Global.listFinal.length; i++) {
|
|||
|
if (Global.listFinal[i]["used"]) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (Global.listFinal[i]["item"]==args["item"] && Global.listFinal[i]["bidder"]==requester) {
|
|||
|
winningBid = true;
|
|||
|
Global.listFinal[i]["used"] = true;
|
|||
|
Global.listFinal[i]["result"] = "Success";
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!winningBid) {
|
|||
|
return "Access Denied";
|
|||
|
}
|
|||
|
print(args["item"] + " used by " + requester);
|
|||
|
return "Success";
|
|||
|
}
|
|||
|
|
|||
|
export function getFinalPrice(arg) {
|
|||
|
var args = JSON.parse(arg);
|
|||
|
var winningPrice = 0;
|
|||
|
for (var i=0; i < Global.listFinal.length; i++) {
|
|||
|
if (Global.listFinal[i]["item"]==args["item"] && Global.listFinal[i]["bidder"]==requester) {
|
|||
|
winningPrice = Global.listFinal[i]["bidderPrice"];
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
return winningPrice;
|
|||
|
}
|
|||
|
|
|||
|
export function resetStatus(arg) {
|
|||
|
if (requester != Global.owner) {
|
|||
|
return "Access Denied"
|
|||
|
}
|
|||
|
Global.bids = [];
|
|||
|
Global.asks = [];
|
|||
|
Global.listFinal = [];
|
|||
|
Global.status = "Bidding";
|
|||
|
return "Success";
|
|||
|
}
|
|||
|
|
|||
|
function sortObjectArray(arr, prop, isAsc) {
|
|||
|
//数组arr按照属性prp的值升序/降序排列
|
|||
|
if (isAsc) {
|
|||
|
for (var a=0; a < arr.length; a++) {
|
|||
|
for (var b=0; b < arr.length-1-a; b++) {
|
|||
|
if (arr[b][prop] > arr[b+1][prop]) {
|
|||
|
var tmp = arr[b];
|
|||
|
arr[b] = arr[b+1];
|
|||
|
arr[b+1] = tmp;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for (var a=0; a < arr.length; a++) {
|
|||
|
for (var b=0; b < arr.length-1-a; b++) {
|
|||
|
if (arr[b][prop] < arr[b+1][prop]) {
|
|||
|
var tmp = arr[b];
|
|||
|
arr[b] = arr[b+1];
|
|||
|
arr[b+1] = tmp;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return arr;
|
|||
|
}
|
|||
|
|
|||
|
function findAllElements(arr, prop, value) {
|
|||
|
//找到arr的prop属性等于value的所有元素
|
|||
|
var newArr = [];
|
|||
|
for (var a = 0; a < arr.length; a++) {
|
|||
|
if (arr[a][prop] == value) {
|
|||
|
newArr.push(arr[a]);
|
|||
|
}
|
|||
|
}
|
|||
|
return newArr;
|
|||
|
}
|
|||
|
|
|||
|
export function getFinalListOwner(arg) {
|
|||
|
if (requester != Global.owner) {
|
|||
|
return "Access Denied";
|
|||
|
}
|
|||
|
var retList = [];
|
|||
|
for (var i = 0; i < Global.listFinal.length; i++) {
|
|||
|
var fin = {};
|
|||
|
fin["item"] = Global.listFinal[i]["item"];
|
|||
|
fin["seller"] = Global.listFinal[i]["seller"];
|
|||
|
fin["bidder"] = Global.listFinal[i]["bidder"];
|
|||
|
fin["sellerPrice"] = Global.listFinal[i]["sellerPrice"];
|
|||
|
fin["bidderPrice"] = Global.listFinal[i]["bidderPrice"];
|
|||
|
fin["used"] = Global.listFinal[i]["used"];
|
|||
|
fin["result"] = "Unknown";
|
|||
|
retList.push(fin);
|
|||
|
}
|
|||
|
return JSON.stringify(retList);
|
|||
|
}
|
|||
|
|
|||
|
export function getFinalListPrivate(arg) {
|
|||
|
var retList = [];
|
|||
|
for (var i = 0; i < Global.listFinal.length; i++) {
|
|||
|
var fin = {};
|
|||
|
fin["item"] = Global.listFinal[i]["item"];
|
|||
|
fin["used"] = Global.listFinal[i]["used"];
|
|||
|
if (Global.bids[i]["bidder"]==requester && Global.bids[i]["seller"]==requester) {
|
|||
|
fin["seller"] = Global.listFinal[i]["seller"];
|
|||
|
fin["bidder"] = Global.listFinal[i]["bidder"];
|
|||
|
fin["sellerPrice"] = Global.listFinal[i]["sellerPrice"];
|
|||
|
fin["bidderPrice"] = Global.listFinal[i]["bidderPrice"];
|
|||
|
fin["result"] = Global.listFinal[i]["result"];
|
|||
|
fin["canExecute"] = true;
|
|||
|
retList.push(fin);
|
|||
|
fin["result"] = Global.listFinal[i]["result"];
|
|||
|
} else if (Global.bids[i]["bidder"]==requester) {
|
|||
|
fin["seller"] = "Anonymous";
|
|||
|
fin["bidder"] = Global.listFinal[i]["bidder"];
|
|||
|
fin["sellerPrice"] = "Unknown";
|
|||
|
fin["bidderPrice"] = Global.listFinal[i]["bidderPrice"];
|
|||
|
fin["result"] = Global.listFinal[i]["result"];
|
|||
|
fin["canExecute"] = true;
|
|||
|
retList.push(fin);
|
|||
|
} else if (Global.bids[i]["seller"]==requester) {
|
|||
|
fin["seller"] = Global.listFinal[i]["seller"];
|
|||
|
fin["bidder"] = "Anonymous";
|
|||
|
fin["sellerPrice"] = Global.listFinal[i]["sellerPrice"];
|
|||
|
fin["bidderPrice"] = "Unknown";
|
|||
|
fin["result"] = "Unknown";
|
|||
|
fin["canExecute"] = false;
|
|||
|
retList.push(fin);
|
|||
|
}
|
|||
|
}
|
|||
|
return JSON.stringify(retList);
|
|||
|
}
|
|||
|
}
|