-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprotocol_function.py
190 lines (143 loc) · 5.37 KB
/
protocol_function.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import math
class BidInfo(object):
def __init__(self, tokens,reputation,stake,userId,contributionsSize):
self.tokens = float(tokens)
self.reputation = float(reputation)
self.stake = float(stake)
self.userId = userId
self.contributionsSize = contributionsSize
def debug(self,logger):
if(logger):
logger.info('tokens: '+str(self.tokens))
logger.info('reputation: '+str(self.reputation))
logger.info('stake: '+str(self.stake))
logger.info('userId: '+str(self.userId))
class FIn(object):
def __init__(self, bids,current_bid,total_rep,a,contributionsSize):
self.bids = bids
self.current_bid = current_bid
self.total_system_reputation = total_rep
self.a = a
self.contributionsSize = contributionsSize
def isValid(self):
if (not self.bids or
not self.total_system_reputation or
not self) and (self.contributionsSize > 1):
return False
return True
def debug(self,logger):
if(logger):
logger.info('\n')
logger.info('F input:')
"""
logger.info('bids:')
for bid in self.bids:
bid.debug(logger)
"""
logger.info('current bid: ')
self.current_bid.debug(logger)
logger.info('total system reputation: '+str(self.total_system_reputation))
return True
class FOut(object):
def __init__(self):
self.evaluation = None
self.rep_distributions = {}
self.error_occured = False
self.error_code = None
def debug(self,logger):
if(logger):
logger.info('\n')
logger.info('F output:')
logger.info('---- reputation distribution between owners:'+str(self.rep_distributions))
logger.info('---- current evaluation: '+str(self.evaluation))
return True
class AbstractProtocolFunction(object):
def execute(self,fIn):
pass
class ProtocolFunctionV1(AbstractProtocolFunction):
def __init__(self,logger = None):
self.logger = logger
def log(self,messsage,level = 'info'):
if(self.logger):
self.logger.info(messsage)
return True
def decay(self,vi, vn,a):
#decay = math.atan(1 / abs(vi - vn+0.1))
decay = math.atan(1/(pow(10,(int(a)/50))*abs(vi-vn)/(min(vi,vn)+0.00001)+0.0001))/1.57
return decay
def distribute_current_bid_rep(self,fIn,fout):
current_bid = fIn.current_bid
bids = fIn.bids
summ = 0;
#calculate total sum of Weight * Decay
for bid in bids:
summ += bid.reputation * self.decay(bid.tokens, current_bid.tokens,fIn.a)
#self.log("sum of Weight * Decay = " + str(summ))
#reallocate reputation
self.log("\n")
self.log(" ---- total rep to be distributed (current_bid.stake) === " + str(current_bid.stake))
for bid in bids:
current_decay = self.decay(bid.tokens, current_bid.tokens,fIn.a)
if fIn.contributionsSize > 1 :
new_rep_weight = ( bid.reputation * current_decay ) / summ
else:
new_rep_weight = 0
# bug fix: we round up and thus create reputation from thin air
#bidders_rep_distribution = math.ceil(float(current_bid.stake) * new_rep_weight )
bidders_rep_distribution = current_bid.stake * new_rep_weight
fout.rep_distributions[str(bid.userId)] = bidders_rep_distribution
# debug:
self.log("\n")
self.log("calculating reputation distibution for bidder :" + str(bid.userId))
self.log("bidders evaluation: = " + str(bid.tokens) + ", current bid = " + str(current_bid.tokens))
self.log("calculated decay = " + str(current_decay))
self.log('new reputation percentage :'+str(new_rep_weight))
self.log("---- current bidders reputation distribution === " + str(bidders_rep_distribution))
return True
def calcCurrentEvaluation(self,fIn,fout):
self.log("calculating current evaluation:")
bids = fIn.bids
if fIn.contributionsSize == 1 :
for bid in bids:
current_evaluation = bid.tokens
fout.evaluation = current_evaluation
return True
# get reputation on zero (un-invested reputation)
total_invested_rep = 0
for bid in bids:
total_invested_rep = total_invested_rep + bid.reputation
uninvested_rep = fIn.total_system_reputation - total_invested_rep
# Sort by tokens : (To sort the list in place...)
bids.sort(key=lambda x: x.tokens, reverse=False)
#bids_sorted_by_tokens = sorted(bids, key=lambda bid: bid.tokens, reverse=False)
# check if we passed 50% of total rep in system if so we hit the median:
if( uninvested_rep > fIn.total_system_reputation/2 ):
# we hit the median so update current bid with current evaluation:
self.log("uninvested_rep is greater than median - evaluation is 0.")
fout.evaluation = 0
return True
acumulated_rep = uninvested_rep
for bid in bids:
acumulated_rep = acumulated_rep + bid.reputation
# check if we passed 50% of total rep in system if so we hit the median:
if( acumulated_rep > fIn.total_system_reputation/2 ):
# we hit the median so update current bid with current evaluation:
current_evaluation = bid.tokens
fout.evaluation = current_evaluation
self.log("acumulated_rep is greater than median - evaluation is :"+str(fout.evaluation))
return True
fout.evaluation = None
fout.error_occured = True
fout.error_code = "current evaluation - calculation error."
return True
def execute(self,fin):
fout = FOut()
if (not fin.isValid()):
fout.error_occured = True
fout.error_code = "input invalid."
return fout
fin.debug(self.logger)
self.distribute_current_bid_rep(fin,fout)
self.calcCurrentEvaluation(fin,fout)
fout.debug(self.logger)
return fout