# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 2
#     language: python
#     name: python2
# ---

from lectures_to_viewers import getViewersToLectures
from video_annotations import ml_004 as vid
from get_seek_chains import getSeekChainsFast

# +
#import cPickle as pickle

#video_to_seek_chains = pickle.load(open('/lfs/local/0/geza/new_seek_chains/video_to_seek_chains.pickle'))

# +
import csv
import ujson as json
from memoized import memoized

@memoized
def loadjson(table_name):
  return json.load(open('/lfs/local/0/geza/ml-004_data_export/' + table_name + '.json'))

def get_table_path(table_name):
  csv_path = '/lfs/local/0/geza/ml-004_data_export/'
  return csv_path + table_name + '.csv'

def get_table_data(table_name):
  return csv.DictReader(open(get_table_path(table_name)), doublequote=False, delimiter=',', escapechar='\\')

def print_first_lines(table_name, n=10):
  for x in get_table_data(table_name):
    if n <= 0:
      break
    n -= 1
    print x


# -

import numpy

lecture_to_user_to_seek_event_timestamps = json.load(open('/lfs/local/0/geza/lecture_to_user_to_seek_event_timestamps.json'))

lecture_to_user_to_simple_seek_chains = json.load(open('/lfs/local/0/geza/new_seek_chains/lecture_to_user_to_simple_seek_chains.json'))

lecture_to_user_to_simple_seek_events = json.load(open('/lfs/local/0/geza/new_seek_chains/lecture_to_user_to_simple_seek_events.json'))

# +
#quiz_to_correct_answer = json.load(open('/lfs/local/0/geza/quiz_to_correct_answer.json'))

# +
#submission_id_to_answer = json.load(open('/lfs/local/0/geza/submission_id_to_answer.json'))
# -

submission_id_to_correct = json.load(open('/lfs/local/0/geza/submission_id_to_correct.json'))

# +
invideo_quiz_itemids = set()

for line in get_table_data('quiz_metadata'):
  if line['deleted'] != '0':
    continue
  if line['duration'] != '0':
    continue
  quiz_id = int(line['id'])
  if quiz_id > 144:
    continue
  if line['quiz_type'] != 'video':
    continue
  invideo_quiz_itemids.add(quiz_id)


# +
# exclude the quizzes with more than 1 question

invideo_quiz_itemids = set([2, 3, 4, 5, 6, 7, 9, 10, 11, 25, 26, 27, 28, 29, 30, 31, 32, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 64, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 129])
# -

print invideo_quiz_itemids

'''
user_to_quiz_to_attempts = {}

for line in loadjson('kvs_course.quiz.saved'):
  key,value = line
  parts = key.split('.')
  quiz_id = int(parts[1].split(':')[1])
  user_id = parts[2].split(':')[1]
  timestamp = int(value['saved_time'])
  if user_id not in user_to_quiz_to_attempts:
    user_to_quiz_to_attempts[user_id] = {}
  if quiz_id not in user_to_quiz_to_attempts[user_id]:
    user_to_quiz_to_attempts[user_id][quiz_id] = []
  else:
    print 'duplicates found'
    print line
    print user_to_quiz_to_attempts[user_id][quiz_id]
    break
  user_to_quiz_to_attempts[user_id][quiz_id].append(timestamp)
'''

# +
submission_id_to_start_time = {}
submission_id_to_saved_time = {}

for line in loadjson('kvs_course.quiz.submission'):
  key,value = line
  parts = key.split('.')
  submission_id = int(parts[1].split(':')[1])
  #timestamp = int(value['saved_time'])
  saved_time = int(value['saved_time'])
  start_time = int(value['start_time'])
  #submission_id_to_timestamp[submission_id] = timestamp
  submission_id_to_start_time[submission_id] = start_time
  submission_id_to_saved_time[submission_id] = saved_time


# +
#print user_to_quiz_to_attempts

# +
#print submission_id_to_correct.keys()[0:2]

# +

user_to_quiz_to_attempts = {}

for line in get_table_data('quiz_submission_metadata'):
  item_id = int(line['item_id'])
  submission_id = int(line['id'])
  #print line['submission_time']
  #if int(line['submission_time']) > 1388538061: # newer than jan 1, 2014
  submission_time = int(line['submission_time'])
  #if submission_id not in submission_id_to_saved_time:
  #  continue
  #submission_time = submission_id_to_saved_time[submission_id]
  if submission_time > 1391185339: # newer than jan 31, 2014
    continue
  if str(submission_id) not in submission_id_to_correct:
    continue
  is_correct = submission_id_to_correct[str(submission_id)]
  if item_id not in invideo_quiz_itemids:
    continue
  user_id = line['session_user_id']
  if user_id not in user_to_quiz_to_attempts:
    user_to_quiz_to_attempts[user_id] = {}
  if item_id not in user_to_quiz_to_attempts[user_id]:
    user_to_quiz_to_attempts[user_id][item_id] = []
  user_to_quiz_to_attempts[user_id][item_id].append({'timestamp': submission_time, 'correct': is_correct})



# +
lecture_id_to_title = {}
lecture_title_to_id = {}

for line in get_table_data('lecture_metadata'):
  if line['deleted'] != '0':
    continue
  if line['final'] != '1':
    continue
  lecture_id = int(line['id'])
  if lecture_id > 114:
    continue
  title = line['title']
  lecture_id_to_title[lecture_id] = title
  if title in lecture_title_to_id:
    print 'duplicate:'
    print title
    print lecture_id
    print lecture_title_to_id[title]
    print line
  lecture_title_to_id[title] = lecture_id

# +
quiz_id_to_lecture_title = {}

for line in get_table_data('quiz_metadata'):
  if line['deleted'] != '0':
    continue
  if line['duration'] != '0':
    continue
  quiz_id = int(line['id'])
  if quiz_id > 144:
    continue
  if line['quiz_type'] != 'video':
    continue
  title = line['title']
  quiz_id_to_lecture_title[quiz_id] = title

# +
lecture_id_to_quizzes = {}
quiz_to_lecture_id = {}

