""" 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) })