Esempio n. 1
0
def populate():
    print('Populating Survey and Question ... ', end='')
    Survey.objects.all().delete()
    Question.objects.all().delete()
    Choice.objects.all().delete()
    Response.objects.all().delete()
    userList = User.objects.first()
    for title in titles:
        survey = Survey()
        survey.title = title
        survey.description = title
        survey.date = datetime.date.today()
        survey.startDate = survey.date
        survey.endDate = survey.startDate + datetime.timedelta(60)
        survey.user = userList
        survey.emailContent = '新的問題開始'
        survey.save()
        for content in contents:
            question = Question()
            question.survey = survey
            question.title += 'Q:' + title
            question.description += title + content + '\n'
            question.save()
            Choice.objects.create(question=question, name='是')
            Choice.objects.create(question=question, name='否,另有要事')
    print('done')
Esempio n. 2
0
 def post(self, request, *args, **kwargs):
     warnings = []
     data = json.loads(request.POST.get('r'))
     title = data.get('title', '')
     slug = slugify(data.get('slug') or title)
     if not slug:
         warnings.append(_('Please enter a valid title.'))
         return HttpResponse(json.dumps({'status': 'failure', 'warnings': warnings}), mimetype='application/json')
     try:
         survey = self.get_object()
         if slug != survey.slug:
             warnings.append(_("This survey's URL has been changed. Be sure to update any QR code images."))
     except AttributeError:
         survey = Survey(creator=request.user)
     survey.title = title
     survey.slug = slug
     survey.description = data.get('description', '')
     try:
         survey.save()
     except IntegrityError:
         warnings = [_('That title is already taken. Please choose a different one.')]
         return HttpResponse(json.dumps({'status': 'failure', 'warnings': warnings}), mimetype='application/json')
     # delete existing questions
     # due to cascading deletes, this will also delete choices
     QuestionGroup.objects.filter(pk__in=survey.question_set.all().values_list('group')).delete()
     survey.question_set.all().delete()
     questions = data.get('questions', [])
     groups = data.get('groups', [])
     survey.add_questions(questions, groups)
     return HttpResponse(json.dumps({'status': 'success', 'warnings': warnings, 'url': reverse('surveydashboard', args=[survey.slug])}), mimetype='application/json')
Esempio n. 3
0
class TestSurvey(TestCase):
    def setUp(self):
        self.Sv = Survey()
        self.Sv.name = "Plantas"
        self.Sv.description = "ya jale todo"
        self.Sv.save()

        self.Qs = Question()
        self.Qs.question_text = "¿es GG?"
        self.Qs.survey = self.Sv

        self.Rs = Response()
        self.name = "Carlos"
        self.survey = self.Sv

        self.BRs = BaseResponse()
        self.BRs.response = self.Rs
        self.BRs.question = self.Qs
        self.BRs.response_text = "Al año con fuerza"

    def testdatabase(self):
        all_database = Survey.objects.all()
        assert len(all_database) == 1

        only_database = all_database[0]

        assert only_database == self.Sv
Esempio n. 4
0
 def test_save_modified_time(self):
     s = Survey(name='Survey')
     minute_slice = slice(0, 17)
     time = str(datetime.datetime.now())
     s.save()
     saved_time = str(s.created_at)
     self.assertEqual(saved_time[minute_slice], time[minute_slice])
Esempio n. 5
0
 def test_save_modified_time(self):
     s = Survey(name='Survey')
     minute_slice = slice(0, 17)
     time = str(datetime.datetime.now())
     s.save()
     saved_time = str(s.created_at)
     self.assertEqual(saved_time[minute_slice], time[minute_slice])
Esempio n. 6
0
def submit(request):
    if request.method == 'POST':
        s = Survey(data = request.raw_post_data,
                   remote_addr = request.META["REMOTE_ADDR"],
                   user_agent = request.META["HTTP_USER_AGENT"])
        s.save()

    return HttpResponse("OK")