for quiz_id,lecture_title in quiz_id_to_lecture_title.items():
  if lecture_title not in lecture_title_to_id:
    print quiz_id
    print quiz_id_to_xml[quiz_id]
    continue
  lecture_id = lecture_title_to_id[lecture_title]
  if lecture_id not in lecture_id_to_quizzes:
    lecture_id_to_quizzes[lecture_id] = []
  lecture_id_to_quizzes[lecture_id].append(quiz_id)
  quiz_to_lecture_id[quiz_id] = lecture_id

# -

import xml.etree.ElementTree as et

# +
quiz_id_to_video_time = {}

for key,value in loadjson('kvs_course.quiz.xml'):
  try:
    tree = et.fromstring(value.encode('utf-8'))
    time = list(tree.iter('video'))[0].get('time') #.text
    time = float(time)
    parts = key.split('.')
    quiz_id = parts[1].split(':')[1]
    quiz_id = int(quiz_id)
    quiz_id_to_video_time[quiz_id] = time
  except:
    continue

# +
lecture_id_to_quiz_times = {}

for lecture_id,quizzes in lecture_id_to_quizzes.items():
  lecture_id_to_quiz_times[lecture_id] = []
  for quiz_id in quizzes:
    quiz_time = quiz_id_to_video_time[quiz_id]
    lecture_id_to_quiz_times[lecture_id].append(quiz_time)
# -

print lecture_id_to_quiz_times

print quiz_id_to_video_time

# +
#quiz_2_answer_distributions = {}

#for key,value in loadjson('kvs_course.quiz.saved'):
#  print key
#  print value
#  break
# -

# # what percent of quiz attempts are correct?

# +
#print len(submission_id_to_correct)

# +
total_correct_attempts = 0
total_incorrect_attempts = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    incorrect_attempts = [x for x in attempts if not x['correct']]
    correct_attempts = [x for x in attempts if x['correct']]
    total_correct_attempts += len(correct_attempts)
    total_incorrect_attempts += len(incorrect_attempts)


# -

print total_correct_attempts / float(total_correct_attempts + total_incorrect_attempts)
print total_incorrect_attempts / float(total_correct_attempts + total_incorrect_attempts)

# +
correct_on_first_try = 0
incorrect_on_first_try = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    first_attempt = attempts[0]
    if first_attempt['correct']:
      correct_on_first_try += 1
    else:
      incorrect_on_first_try += 1
# -

print correct_on_first_try / float(correct_on_first_try + incorrect_on_first_try)


def num_incorrect_attempts_before_correct(attempts):
  idx = 0
  for x in attempts:
    if x['correct']:
      return idx
    idx += 1
  return None


def get_incorrect_attempts(attempts):
  incorrect_attempts_before_correct = []
  if len(attempts) == 0:
    return []
  if attempts[0]['correct']:
    return []
  first_attempt = attempts[0]['timestamp']
  for x in attempts:
    timestamp = x['timestamp']
    time_finding_answer = timestamp - first_attempt
    if time_finding_answer > 1800:
      break
    if time_finding_answer < 0:
      break
    if x['correct']:
      break
    incorrect_attempts_before_correct.append(x)
  return incorrect_attempts_before_correct


# +
num_incorrect_attempts = []

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if attempts[0]['correct']:
      continue
    first_attempt = attempts[0]['timestamp']
    incorrect_attempts_before_correct = get_incorrect_attempts(attempts)
    num_incorrect_attempts.append(len(incorrect_attempts_before_correct))

# -

print numpy.mean(num_incorrect_attempts)

# +
num_incorrect_attempts_before_correct_log = []
num_incorrect_v2 = []

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if attempts[0]['correct']:
      continue
    correct_attempts = [x for x in attempts if x['correct']]
    incorrect_attempts = [x for x in attempts if not x['correct']]
    if len(correct_attempts) == 0: # never got it right
      continue
    first_incorrect = incorrect_attempts[0]
    first_correct = correct_attempts[0]
    time_finding_answer = first_correct['timestamp'] - first_incorrect['timestamp']
    if time_finding_answer < 0:
      continue
    if time_finding_answer > 1800: # more than 30 minutes
      continue
    incorrect_before_correct = num_incorrect_attempts_before_correct(attempts)
    num_incorrect_attempts_before_correct_log.append(incorrect_before_correct)
    num_incorrect_v2.append(len(get_incorrect_attempts(attempts)))

# -

print numpy.mean(num_incorrect_v2)

print numpy.mean(num_incorrect_attempts_before_correct_log)

print len([x for x in num_incorrect_attempts_before_correct_log if x == 1]) / float(len(num_incorrect_attempts_before_correct_log))

print len([x for x in num_incorrect_attempts_before_correct_log if x >= 2]) / float(len(num_incorrect_attempts_before_correct_log))

# +
incorrect_answer_will_eventually_get_correct = 0
incorrect_answer_will_eventually_get_correct_within_30 = 0
incorrect_answer_total = 0

num_attempts_by_users_who_never_got_correct = []
time_before_final_attempt = []

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    incorrect_attempts = [x for x in attempts if not x['correct']]
    correct_attempts = [x for x in attempts if x['correct']]
    if len(incorrect_attempts) == 0:
      continue
    incorrect_answer_total += 1
    if len(correct_attempts) == 0:
      first_incorrect_attempt_time = incorrect_attempts[0]['timestamp']
      incorrect_attempts_within_30min = [x for x in incorrect_attempts if abs(x['timestamp'] - first_incorrect_attempt_time) < 1800]
      num_attempts_by_users_who_never_got_correct.append(len(incorrect_attempts_within_30min))
      final_incorrect_attempt_time = incorrect_attempts_within_30min[len(incorrect_attempts_within_30min) - 1]['timestamp']
      time_before_final_attempt.append(final_incorrect_attempt_time - first_incorrect_attempt_time)
      continue
    first_incorrect = incorrect_attempts[0]
    first_correct = correct_attempts[0]
    time_finding_answer = first_correct['timestamp'] - first_incorrect['timestamp']
    if time_finding_answer < 0:
      continue
    incorrect_answer_will_eventually_get_correct += 1
    if time_finding_answer > 1800: # more than 30 minutes
      continue
    incorrect_answer_will_eventually_get_correct_within_30 += 1
# -

