def test_filter_admin_has_access_recursive_from_subject(self):
     admin1 = UserBuilder('admin1').user
     nodebuilder = NodeBuilder('docku')
     assignment1 = nodebuilder.add_subject('subject1')\
         .add_admins(admin1)\
         .add_6month_active_period()\
         .add_assignment('assignment1').assignment
     nodebuilder.add_subject('subject2')\
         .add_6month_active_period()\
         .add_assignment('assignment2')
     qry = Assignment.objects.filter_admin_has_access(admin1)
     self.assertEquals(qry.count(), 1)
     self.assertEquals(qry[0], assignment1)
    def test_waiting_for_deliveries_render(self):
        deadlinebuilder = NodeBuilder.quickadd_ducku()\
            .add_subject(short_name='atestcourse', long_name='A Test Course')\
            .add_6month_active_period(short_name='testperiod', long_name='Test Period')\
            .add_assignment('testassignment', long_name='Test Assignment One')\
            .add_group(students=[self.testuser])\
            .add_deadline_in_x_weeks(weeks=1)
        deadlinebuilder.add_delivery_x_hours_before_deadline(hours=1)
        response = self._get_as('testuser')
        self.assertEquals(response.status_code, 200)
        selector = htmls.S(response.content)
        self.assertEquals(selector.count('#objecttableview-table tbody tr'), 1)

        # selector.one('#objecttableview-table tbody tr td:nth-child(1)').prettyprint()
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(1)').alltext_normalized,
            'Test Assignment One')
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(2)').alltext_normalized,
            'A Test Course - Test Period')
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(3)').alltext_normalized,
            'atestcourse - testperiod')
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(4)').alltext_normalized,
            u'6 days, 23 hours from now')
        self.assertTrue(selector.exists('#objecttableview-table tbody tr td:nth-child(4) .text-success'))
    def handle(self, *args, **options):
        self.grandma = UserBuilder('grandma',
                                   full_name='Elvira "Grandma" Coot',
                                   is_superuser=True).user
        self.thor = UserBuilder('thor',
                                full_name='God of Thunder and Battle').user
        self.donald = UserBuilder('donald',
                                  full_name='Donald Duck').user
        self.scrooge = UserBuilder('scrooge',
                                   full_name='Scrooge McDuck').user
        self.examiners = [self.donald, self.scrooge, self.thor]

        self.bad_students = {}
        for username, full_name in bad_students:
            self.bad_students[username] = self.create_or_get_user(username, full_name=full_name)
        self.good_students = {}
        for username, full_name in good_students:
            self.good_students[username] = self.create_or_get_user(username, full_name=full_name)
        self.allstudentslist = list(self.bad_students.values()) + list(list(self.good_students.values()))
        self.april = UserBuilder('april', full_name='April Duck').user

        for user in [self.thor, self.donald, self.april]:
            user.languagecode = 'nb'
            user.save()

        self.duckburgh = NodeBuilder('duckburgh', long_name="University of Duckburgh")
        self.add_emptycourse()
        self.add_duck1100()
        # self.add_hugecourse()
        self.create_feedbackset_complete()
    def test_render(self):
        deadlinebuilder = NodeBuilder.quickadd_ducku()\
            .add_subject(short_name='atestcourse', long_name='A Test Course')\
            .add_6month_active_period(short_name='testperiod', long_name='Test Period')\
            .add_assignment('testassignment', long_name='Test Assignment One')\
            .add_group(students=[self.testuser])\
            .add_deadline_in_x_weeks(weeks=1)
        deliverybuilder = deadlinebuilder.add_delivery_x_hours_before_deadline(hours=1)
        response = self._get_as('testuser')
        self.assertEquals(response.status_code, 200)
        selector = htmls.S(response.content)
        self.assertEquals(selector.count('#objecttableview-table tbody tr'), 1)

        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(1) a').alltext_normalized,
            'Test Assignment One - Delivery#1')
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(1) a')['href'],
            crinstance.reverse_cradmin_url(
                instanceid='devilry_student_group',
                appname='deliveries',
                roleid=deliverybuilder.delivery.deadline.assignment_group_id,
                viewname='deliverydetails',
                kwargs={'pk': deliverybuilder.delivery.pk}))
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(2)').alltext_normalized,
            'A Test Course - Test Period')
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(3)').alltext_normalized,
            'atestcourse - testperiod')
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(4)').alltext_normalized,
            htmls.normalize_whitespace(naturaltime(deliverybuilder.delivery.time_of_delivery)))
    def test_render(self):
        periodbuilder = NodeBuilder.quickadd_ducku()\
            .add_subject(short_name='atestcourse', long_name='A Test Course')\
            .add_6month_active_period(short_name='testperiod', long_name='Test Period')\
            .add_relatedstudents(self.testuser)
        response = self._get_as('testuser')
        self.assertEquals(response.status_code, 200)
        selector = htmls.S(response.content)
        self.assertEquals(selector.count('#objecttableview-table tbody tr'), 1)

        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(1)').alltext_normalized,
            'A Test Course - Test Period')
        self.assertEquals(
            selector.one('#objecttableview-table tbody tr td:nth-child(1) a')['href'],
            crinstance.reverse_cradmin_url(
                instanceid='devilry_student_period',
                appname='assignments',
                roleid=periodbuilder.period.id))