Esempio n. 7
0
    def handle(self, *args, **options):
        # TODO: Remove or improve before production...
        logger.info('Deleting all surveys...')

        User.objects.filter(is_staff=False).delete()
        Survey.objects.all().delete()
        ChallengeDetail.objects.all().delete()

        logger.info('Starting import...')
        df = pd.read_excel(path.join(settings.BASE_DIR, 'respondents.xlsx'), sheetname='Delegates')
        df.fillna('', inplace=True)

        for idx, survey in df.iterrows():
            data_raw = survey.to_dict()
            data = {k: str(v).strip() for k, v in data_raw.items()}

            try:
                country = Country.objects.get(name=data.get('country_of_operation'))
                data.update({'country_of_operation': country})

            except Country.DoesNotExist:
                logger.warning('Could not find country %s' % data.get('country_of_operation'))
                data.update({'country_of_operation': None})

            del data['countries']

            # Create and associate user
            username = slugify(data.get('name')).replace('-', '_')
            slug = '{0}_{1}'.format(data.get('slug')[2:] or slug_generator(), username)
            logger.info(slug)
            user = User.objects.create_user(username[:30], data.get('email', ''), slug)

            survey = Survey(**data)
            survey.slug = slug
            survey.user = user
            survey.save()
            assign_perm('change_survey', user, obj=survey)

            # Creating challenges
            # for challenge in Challenge.objects.all():
            #     ChallengeDetail.objects.create(owner=slug, challenge=challenge)

            for rank in range(1, 4):
                ChallengeDetail.objects.create(respondent=survey, rank=rank)

            # try:
            #     Survey(**data).save()
            # except IntegrityError:
            #     logger.excep('Integ exisits: %s ' % data)
            # except:
            #     logger.exception(data)
            # else:
            #     for challenge in Challenge.objects.all():
            #         ChallengeDetail.objects.create(slug, challenge)

        logger.info('Done')
Esempio n. 8
0
def login_user(request, slug):
    logger.info('Slug is: {}, trying to log in...'.format(slug))

    request.session['survey_slug'] = slug
    request.session.save()
    survey_instance = None

    try:
        survey_instance = Survey.objects.get(slug=slug)

    except Survey.DoesNotExist:
        logger.info('Survey does not exist...')
        user = User(username=slug[30:])
        user.set_password(slug)
        user.email = ''
        user.save()
        logger.info('Saved new user... {}'.format(user))
        survey_instance = Survey(slug=slug, user=user)
        survey_instance.save()
        logger.info('Saved new survey... {}'.format(survey_instance))

        for rank in range(1, 4):
            ChallengeDetail.objects.create(respondent=survey_instance, rank=rank)
            logger.info('Added new ChallengeDetail with respondent = {} and rank = {}'.format(survey_instance, rank))

    else:
        logger.info('Found survey and use!:')

    finally:
        if request.user.is_staff:
            logger.info('Staff in the house!!')

        else:
            user = authenticate(username=survey_instance.user.username, password=slug)
            logger.info('Not staff, who is %s' % survey_instance.user.username)

            if user is not None:
                # If staff member is testing
                if user.is_active:
                    logger.info('User is active!')
                    login(request, user)
                    # Redirect to a success page
                else:
                    logger.warn('User not active')
                    pass
                    # Return a 'disabled account' error message
            else:
                logger.warn('Authentication Failed')
                pass
                # Return an 'invalid login' error message.

        # logger.info('Confirming that survey_slug is stored: {}'.format(request.session['survey_slug']))
        return HttpResponseRedirect(reverse('survey:about'))
Esempio n. 9
0
 def post(self, request, *args, **kwargs):
     warnings = []
     data = json.loads(request.POST.get('r'))
     title = data.get('title', '')
     slug = slugify(data.get('slug') or title)
     if not slug:
         warnings.append(_('Please enter a valid title.'))
         return HttpResponse(json.dumps({
             'status': 'failure',
             'warnings': warnings
         }),
                             mimetype='application/json')
     try:
         survey = self.get_object()
         if slug != survey.slug:
             warnings.append(
                 _("This survey's URL has been changed. Be sure to update any QR code images."
                   ))
     except AttributeError:
         survey = Survey(creator=request.user)
     survey.title = title
     survey.slug = slug
     survey.description = data.get('description', '')
     try:
         survey.save()
     except IntegrityError:
         warnings = [
             _('That title is already taken. Please choose a different one.'
               )
         ]
         return HttpResponse(json.dumps({
             'status': 'failure',
             'warnings': warnings
         }),
                             mimetype='application/json')
     # delete existing questions
     # due to cascading deletes, this will also delete choices
     QuestionGroup.objects.filter(
         pk__in=survey.question_set.all().values_list('group')).delete()
     survey.question_set.all().delete()
     questions = data.get('questions', [])
     groups = data.get('groups', [])
     survey.add_questions(questions, groups)
     return HttpResponse(json.dumps({
         'status':
         'success',
         'warnings':
         warnings,
         'url':
         reverse('surveydashboard', args=[survey.slug])
     }),
                         mimetype='application/json')