print numpy.mean([min(x, 3) for x in num_attempts_by_users_who_never_got_correct])

print numpy.median(time_before_final_attempt), numpy.mean(time_before_final_attempt), numpy.std(time_before_final_attempt)



print len([x for x in num_attempts_by_users_who_never_got_correct if x == 1]) / float(len(num_attempts_by_users_who_never_got_correct))
print len([x for x in num_attempts_by_users_who_never_got_correct if x == 2]) / float(len(num_attempts_by_users_who_never_got_correct))
print len([x for x in num_attempts_by_users_who_never_got_correct if x >= 3]) / float(len(num_attempts_by_users_who_never_got_correct))







print incorrect_answer_will_eventually_get_correct_within_30 / float(incorrect_answer_total)
print incorrect_answer_will_eventually_get_correct / float(incorrect_answer_total)



# +
time_until_first_correct_answer = []

incorrect_answer_will_eventually_get_correct = 0
incorrect_answer_total = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    incorrect_attempts = [x for x in attempts if not x['correct']]
    correct_attempts = [x for x in attempts if x['correct']]
    if len(incorrect_attempts) == 0:
      continue
    if len(correct_attempts) == 0:
      continue
    first_incorrect = incorrect_attempts[0]
    first_correct = correct_attempts[0]
    time_finding_answer = first_correct['timestamp'] - first_incorrect['timestamp']
    if time_finding_answer < 0:
      continue
    if time_finding_answer > 1800: # more than 30 minutes
      continue
    time_until_first_correct_answer.append(time_finding_answer)
    
# -

print numpy.median(time_until_first_correct_answer)

print numpy.mean(time_until_first_correct_answer)

print numpy.std(time_until_first_correct_answer)

combined_distribution = time_before_final_attempt + time_until_first_correct_answer
print numpy.median(combined_distribution)
print numpy.mean(combined_distribution)
print numpy.std(combined_distribution)

# +
#print correct_on_first_try / float(correct_on_first_try + )
# -

print incorrect_answer_will_eventually_get_correct / float(incorrect_answer_total)

# # what % of the time do users seek before they try re-answering the question?

# +
time_until_first_correct_answer = []

incorrect_answer_will_eventually_get_correct = 0
incorrect_answer_total = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    incorrect_attempts = [x for x in attempts if not x['correct']]
    correct_attempts = [x for x in attempts if x['correct']]
    if len(incorrect_attempts) == 0:
      continue
    if len(correct_attempts) == 0:
      continue
    first_incorrect = incorrect_attempts[0]['timestamp']
    first_correct = correct_attempts[0]['timestamp']
    time_finding_answer = first_correct - first_incorrect
    if time_finding_answer < 0:
      continue
    if time_finding_answer > 1800: # more than 30 minutes
      continue
    #time_until_first_correct_answer.append(time_finding_answer)
    

# +
num_quiz_attempts_total = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

time_spent_withseek = []
time_spent_noseek = []

exit_loop = False

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if exit_loop:
      break
    incorrect_attempts = [x for x in attempts if not x['correct']]
    correct_attempts = [x for x in attempts if x['correct']]
    if len(incorrect_attempts) == 0:
      continue
    if len(correct_attempts) == 0:
      continue
    first_incorrect_attempt = incorrect_attempts[0]['timestamp']
    first_correct_attempt = correct_attempts[0]['timestamp']
    time_finding_answer = first_correct_attempt - first_incorrect_attempt
    if time_finding_answer < 0:
      continue
    if time_finding_answer > 1800: # more than 30 minutes
      continue
    lecture_id = quiz_to_lecture_id[int(quiz_id)]
    if int(lecture_id) not in lectures_with_single_invideo_quiz:
      continue
    video_time = quiz_id_to_video_time[int(quiz_id)]
    is_seeker = False
    if user in lecture_to_user_to_simple_seek_chains[str(lecture_id)]:
      num_quiz_attempts_total += 1
      seek_events = lecture_to_user_to_simple_seek_chains[str(lecture_id)][user]
      for x in seek_events:
        if exit_loop:
          break
        timestamp = x['timestamp']
        if int(first_incorrect_attempt)*1000 <= int(timestamp) <= int(first_correct_attempt)*1000:
          num_quiz_attempts_withseek += 1
          direction = 'forward'
          if float(x['end']) < video_time:
            direction = 'backward'
          if direction == 'forward':
            num_quiz_attempts_withseek_forward += 1
          else:
            num_quiz_attempts_withseek_backward += 1
          time_spent_withseek.append(time_finding_answer)
          is_seeker = True
          break
    if not is_seeker:
      time_spent_noseek.append(time_finding_answer)

# +
num_quiz_attempts_total = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

time_spent_withseek_forward = []
time_spent_withseek_backward = []
time_spent_withseek = []
time_spent_noseek = []

incorrect_attempts_noseek = []
incorrect_attempts_withseek = []
incorrect_attempts_withseek_forward = []
incorrect_attempts_withseek_backward = []

exit_loop = False

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if exit_loop:
      break
    incorrect_attempts = [x for x in attempts if not x['correct']]
    correct_attempts = [x for x in attempts if x['correct']]
    if len(incorrect_attempts) == 0:
      continue
    if len(correct_attempts) == 0:
      continue
    first_incorrect_attempt = incorrect_attempts[0]['timestamp']
    first_correct_attempt = correct_attempts[0]['timestamp']
    time_finding_answer = first_correct_attempt - first_incorrect_attempt
    if time_finding_answer < 0:
      continue
    if time_finding_answer > 1800: # more than 30 minutes
      continue
    lecture_id = quiz_to_lecture_id[int(quiz_id)]
    if int(lecture_id) not in lectures_with_single_invideo_quiz:
      continue
    video_time = quiz_id_to_video_time[int(quiz_id)]
    is_seeker = False
    if user in lecture_to_user_to_simple_seek_chains[str(lecture_id)]:
      num_quiz_attempts_total += 1
      seek_events = lecture_to_user_to_simple_seek_chains[str(lecture_id)][user]
      for x in seek_events:
        if exit_loop:
          break
        timestamp = x['timestamp']
        if int(first_incorrect_attempt)*1000 <= int(timestamp) <= int(first_correct_attempt)*1000:
          num_quiz_attempts_withseek += 1
          direction = 'forward'
          if float(x['end']) < video_time:
            direction = 'backward'
          if direction == 'forward':
            time_spent_withseek_forward.append(time_finding_answer)
            incorrect_attempts_withseek_forward.append(len(get_incorrect_attempts(attempts)))
            num_quiz_attempts_withseek_forward += 1
          else:
            time_spent_withseek_backward.append(time_finding_answer)
            incorrect_attempts_withseek_backward.append(len(get_incorrect_attempts(attempts)))
            num_quiz_attempts_withseek_backward += 1
          time_spent_withseek.append(time_finding_answer)
          incorrect_attempts_withseek.append(len(get_incorrect_attempts(attempts)))
          is_seeker = True
          break
    if not is_seeker:
      incorrect_attempts_noseek.append(len(get_incorrect_attempts(attempts)))
      time_spent_noseek.append(time_finding_answer)
