Files
consensus/NPoS/auctiondynamicthing.py
2019-05-09 15:52:06 +02:00

95 lines
3.6 KiB
Python

class auction:
def __init__(self):
#Note that ranges are intervals not slices;
#the lenth 1 range has start=end not end=start+1
self.ranges = [(start,end) for end in range(4) for start in range(end+1)]
self.winningbidsonranges=[(None,0) for _ in self.ranges]
def bid(self,bidid,start,end,amount,verbose=False):
if verbose:
print(bidid," bids ",amount," on [",start,",",end,"]")
#Bid should intersect with all winning bids by same bidder
for rangeotherbid in [i for i,w in zip(self.ranges,self.winningbidsonranges) if w[0]==bidid]:
if rangeotherbid[0] > end + 1 or rangeotherbid[1] + 1 < start:
if verbose:
print("Invalid bid as winning on [",rangeotherbid[0],",",rangeotherbid[1],"]")
return
rangeindex=self.ranges.index((start,end))
_,currentwinningbid=self.winningbidsonranges[rangeindex]
if amount > currentwinningbid:
self.winningbidsonranges[rangeindex] = (bidid,amount)
def bestbidonrangeandvalue(self,start,end):
rangeindex=self.ranges.index((start,end))
return ((self.winningbidsonranges[rangeindex][0],start,end), self.winningbidsonranges[rangeindex][1]*(end-start+1))
def calculatewinners(self):
bestwinnersendingat=[([],0) for _ in range(4)]
for i in range(4):
bidderrange,value=self.bestbidonrangeandvalue(0,i)
bestwinnersendingat[i]=([bidderrange],value)
for j in range(i):
bidderrange,value = self.bestbidonrangeandvalue(j+1,i)
value += bestwinnersendingat[j][1]
if value > bestwinnersendingat[i][1]:
newwinners=bestwinnersendingat[j][0]+[bidderrange]
bestwinnersendingat[i]=(newwinners,value)
return bestwinnersendingat[3]
def example1():
a=auction()
a.bid("x",0,3,1,True)
a.bid("a",0,0,2,True)
a.bid("a",2,2,53,True)
a.bid("b",1,1,1,True)
a.bid("c",2,2,1,True)
a.bid("d",3,3,1,True)
print(a.calculatewinners())
a.bid("x",0,3,2,True)
print(a.calculatewinners())
import unittest
class AuctionTests(unittest.TestCase):
def testbids(self):
a=auction();
#We could even allow zero bids but we don't now:
a.bid("a",0,3,0, False)
self.assertIsNone(a.bestbidonrangeandvalue(0,3)[0][0])
a.bid("a",0,3,1, False)
self.assertEqual(a.bestbidonrangeandvalue(0,3)[0][0],"a")
#Overlapping bids are fine
a.bid("a",0,0,1, False)
self.assertEqual(a.bestbidonrangeandvalue(0,0)[0][0],"a")
# Separated bids are not
a.bid("a",2,2,1, False)
self.assertIsNone(a.bestbidonrangeandvalue(2,2)[0][0])
# Contiguous can be
a.bid("a",1,1,1, False)
self.assertEqual(a.bestbidonrangeandvalue(1,1)[0][0],"a")
#Equal bids don't win
a.bid("b",0,3,1, False)
self.assertEqual(a.bestbidonrangeandvalue(0,3)[0][0],"a")
#Higher bids do
a.bid("b",0,3,2, False)
self.assertEqual(a.bestbidonrangeandvalue(0,3)[0][0],"b")
def testExample1(self):
a=auction()
a.bid("x",0,3,1)
a.bid("a",0,0,2)
a.bid("a",2,2,53)
a.bid("b",1,1,1)
a.bid("c",2,2,1)
a.bid("d",3,3,1)
self.assertEqual(a.calculatewinners(), ([('a', 0, 0), ('b', 1, 1), ('c', 2, 2), ('d', 3, 3)], 5))
a.bid("x",0,3,2)
self.assertEqual(a.calculatewinners(),([('x', 0, 3)], 8))