Esempio n. 10
0
def create_survey(request):
    if request.POST:
        survey_title = request.POST.get("survey_title")
        survey_description = request.POST.get("survey_description")
        if survey_title == "New Survey(Click to change)":
            survey_title = "No title"
        if survey_description == "Add description here" or survey_description == "Click here to add...":
            survey_description = ""
        publishBool = request.POST.get("publishBool")
        survey = Survey(title=survey_title)
        survey.description = survey_description
        creator = User.objects.get(id = int(request.POST.get( "creatorID")))
        survey.user = creator
        survey.theme_name = request.POST.get("theme_name")
        deadline = request.POST.get("survey_deadline")
        survey.deadline = datetime.strptime(deadline.strip(), "%d/%m/%Y")
        survey.save()
        collaborators = request.POST.get("collaborators")
        collaborators = collaborators.split(",")
        try:
            collaborators.remove("")
        except BaseException as e:
            pass
        for collaborator_id in collaborators:
            collaboration = Collaboration()
            collaboration.user = User.objects.get(id = int(collaborator_id))
            collaboration.survey = survey
            collaboration.is_active = True
            collaboration.save()

        if publishBool == 'true':
            survey.is_published = True
            survey.save()
        surveyID = survey.id
        dict = {"surveyID": surveyID, "survey_key": survey.key}
        return HttpResponse(simplejson.dumps(dict), mimetype='application/javascript')
    return error_jump(request)