# -

print numpy.mean(incorrect_attempts_noseek)
print numpy.mean(incorrect_attempts_withseek)
print numpy.mean(incorrect_attempts_withseek_backward)
print numpy.mean(incorrect_attempts_withseek_forward)

# +

print numpy.median(time_spent_withseek_backward), numpy.mean(time_spent_withseek_backward), numpy.std(time_spent_withseek_backward)
print numpy.median(time_spent_withseek_forward), numpy.mean(time_spent_withseek_forward), numpy.std(time_spent_withseek_forward)


# -

print numpy.median(time_spent_withseek), numpy.mean(time_spent_withseek), numpy.std(time_spent_withseek)
print numpy.median(time_spent_noseek), numpy.mean(time_spent_noseek), numpy.std(time_spent_noseek)

print num_quiz_attempts_total
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / num_quiz_attempts_total
print num_quiz_attempts_withseek_forward, float(num_quiz_attempts_withseek_forward) / num_quiz_attempts_withseek
print num_quiz_attempts_withseek_backward, float(num_quiz_attempts_withseek_backward) / num_quiz_attempts_withseek

# +
num_quiz_attempts_noseek = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

#lectures_with_single_invideo_quiz = set([2, 3, 4, 5, 6, 7, 9, 10, 11, 25, 26, 27, 28, 29, 30, 31, 32, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 64, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 129])
lectures_with_single_invideo_quiz = set([4, 5, 6, 7, 9, 10, 25, 26, 27, 28, 29, 30, 31, 32, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 64, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 129])

exit_loop = False

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  if exit_loop:
    break
  for quiz_id,attempts in quiz_to_attempts.items():
    if exit_loop:
      break
    if len(attempts) <= 1:
      continue
    first_attempt = attempts[0]
    last_attempt = attempts[len(attempts) - 1]
    if last_attempt - first_attempt > 1800:
      continue
    lecture_id = quiz_to_lecture_id[int(quiz_id)]
    if int(lecture_id) not in lectures_with_single_invideo_quiz:
      continue
    video_time = quiz_id_to_video_time[int(quiz_id)]
    num_quiz_attempts_noseek += 1
    if user in lecture_to_user_to_simple_seek_chains[str(lecture_id)]:
      seek_events = lecture_to_user_to_simple_seek_chains[str(lecture_id)][user]
      for x in seek_events:
        if exit_loop:
          break
        timestamp = x['timestamp']
        if int(first_attempt)*1000 <= int(timestamp) <= int(last_attempt)*1000:
          num_quiz_attempts_withseek += 1
          #print x
          #direction = x['direction']
          direction = 'forward'
          if float(x['end']) < video_time:
            direction = 'backward'
          #if x['direction'] == 'forward':
          if direction == 'forward':
            num_quiz_attempts_withseek_forward += 1
          else:
            num_quiz_attempts_withseek_backward += 1
          break
      #break
    #break
  #break
# -

print num_quiz_attempts_noseek
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / (num_quiz_attempts_noseek + num_quiz_attempts_withseek)
print num_quiz_attempts_withseek_forward, float(num_quiz_attempts_withseek_forward) / num_quiz_attempts_withseek
print num_quiz_attempts_withseek_backward, float(num_quiz_attempts_withseek_backward) / num_quiz_attempts_withseek

# # what percentage of the back-seeks (where src=in-video quiz and dest=before in-video quiz) does this account for?

from datetime import datetime

# +
#print user_to_quiz_to_attempts
# -

