Fix calculation algorithm

This commit is contained in:
taizan-hokuto
2019-12-21 20:06:55 +09:00
parent 18666199b7
commit 5a79f26fa7
5 changed files with 86 additions and 41 deletions

View File

@@ -21,7 +21,7 @@ class RingQueue:
キュー内に余裕があるか。キュー内のアイテム個数が、キューの最大個数未満であればTrue。 キュー内に余裕があるか。キュー内のアイテム個数が、キューの最大個数未満であればTrue。
""" """
def __init__(self, capacity = 10): def __init__(self, capacity):
""" """
コンストラクタ コンストラクタ
@@ -82,29 +82,29 @@ class SpeedCalculator(ChatProcessor, RingQueue):
チャットの勢いを計算するクラス チャットの勢いを計算するクラス
Parameter Parameter
---------- ----------
capacity : int
格納するチャットブロックの数 格納するチャットブロックの数
""" """
def __init__(self, capacity, video_id): def __init__(self, capacity = 10):
super().__init__(capacity) super().__init__(capacity)
self.video_id=video_id
self.speed = 0 self.speed = 0
def process(self, chat_components: list): def process(self, chat_components: list):
chatdata = []
if chat_components: if chat_components:
for component in chat_components: for component in chat_components:
if component.get("chatdata"):
chatdata = component.get('chatdata') chatdata.extend(component.get("chatdata"))
if chatdata is None:
return self.speed
self.speed = self.calc(chatdata)
return self.speed
def _value(self): self._put_chatdata(chatdata)
self.speed = self._calc_speed()
return self.speed
def _calc_speed(self):
""" """
ActionsQueue内のチャットデータリストから、 RingQueue内のチャットデータリストから、
チャット速度を計算して返す チャット速度を計算して返す
Return Return
@@ -123,24 +123,19 @@ class SpeedCalculator(ChatProcessor, RingQueue):
except IndexError: except IndexError:
return 0 return 0
def _get_timestamp(self, action :dict): def _put_chatdata(self,actions):
""" """
チャットデータのtimestampUsecを読み取る チャットデータからタイムスタンプを読み取り、RingQueueに投入する。
liveChatTickerSponsorItemRenderer等のtickerデータは時刻格納位置が Parameter
異なるため、時刻データなしとして扱う ---------
actions : List[dict]
チャットデータ(addChatItemAction) のリスト
""" """
try: def _put_emptydata():
item = action['addChatItemAction']['item']
timestamp = int(item[list(item.keys())[0]]['timestampUsec'])
except (KeyError,TypeError):
return None
return timestamp
def calc(self,actions):
def empty_data():
''' '''
データがない場合にゼロのデータをリングキューに入れる enqueue empty data when no chat data.
Return: int
speed value after enqueueing empty data
''' '''
timestamp_now = calendar.timegm(datetime.datetime. timestamp_now = calendar.timegm(datetime.datetime.
now(pytz.utc).utctimetuple()) now(pytz.utc).utctimetuple())
@@ -149,10 +144,21 @@ class SpeedCalculator(ChatProcessor, RingQueue):
'starttime':int(timestamp_now), 'starttime':int(timestamp_now),
'endtime':int(timestamp_now) 'endtime':int(timestamp_now)
}) })
return self._value()
def _get_timestamp(action :dict):
"""
チャットデータのtimestampUsecを読み取る
"""
try:
item = action['addChatItemAction']['item']
timestamp = int(item[list(item.keys())[0]]['timestampUsec'])
except (KeyError,TypeError):
return None
return timestamp
if actions is None or len(actions)==0: if actions is None or len(actions)==0:
return empty_data _put_emptydata()
return
#actions内の時刻データを持つチャットデータの数tickerは除く #actions内の時刻データを持つチャットデータの数tickerは除く
counter=0 counter=0
@@ -163,7 +169,7 @@ class SpeedCalculator(ChatProcessor, RingQueue):
for action in actions: for action in actions:
#チャットデータからtimestampUsecを読み取る #チャットデータからtimestampUsecを読み取る
gettime = self._get_timestamp(action) gettime = _get_timestamp(action)
#時刻のないデータだった場合は次の行のデータで読み取り試行 #時刻のないデータだった場合は次の行のデータで読み取り試行
if gettime is None: if gettime is None:
@@ -177,11 +183,12 @@ class SpeedCalculator(ChatProcessor, RingQueue):
endtime = gettime endtime = gettime
#チャットの数をインクリメント #チャットの数をインクリメント
counter+=1 counter += 1
#チャット速度用のデータをリングキューに送る #チャット速度用のデータをリングキューに送る
if starttime is None or endtime is None: if starttime is None or endtime is None:
return empty_data _put_emptydata()
return
self.put({ self.put({
'chat_count':counter, 'chat_count':counter,
@@ -189,4 +196,3 @@ class SpeedCalculator(ChatProcessor, RingQueue):
'endtime':int(endtime/1000000) 'endtime':int(endtime/1000000)
}) })
return self._value()

View File

@@ -12,14 +12,14 @@ from pytchat.processors.speed_calculator import SpeedCalculator
parser = Parser() parser = Parser()
def test_speed_1(mocker): def test_speed_1(mocker):
'''test speed normal '''test speed calculation with normal json.
test json has 15 chatdata, duration is 30 seconds, test json has 15 chatdata, duration is 30 seconds,
so the speed of chatdata is 30 chats/minute. so the speed of chatdata is 30 chats/minute.
''' '''
processor = SpeedCalculator(capacity=30,video_id="") processor = SpeedCalculator(capacity=30)
_json = _open_file("tests/testdata/speed/speedtest1.json") _json = _open_file("tests/testdata/speed/speedtest_normal.json")
_, chatdata = parser.parse(json.loads(_json)) _, chatdata = parser.parse(json.loads(_json))
data = { data = {
@@ -31,13 +31,27 @@ def test_speed_1(mocker):
assert 30 == ret assert 30 == ret
def test_speed_2(mocker): def test_speed_2(mocker):
'''test speed with no valid chat data '''test speed calculation with no valid chat data.
''' '''
processor = SpeedCalculator(capacity=30)
processor = SpeedCalculator(capacity=30,video_id="") _json = _open_file("tests/testdata/speed/speedtest_undefined.json")
_json = _open_file("tests/testdata/speed/speedtest_none.json") _, chatdata = parser.parse(json.loads(_json))
data = {
"video_id" : "",
"timeout" : 10,
"chatdata" : chatdata
}
ret = processor.process([data])
assert 0 == ret
def test_speed_3(mocker):
'''test speed calculation with empty data.
'''
processor = SpeedCalculator(capacity=30)
_json = _open_file("tests/testdata/speed/speedtest_empty.json")
_, chatdata = parser.parse(json.loads(_json)) _, chatdata = parser.parse(json.loads(_json))
data = { data = {
@@ -52,3 +66,4 @@ def test_speed_2(mocker):
def _open_file(path): def _open_file(path):
with open(path,mode ='r',encoding = 'utf-8') as f: with open(path,mode ='r',encoding = 'utf-8') as f:
return f.read() return f.read()
_put_chatdata

View File

@@ -0,0 +1,24 @@
{
"timing": {
"info": {
"st": 164
}
},
"csn": "",
"response": {
"responseContext": {
},
"continuationContents": {
"liveChatContinuation": {
"continuations": [{
"timedContinuationData": {
"timeoutMs": 10000,
"continuation": "continuation"
}
}]
}
}
}
}