187 lines
5.3 KiB
Python
187 lines
5.3 KiB
Python
"""
|
|
speed_calculator.py
|
|
チャットの勢いを算出するChatProcessor
|
|
Calculate speed of chat.
|
|
"""
|
|
import time
|
|
from .. chat_processor import ChatProcessor
|
|
|
|
|
|
class RingQueue:
|
|
"""
|
|
リング型キュー
|
|
|
|
Attributes
|
|
----------
|
|
items : list
|
|
格納されているアイテムのリスト。
|
|
first_pos : int
|
|
キュー内の一番古いアイテムを示すリストのインデックス。
|
|
last_pos : int
|
|
キュー内の一番新しいアイテムを示すリストのインデックス。
|
|
mergin : boolean
|
|
キュー内に余裕があるか。キュー内のアイテム個数が、キューの最大個数未満であればTrue。
|
|
"""
|
|
|
|
def __init__(self, capacity):
|
|
"""
|
|
コンストラクタ
|
|
|
|
Parameter
|
|
----------
|
|
capacity:このキューに格納するアイテムの最大個数。
|
|
格納時に最大個数を超える場合は一番古いアイテムから
|
|
上書きする。
|
|
"""
|
|
if capacity <= 0:
|
|
raise ValueError
|
|
self.items = list()
|
|
self.capacity = capacity
|
|
self.first_pos = 0
|
|
self.last_pos = 0
|
|
self.mergin = True
|
|
|
|
def put(self, item):
|
|
"""
|
|
引数itemに指定されたアイテムをこのキューに格納する。
|
|
キューの最大個数を超える場合は、一番古いアイテムの位置に上書きする。
|
|
|
|
Parameter
|
|
----------
|
|
item:格納するアイテム
|
|
"""
|
|
if self.mergin:
|
|
self.items.append(item)
|
|
self.last_pos = len(self.items) - 1
|
|
if self.last_pos == self.capacity - 1:
|
|
self.mergin = False
|
|
return
|
|
self.last_pos += 1
|
|
if self.last_pos > self.capacity - 1:
|
|
self.last_pos = 0
|
|
self.items[self.last_pos] = item
|
|
|
|
self.first_pos += 1
|
|
if self.first_pos > self.capacity - 1:
|
|
self.first_pos = 0
|
|
|
|
def get(self):
|
|
"""
|
|
キュー内の一番古いアイテムへの参照を返す
|
|
(アイテムは削除しない)
|
|
|
|
Return
|
|
----------
|
|
キュー内の一番古いアイテムへの参照
|
|
"""
|
|
return self.items[self.first_pos]
|
|
|
|
def item_count(self):
|
|
return len(self.items)
|
|
|
|
|
|
class SpeedCalculator(ChatProcessor, RingQueue):
|
|
"""
|
|
Calculate the momentum of the chat.
|
|
|
|
Divide the difference between the time of the first chat and
|
|
the time of the last chat in the chat data over a period of
|
|
time by the number of chats and convert it to speed per minute.
|
|
|
|
Parameter
|
|
----------
|
|
capacity : int
|
|
Maximum number of data for calculating chat momentum
|
|
to be stored in RingQueue.
|
|
"""
|
|
|
|
def __init__(self, capacity=10):
|
|
super().__init__(capacity)
|
|
self.speed = 0
|
|
|
|
def process(self, chat_components: list):
|
|
chatdata = []
|
|
if chat_components:
|
|
for component in chat_components:
|
|
if component.get("chatdata"):
|
|
chatdata.extend(component.get("chatdata"))
|
|
|
|
self._put_chatdata(chatdata)
|
|
self.speed = self._calc_speed()
|
|
return self.speed
|
|
|
|
def _calc_speed(self):
|
|
"""
|
|
Calculates the chat speed based on the data list for calculating
|
|
the chat momentum in RingQueue.
|
|
|
|
Return
|
|
---------------------------
|
|
Chat speed (number of chats converted per minute)
|
|
"""
|
|
try:
|
|
# Total number of chats in the queue
|
|
total = sum(item['chat_count'] for item in self.items)
|
|
# Interval between the first and last chats in the queue
|
|
duration = (self.items[self.last_pos]['endtime'] - self.items[self.first_pos]['starttime'])
|
|
if duration != 0:
|
|
return int(total * 60 / duration)
|
|
return 0
|
|
except IndexError:
|
|
return 0
|
|
|
|
def _put_chatdata(self, actions):
|
|
"""
|
|
Parameter
|
|
---------
|
|
actions : List[dict]
|
|
List of addChatItemActions
|
|
"""
|
|
def _put_emptydata():
|
|
timestamp_now = int(time.time())
|
|
self.put({
|
|
'chat_count': 0,
|
|
'starttime': int(timestamp_now),
|
|
'endtime': int(timestamp_now)
|
|
})
|
|
|
|
def _get_timestamp(action: dict):
|
|
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:
|
|
_put_emptydata()
|
|
return
|
|
|
|
counter = 0
|
|
starttime = None
|
|
endtime = None
|
|
|
|
for action in actions:
|
|
# Get timestampUsec from chatdata
|
|
gettime = _get_timestamp(action)
|
|
|
|
if gettime is None:
|
|
continue
|
|
|
|
if starttime is None:
|
|
starttime = gettime
|
|
|
|
endtime = gettime
|
|
|
|
counter += 1
|
|
|
|
if starttime is None or endtime is None:
|
|
_put_emptydata()
|
|
return
|
|
|
|
self.put({
|
|
'chat_count': counter,
|
|
'starttime': int(starttime / 1000000),
|
|
'endtime': int(endtime / 1000000)
|
|
})
|