'''
back_seeks_no_attempts = 0
back_seeks_before_attempts = 0
back_seeks_between_attempts = 0
back_seeks_after_attempts = 0
back_seeks_from_quiz_total = 0

multiple_quiz_attempts = 0

lectures_with_single_invideo_quiz = set([2, 3, 4, 5, 6, 7, 9, 10, 11, 25, 26, 27, 28, 29, 30, 31, 32, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 64, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 129])



exit_loop = False

num_printed = 0

for lecture_id,user_to_seek_timestamps in lecture_to_user_to_seek_event_timestamps:
  # does this lecture have exactly one in-video quiz?
  if int(lecture_id) not in lectures_with_single_invideo_quiz:
    continue
  quiz_time = float(lecture_id_to_quiz_times[int(lecture_id)][0])
  quiz_id = int(lecture_id_to_quizzes[int(lecture_id)][0])
  for user,seek_event_timestamps in user_to_seek_timestamps.iteritems():
    quiz_attempt_timestamps = []
    if user in user_to_quiz_to_attempts:
      if quiz_id in user_to_quiz_to_attempts[user]:
        quiz_attempt_timestamps = user_to_quiz_to_attempts[user][quiz_id]
        quiz_attempt_timestamps = [x*1000 for x in quiz_attempt_timestamps] # convert from seconds to milliseconds
    for timestamp in seek_event_timestamps:
      

for lecture_id,user_to_simple_seek_chains in lecture_to_user_to_simple_seek_chains.iteritems():
  if exit_loop:
    break
  # does this lecture have exactly one in-video quiz?
  if int(lecture_id) not in lectures_with_single_invideo_quiz:
    continue
  quiz_time = float(lecture_id_to_quiz_times[int(lecture_id)][0])
  quiz_id = int(lecture_id_to_quizzes[int(lecture_id)][0])
  for user_id,simple_seek_chains in user_to_simple_seek_chains.iteritems():
    if exit_loop:
      break
    quiz_attempt_timestamps = []
    if user in user_to_quiz_to_attempts:
      if quiz_id in user_to_quiz_to_attempts[user]:
        quiz_attempt_timestamps = user_to_quiz_to_attempts[user][quiz_id]
        first_quiz_attempt = quiz_attempt_timestamps[0]
        #quiz_attempt_timestamps = [x for x in quiz_attempt_timestamps if first_quiz_attempt <= x <= first_quiz_attempt + 1800]
        quiz_attempt_timestamps = [x*1000 for x in quiz_attempt_timestamps] # convert from seconds to milliseconds
    for seek_chain in simple_seek_chains:
      if exit_loop:
        break
      # does it start from the in-video quiz?
      start = seek_chain['start']
      end = seek_chain['end']
      direction = seek_chain['direction'] # forward or back
      timestamp = seek_chain['timestamp']
      #if len(simple_seek_chains) < 10:
      #  continue
      #print datetime.fromtimestamp(timestamp/1000)
      #num_printed += 1
      #if num_printed >= 1000:
      #  exit_loop = True
      #  break
      #if (quiz_time - 10 <= start <= quiz_time + 10) and direction == 'back' and end < quiz_time:
      if (quiz_time - 1 <= start <= quiz_time + 1) and direction == 'back' and end < quiz_time:
        back_seeks_from_quiz_total += 1
        # back seek from quiz. does it occur between or after 
        if len(quiz_attempt_timestamps) == 0:
          back_seeks_no_attempts += 1
        if len(quiz_attempt_timestamps) > 0:
          first_quiz_attempt = quiz_attempt_timestamps[0]
          last_quiz_attempt = quiz_attempt_timestamps[len(quiz_attempt_timestamps) - 1]
          #if True:
          #if len(quiz_attempt_timestamps) > 1:
          #  print timestamp # this is in nov 7th (much later)
          #  print quiz_attempt_timestamps # this is in october 29th (much earlier)
          #  exit_loop = True
          #  break
          if timestamp >= first_quiz_attempt and abs(first_quiz_attempt - timestamp) < 1800*1000:
            # within 30 minutes and after the first quiz attempt
            if len(quiz_attempt_timestamps) > 1:
              multiple_quiz_attempts += 1
              #if int(first_quiz_attempt) <= int(timestamp) <= int(last_quiz_attempt):
              if True:
                # back seek occurred between attempts
                back_seeks_between_attempts += 1
          if last_quiz_attempt < timestamp:
            back_seeks_after_attempts += 1
          if first_quiz_attempt > timestamp:
            back_seeks_before_attempts += 1
'''

print back_seeks_no_attempts
print back_seeks_before_attempts
print back_seeks_between_attempts
print back_seeks_after_attempts
print back_seeks_from_quiz_total
print multiple_quiz_attempts

# +
#print user_to_quiz_to_attempts['abcea9860ecfb2fef5140bc9e504f529ed33eb39']

# +
num_quiz_attempts_total = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

time_spent_withseek = []
time_spent_noseek = []

exit_loop = False

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if exit_loop:
      break
    incorrect_attempts = [x for x in attempts if not x['correct']]
    correct_attempts = [x for x in attempts if x['correct']]
    if len(incorrect_attempts) == 0:
      continue
    if len(correct_attempts) == 0:
      continue
    first_incorrect_attempt = incorrect_attempts[0]['timestamp']
    first_correct_attempt = correct_attempts[0]['timestamp']
    time_finding_answer = first_correct_attempt - first_incorrect_attempt
    if time_finding_answer < 0:
      continue
    if time_finding_answer > 1800: # more than 30 minutes
      continue
    lecture_id = quiz_to_lecture_id[int(quiz_id)]
    if int(lecture_id) not in lectures_with_single_invideo_quiz:
      continue
    video_time = quiz_id_to_video_time[int(quiz_id)]
    is_seeker = False
    if user in lecture_to_user_to_simple_seek_chains[str(lecture_id)]:
      num_quiz_attempts_total += 1
      seek_events = lecture_to_user_to_simple_seek_chains[str(lecture_id)][user]
      for x in seek_events:
        if exit_loop:
          break
        timestamp = x['timestamp']
        if int(first_incorrect_attempt)*1000 <= int(timestamp) <= int(first_correct_attempt)*1000:
          num_quiz_attempts_withseek += 1
          direction = 'forward'
          if float(x['end']) < video_time:
            direction = 'backward'
          if direction == 'forward':
            num_quiz_attempts_withseek_forward += 1
          else:
            num_quiz_attempts_withseek_backward += 1
          time_spent_withseek.append(time_finding_answer)
          is_seeker = True
          break
    if not is_seeker:
      time_spent_noseek.append(time_finding_answer)

# +
back_seeks_no_attempts = 0
back_seeks_before_attempts = 0
back_seeks_between_attempts = 0
back_seeks_after_attempts = 0
back_seeks_from_quiz_total = 0

back_seeks_before_first_correct = 0
back_seeks_after_first_correct = 0

back_seeks_after_first_correct_diff_session = 0

back_seeks_before_first_incorrect = 0

back_seeks_between_first_incorrect_and_first_correct = 0

back_seeks_between_first_incorrect_and_last_incorrect = 0

back_seeks_after_last_incorrect = 0

back_seeks_after_last_incorrect_diff_session = 0

back_seeks_after_already_correct = 0

back_seeks_after_already_correct_diff_session = 0

multiple_quiz_attempts = 0

lectures_with_single_invideo_quiz = set([2, 3, 4, 5, 6, 7, 9, 10, 11, 25, 26, 27, 28, 29, 30, 31, 32, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 64, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 129])



exit_loop = False

num_printed = 0