class Command(BaseCommand):
    help = 'Create a database for demo/testing.'

    def handle(self, *args, **options):
        self.grandma = UserBuilder('grandma',
                                   full_name='Elvira "Grandma" Coot',
                                   is_superuser=True).user
        self.thor = UserBuilder('thor',
                                full_name='God of Thunder and Battle').user
        self.donald = UserBuilder('donald',
                                  full_name='Donald Duck').user
        self.scrooge = UserBuilder('scrooge',
                                   full_name='Scrooge McDuck').user
        self.examiners = [self.donald, self.scrooge, self.thor]

        self.bad_students = {}
        for username, full_name in bad_students:
            self.bad_students[username] = self.create_or_get_user(username, full_name=full_name)
        self.good_students = {}
        for username, full_name in good_students:
            self.good_students[username] = self.create_or_get_user(username, full_name=full_name)
        self.allstudentslist = list(self.bad_students.values()) + list(list(self.good_students.values()))
        self.april = UserBuilder('april', full_name='April Duck').user

        for user in [self.thor, self.donald, self.april]:
            user.languagecode = 'nb'
            user.save()

        self.duckburgh = NodeBuilder('duckburgh', long_name="University of Duckburgh")
        self.add_emptycourse()
        self.add_duck1100()
        # self.add_hugecourse()
        self.create_feedbackset_complete()

    def create_or_get_user(self, username, full_name):
        try:
            return UserBuilder(username, full_name=full_name).user
        except ValidationError:
            if settings.DJANGO_CRADMIN_USE_EMAIL_AUTH_BACKEND:
                shortname = '{}@example.com'.format(username)
            else:
                shortname = username
            return get_user_model().objects.get(shortname=shortname)

    def build_random_pointassignmentdata(self,
                                         periodbuilder, weeks_ago, short_name, long_name,
                                         filecount,
                                         feedback_percent=100,
                                         bad_students=None, good_students=None):
        bad_students_iterator = bad_students or self.bad_students.itervalues()
        good_students_iterator = good_students or self.good_students.itervalues()

        assignmentbuilder = periodbuilder.add_assignment_x_weeks_ago(
            weeks=weeks_ago,
            short_name=short_name, long_name=long_name,
            passing_grade_min_points=1,
            grading_system_plugin_id='devilry_gradingsystemplugin_points',
            points_to_grade_mapper='raw-points',
            max_points=filecount,
            first_deadline=DateTimeBuilder.now().minus(weeks=weeks_ago - 1)
        )

        def create_group(user, minpoints, maxpoints, examiner):
            def create_old_delivery_structure():
                deadlinebuilder = groupbuilder \
                    .add_deadline(
                        deadline=Deadline.reduce_datetime_precision(
                            assignmentbuilder.assignment.first_deadline))

                deliverybuilder = deadlinebuilder.add_delivery_x_hours_before_deadline(
                    hours=random.randint(1, 30))
                used_filenames = set()
                for number in xrange(filecount):
                    while True:
                        deliveryfile = random.choice(programs)
                        filename = deliveryfile['filename']
                        if filename not in used_filenames:
                            used_filenames.add(filename)
                            break
                    deliverybuilder.add_filemeta(
                        filename=deliveryfile['filename'],
                        data=deliveryfile['data'])

                if random.randint(0, 100) <= feedback_percent:
                    feedback = StaticFeedback.from_points(
                        assignment=assignmentbuilder.assignment,
                        saved_by=examiner,
                        delivery=deliverybuilder.delivery,
                        rendered_view=self._lorem_paras(random.randint(1, 5)),
                        points=random.randint(minpoints, maxpoints))
                    feedback.save()

            def create_feedbackset_structure():

                def randomize_files():
                    return random.sample(comment_files, int(random.uniform(0, len(comment_files))))

                def get_comment_text():
                    return comment_texts[int(random.uniform(0, len(comment_texts)))]

                feedbacksetbuilder = groupbuilder.add_feedback_set(
                    points=random.randint(minpoints, maxpoints),
                    published_by=examiner,
                    created_by=examiner,
                    deadline_datetime=DateTimeBuilder.now().minus(weeks=weeks_ago),
                    gradeform_json="test"
                )

                # add student delivery
                feedbacksetbuilder.add_groupcomment(
                    files=randomize_files(),
                    user=user,
                    user_role="student",
                    instant_publish=True,
                    visible_for_students=True,
                    text=get_comment_text(),
                    published_datetime=DateTimeBuilder.now().minus(weeks=weeks_ago, days=4))

                users = [{'user': user, 'role': 'student'}, {'user': examiner, 'role': 'examiner'}]
                # add random comments
                for i in xrange(0, int(random.uniform(0, 5))):
                    random_user = users[int(random.uniform(0, 1))]
                    feedbacksetbuilder.add_groupcomment(
                        files=randomize_files(),
                        user=random_user['user'],
                        user_role=random_user['role'],
                        instant_publish=True,
                        visible_for_students=True,
                        text=get_comment_text(),
                        published_datetime=DateTimeBuilder.now().minus(weeks=weeks_ago, days=3,
                                                                       hours=int(random.uniform(0, 23))))

                # add examiner feedback
                feedbacksetbuilder.add_groupcomment(
                    files=randomize_files(),
                    user=examiner,
                    user_role="examiner",
                    instant_publish=bool(random.getrandbits(1)),
                    visible_for_students=True,
                    text=get_comment_text(),
                    published_datetime=DateTimeBuilder.now().minus(weeks=weeks_ago, days=2))

            try:
                relatedstudent = RelatedStudent.objects.get(period=assignmentbuilder.assignment.period,
                                                            user=user)
            except:
                print()
                print("*" * 70)
                print()
                print(user)
                print()
                print("*" * 70)
                print()

                raise
            groupbuilder = assignmentbuilder.add_group(
                relatedstudents=[relatedstudent], examiners=[examiner])

            if weeks_ago > 52:
                create_old_delivery_structure()
            else:
                create_feedbackset_structure()

        for user in bad_students_iterator:
            create_group(user, minpoints=0, maxpoints=filecount / 2,
                         examiner=random.choice(self.examiners))
        for user in good_students_iterator:
            create_group(user, minpoints=filecount / 2, maxpoints=filecount,
                         examiner=random.choice(self.examiners))
        create_group(self.april, minpoints=1, maxpoints=filecount,
                     examiner=self.donald)
        return assignmentbuilder

    def _as_relatedstudents(self, users, tags):
        return [RelatedStudent(user=user, tags=tags) for user in users]

    def add_emptycourse(self):
        democourse = self.duckburgh.add_subject(
            short_name='democourse',
            long_name='DEMO101 - A demo course')
        democourse.add_admins(self.thor)
        print
        print("*" * 70)
        print
        print('Empty course named "DEMO101 - A demo course" added')
        print
        print("*" * 70)
        print

    def add_hugecourse(self):
        duck1100 = self.duckburgh.add_subject(
            short_name='hugecourse',
            long_name='HUGE1000 - A huge testcourse')
        duck1100.add_admins(self.thor)

        periodbuilder = duck1100.add_6month_active_period(
            short_name='testsemester', long_name='Testsemester',
            relatedexaminers=[
                RelatedExaminer(user=self.thor, tags=''),
                RelatedExaminer(user=self.donald, tags='group1'),
                RelatedExaminer(user=self.scrooge, tags='group2')
            ])

        bad_studentusers = []
        good_studentusers = []
        relatedstudents = []
        for x in xrange(2000):
            studentuser = UserBuilder('student{}'.format(x)).user
            if random.randint(0, 1):
                good_studentusers.append(studentuser)
            else:
                bad_studentusers.append(studentuser)
            relatedstudent = RelatedStudent(
                period=periodbuilder.period,
                user=studentuser,
                tags='group{}'.format(random.randint(1, 2)))
            relatedstudents.append(relatedstudent)
        RelatedStudent.objects.bulk_create(relatedstudents)

        self.build_random_pointassignmentdata(
            periodbuilder=periodbuilder,
            weeks_ago=2, filecount=2,
            short_name='oblig1', long_name='Obligatory assignment one',
            bad_students=bad_studentusers,
            good_students=good_studentusers)

    def add_duck1100(self):
        duck1100 = self.duckburgh.add_subject(
            short_name='duck1100',
            long_name='DUCK1100 - Programming for the natural sciences')
        duck1100.add_admins(self.thor)

        relatedstudents = [
            RelatedStudent(user=self.april, tags='group1'),
        ]
        relatedstudents.extend(self._as_relatedstudents(self.good_students.values(), 'group1'))
        relatedstudents.extend(self._as_relatedstudents(self.bad_students.values(), 'group2'))
        testsemester = duck1100.add_6month_active_period(
            short_name='testsemester', long_name='Testsemester',
            relatedstudents=relatedstudents,
            relatedexaminers=[
                RelatedExaminer(user=self.thor, tags=''),
                RelatedExaminer(user=self.donald, tags='group1'),
                RelatedExaminer(user=self.scrooge, tags='group2')
            ])

        # old_relatedstudentusers = [
        #     self.thor,
        #     self.april, self.bad_students['dewey'],
        #     self.bad_students['louie'], self.bad_students['june'],
        #     self.good_students['loki'], self.good_students['kvasir']]
        # old_relatedstudents = self._as_relatedstudents(old_relatedstudentusers, tags='')
        oldtestsemester = duck1100.add_6month_lastyear_period(
            short_name='oldtestsemester', long_name='Old testsemester',
            relatedstudents=relatedstudents,
            relatedexaminers=[
                RelatedExaminer(user=self.thor, tags=''),
                RelatedExaminer(user=self.donald, tags='group1'),
                RelatedExaminer(user=self.scrooge, tags='group2')
            ])

        for periodbuilder, weekoffset in [
                (oldtestsemester, 52),
                (testsemester, 0)]:
            self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset + 6, filecount=4,
                short_name='week1', long_name='Week 1')
            self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset + 5, filecount=2,
                short_name='week2', long_name='Week 2')
            self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset + 4, filecount=4,
                short_name='week3', long_name='Week 3')
            self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset + 3, filecount=8,
                short_name='week4', long_name='Week 4')

            if weekoffset == 0:
                self.build_random_pointassignmentdata(
                    periodbuilder=periodbuilder,
                    weeks_ago=weekoffset + 1, filecount=6,
                    short_name='week5', long_name='Week 5',
                    feedback_percent=50)

                week6 = periodbuilder.add_assignment_x_weeks_ago(
                    weeks=weekoffset, short_name='week6', long_name='Week 6',
                    passing_grade_min_points=1,
                    grading_system_plugin_id='devilry_gradingsystemplugin_points',
                    points_to_grade_mapper='raw-points',
                    max_points=6
                )
                for user in self.allstudentslist + [self.april]:
                    examiner = random.choice(self.examiners)
                    week6 \
                        .add_group(students=[user], examiners=[examiner]) \
                        .add_deadline(deadline=Deadline.reduce_datetime_precision(DateTimeBuilder.now().plus(days=7)))
            else:
                self.build_random_pointassignmentdata(
                    periodbuilder=periodbuilder,
                    weeks_ago=weekoffset + 1, filecount=1,
                    short_name='week5', long_name='Week 5')
                self.build_random_pointassignmentdata(
                    periodbuilder=periodbuilder,
                    weeks_ago=weekoffset, filecount=2,
                    short_name='week6', long_name='Week 6')

        print
        print("*" * 70)
        print
        print('duck1100 added')
        print
        print("*" * 70)
        print

    def create_feedbackset_complete(self):
        # Create a finished feedback_set for a specified user on a new subject
        # and a new assingment in the current period
        student = UserBuilder('psylocke', full_name='Elisabeth Braddock').user
        examiner = UserBuilder('magneto', full_name='Erik Lehnsherr').user
        examiner2 = UserBuilder('beast', full_name='Hank McCoy').user

        first_deadline = timezone.now() - timezone.timedelta(weeks=2, days=1)


        assignment_setup_gradeform_json = {
            "type": "advanced",
            "id": "uyagsfuyg43t763t42gtysfeg82376rf2uytf27836dgfweytfgv7238",
            "schema":
            [

                {
                  "id": "uasgf87###ASDSAIDQuestion title",
                  "title":"Question title",
                  "explanation":"Explanation of how to fill in",
                  "options_type":"range",
                  "range_from": 0,
                  "range_to": 100,
                  "value": 50,
                  "comment": ""
                },

                {
                  "id": "uasek32002AIDQuestion title",
                  "title":"Question title",
                  "explanation":"Explanation of how to fill in",
                  "options_type":"single_select",
                  "options":
                  [
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""},
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""},
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""},
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""}
                  ]
                },

                {
                  "id": "ullsoqppp987#@asdIDQuestion title",
                  "title":"Question title",
                  "explanation":"Explanation of how to fill in",
                  "options_type":"multi_select",
                  "options":
                  [
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""},
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""},
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""},
                    {"value": "false", "points": 1, "choise_text":"some choise", "comment": ""}
                  ]
                },

                {
                  "id": "sdaikjfoa4788698236487263847iwufghQuestion title",
                  "title":"Question title",
                  "explanation":"Explanation of how to fill in",
                  "options_type":"feedback",
                  "feedback": "some written feedback in a textarea"
                }
            ]
        }

        data = {
            'type': 'advanced',
            'scheme': [
                {"points_max": "5", "points_achieved": "5", "text": "Has the student documented the code?", "comment": "Great documentation"},
                {"points_max": "5", "points_achieved": "3", "text": "Implemented own datastructures?", "comment": "You where meant to implement all datastructures. You didn't implement the hashmap ='("},
                {"points_max": "5", "points_achieved": "4", "text": "Has the student understood the different pros and cons for the datastructures?", "comment": "Shows good understanding"},
                {"points_max": "5", "points_achieved": "0", "text": "Fullfilling designdocument?", "comment": "You where supposed to deliver a document with CONTENT, not an empty one!"},
            ]
        }

        periodbuilder = self.duckburgh.add_subject(
            short_name='inf7020',
            long_name='INF7020 Programming for World Domination and Crashing Non-Mutant Economy',
        ).add_6month_active_period(
            short_name='testsemester',
            long_name='Testsemester',
            relatedexaminers=[
                RelatedExaminer(user=examiner),
                RelatedExaminer(user=examiner2),
            ],
            relatedstudents=[student])
        assignmentgroupbuilder = periodbuilder.add_assignment(
            'Oblig 1 - Domination',
            passing_grade_min_points=3,
            max_points=10,
            first_deadline=first_deadline,
            gradeform_setup_json=json.dumps(assignment_setup_gradeform_json)
        ).add_group()

        assignmentgroupbuilder.add_candidates_from_relatedstudents(
            *periodbuilder.period.relatedstudent_set.all())
        assignmentgroupbuilder.add_examiners(examiner, examiner2)

        feedbacksetbuilder1 = assignmentgroupbuilder.add_feedback_set(
            points=1,
            published_by=examiner,
            created_by=examiner,
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=5, hours=2),
            created_datetime=DateTimeBuilder.now().minus(weeks=4),
            deadline_datetime=first_deadline,
            gradeform_json=json.dumps(data)
        )

        # Event summary for feedback_set 1
        feedbacksetbuilder1.add_groupcomment(
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text="I don't know how to solve this, can't I just use my private army?",
            published_datetime=DateTimeBuilder.now().minus(weeks=2, days=2)
        )

        feedbacksetbuilder1.add_groupcomment(
            user=examiner,
            user_role='examiner',
            instant_publish=True,
            visible_for_students=True,
            text="No no no, you're here to learn how to get domination using information "
                 "technology. Later you will learn to use automate your abilities by programming them.",
            published_datetime=DateTimeBuilder.now().minus(weeks=2, days=2)
        )

        feedbacksetbuilder1.add_groupcomment(
            files=[comment_files[0]],
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text='Here my assignment! I think I have a great solution! =D',
            published_datetime=DateTimeBuilder.now().minus(weeks=2, days=1, hours=1)
        )

        feedbacksetbuilder1.add_groupcomment(
            files=[comment_files[1]],
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text='Wuups! Forgot this file!',
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=5, hours=3)
        )

        feedbacksetbuilder1.add_groupcomment(
            files=[comment_files[1]],
            user=examiner,
            user_role='examiner',
            instant_publish=True,
            visible_for_students=True,
            text="You failed miserably! Try to actually understand the problem. Printing 'hello world, I own you now' "
                 "everywhere won't get you anywhere!",
            published_datetime=feedbacksetbuilder1.feedback_set.published_datetime
            # DateTimeBuilder.now().minus(weeks=1, days=5, hours=1)
        )

        feedbacksetbuilder1.add_groupcomment(
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text='Noooooooo! New try pls?',
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=4, hours=23)
        )

        feedbacksetbuilder1.add_groupcomment(
            user=examiner,
            user_role='examiner',
            instant_publish=True,
            visible_for_students=True,
            text="Ok, I'll give you a second try!",
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=4, hours=22)
        )


        # Event summary for feedback_set 2
        feedbacksetbuilder2 = assignmentgroupbuilder.add_feedback_set(
            points=10,
            published_by=examiner,
            created_by=examiner,
            published_datetime=DateTimeBuilder.now().minus(weeks=0, days=3),
            created_datetime=DateTimeBuilder.now().minus(weeks=1, days=4, hours=21),
            deadline_datetime=DateTimeBuilder.now().minus(weeks=1),
            gradeform_json=json.dumps(data)
        )

        feedbacksetbuilder2.add_groupcomment(
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text="Thanks!",
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=4, hours=18)
        )

        feedbacksetbuilder2.add_groupcomment(
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text="Do you like cashew nuts?",
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=4, hours=16)
        )

        feedbacksetbuilder2.add_groupcomment(
            user=examiner,
            user_role='examiner',
            instant_publish=True,
            visible_for_students=True,
            text="Stay on topic please... But, yes...",
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=3)
        )

        feedbacksetbuilder2.add_groupcomment(
            files=[comment_files[0], comment_files[1]],
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text='Here we go again!',
            published_datetime=DateTimeBuilder.now().minus(weeks=1, days=2)
        )

        feedbacksetbuilder2.add_groupcomment(
            files=[comment_files[2]],
            user=examiner,
            user_role='examiner',
            instant_publish=True,
            visible_for_students=True,
            text="Great job! You must be the most evil mutant I have ever met! Keep going like this, "
                 "and you'll own the entire planet in no time!",
            published_datetime=feedbacksetbuilder2.feedback_set.published_datetime
            # DateTimeBuilder.now().minus(weeks=0, days=3)
        )

        feedbacksetbuilder2.add_groupcomment(
            user=student,
            user_role='student',
            instant_publish=True,
            visible_for_students=True,
            text="Thanks! Sorry for the first delivery, I was so hungover when I worked on that!",
            published_datetime=DateTimeBuilder.now().minus(weeks=0, days=2)
        )

    def _lorem_paras(self, count):
        return markdown_full(u'\n\n'.join(
            lorem_ipsum.paragraphs(count, common=False))
        )
