mirror of
https://gitee.com/BDWare/agent-backend
synced 2025-01-10 18:04:13 +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);
|
||
}
|
||
} |