for lecture_id,user_to_simple_seek_chains in lecture_to_user_to_simple_seek_chains.iteritems():
  if exit_loop:
    break
  # does this lecture have exactly one in-video quiz?
  if int(lecture_id) not in lectures_with_single_invideo_quiz:
    continue
  quiz_time = float(lecture_id_to_quiz_times[int(lecture_id)][0])
  quiz_id = int(lecture_id_to_quizzes[int(lecture_id)][0])
  for user_id,simple_seek_chains in user_to_simple_seek_chains.iteritems():
    if exit_loop:
      break
    quiz_attempts = []
    correct_quiz_attempts = []
    incorrect_quiz_attempts = []
    if user_id in user_to_quiz_to_attempts:
      if quiz_id in user_to_quiz_to_attempts[user_id]:
        quiz_attempts = user_to_quiz_to_attempts[user_id][quiz_id]
        correct_quiz_attempts = [x['timestamp']*1000 for x in quiz_attempts if x['correct']]
        incorrect_quiz_attempts = [x['timestamp']*1000 for x in quiz_attempts if not x['correct']]
    for seek_chain in simple_seek_chains:
      if exit_loop:
        break
      # does it start from the in-video quiz?
      start = seek_chain['start']
      end = seek_chain['end']
      direction = seek_chain['direction'] # forward or back
      timestamp = seek_chain['timestamp']
      if (quiz_time - 1 <= start <= quiz_time + 1) and direction == 'back' and end < quiz_time:
        back_seeks_from_quiz_total += 1
        # back seek from quiz. does it occur between or after 
        if len(quiz_attempts) == 0:
          back_seeks_no_attempts += 1
        if len(quiz_attempts) > 0:
          # got correct first time?
          is_correct_first_time = quiz_attempts[0]['correct']
          # note that we're assuming we have the right seek chain here. ie not taking into account duplicate sessions
          # probably want to check that it's within 30 minutes of first answer time
          if is_correct_first_time:
            first_answer_time = correct_quiz_attempts[0]
            if first_answer_time > timestamp:
              # back seek before first attempt (which was correct)
              back_seeks_before_first_correct += 1
              break
            else:
              if abs(timestamp - first_answer_time) > 60*1000:
                back_seeks_after_first_correct_diff_session += 1
              else:
                back_seeks_after_first_correct += 1
              break
          else:
            # incorrect first time
            first_answer_time = incorrect_quiz_attempts[0]
            if first_answer_time > timestamp:
              # back seek before first attempt (which was incorrect)
              back_seeks_before_first_incorrect += 1
              continue
            else:
              if len(correct_quiz_attempts) > 0:
                # got it wrong first time but eventually got it right!
                first_correct_answer_time = correct_quiz_attempts[0]
                if first_correct_answer_time > timestamp:
                  back_seeks_between_first_incorrect_and_first_correct += 1
                  continue
                else:
                  if abs(timestamp - first_answer_time) > 60*1000:
                    back_seeks_after_already_correct_diff_session += 1
                  else:
                    back_seeks_after_already_correct += 1
                  continue # this seek occurred after we already got the answer correct
              else:
                # got it wrong and never got it right
                last_incorrect_answer_time = incorrect_quiz_attempts[len(incorrect_quiz_attempts) - 1]
                if timestamp < last_incorrect_answer_time:
                  back_seeks_between_first_incorrect_and_last_incorrect += 1
                  break
                else:
                  if abs(timestamp - first_answer_time) > 60*1000:
                    back_seeks_after_last_incorrect_diff_session += 1
                  else:
                    back_seeks_after_last_incorrect += 1
                  break

# +
total_back_seeks_in_session = (back_seeks_no_attempts + back_seeks_before_first_correct + back_seeks_before_first_incorrect + back_seeks_after_first_correct + back_seeks_between_first_incorrect_and_first_correct + back_seeks_after_already_correct + back_seeks_after_last_incorrect + back_seeks_between_first_incorrect_and_last_incorrect) 

print 'back_seeks_no_attempts', back_seeks_no_attempts, back_seeks_no_attempts / float(total_back_seeks_in_session)
print 'back_seeks_before_first_correct', back_seeks_before_first_correct, back_seeks_before_first_correct / float(total_back_seeks_in_session)
print 'back_seeks_before_first_incorrect', back_seeks_before_first_incorrect, back_seeks_before_first_incorrect / float(total_back_seeks_in_session)
print 'back_seeks_after_first_correct', back_seeks_after_first_correct, back_seeks_after_first_correct / float(total_back_seeks_in_session)
print 'back_seeks_between_first_incorrect_and_first_correct', back_seeks_between_first_incorrect_and_first_correct, back_seeks_between_first_incorrect_and_first_correct / float(total_back_seeks_in_session)
print 'back_seeks_after_already_correct', back_seeks_after_already_correct, back_seeks_after_already_correct / float(total_back_seeks_in_session)
print 'back_seeks_after_last_incorrect', back_seeks_after_last_incorrect, back_seeks_after_last_incorrect / float(total_back_seeks_in_session)
print 'back_seeks_between_first_incorrect_and_last_incorrect', back_seeks_between_first_incorrect_and_last_incorrect, back_seeks_between_first_incorrect_and_last_incorrect / float(total_back_seeks_in_session)

print 'back_seeks_after_first_correct_diff_session', back_seeks_after_first_correct_diff_session, back_seeks_after_first_correct_diff_session / float(total_back_seeks_in_session)
print 'back_seeks_after_already_correct_diff_session', back_seeks_after_already_correct_diff_session, back_seeks_after_already_correct_diff_session / float(total_back_seeks_in_session)
print 'back_seeks_after_last_incorrect_diff_session', back_seeks_after_last_incorrect_diff_session, back_seeks_after_last_incorrect_diff_session / float(total_back_seeks_in_session)



# +
back_seeks_no_attempts = 0
back_seeks_before_attempts = 0
back_seeks_between_attempts = 0
back_seeks_after_attempts = 0
back_seeks_from_quiz_total = 0

multiple_quiz_attempts = 0

lectures_with_single_invideo_quiz = set([2, 3, 4, 5, 6, 7, 9, 10, 11, 25, 26, 27, 28, 29, 30, 31, 32, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 64, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 129])



exit_loop = False

num_printed = 0