class Command(BaseCommand):
    help = 'Create a database for demo/testing.'

    def handle(self, *args, **options):
        self.grandma = UserBuilder('grandma',
            full_name='Elvira "Grandma" Coot',
            is_superuser=True, is_staff=True).user
        self.thor = UserBuilder('thor',
            full_name='God of Thunder and Battle').user
        self.donald = UserBuilder('donald',
            full_name='Donald Duck').user
        self.scrooge = UserBuilder('scrooge',
            full_name='Scrooge McDuck').user
        self.examiners = [self.donald, self.scrooge, self.thor]

        self.bad_students = {}
        for username, full_name in bad_students:
            self.bad_students[username] = self.create_or_get_user(username, full_name=full_name)
        self.good_students = {}
        for username, full_name in good_students:
            self.good_students[username] = self.create_or_get_user(username, full_name=full_name)
        self.allstudentslist = list(self.bad_students.values()) + list(list(self.good_students.values()))
        self.april = UserBuilder('april', full_name='April Duck').user

        for user in [self.thor, self.donald, self.april]:
            user.devilryuserprofile.languagecode = 'nb'
            user.devilryuserprofile.save()

        self.duckburgh = NodeBuilder('duckburgh', long_name="University of Duckburgh")
        self.add_duck1100()
        # self.add_hugecourse()

    def create_or_get_user(self, username, full_name):
        try:
            return UserBuilder(username, full_name=full_name).user
        except ValidationError:
            return get_user_model().objects.get(username=username)

    def build_random_pointassignmentdata(self,
                                         periodbuilder, weeks_ago, short_name, long_name,
                                         filecount,
                                         feedback_percent=100,
                                         bad_students=None, good_students=None):
        bad_students_iterator = bad_students or self.bad_students.itervalues()
        good_students_iterator = good_students or self.good_students.itervalues()

        assignmentbuilder = periodbuilder.add_assignment_x_weeks_ago(
            weeks=weeks_ago,
            short_name=short_name, long_name=long_name,
            passing_grade_min_points=1,
            grading_system_plugin_id='devilry_gradingsystemplugin_points',
            points_to_grade_mapper='raw-points',
            max_points=filecount,
            first_deadline=DateTimeBuilder.now().minus(weeks=weeks_ago-1)
        )

        def create_group(user, minpoints, maxpoints, examiner):
            groupbuilder = assignmentbuilder.add_group(
                students=[user], examiners=[examiner])
            deadlinebuilder = groupbuilder\
                .add_deadline(
                    deadline=Deadline.reduce_datetime_precision(assignmentbuilder.assignment.first_deadline))

            deliverybuilder = deadlinebuilder.add_delivery_x_hours_before_deadline(
                hours=random.randint(1, 30))
            used_filenames = set()
            for number in xrange(filecount):
                while True:
                    deliveryfile = random.choice(programs)
                    filename = deliveryfile['filename']
                    if filename not in used_filenames:
                        used_filenames.add(filename)
                        break
                deliverybuilder.add_filemeta(
                    filename=deliveryfile['filename'],
                    data=deliveryfile['data'])

            if random.randint(0, 100) <= feedback_percent:
                feedback = StaticFeedback.from_points(
                    assignment=assignmentbuilder.assignment,
                    saved_by=examiner,
                    delivery=deliverybuilder.delivery,
                    rendered_view=self._lorem_paras(random.randint(1, 5)),
                    points=random.randint(minpoints, maxpoints))
                feedback.save()

        for user in bad_students_iterator:
            create_group(user, minpoints=0, maxpoints=filecount/2,
                         examiner=random.choice(self.examiners))
        for user in good_students_iterator:
            create_group(user, minpoints=filecount/2, maxpoints=filecount,
                         examiner=random.choice(self.examiners))
        create_group(self.april, minpoints=1, maxpoints=filecount,
                     examiner=self.donald)
        return assignmentbuilder

    def _as_relatedstudents(self, users, tags):
        return [RelatedStudent(user=user, tags=tags) for user in users]

    def add_hugecourse(self):
        duck1100 = self.duckburgh.add_subject(
            short_name='hugecourse',
            long_name='HUGE1000 - A huge testcourse')
        duck1100.add_admins(self.thor)

        periodbuilder = duck1100.add_6month_active_period(
            short_name='testsemester', long_name='Testsemester',
            relatedexaminers=[
                RelatedExaminer(user=self.thor, tags=''),
                RelatedExaminer(user=self.donald, tags='group1'),
                RelatedExaminer(user=self.scrooge, tags='group2')
            ])

        bad_studentusers = []
        good_studentusers = []
        relatedstudents = []
        for x in xrange(2000):
            studentuser = UserBuilder('student{}'.format(x)).user
            if random.randint(0, 1):
                good_studentusers.append(studentuser)
            else:
                bad_studentusers.append(studentuser)
            relatedstudent = RelatedStudent(
                period=periodbuilder.period,
                user=studentuser,
                tags='group{}'.format(random.randint(1, 2)))
            relatedstudents.append(relatedstudent)
        RelatedStudent.objects.bulk_create(relatedstudents)

        self.build_random_pointassignmentdata(
            periodbuilder=periodbuilder,
            weeks_ago=2, filecount=2,
            short_name='oblig1', long_name='Obligatory assignment one',
            bad_students=bad_studentusers,
            good_students=good_studentusers)

    def add_duck1100(self):
        duck1100 = self.duckburgh.add_subject(
            short_name='duck1100',
            long_name='DUCK1010 - Programming for the natural sciences')
        duck1100.add_admins(self.thor)

        relatedstudents = [RelatedStudent(user=self.april, tags='group1')]
        relatedstudents.extend(self._as_relatedstudents(self.good_students.values(), 'group1'))
        relatedstudents.extend(self._as_relatedstudents(self.bad_students.values(), 'group2'))
        testsemester = duck1100.add_6month_active_period(
            short_name='testsemester', long_name='Testsemester',
            relatedstudents=relatedstudents,
            relatedexaminers=[
                RelatedExaminer(user=self.thor, tags=''),
                RelatedExaminer(user=self.donald, tags='group1'),
                RelatedExaminer(user=self.scrooge, tags='group2')
            ])

        old_relatedstudentusers = [
            self.april, self.bad_students['dewey'],
            self.bad_students['louie'], self.bad_students['june'],
            self.good_students['loki'], self.good_students['kvasir']]
        old_relatedstudents = self._as_relatedstudents(old_relatedstudentusers, tags='')
        oldtestsemester = duck1100.add_6month_lastyear_period(
            short_name='oldtestsemester', long_name='Old testsemester',
            relatedstudents=old_relatedstudents,
            relatedexaminers=[
                RelatedExaminer(user=self.thor, tags=''),
                RelatedExaminer(user=self.donald, tags='group1'),
                RelatedExaminer(user=self.scrooge, tags='group2')
            ])

        for periodbuilder, weekoffset in [
                (oldtestsemester, 52),
                (testsemester, 0)]:
            week1 = self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset+6, filecount=4,
                short_name='week1', long_name='Week 1')
            week2 = self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset+5, filecount=2,
                short_name='week2', long_name='Week 2')
            week3 = self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset+4, filecount=4,
                short_name='week3', long_name='Week 3')
            week4 = self.build_random_pointassignmentdata(
                periodbuilder=periodbuilder,
                weeks_ago=weekoffset+3, filecount=8,
                short_name='week4', long_name='Week 4')

            if weekoffset == 0:
                week5 = self.build_random_pointassignmentdata(
                    periodbuilder=periodbuilder,
                    weeks_ago=weekoffset+1, filecount=6,
                    short_name='week5', long_name='Week 5',
                    feedback_percent=50)

                week6 = periodbuilder.add_assignment_x_weeks_ago(
                    weeks=weekoffset, short_name='week6', long_name='Week 6',
                    passing_grade_min_points=1,
                    grading_system_plugin_id='devilry_gradingsystemplugin_points',
                    points_to_grade_mapper='raw-points',
                    max_points=6
                )
                for user in self.allstudentslist + [self.april]:
                    examiner = random.choice(self.examiners)
                    week6\
                        .add_group(students=[user], examiners=[examiner])\
                        .add_deadline(deadline=Deadline.reduce_datetime_precision(DateTimeBuilder.now().plus(days=7)))
            else:
                week5 = self.build_random_pointassignmentdata(
                    periodbuilder=periodbuilder,
                    weeks_ago=weekoffset+1, filecount=1,
                    short_name='week5', long_name='Week 5')
                week6 = self.build_random_pointassignmentdata(
                    periodbuilder=periodbuilder,
                    weeks_ago=weekoffset, filecount=2,
                    short_name='week6', long_name='Week 6')


    def _lorem_paras(self, count):
        return markdown_full(u'\n\n'.join(lorem_ipsum.paragraphs(count, common=False)))