<s> from __future__ import division <EOL> import datetime <EOL> from collections import Counter <EOL> from bandicoot . helper . tools import Colors <EOL> from bandicoot . helper . group import _binning <EOL> import bandicoot as bc <EOL> class Record ( object ) : <EOL> """<STR_LIT>""" <EOL> __slots__ = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> def __init__ ( self , interaction , direction , correspondent_id , datetime , call_duration , position ) : <EOL> self . interaction = interaction <EOL> self . direction = direction <EOL> self . correspondent_id = correspondent_id <EOL> self . datetime = datetime <EOL> self . call_duration = call_duration <EOL> self . position = position <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" + "<STR_LIT:U+002CU+0020>" . join ( map ( lambda x : "<STR_LIT>" % ( x , getattr ( self , x ) ) , self . __slots__ ) ) + "<STR_LIT:)>" <EOL> def __eq__ ( self , other ) : <EOL> if isinstance ( other , self . __class__ ) and self . __slots__ == other . __slots__ : <EOL> return all ( getattr ( self , attr ) == getattr ( other , attr ) for attr in self . __slots__ ) <EOL> return False <EOL> def __hash__ ( self ) : <EOL> return hash ( self . __repr__ ( ) ) <EOL> def matches ( self , other ) : <EOL> """<STR_LIT>""" <EOL> return self . interaction == other . interaction and self . direction != other . direction and self . call_duration == other . call_duration and abs ( ( self . datetime - other . datetime ) . total_seconds ( ) ) < <NUM_LIT:30> <EOL> def all_matches ( self , iterable ) : <EOL> return filter ( self . matches , iterable ) <EOL> def has_match ( self , iterable ) : <EOL> return len ( self . all_matches ( iterable ) ) > <NUM_LIT:0> <EOL> class Position ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , antenna = None , location = None ) : <EOL> self . antenna = antenna <EOL> self . location = location <EOL> def _get_location ( self , user ) : <EOL> if self . location : <EOL> return self . location <EOL> elif self . antenna : <EOL> return user . antennas . get ( self . antenna ) <EOL> else : <EOL> return None <EOL> def type ( self ) : <EOL> if self . antenna : <EOL> return '<STR_LIT>' <EOL> else : <EOL> return '<STR_LIT>' <EOL> def __repr__ ( self ) : <EOL> if self . antenna and self . location : <EOL> return "<STR_LIT>" % ( self . antenna , self . location ) <EOL> if self . antenna : <EOL> return "<STR_LIT>" % self . antenna <EOL> if self . location : <EOL> return "<STR_LIT>" % self . location <EOL> return "<STR_LIT>" <EOL> def __eq__ ( self , other ) : <EOL> if not isinstance ( other , Position ) : <EOL> return False <EOL> if self . antenna and other . antenna : <EOL> return self . antenna == other . antenna <EOL> if self . location and other . location : <EOL> return self . location == other . location <EOL> if not self . location and not self . antenna and not other . location and not other . antenna : <EOL> return True <EOL> return False <EOL> def __ne__ ( self , other ) : <EOL> return not self . __eq__ ( other ) <EOL> def __hash__ ( self ) : <EOL> return hash ( self . __repr__ ( ) ) <EOL> class User ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . _records = [ ] <EOL> self . _antennas = { } <EOL> self . name = None <EOL> self . antennas_path = None <EOL> self . attributes_path = None <EOL> self . start_time = None <EOL> self . end_time = None <EOL> self . night_start = datetime . time ( <NUM_LIT> ) <EOL> self . night_end = datetime . time ( <NUM_LIT:7> ) <EOL> self . weekend = [ <NUM_LIT:6> , <NUM_LIT:7> ] <EOL> self . home = None <EOL> self . has_text = False <EOL> self . has_call = False <EOL> self . has_antennas = False <EOL> self . attributes = { } <EOL> self . ignored_records = None <EOL> self . percent_outofnetwork_calls = <NUM_LIT:0> <EOL> self . percent_outofnetwork_texts = <NUM_LIT:0> <EOL> self . percent_outofnetwork_contacts = <NUM_LIT:0> <EOL> self . percent_outofnetwork_call_durations = <NUM_LIT:0> <EOL> self . network = { } <EOL> @ property <EOL> def antennas ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _antennas <EOL> @ antennas . setter <EOL> def antennas ( self , input_ ) : <EOL> self . _antennas = input_ <EOL> self . has_antennas = len ( input_ ) > <NUM_LIT:0> <EOL> for r in self . _records : <EOL> if r . position . antenna in self . _antennas : <EOL> r . position . location = self . _antennas [ r . position . antenna ] <EOL> else : <EOL> r . position . location = None <EOL> @ property <EOL> def records ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _records <EOL> @ records . setter <EOL> def records ( self , input ) : <EOL> self . _records = sorted ( input , key = lambda r : r . datetime ) <EOL> if len ( self . _records ) > <NUM_LIT:0> : <EOL> self . start_time = self . _records [ <NUM_LIT:0> ] . datetime <EOL> self . end_time = self . _records [ - <NUM_LIT:1> ] . datetime <EOL> self . has_call = False <EOL> self . has_text = False <EOL> self . has_antennas = False <EOL> for r in self . _records : <EOL> if r . interaction == '<STR_LIT:text>' : <EOL> self . has_text = True <EOL> elif r . interaction == '<STR_LIT>' : <EOL> self . has_call = True <EOL> if r . position . type ( ) == '<STR_LIT>' : <EOL> self . has_antennas = True <EOL> self . recompute_home ( ) <EOL> def recompute_missing_neighbors ( self ) : <EOL> """<STR_LIT>""" <EOL> oon_records = [ r for r in self . records if self . network . get ( r . correspondent_id , None ) is None ] <EOL> num_oon_calls = len ( [ r for r in oon_records if r . interaction == '<STR_LIT>' ] ) <EOL> num_oon_texts = len ( [ r for r in oon_records if r . interaction == '<STR_LIT:text>' ] ) <EOL> num_oon_neighbors = len ( set ( x . correspondent_id for x in oon_records ) ) <EOL> oon_call_durations = sum ( [ r . call_duration for r in oon_records if r . interaction == '<STR_LIT>' ] ) <EOL> num_calls = len ( [ r for r in self . records if r . interaction == '<STR_LIT>' ] ) <EOL> num_texts = len ( [ r for r in self . records if r . interaction == '<STR_LIT:text>' ] ) <EOL> total_neighbors = len ( set ( x . correspondent_id for x in self . records ) ) <EOL> total_call_durations = sum ( [ r . call_duration for r in self . records if r . interaction == '<STR_LIT>' ] ) <EOL> def _safe_div ( a , b , default ) : <EOL> return a / b if b != <NUM_LIT:0> else default <EOL> self . percent_outofnetwork_calls = _safe_div ( num_oon_calls , num_calls , <NUM_LIT:0> ) <EOL> self . percent_outofnetwork_texts = _safe_div ( num_oon_texts , num_texts , <NUM_LIT:0> ) <EOL> self . percent_outofnetwork_contacts = _safe_div ( num_oon_neighbors , total_neighbors , <NUM_LIT:0> ) <EOL> self . percent_outofnetwork_call_durations = _safe_div ( oon_call_durations , total_call_durations , <NUM_LIT:0> ) <EOL> def describe ( self ) : <EOL> """<STR_LIT>""" <EOL> def format_int ( name , n ) : <EOL> if n == <NUM_LIT:0> or n == <NUM_LIT:1> : <EOL> return "<STR_LIT>" % ( n , name [ : - <NUM_LIT:1> ] ) <EOL> else : <EOL> return "<STR_LIT>" % ( n , name ) <EOL> empty_box = Colors . OKGREEN + '<STR_LIT>' + Colors . ENDC + '<STR_LIT:U+0020>' <EOL> filled_box = Colors . OKGREEN + '<STR_LIT>' + Colors . ENDC + '<STR_LIT:U+0020>' <EOL> if self . start_time is None : <EOL> print empty_box + "<STR_LIT>" <EOL> else : <EOL> print ( filled_box + format_int ( "<STR_LIT>" , len ( self . records ) ) + <EOL> "<STR_LIT>" % ( self . start_time , self . end_time ) ) <EOL> nb_contacts = bc . individual . number_of_contacts ( self , interaction = '<STR_LIT>' , groupby = None ) <EOL> nb_contacts = nb_contacts [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> if nb_contacts : <EOL> print filled_box + format_int ( "<STR_LIT>" , nb_contacts ) <EOL> else : <EOL> print empty_box + "<STR_LIT>" <EOL> if self . has_attributes : <EOL> print filled_box + format_int ( "<STR_LIT>" , len ( self . attributes ) ) <EOL> else : <EOL> print empty_box + "<STR_LIT>" <EOL> if len ( self . antennas ) == <NUM_LIT:0> : <EOL> print empty_box + "<STR_LIT>" <EOL> else : <EOL> print filled_box + format_int ( "<STR_LIT>" , len ( self . antennas ) ) <EOL> if self . has_home : <EOL> print filled_box + "<STR_LIT>" <EOL> else : <EOL> print empty_box + "<STR_LIT>" <EOL> if self . has_text : <EOL> print filled_box + "<STR_LIT>" <EOL> else : <EOL> print empty_box + "<STR_LIT>" <EOL> if self . has_call : <EOL> print filled_box + "<STR_LIT>" <EOL> else : <EOL> print empty_box + "<STR_LIT>" <EOL> if self . has_network : <EOL> print filled_box + "<STR_LIT>" <EOL> else : <EOL> print empty_box + "<STR_LIT>" <EOL> def recompute_home ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . night_start < self . night_end : <EOL> night_filter = lambda r : self . night_end > r . datetime . time ( ) > self . night_start <EOL> else : <EOL> night_filter = lambda r : not ( self . night_end < r . datetime . time ( ) < self . night_start ) <EOL> candidates = list ( _binning ( filter ( night_filter , self . _records ) ) ) <EOL> if len ( candidates ) == <NUM_LIT:0> : <EOL> self . home = None <EOL> else : <EOL> self . home = Counter ( candidates ) . most_common ( ) [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] <EOL> return self . home <EOL> @ property <EOL> def has_home ( self ) : <EOL> return self . home is not None <EOL> @ property <EOL> def has_attributes ( self ) : <EOL> return len ( self . attributes ) != <NUM_LIT:0> <EOL> @ property <EOL> def has_network ( self ) : <EOL> return self . network != { } <EOL> def set_home ( self , new_home ) : <EOL> """<STR_LIT>""" <EOL> if type ( new_home ) is Position : <EOL> self . home = new_home <EOL> elif type ( new_home ) is tuple : <EOL> self . home = Position ( location = new_home ) <EOL> else : <EOL> self . home = Position ( antenna = new_home ) </s>
