Scorum
|
Here are some details and insights abount how advertising budgets work.
User can specify arbitrary start_time
and deadline
with no reference to blockchain blocks interval. So we need to align (if they weren't aligned) these parameters by blockchain block interval which is equal 3 sec for now.
Let's say genesis time (block #0) is 0 sec and each following block time is greater then previous block time for 3 sec.
Block time (+sec) | +0 | +3 | +6 | +9 | +12 | +15 |
Block # | 0 | 1 | 2 | 3 | 4 | 5 |
Let's say start_time
equals 2sec and deadline
equals 10sec, i.e. start_time
is in between block #0 and block #1 and deadline
is in between block #3 and block #4. In such cases both start_time
and deadline
will be aligned by greater bound i.e. in this case budget will start in block #1 and ends in block #4.
Block time (+sec) | +0 | +3 | +6 | +9 | +12 | +15 |
Block # | 0 | 1 | 2 | 3 | 4 | 5 |
Budget bounds | start | - | - | finish | 5 | |
When created | x |
Let's say we have already aligned start_time
and deadline
. Is they are not then we will align them using method described start_time and deadline alignment section.
In order to evaluate per_block payment we need to divide budget balance on per_block payments count which, in turn, equals:
I.e. per block payment equals:
Fox example, if budget balance equals 100 SCR, start_time
equals 3sec and deadline
equals 12 sec, then there will be 4 payments by 25 SCR each in blocks #1,#2,#3,#4.
NOTE: Payments are also occurred in block #1 where budget starts and in block #4 where budgets ends.
Block time (+sec) | +0 | +3 | +6 | +9 | +12 | +15 |
Block # | 0 | 1 | 2 | 3 | 4 | 5 |
Budget bounds | start | - | - | finish | ||
Budget balance | 100 | 75 | 50 | 25 | 0 | |
When created | x | |||||
When started | x | |||||
Payment occurred | x | x | x | x | ||
Payment amount | 25 | 25 | 25 | 25 |
In this case start_time
will be aligned to the next block time after head block (see start_time and deadline alignment). If no blocks were missed then start_time
will be equal to current applying block time.
Let's say we are creating budget in block #2 (+6 sec) with start_time
which equals 1 sec and deadline
which equals 12 sec. In this case start_time
will be aligned to block #1 and will be equal 3 sec.
Block time (+sec) | +0 | +3 | +6 | +9 | +12 | +15 | +18 | ||
Time (+sec) | +0 | +3 | +4 | +5 | +6 | +9 | +12 | +15 | +18 |
Block # | 0 | 1 | 2 | 3 | 4 | 5 | 6 | ||
Not aligned budget bounds | start | finish | |||||||
Aligned budget bounds | start | - | - | finish | |||||
When created | x | ||||||||
When started | x | ||||||||
Payment occured | x | x | x | x | |||||
Budget balance | 75 | 50 | 25 | 0 | |||||
Payment amount | 25 | 25 | 25 | 25 |
If (during budget creation) previous block is missed and start_time
equal 1 sec then start_time
will be aligned to 3 sec and per block payment will be equal [100 / ((15 - 3) / 3 + 1)]
i.e. 20 SCR. 20 SCR will be returned to owner after budget will close.
NOTE:
- Per block payment is evaluated to 20 SCR (based on
start_time
anddeadline
)- Budget balance isn't empty after 3rd payment and 20 SCR should be returned to budget's owner.
Block time (+sec) | +0 | +6 | +9 | +12 | +15 | +18 | |||
Time (+sec) | +0 | +1 | +2 | +3 | +6 | +9 | +12 | +15 | +18 |
Block # | 0 | missed | 1 | 2 | 3 | 4 | 5 | ||
Not aligned budget bounds | start | finish | |||||||
Aligned budget bounds | start | - | - | - | finish | ||||
When created | x | ||||||||
When started | x | ||||||||
Payment occured | x | x | x | x | |||||
Budget balance | 100 | 80 | 60 | 40 | 20 | ||||
Payment amount | 20 | 20 | 20 | 20 |
We can say that
start_time
means that budget won't start before this time but it could start after this timestamp because of missed blocks.
In order to optimize budget payments events count and do not overload blockchain with tons of events we decided to accumulate all payments from advertising auction in special pending buffers. There are two of them in each budget. The first one accumulates SCR which should be returned to owners account(owner_pending_income). The second one accumulates SCR which should be transferred to dev pool and activity reward pool (budget_pending_outgo). Each week starting from previous cashout all cash from first pending buffer goes to budget's owner and all cash from second pending buffer is distributed across dev pool and activity reward pool.
If deadline
occurs earlier than next cashout then we are performing cashout immediately in current block and closing budget.
Let's say we are starting budget with such specs:
deadline
in block #12[1210 / ((36 - 3) / 3 + 1)]
i.e. 100 SCRNOTE: Budget balance do not divide completely on per block counts so the rest (which is equal 10 SCR) will be returned to owner after budget will be closed.
Block time (+sec) | +0 | +3 | +6 | +9 | +12 | +15 | +18 | +21 | +24 | +27 | +30 | +33 | +36 | +39 |
Block # | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
Budget bounds | start | - | - | - | - | - | - | - | - | - | - | finish | ||
When created | x | |||||||||||||
Payment occured | x | x | x | x | x | x | x | x | x | x | x | x | ||
Cashout occured | x | x | x | |||||||||||
Budget outgo | 80 | 160 | 240 | 320 | 0 | 80 | 160 | 240 | 320 | 0 | 80 | 0 | ||
Owner income | 20 | 40 | 60 | 80 | 0 | 20 | 40 | 60 | 80 | 0 | 20 | 0 | ||
Budget balance | 1210 | 1110 | 1010 | 910 | 810 | 710 | 610 | 510 | 410 | 310 | 210 | 110 | 0 | |
Owner balance | 790 | 790 | 790 | 790 | 790 | 890 | 890 | 890 | 890 | 890 | 990 | 990 | 1040 | |
Dev + reward pool | 0 | 0 | 0 | 0 | 0 | 400 | 400 | 400 | 400 | 400 | 800 | 800 | 960 |
First of all this is a valid case and budget will be created.
Per block payment will equal all budget's balance. Such budget can participate advertising auction.
After auction such budget will be closed.
Our web platform has various places to put advertising on it. Some of these places are better, some are worse. Advertisers which are ready to pay max value obtain better place for its' ads. Each advertising place has its own coefficient from 1 to 100.
Let's say we have:
N
budgets (N >= 0
)M
auction coefficients (M >= 1
)Algorithm:
BCNT
) which will participate in auction as BCNT = min(N,M)
spent_amount
for each budget like for (i = BCNT-1; i >=0; --i)
(from min per_block to max):i == BCNT-1 and N > BCNT
then spent_amount[i] = per_block[i+1]
i == BCNT-1 and N == BCNT
then spent_amount[i] = per_block[i]
spent_amount[i] = min(spent_amount[i+1] + per_block[i+1]*(coeff[i] - coeff[i+1])/coeff[0], per_block[i])