Esempio n. 11
0
class SurveyModel(TestCase):
    """Test Survey, Section, Branching, Result, ResultAggregate Model"""

    fixtures = ['auth_user.json', 'gateway.json', 'dialer_setting.json',
                'user_profile.json',  # 'contenttype.json',
                'phonebook.json', 'contact.json',
                'dnc_list.json', 'dnc_contact.json',
                'campaign.json', 'subscriber.json',
                'callrequest.json', 'voipcall.json',
                'survey_template.json', 'survey.json',
                'section_template.json', 'section.json',
                'branching.json',
                ]

    def setUp(self):
        self.user = User.objects.get(username='******')

        # Survey_template model
        self.survey_template = Survey_template(
            name='test_survey',
            user=self.user,
        )
        self.survey_template.save()

        # Survey model
        self.survey = Survey(
            name='test_survey',
            user=self.user,
        )
        self.survey.save()
        self.assertEqual(self.survey.__unicode__(), u'test_survey')

        # Section_template
        self.section_template = Section_template.objects.get(pk=1)
        self.section_template.survey.name = 'New Survey'
        self.section_template.save()

        # Section model
        self.section = Section.objects.get(pk=1)
        self.section.save()
        self.assertTrue(self.section.__unicode__())

        # Branching_template model
        self.branching_template = Branching_template(
            keys=5,
            section=self.section_template,
        )
        self.branching_template.save()

        # Branching model
        self.branching = Branching(
            keys=5,
            section=self.section,
        )
        self.branching.save()
        self.assertTrue(self.branching.__unicode__())

        # Result model
        self.result = Result(
            section=self.section,
            callrequest_id=1,
            response='apple'
        )
        self.result.save()
        self.assertEqual(
            self.result.__unicode__(), '[1] [1] call transfer = apple')

        # ResultAggregate model
        self.result_aggregate = ResultAggregate(
            survey=self.survey,
            section=self.section,
            count=1,
            response='apple'
        )
        self.result_aggregate.save()
        self.assertEqual(
            self.result_aggregate.__unicode__(), '[1] [1] call transfer = apple')

    def test_survey_forms(self):
        self.assertEqual(self.survey_template.name, "test_survey")
        #self.assertEqual(self.section_template.survey, self.survey_template)
        self.assertEqual(self.branching_template.section, self.section_template)
        self.assertEqual(self.result.section, self.section)

        form = PlayMessageSectionForm(self.user, instance=self.section_template)
        obj = form.save(commit=False)
        obj.question = "test question"
        obj.type = 1
        obj.survey = self.survey_template
        obj.save()

        form = MultipleChoiceSectionForm(self.user, instance=self.section_template)
        obj = form.save(commit=False)
        obj.type = 2
        obj.question = "test question"
        obj.key_0 = "apple"
        obj.survey = self.survey_template
        obj.save()

        form = RatingSectionForm(self.user,
                                 instance=self.section_template)
        obj = form.save(commit=False)
        obj.type = 3
        obj.question = "test question"
        obj.rating_laps = 5
        obj.survey_template = self.survey_template
        obj.save()

        form = CaptureDigitsSectionForm(self.user,
                                        instance=self.section_template)
        obj = form.save(commit=False)
        obj.type = 4
        obj.question = "test question"
        obj.number_digits = 2
        obj.min_number = 1
        obj.max_number = 100
        obj.survey = self.survey_template
        obj.save()

        form = RecordMessageSectionForm(self.user)
        obj = form.save(commit=False)
        obj.type = 5
        obj.question = "test question"
        obj.survey = self.survey_template
        obj.save()

        form = CallTransferSectionForm(self.user)
        obj = form.save(commit=False)
        obj.type = 6
        obj.question = "test question"
        obj.phonenumber = 1234567890
        obj.survey = self.survey_template
        obj.save()

        form = SMSSectionForm(self.user)
        obj = form.save(commit=False)
        obj.type = 10
        obj.question = "sms question"
        obj.sms_text = "this is test sms"
        obj.survey = self.survey_template
        obj.save()

        form = ScriptForm()
        obj = form.save(commit=False)
        obj.script = 'xyz'
        obj.survey = self.survey_template
        obj.save()

        form = SurveyDetailReportForm(self.user)

    def teardown(self):
        self.survey_template.delete()
        self.survey.delete()
        self.section_template.delete()
        self.section.delete()
        self.branching_template.delete()
        self.branching.delete()
        self.result.delete()
        self.result_aggregate.delete()
def buildSurvey(user,phone_number):
    print "build survey"
    thedatetime = datetime.datetime.now().strftime("%Y:%m:%d:%H:%M:%S")
    title = str(phone_number) + "/" + thedatetime
    survey = Survey(title = title)
    survey.save()
    textmessagelist = []
    for conver in user.sms_conversation_set.all():
        for message in conver.sms_message_set.all():
            if message.from_last_day():
                textmessagelist.append("  recipient: " + message.recipient)
                textmessagelist.append("\t message: " + decrypt(key,message.SmSbody))
    facemessagelist = []
    for faceConver in user.facebook_conversation_set.all():
        for faceMessage in faceConver.facebook_messages_set.all():
            if faceMessage.from_last_day():
                facemessagelist.append("  text: " + decrypt(key,faceMessage.body))
    faceactlist = []
    faceComm = []
    for faceact in user.facebook_activity_set.all():
        if faceact.from_last_day():
	    try:
            	md = decrypt(key, faceact.message)
	    except Exception as e:
		print e
	    fmsg = faceact.message
	    #print "new facebook key=[%s] orig=[%s] decrypt=[%s, %d]" % (key, faceact.message, md, len(md))
            if decrypt(key,faceact.message):
                faceactlist.append("  activity:" + decrypt(key,faceact.message))
		#print "added activity", len(faceactlist)
	    else:
		#print "no activity. decrypt failed?"
		pass
        for com in faceact.facebook_comments_set.all():
            if decrypt(key,com.text):
                faceComm.append(" comment:" + decrypt(key,com.text))
    twitterStatus = []
    qs = list(twitter_status.objects.filter(author = user))
    for twitterstatus in qs:
        if twitterstatus.from_last_day():
            twitterStatus.append("   twitter status :" + twitterstatus.body + "\n")
    print(textmessagelist)
    if not textmessagelist:
        textmessagelist.append("No text messages sent in last day")
    text = "Text messages from last day: \n" + "\n".join(textmessagelist)
    q1 = survey.question_set.create(text = text,atype=1)
    y1 = q1.choice_set.create(choice_text="Yes")
    n1 = q1.choice_set.create(choice_text="No")
    print(facemessagelist)
    if not facemessagelist:
        facemessagelist.append("No facebook instant massages from last day")
    text2 = "Facebook message from last day: \n" + "\n".join(facemessagelist)+ "\n".join(faceComm)
    q2 = survey.question_set.create(text = text2,atype=1)
    y2 = q2.choice_set.create(choice_text="Yes")
    n2 = q2.choice_set.create(choice_text="No")
    print("activity list %s %d", str(faceactlist), len(faceactlist))
    if not faceactlist:
        faceactlist.append("No facebook activities from last day")
    text4 = "Facebook activities from last day: \n" + "\n".join(faceactlist)
    q4 = survey.question_set.create(text = text4,atype=1)
    y4 = q4.choice_set.create(choice_text="Yes")
    n4 = q4.choice_set.create(choice_text="No")
    if not twitterStatus:
        twitterStatus.append("No new twitter status")
    text3 = "Twitter status from last day: \n" + "\n".join(twitterStatus)
    q3 = survey.question_set.create(text = text3,atype=1)
    y3 = q3.choice_set.create(choice_text="Yes")
    n3 = q3.choice_set.create(choice_text="No")
    return survey
