

class Site(object):

    def __init__(self):
        self.op_events = []
        self.chats = {}
        self.emails = {}
        self.operators = set()
        self.visitors = set()

    def add_operator_event(self, ts, op, state):
        self.transitions = \
            sorted(set(self.op_events + [(ts, op, state)]))
        self.operators.add(op)
    
    def get_state(self, time_stamp):
        op_count = 0
        for ts, op, state in self.transitions:
            if time_stamp >= ts:
                break
            change = 1 if state == 'online' else -1
            op_count += change
        return 'online' if op_count else 'offline'

    def add_chat(self, time_stamp, visitor):
        if time_stamp in self.chats or time_stamp in self.emails:
            return
        state = self.get_state(time_stamp)
        if state == 'online':
            self.chats[time_stamp] = visitor
        else:
            self.emails[time_stamp] = visitor
        self.visitors.add(visitor)

    def report(self, site_id):
        print "{site_id},messages={messages},emails={emails},operators={operators},visitors={visitors}".format(
            site_id=site_id, messages=len(self.chats), emails=len(self.emails), 
            operators=len(self.operators), visitors=len(self.visitors))

def main():
    import sys
    import json
    fname = sys.argv[1]

    sites = {}
    
    with open(fname) as f:
       for line in f.readlines():
           data = json.loads(line)
           site_id = data['site_id']
           site = sites.setdefault(site_id, Site())
           if data['type'] == 'status':
               site.add_operator_event(data['timestamp'], data['from'], data['data']['status'])
          
    with open(fname) as f:
        for line in f.readlines():
            data = json.loads(line.strip())
            site_id = data['site_id']
            site = sites[site_id]
            if data['type'] == 'message':
                site.add_chat(data['timestamp'], data['from'])

    for site_id, site in sites.items():
       site.report(site_id)


if __name__ == '__main__':
    main()

@@ -69,10 +69,10 @@
 s = 
-%5B%5D
+%7B%7D
 %0A   
@@ -85,26 +85,29 @@
 elf.chats = 
-%7B%7D
+set()
 %0A        sel
@@ -113,26 +113,29 @@
 lf.emails = 
-%7B%7D
+set()
 %0A        sel
@@ -251,34 +251,23 @@
 elf.
-transitions = %5C%0A          
+op_events%5Bop%5D =
   so
@@ -293,16 +293,28 @@
 ents
+.get(op, %5B%5D)
  + %5B(ts,
  op,
@@ -309,20 +309,16 @@
  + %5B(ts,
- op,
  state)%5D
@@ -393,24 +393,25 @@
 stamp):%0A
+#
         
 op_count
@@ -406,20 +406,55 @@
     
-op_count = 0
+import pdb; pdb.set_trace()%0A        states = %5B%5D
 %0A   
@@ -466,40 +466,158 @@
 for 
-ts, op, state in self.transition
+op, events in self.op_events.items():%0A            prev_state = 'offline'# if events%5B0%5D%5B1%5D == 'online' else 'online'%0A            for ts, state in event
 s:%0A 
@@ -619,34 +619,43 @@
 ts:%0A            
-if
+    if ts %3E
  time_stamp %3E= t
@@ -653,16 +653,14 @@
 tamp
- %3E= ts:%0A
+:%0A    
     
@@ -693,78 +693,102 @@
     
-change = 1 if state == 'online' else -1%0A            op_count += change
+    prev_state = state%0A            states.append(prev_state)%0A        #print time_stamp, states
 %0A   
@@ -815,16 +815,27 @@
  if 
-op_count
+'online' in states 
  els
@@ -1072,17 +1072,21 @@
 lf.chats
-%5B
+.add(
 time_sta
@@ -1083,35 +1083,25 @@
 d(time_stamp
-%5D = visitor
+)
 %0A        els
@@ -1126,17 +1126,21 @@
 f.emails
-%5B
+.add(
 time_sta
@@ -1145,19 +1145,9 @@
 tamp
-%5D = visitor
+)
 %0A   
@@ -1560,24 +1560,34 @@
 s = %7B%7D%0A    %0A
+    i = 0%0A
     with ope
@@ -1627,32 +1627,111 @@
  f.readlines():%0A
+#           if i %25 10000 == 0: print 'first pass %7B%7D'.format(i)%0A           i+=1%0A
            data 
@@ -1979,79 +1979,244 @@
 %5D)%0A 
-         %0A    with open(fname) as f:%0A        for line in f.readlines():
+%0A#    from pprint import pprint%0A#    pprint(sites.values()%5B0%5D.op_events)%0A         %0A    i = 0%0A    with open(fname) as f:%0A        for line in f.readlines():%0A#            if i %25 10000 == 0: print 'second pass %7B%7D'.format(i)%0A            i+=1
 %0A   
@@ -2366,24 +2366,65 @@
  'message':%0A
+                #print data%5B'timestamp'%5D%0A
             
@@ -2500,16 +2500,23 @@
 site in 
+sorted(
 sites.it
@@ -2512,32 +2512,55 @@
 ed(sites.items()
+, key=lambda _e: _e%5B0%5D)
 :%0A       site.re

fix logic for site online / offline seems like I needed to track it per operator, took too long to figure out