for lecture_id,user_to_simple_seek_chains in lecture_to_user_to_simple_seek_chains.iteritems():
  if exit_loop:
    break
  # does this lecture have exactly one in-video quiz?
  if int(lecture_id) not in lectures_with_single_invideo_quiz:
    continue
  quiz_time = float(lecture_id_to_quiz_times[int(lecture_id)][0])
  quiz_id = int(lecture_id_to_quizzes[int(lecture_id)][0])
  for user_id,simple_seek_chains in user_to_simple_seek_chains.iteritems():
    if exit_loop:
      break
    quiz_attempt_timestamps = []
    if user_id in user_to_quiz_to_attempts:
      if quiz_id in user_to_quiz_to_attempts[user_id]:
        quiz_attempt_timestamps = user_to_quiz_to_attempts[user_id][quiz_id]
        first_quiz_attempt = quiz_attempt_timestamps[0]
        #quiz_attempt_timestamps = [x for x in quiz_attempt_timestamps if first_quiz_attempt <= x <= first_quiz_attempt + 1800]
        quiz_attempt_timestamps = [x*1000 for x in quiz_attempt_timestamps] # convert from seconds to milliseconds
        #print quiz_attempt_timestamps
        #num_printed += 1
        #if num_printed >= 1000:
        #  exit_loop = True
        #  break
    for seek_chain in simple_seek_chains:
      if exit_loop:
        break
      # does it start from the in-video quiz?
      start = seek_chain['start']
      end = seek_chain['end']
      direction = seek_chain['direction'] # forward or back
      timestamp = seek_chain['timestamp']
      #timestamp = timestamp + 1000 * 7 * 3600
      #if len(simple_seek_chains) != 1:
      #  continue
      #if len(quiz_attempt_timestamps) != 1:
      #  continue
      #print datetime.fromtimestamp(timestamp/1000), datetime.fromtimestamp(quiz_attempt_timestamps[0]/1000)
      #num_printed += 1
      #if num_printed >= 1000:
      #  exit_loop = True
      #  break
      #if (quiz_time - 10 <= start <= quiz_time + 10) and direction == 'back' and end < quiz_time:
      if (quiz_time - 1 <= start <= quiz_time + 1) and direction == 'back' and end < quiz_time:
        back_seeks_from_quiz_total += 1
        # back seek from quiz. does it occur between or after 
        if len(quiz_attempt_timestamps) == 0:
          back_seeks_no_attempts += 1
        if len(quiz_attempt_timestamps) > 0:
          first_quiz_attempt = quiz_attempt_timestamps[0]
          last_quiz_attempt = quiz_attempt_timestamps[len(quiz_attempt_timestamps) - 1]
          #if True:
          #if len(quiz_attempt_timestamps) > 1:
          #  print timestamp # this is in nov 7th (much later)
          #  print quiz_attempt_timestamps # this is in october 29th (much earlier)
          #  exit_loop = True
          #  break
          if timestamp >= first_quiz_attempt and abs(first_quiz_attempt - timestamp) < 1800*1000:
            # within 30 minutes and after the first quiz attempt
            if len(quiz_attempt_timestamps) > 1:
              multiple_quiz_attempts += 1
              if int(first_quiz_attempt) <= int(timestamp) <= int(last_quiz_attempt):
                # back seek occurred between attempts
                back_seeks_between_attempts += 1
          if last_quiz_attempt < timestamp and abs(first_quiz_attempt - timestamp) < 1800*1000:
            back_seeks_after_attempts += 1
          if first_quiz_attempt > timestamp and abs(first_quiz_attempt - timestamp) < 1800*1000:
            back_seeks_before_attempts += 1
# -

print back_seeks_no_attempts
print back_seeks_before_attempts
print back_seeks_between_attempts
print back_seeks_after_attempts
print back_seeks_from_quiz_total
print multiple_quiz_attempts

print back_seeks_from_quiz_total

# +
num_quiz_attempts_noseek = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if len(attempts) <= 1:
      continue
    first_attempt = attempts[0]
    last_attempt = attempts[len(attempts) - 1]
    if last_attempt - first_attempt > 1800:
      continue
    lecture_id = quiz_to_lecture_id[quiz_id]
    video_time = quiz_id_to_video_time[int(quiz_id)]
    num_quiz_attempts_noseek += 1
    if user in lecture_to_user_to_simple_seek_chains[str(lecture_id)]:
      seek_events = lecture_to_user_to_simple_seek_chains[str(lecture_id)][user]
      for x in seek_events:
        timestamp = x['timestamp']
        if int(first_attempt)*1000 <= int(timestamp) <= int(last_attempt)*1000:
          num_quiz_attempts_withseek += 1
          #print x
          direction = 'forward'
          if float(x['end']) < video_time:
            direction = 'backward'
          #if x['direction'] == 'forward':
          if direction == 'forward':
            num_quiz_attempts_withseek_forward += 1
          else:
            num_quiz_attempts_withseek_backward += 1
          break
      #break
    #break
  #break
# -

print num_quiz_attempts_noseek
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / (num_quiz_attempts_noseek + num_quiz_attempts_withseek)
print num_quiz_attempts_withseek_forward, float(num_quiz_attempts_withseek_forward) / num_quiz_attempts_withseek
print num_quiz_attempts_withseek_backward, float(num_quiz_attempts_withseek_backward) / num_quiz_attempts_withseek

# +
num_quiz_attempts_noseek = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if len(attempts) <= 1:
      continue
    first_attempt = attempts[0]
    last_attempt = attempts[len(attempts) - 1]
    if last_attempt - first_attempt > 1800:
      continue
    lecture_id = quiz_to_lecture_id[quiz_id]
    video_time = quiz_id_to_video_time[int(quiz_id)]
    num_quiz_attempts_noseek += 1
    if user in lecture_to_user_to_simple_seek_events[str(lecture_id)]:
      seek_events = lecture_to_user_to_simple_seek_events[str(lecture_id)][user]
      for x in seek_events:
        timestamp = x['timestamp']
        if int(first_attempt)*1000 <= int(timestamp) <= int(last_attempt)*1000:
          num_quiz_attempts_withseek += 1
          #if x['direction'] == 'forward':
          direction = 'forward'
          if float(x['end']) < video_time:
            direction = 'backward'
          if direction == 'forward':
            num_quiz_attempts_withseek_forward += 1
          else:
            num_quiz_attempts_withseek_backward += 1
          break
# -

