agent-backend/contracts/Incentives/Incentives.yjs

359 lines
12 KiB
Plaintext
Raw Permalink Normal View History

2021-09-26 04:49:24 +00:00
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);
}
}