Esempio n. 13
0
def save_survey(request, surveyID):
    if request.POST:
        question_type = request.POST.get("question_type")
        question_no = request.POST.get("question_no")
        question_helptext = request.POST.get("question_helptext")
        is_required = request.POST.get("is_required")
        if question_helptext == "Click here to add...":
            question_helptext == ""
        question_title = request.POST.get("question_title")
        selections = request.POST.get("selections")
        attributes = request.POST.get("attributes")
        if int(surveyID) == 0:
            survey = Survey(title="no title")
            survey.save()
            surveyID = survey.id
        if question_type == "paragraph":
            question = ParagraphQuestion()
        elif question_type == "numeric":
            question = NumericQuestion()
        elif question_type == "multiplechoice":
            question = MultipleChoiceQuestion()
        elif question_type == "checkbox":
            question = CheckboxQuestion()
        elif question_type == "scale":
            question = ScaleQuestion()
        elif question_type == "text":
            question = TextQuestion()
        elif question_type == "date":
            question = DateQuestion()
        else:
            return
        question.survey = Survey.objects.get(id=surveyID)
        question.id_in_survey = question_no
        question.title = question_title.strip()
        question.help_text = question_helptext
        question.max_no_characters = 0
        if is_required == 'true':
            question.is_required = True
        else:
            question.is_required = False
        question.save()
        if question_type == "paragraph":
            attributes_list = attributes.split("@#@")
            question.max_no_characters = int(attributes_list[0])
        elif question_type == "numeric":
            attributes_list = attributes.split("@#@")
            question.max_value = float(attributes_list[0])
            question.min_value = float(attributes_list[1])
        elif question_type == "multiplechoice":
            choices = selections.split("@#@")
            choices.pop()
            count = 0
            for choice_label in choices:
                count += 1
                choice = MultipleChoice()
                choice.question = question
                choice.label = choice_label
                choice.id_in_question = count
                choice.save()
        elif question_type == "checkbox":
            attributes_list = attributes.split("@#@")
            question.max_checked = int(attributes_list[0])
            question.min_checked = int(attributes_list[1])
            choices = selections.split("@#@")
            choices.pop()
            count = 0
            for choice_label in choices:
                count += 1
                choice = CheckboxChoice()
                choice.question = question
                choice.label = choice_label
                choice.id_in_question = count
                choice.save()
        elif question_type == "scale":
            attributes_list = attributes.split("@#@")
            question.max_value = float(attributes_list[0])
            question.min_value = float(attributes_list[1])
            question.increment = float(attributes_list[2])
        elif question_type == "date":
            attributes_list = attributes.split("@#@")
            question.min_value = datetime.strptime(attributes_list[0].strip(),"%d/%m/%Y")
            question.max_value = datetime.strptime(attributes_list[1].strip(),"%d/%m/%Y")
            question.start_value = datetime.strptime(attributes_list[2].strip(),"%d/%m/%Y")
        elif question_type == "text":
            attributes_list = attributes.split("@#@")
            question.max_no_characters = int(attributes_list[0])
        else:
            return
        question.save()
        dict = {"surveyID": surveyID}
        return HttpResponse(simplejson.dumps(dict), mimetype='application/javascript')
    return error_jump(request)
