#!/usr/bin/python3

from math import exp, pow, factorial
from viewer import *

"""doc
	@method
	Prob_AccDataUnderTH:
		calculate the probability that i-th packet accumulate in T ms under threshold
	Prob_AccDataUnderTH:
		calculate the probability that i-th packet accumulate in T ms over threshold
	LengthAwkSlpCyl: calc awake-sleep-cycle, K (TTI)
	DataAcc: calc data accumulation, DataAcc (#packet)
"""
def Prob_AccDataUnderTH(lambd, threshold, simTime):
	threshold= int(threshold) if type(threshold) is float else threshold
	p_accumulate = 0

	while threshold >= 0:

		# p_accumulate += exp(-1*lambd*time)*pow(lambd*time, threshold)/factorial(threshold);
		tmp_p = exp(-1*lambd*simTime)

		# bug: exp value may too small to calc
		if tmp_p<=0:
			msg_warning("exp value is too small to calculate")
			return

		for i in range(1, threshold+1):
			tmp_p *= lambd*simTime/i

		p_accumulate += tmp_p;
		threshold -= 1

	# print("-	p_accumulate: %g" % p_accumulate)
	return p_accumulate

def Prob_AccDataOverTH(lambd, threshold, simTime):
	prob = Prob_AccDataUnderTH(lambd, threshold, simTime)
	return 1-prob if prob else 1

def LengthAwkSlpCyl(lambd, DATA_TH, PROB_TH= 0.8, view= None):

	# print("Calculating awake-sleep-cycle with DATA_TH(%d pkt), PROB_TH(%.2f)" % (DATA_TH, PROB_TH));
	K= 1			# ms
	d_K= dict()		# {K: prob}

	while True:

		p_acc= Prob_AccDataOverTH(lambd, DATA_TH, K)
		d_K[K]= p_acc
		# print("Get	prob: %f in %d TTI" % (p_acc, K))

		if p_acc > PROB_TH:
			break

		K+=1

	return d_K if view is True else K

def DataAcc(lambd, K, PROB_TH= 0.8, view= None):

	# print("Calculating number of packet accumulate in %d TTI with lambd %g (packet/ms)" %(K, lambd))
	pkt=0			# number of packet
	d_K= dict()		# {pkt: prob}

	while True:

		p_acc= Prob_AccDataUnderTH(lambd, pkt, K)
		d_K[pkt]= p_acc
		# print("Get	prob: %f in %d TTI only accumulate %d packet" % (p_acc, K, pkt))

		if not p_acc:
			msg_warning("exp value is too small to calculate")
			return

		if p_acc > PROB_TH:
			break

		pkt+= 1;

	return d_K if view is True else pkt;

def getDataTH(capacity, pkt_size, percent=0.8):
	return (capacity/pkt_size)*percent

if __name__ == "__main__":

	# For same UE, larger PROB_TH leads to larger K value
	# Fake UE info:
	#	bufSize= 8000 bits
	# 	lambd= (50 bit/ms) / pktSize (800 bits)
	#	DATA_TH= int(testUE.buf[testUE.status] * 0.8 / pktSize)= int(6400/800) = 8
	#	PROB_TH1= 0.8, PROB_TH2= 0.2
	lambd=50/800
	Data_TH=8
	P1=0.8
	P2=0.2

	K_star = LengthAwkSlpCyl(lambd, Data_TH, P1, True)
	K_caret = LengthAwkSlpCyl(lambd, Data_TH, P2, True)
	# K_caret = DataAcc(lambd, max(K_star), P1, True)

	print(max(K_star))
	print(max(K_caret))

	# plt.figure(1);
	# plt.title("Distribution of K_star and K_caret");
	# plt.xlabel("K(TTI)");
	# plt.ylabel("P");
	# plt.plot(sorted(K_star.keys()), sorted(K_star.values()), color= 'red');
	# plt.plot(sorted(K_caret.keys()), sorted(K_caret.values()), color= 'blue');
	# plt.grid(True);
	# plt.show()

@@ -1159,36 +1159,24 @@
 PROB_TH= 0.8
-, view= None
 ):%0A%0A%09# print
@@ -1283,34 +1283,8 @@
 # ms
-%0A%09d_K= dict()%09%09# %7BK: prob%7D
 %0A%0A%09w
@@ -1346,24 +1346,8 @@
  K)%0A
-%09%09d_K%5BK%5D= p_acc%0A
 %09%09# 
@@ -1444,33 +1444,8 @@
 urn 
-d_K if view is True else 
 K%0A%0Ad
@@ -1481,20 +1481,8 @@
  0.8
-, view= None
 ):%0A%0A
@@ -1612,36 +1612,8 @@
 cket
-%0A%09d_K= dict()%09%09# %7Bpkt: prob%7D
 %0A%0A%09w
@@ -1672,26 +1672,8 @@
  K)%0A
-%09%09d_K%5Bpkt%5D= p_acc%0A
 %09%09# 
@@ -1886,33 +1886,8 @@
 urn 
-d_K if view is True else 
 pkt;

iter L record