From 5d9f1fcc26d9090e2250fc39543dbff00abf8d3a Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Fri, 17 Jun 2016 06:32:46 +0300 Subject: add basic "online periods" extraction --- vk/user.py | 17 +++++++-- vk/utils/tracking/__init__.py | 3 +- vk/utils/tracking/db/record.py | 13 ++++++- vk/utils/tracking/online_periods.py | 59 ++++++++++++++++++++++++++++++ vk/utils/tracking/utils/how_much_online.py | 6 ++- 5 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 vk/utils/tracking/online_periods.py diff --git a/vk/user.py b/vk/user.py index 80702f6..c2ed623 100644 --- a/vk/user.py +++ b/vk/user.py @@ -93,10 +93,10 @@ class LastSeen(MutableMapping): def __delitem__(self, field): del self._fields[field] - def __iter__(self, field): + def __iter__(self): return iter(self._fields) - def __len__(self, field): + def __len__(self): return len(self._fields) @staticmethod @@ -199,9 +199,20 @@ class User(Hashable, MutableMapping): else: raise TypeError() + def _parse_bool(x): + if isinstance(x, str): + if str(True) == x: + return True + elif str(False) == x: + return False + else: + raise ValueError() + else: + return bool(x) + _FIELD_PARSERS = { UserField.UID: int, - UserField.ONLINE: bool, + UserField.ONLINE: _parse_bool, UserField.LAST_SEEN: _parse_last_seen, } diff --git a/vk/utils/tracking/__init__.py b/vk/utils/tracking/__init__.py index 2e8b02e..8934d94 100644 --- a/vk/utils/tracking/__init__.py +++ b/vk/utils/tracking/__init__.py @@ -2,6 +2,7 @@ # This file is licensed under the terms of the MIT License. # See LICENSE.txt for details. +from .online_periods import OnlinePeriodEnumerator from .status_tracker import StatusTracker -__all__ = 'status_tracker', +__all__ = 'online_periods', 'status_tracker', diff --git a/vk/utils/tracking/db/record.py b/vk/utils/tracking/db/record.py index fd684cc..fd276fc 100644 --- a/vk/utils/tracking/db/record.py +++ b/vk/utils/tracking/db/record.py @@ -102,14 +102,23 @@ class Record(MutableMapping): assert False return record + def _update_last_seen_field(self, last_seen, field): + if field is LastSeenField.TIME: + last_seen[field] = self[field].dt + else: + last_seen[field] = self[field] + + def _update_user_field(self, user, field): + user[field] = self[field] + def to_user(self): user = User() last_seen = LastSeen() for field in self: if isinstance(field, LastSeenField): - last_seen[field] = self[field] + self._update_last_seen_field(last_seen, field) elif isinstance(field, UserField): - user[field] = self[field] + self._update_user_field(user, field) else: assert False if len(last_seen): diff --git a/vk/utils/tracking/online_periods.py b/vk/utils/tracking/online_periods.py new file mode 100644 index 0000000..9a99863 --- /dev/null +++ b/vk/utils/tracking/online_periods.py @@ -0,0 +1,59 @@ +# Copyright 2016 Egor Tensin +# This file is licensed under the terms of the MIT License. +# See LICENSE.txt for details. + +from collections.abc import MutableMapping + +from vk.user import User + +class OnlinePeriodEnumerator(MutableMapping): + def __init__(self): + self._records_by_user = {} + + def __getitem__(self, key): + return self._records_by_user[self._normalize_key(key)] + + def __setitem__(self, key, value): + self._records_by_user[self._normalize_key(key)] = value + + def __delitem__(self, key): + del self._records_by_user[self._normalize_key(key)] + + def __iter__(self): + return iter(self._records_by_user) + + def __len__(self): + return len(self._records_by_user) + + @staticmethod + def _normalize_key(key): + return key.get_uid() if isinstance(key, User) else key + + def enum(self, db_reader): + for record in db_reader: + period = self._insert_record(record) + #print(period) + if period is not None: + yield period + + def _insert_record(self, record): + return self._insert_user(record.to_user()) + + def _known_user(self, user): + return user.get_uid() in self._records_by_user + + def _unknown_user(self, user): + return not self._known_user(user) + + def _insert_user(self, user): + if user not in self or self[user].is_offline(): + self[user] = user + #print(2) + return None + if user.is_online(): + #print(3) + print(user._fields) + return None + period = user, self[user].get_last_seen_time(), user.get_last_seen_time() + self[user] = user + return period diff --git a/vk/utils/tracking/utils/how_much_online.py b/vk/utils/tracking/utils/how_much_online.py index c1cf05f..2526f76 100644 --- a/vk/utils/tracking/utils/how_much_online.py +++ b/vk/utils/tracking/utils/how_much_online.py @@ -2,6 +2,7 @@ # This file is licensed under the terms of the MIT License. # See LICENSE.txt for details. +from vk.utils.tracking import OnlinePeriodEnumerator from vk.utils.tracking.db.reader import * if __name__ == '__main__': @@ -14,5 +15,6 @@ if __name__ == '__main__': args = parser.parse_args() with csv.Reader(args.input) as csv_reader: - for record in csv_reader: - print(record.get_timestamp()) + for online_period in OnlinePeriodEnumerator().enum(csv_reader): + user, dt_from, dt_to = online_period + print(user.get_screen_name(), dt_from.isoformat(), dt_to.isoformat()) -- cgit v1.2.3