print num_quiz_attempts_noseek
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / (num_quiz_attempts_noseek + num_quiz_attempts_withseek)
print num_quiz_attempts_withseek_forward, float(num_quiz_attempts_withseek_forward) / num_quiz_attempts_withseek
print num_quiz_attempts_withseek_backward, float(num_quiz_attempts_withseek_backward) / num_quiz_attempts_withseek

# +
num_quiz_attempts_noseek = 0
num_quiz_attempts_withseek = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if len(attempts) <= 1:
      continue
    first_attempt = attempts[0]
    last_attempt = attempts[len(attempts) - 1]
    if last_attempt - first_attempt > 1800:
      continue
    lecture_id = quiz_to_lecture_id[quiz_id]
    num_quiz_attempts_noseek += 1
    if user in lecture_to_user_to_seek_event_timestamps[str(lecture_id)]:
      seek_events = lecture_to_user_to_seek_event_timestamps[str(lecture_id)][user]
      for x in seek_events:
        if int(first_attempt)*1000 <= int(x) <= int(last_attempt)*1000:
          num_quiz_attempts_withseek += 1
          break
# -

print num_quiz_attempts_noseek
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / (num_quiz_attempts_noseek + num_quiz_attempts_withseek)


def current_and_prev_item(l):
  prev_item = None
  is_first = True
  for x in l:
    if is_first:
      is_first = False
    else:
      yield (prev_item, x)
    prev_item = x
    


# +
num_quiz_attempts_noseek = 0
num_quiz_attempts_withseek = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if len(attempts) <= 1:
      continue
    lecture_id = quiz_to_lecture_id[quiz_id]
    for prev_attempt,next_attempt in current_and_prev_item(attempts):
      num_quiz_attempts_noseek += 1
      if user in lecture_to_user_to_seek_event_timestamps[str(lecture_id)]:
        seek_events = lecture_to_user_to_seek_event_timestamps[str(lecture_id)][user]
        for x in seek_events:
          if int(prev_attempt)*1000 <= int(x) <= int(last_attempt)*1000:
            num_quiz_attempts_withseek += 1
            break
# -

print num_quiz_attempts_noseek
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / (num_quiz_attempts_noseek + num_quiz_attempts_withseek)

# +
num_quiz_attempts_noseek = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if len(attempts) <= 1:
      continue
    lecture_id = quiz_to_lecture_id[quiz_id]
    video_time = quiz_id_to_video_time[int(quiz_id)]
    for prev_attempt,next_attempt in current_and_prev_item(attempts):
      if next_attempt - prev_attempt > 1800:
        continue
      num_quiz_attempts_noseek += 1
      if user in lecture_to_user_to_simple_seek_events[str(lecture_id)]:
        seek_events = lecture_to_user_to_simple_seek_events[str(lecture_id)][user]
        for x in seek_events:
          timestamp = x['timestamp']
          if int(prev_attempt)*1000 <= int(timestamp) <= int(last_attempt)*1000:
            num_quiz_attempts_withseek += 1
            direction = 'forward'
            if float(x['end']) < video_time:
              direction = 'backward'
            #if x['direction'] == 'forward':
            if direction == 'forward':
              num_quiz_attempts_withseek_forward += 1
            else:
              num_quiz_attempts_withseek_backward += 1
            break
# -

print num_quiz_attempts_noseek
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / (num_quiz_attempts_noseek + num_quiz_attempts_withseek)
print num_quiz_attempts_withseek_forward, float(num_quiz_attempts_withseek_forward) / num_quiz_attempts_withseek
print num_quiz_attempts_withseek_backward, float(num_quiz_attempts_withseek_backward) / num_quiz_attempts_withseek

# +
num_quiz_attempts_noseek = 0
num_quiz_attempts_withseek = 0
num_quiz_attempts_withseek_forward = 0
num_quiz_attempts_withseek_backward = 0

for user,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    if len(attempts) <= 1:
      continue
    lecture_id = quiz_to_lecture_id[quiz_id]
    video_time = quiz_id_to_video_time[int(quiz_id)]
    for prev_attempt,next_attempt in current_and_prev_item(attempts):
      if next_attempt - prev_attempt > 1800:
        continue
      num_quiz_attempts_noseek += 1
      if user in lecture_to_user_to_simple_seek_chains[str(lecture_id)]:
        seek_events = lecture_to_user_to_simple_seek_chains[str(lecture_id)][user]
        for x in seek_events:
          timestamp = x['timestamp']
          if int(prev_attempt)*1000 <= int(timestamp) <= int(last_attempt)*1000:
            num_quiz_attempts_withseek += 1
            direction = 'forward'
            if float(x['end']) < video_time:
              direction = 'backward'
            #if x['direction'] == 'forward':
            if direction == 'forward':
              num_quiz_attempts_withseek_forward += 1
            else:
              num_quiz_attempts_withseek_backward += 1
            break
# -

print num_quiz_attempts_noseek
print num_quiz_attempts_withseek, float(num_quiz_attempts_withseek) / (num_quiz_attempts_noseek + num_quiz_attempts_withseek)
print num_quiz_attempts_withseek_forward, float(num_quiz_attempts_withseek_forward) / num_quiz_attempts_withseek
print num_quiz_attempts_withseek_backward, float(num_quiz_attempts_withseek_backward) / num_quiz_attempts_withseek



# +
#print video_to_seek_chains.keys()

# +
delay_between_attempts = []

for user_id,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    first_submission = attempts[0]
    current_session_attempts = [x for x in attempts if abs(x - first_submission) < 1800]
    for x in current_session_attempts[1:]:
      delay_between_attempts.append(x - first_submission)


# +
#print user_to_quiz_to_attempts

# +
attempts_per_user = []

for user_id,quiz_to_attempts in user_to_quiz_to_attempts.items():
  for quiz_id,attempts in quiz_to_attempts.items():
    first_submission = attempts[0]
    current_session_attempts = [x for x in attempts if abs(x - first_submission) < 1800]
    attempts_per_user.append(len(current_session_attempts))

attempts_per_user = [min(x, 3) for x in attempts_per_user]

print numpy.mean(attempts_per_user)

StarcoderdataJupyterScriptsDedupFiltered