Esempio n. 14
0
def add_survey(survey_file_path, survey_anime_file_path, survey_late_adds_file_path, year, quarter, is_preseason):
    survey_queryset = Survey.objects.filter(year=year, season=quarter, is_preseason=is_preseason)
    if len(survey_queryset) > 0:
        survey = survey_queryset[0]
        print('Found pre-existing survey: "%s"' % str(survey))

        answer = input('Delete this survey and continue? (Y/N)').lower()
        while answer != 'y' and answer != 'n':
            answer = input('Delete this survey and continue? (Y/N)').lower()
        
        if answer == 'n':
            return

        deletion_count, deletion_dict = Response.objects.filter(survey=survey).delete()
        print('Deleted %i responses: %s' % (deletion_count, str(deletion_dict)))
    else:
        survey = Survey(
            year=year,
            season=quarter,
            is_preseason=is_preseason,
            is_ongoing=False,
        )
        survey.save()
        print('Created a new survey: "%s"' % survey)
    

    # +------------------+
    # | GET SURVEY ANIME |
    # +------------------+
    print('Reading survey anime')
    fa = open(survey_anime_file_path, 'r', encoding='utf8')
    fa.readline()
    
    anime_series_map = {}
    special_anime_map = {}
    for line in fa:
        split = line.split('\t')
        series_str = split[0].strip()
        if series_str and not series_str.isspace():
            anime_series = find_accompanying_anime(series_str.split(' | '), True)
            anime_series_map[series_str] = anime_series
        
        special_str = split[1].strip()
        if special_str and not special_str.isspace():
            special_anime = find_accompanying_anime(special_str.split(' | '), False)
            special_anime_map[special_str] = special_anime

    
    # +---------------+
    # | GET LATE ADDS |
    # +---------------+
    if survey_late_adds_file_path:
        print('Reading late adds')
        fl = open(survey_late_adds_file_path, 'r', encoding='utf8')
        fl.readline()

        for line in fl:
            split = line.split('\t')
            anime_str_maybe = split[0].strip()
            add_response_count_str_maybe = split[1].strip()
            search_int = re.search(r'\d+', add_response_count_str_maybe)

            if search_int:
                add_response_count = int(search_int.group())
                if anime_str_maybe in anime_series_map.keys():
                    anime = anime_series_map[anime_str_maybe]
                elif anime_str_maybe in special_anime_map.keys():
                    anime = special_anime_map[anime_str_maybe]
                else:
                    continue
                
                if not anime:
                    continue

                sar = SurveyAdditionRemoval(
                    anime=anime,
                    is_addition=True,
                    response_count=add_response_count,
                    survey=survey,
                )
                sar.save()
                print('Found late add: "%s" added at %i responses' % (str(anime), add_response_count))

    # +---------------------+
    # | READ SURVEY RESULTS |
    # +---------------------+
    print('Reading survey results')
    f = open(survey_file_path, 'r', encoding='utf8')
    headers = f.readline().split('\t')

    animeresponse_list = []

    line_ctr = 2
    for line in f:
        split = line.split('\t')

        # +-----------------+
        # | CREATE RESPONSE |
        # +-----------------+
        timestamp_str = split[0]
        date_split = timestamp_str.split(' ')[0].split('/')
        time_split = timestamp_str.split(' ')[1].split(':')
        timestamp = datetime(
            year=int(date_split[2]),
            month=int(date_split[0]),
            day=int(date_split[1]),
            hour=int(time_split[0]),
            minute=int(time_split[1]),
            second=int(time_split[2]),
        )

        age_str = split[1]
        age = float(age_str) if age_str != '' else None

        gender_str = split[2]
        if gender_str == 'Male':
            gender = Response.Gender.MALE
        elif gender_str == 'Female':
            gender = Response.Gender.FEMALE
        elif gender_str == 'Other':
            gender = Response.Gender.OTHER
        else:
            gender = None

        response = Response(
            timestamp=timestamp,
            survey=survey,
            age=age,
            gender=gender
        )
        response.save()


        # +-------------------------+
        # | GENERATE ANIMERESPONSES |
        # +-------------------------+
        animeresponse_map = {
            anime: AnimeResponse(anime=anime, response=response, watching=False, underwatched=False) for anime in list(anime_series_map.values()) + list(special_anime_map.values()) if anime is not None
        }
        
        # Get watching anime
        watching_anime_str = split[3]
        watching_anime_list = parse_anime_strlist(watching_anime_str, anime_series_map)
        for anime in watching_anime_list:
            animeresponse_map[anime].watching = True

        # Get underwatched anime if post-season
        if not survey.is_preseason:
            underwatched_anime_str = split[4]
            underwatched_anime_list = parse_anime_strlist(underwatched_anime_str, anime_series_map)
            for anime in underwatched_anime_list:
                animeresponse_map[anime].underwatched = True
        


        header_idx = 4 if survey.is_preseason else 5

        # Get anime scores
        while headers[header_idx].startswith('How good '):
            header = headers[header_idx].strip()

            start = header.index('[')
            end = header.rindex(']')
            anime_str = header[start+1:end].strip()
            anime = anime_series_map[anime_str]

            anime_score_str = split[header_idx].strip()
            if anime and anime_score_str and not anime_score_str.isspace() and anime_score_str != 'N/A':
                anime_score = int(anime_score_str[0])
                animeresponse_map[anime].score = anime_score

            header_idx += 1
        
        # Get surprises/disappointments
        while headers[header_idx].startswith('What are your '):
            header = headers[header_idx].strip()

            start = header.index('[')
            end = header.rindex(']')
            anime_str = header[start+1:end].strip()
            anime = anime_series_map[anime_str]

            expectations_str = split[header_idx].strip()
            if anime and expectations_str and not expectations_str.isspace() and expectations_str != 'N/A':
                expectations = AnimeResponse.Expectations.SURPRISE if expectations_str == 'Surprise' else AnimeResponse.Expectations.DISAPPOINTMENT
                animeresponse_map[anime].expectations = expectations
            
            header_idx += 1
        

        # Get watching special anime
        watching_special_anime_str = split[header_idx]
        watching_special_anime_list = parse_anime_strlist(watching_special_anime_str, special_anime_map)
        for anime in watching_special_anime_list:
            animeresponse_map[anime].watching = True
        
        header_idx += 1

        # Get special anime scores
        while header_idx < len(headers) and headers[header_idx].startswith('How good '):
            header = headers[header_idx].strip()

            start = header.index('[')
            end = header.rindex(']')
            anime_str = header[start+1:end].strip()
            anime = special_anime_map[anime_str]

            anime_score_str = split[header_idx].strip()
            if anime and anime_score_str and not anime_score_str.isspace() and anime_score_str != 'N/A':
                anime_score = int(anime_score_str[0])
                animeresponse_map[anime].score = anime_score

            header_idx += 1


        # Filter and save AnimeResponses
        for animeresponse in animeresponse_map.values():
            if survey.is_preseason:
                keep_animeresponse = animeresponse.watching == True or animeresponse.score is not None
            else:
                keep_animeresponse = animeresponse.watching == True

            if keep_animeresponse:
                animeresponse_list.append(animeresponse)
        
        # Bulk create for performance (SQLite only allows max 999 variables per query, >800 to be safe)
        if len(animeresponse_list) > 800:
            AnimeResponse.objects.bulk_create(animeresponse_list)
            animeresponse_list.clear()

        print('Parsed response %i: "%s: %s %s, %s watching, %s special watching"' % (line_ctr, str(timestamp), str(age) if age is not None else '----', str(gender) if gender is not None else '-', str(len(watching_anime_list)), str(len(watching_special_anime_list))))
        line_ctr += 1
        #print('Watching anime: %s' % str('\n'.join([str(anime) for anime in watching_anime_list])))

        # answer = input('Continue? (Y/N) ')
        # if answer.lower() == 'n':
        #     break
    
    AnimeResponse.objects.bulk_create(animeresponse_list)
    animeresponse_list.clear()