Beispiel #1
0
    def setUp(self):
        # create dummy channel
        channel_id = uuid.uuid4().hex
        root = ContentNode.objects.create(
            id=uuid.uuid4().hex,
            title="root",
            channel_id=channel_id,
            content_id=uuid.uuid4().hex,
        )
        min_timestamp = datetime.datetime(2018, 10, 11)
        self.channel = ChannelMetadata.objects.create(
            id=channel_id,
            name="channel",
            last_updated=min_timestamp,
            root=root)
        lf = LocalFile.objects.create(
            id=uuid.uuid4().hex,
            available=True,
            file_size=1048576  # 1 MB
        )
        File.objects.create(id=uuid.uuid4().hex,
                            contentnode=root,
                            local_file=lf)

        # Load in the user data from the csv file to give a predictable source of user data
        data_path = os.path.join(USER_CSV_PATH)
        with io.open(data_path, mode="r", encoding="utf-8") as f:
            users = [data for data in csv.DictReader(f)]

        n_facilities = 1
        n_classes = 1  # 1 class x 1 facility = 1 class
        n_users = 20  # 20 users x 1 facility = 20 users
        max_timestamp = datetime.datetime(2019, 10, 11)

        self.facilities = user_data.get_or_create_facilities(
            n_facilities=n_facilities)
        for facility in self.facilities:
            dataset = facility.dataset
            # create superuser and login session
            superuser = create_superuser(facility=facility)
            facility.add_role(superuser, role_kinds.ADMIN)
            UserSessionLog.objects.create(
                user=superuser,
                start_timestamp=min_timestamp,
                last_interaction_timestamp=max_timestamp,
            )
            # create lesson and exam for facility
            Lesson.objects.create(created_by=superuser,
                                  title="lesson",
                                  collection=facility)
            exam = Exam.objects.create(creator=superuser,
                                       title="exam",
                                       question_count=1,
                                       collection=facility)

            classrooms = user_data.get_or_create_classrooms(
                n_classes=n_classes, facility=facility)

            # Get all the user data at once so that it is distinct across classrooms
            facility_user_data = random.sample(users, n_classes * n_users)

            # create random content id for the session logs
            self.content_id = uuid.uuid4().hex
            for i, classroom in enumerate(classrooms):
                classroom_user_data = facility_user_data[i * n_users:(i + 1) *
                                                         n_users]
                users = user_data.get_or_create_classroom_users(
                    n_users=n_users,
                    classroom=classroom,
                    user_data=classroom_user_data,
                    facility=facility,
                )
                # create 1 of each type of log per user
                for user in users:
                    for _ in range(1):
                        sessionlog = ContentSessionLog.objects.create(
                            user=user,
                            start_timestamp=min_timestamp,
                            end_timestamp=max_timestamp,
                            content_id=self.content_id,
                            channel_id=self.channel.id,
                            time_spent=60,  # 1 minute
                            kind=content_kinds.EXERCISE,
                        )
                        AttemptLog.objects.create(
                            item="item",
                            start_timestamp=min_timestamp,
                            end_timestamp=max_timestamp,
                            completion_timestamp=max_timestamp,
                            correct=1,
                            sessionlog=sessionlog,
                        )
                        # create 1 anon log per user session log
                        ContentSessionLog.objects.create(
                            dataset=dataset,
                            user=None,
                            start_timestamp=min_timestamp,
                            end_timestamp=max_timestamp,
                            content_id=self.content_id,
                            channel_id=self.channel.id,
                            time_spent=60,  # 1 minute,
                            kind=content_kinds.VIDEO,
                        )
                    for _ in range(1):
                        UserSessionLog.objects.create(
                            user=user,
                            start_timestamp=min_timestamp,
                            last_interaction_timestamp=max_timestamp,
                            device_info="Android,9/Chrome Mobile,86",
                        )
                    for _ in range(1):
                        ContentSummaryLog.objects.create(
                            user=user,
                            start_timestamp=min_timestamp,
                            end_timestamp=max_timestamp,
                            completion_timestamp=max_timestamp,
                            content_id=uuid.uuid4().hex,
                            channel_id=self.channel.id,
                        )
                    for _ in range(1):
                        examlog = ExamLog.objects.create(exam=exam, user=user)
                        ExamAttemptLog.objects.create(
                            examlog=examlog,
                            start_timestamp=min_timestamp,
                            end_timestamp=max_timestamp,
                            completion_timestamp=max_timestamp,
                            correct=1,
                            content_id=uuid.uuid4().hex,
                        )
Beispiel #2
0
    def handle(self, *args, **options):
        # Load in the user data from the csv file to give a predictable source of user data
        data_path = os.path.join(os.path.dirname(__file__), "user_data.csv")
        with io.open(data_path, mode="r", encoding="utf-8") as f:
            user_data = [data for data in csv.DictReader(f)]

        n_seed = options["seed"]
        n_facilities = options["facilities"]
        n_users = options["users"]
        n_classes = options["classes"]
        no_onboarding = options["no_onboarding"]
        num_content_items = options["num_content_items"]
        num_lessons = options["num_lessons"]
        num_exams = options["num_exams"]
        max_channels = options["max_channels"]
        device_name = options["device_name"]
        # TODO(cpauya):
        # num_groups = options["num_groups"]
        # channel_token = options["channel_token"]

        # TODO(cpauya): Default to the computer/VM name so we get a unique name for each VM automatically.
        # if not device_name:
        #     # Default to computer name.
        #     # REF: https://stackoverflow.com/questions/4271740/how-can-i-use-python-to-get-the-system-hostname#4271755
        #     import socket
        #     device_name = socket.gethostname()
        #     utils.logger_info("Defaulting 'device_name' to '{0}'.".format(device_name))

        # Set the random seed so that all operations will be randomized predictably
        random.seed(n_seed)

        # Generate data up to the current time
        now = timezone.now()

        facilities = utils.get_or_create_facilities(
            n_facilities=n_facilities, device_name=device_name
        )

        # Device needs to be provisioned before adding superusers
        if no_onboarding:
            utils.logger_info(
                "Provisioning device. Onboarding will be skipped after starting server."
            )
            provision_device()

        for facility in facilities:
            if no_onboarding:
                utils.logger_info(
                    'Creating superuser "superuser" with password "password" at facility {facility}.'.format(
                        facility=facility.name
                    )
                )
                create_superuser(facility=facility)

            classrooms = utils.get_or_create_classrooms(
                n_classes=n_classes, facility=facility, device_name=device_name
            )

            # TODO(cpauya):
            # if channel_token:
            #     # TODO(cpauya): which table do we get the channel_token field?
            #     channels = ChannelMetadata.objects.filter(channel_token=channel_token)
            # else:
            #     channels = ChannelMetadata.objects.all()[:max_channels]

            channels = ChannelMetadata.objects.all()
            if max_channels and max_channels > 0:
                channels = channels[:max_channels]

            if not channels:
                utils.logger_info(
                    "No channels found, cannot add channel activities for learners."
                )

            # Get all the user data at once so that it is distinct across classrooms
            facility_user_data = random.sample(user_data, n_classes * n_users)

            for i, classroom in enumerate(classrooms):
                classroom_user_data = facility_user_data[
                    i * n_users : (i + 1) * n_users
                ]
                users = utils.get_or_create_classroom_users(
                    n_users=n_users,
                    classroom=classroom,
                    user_data=classroom_user_data,
                    facility=facility,
                    device_name=device_name,
                )

                # Iterate through the slice of the facility_user_data specific to this classroom
                for user, base_data in zip(users, classroom_user_data):
                    # The user data we are fetching from has 'Age' as a characteristic, use this as the "age" of the user
                    # in terms of their content interaction history - older, more content items interacted with!
                    if num_content_items:
                        n_content_items = num_content_items
                    else:
                        n_content_items = int(base_data["Age"])

                    # Loop over all local channels to generate data for each channel
                    utils.logger_info("    Learner {learner}...".format(learner=user))
                    for channel in channels:
                        # TODO(cpauya): check for issue as per Richard's report
                        # REF: https://github.com/learningequality/kolibri/pull/6983#issuecomment-638980072
                        utils.logger_info(
                            "      ==> Adding {channel} channel activity for learner {learner}...".format(
                                channel=channel, learner=user
                            )
                        )
                        utils.add_channel_activity_for_user(
                            n_content_items=n_content_items,
                            channel=channel,
                            user=user,
                            now=now,
                        )

                # create lessons
                utils.create_lessons_for_classroom(
                    classroom=classroom,
                    facility=facility,
                    channels=ChannelMetadata.objects.all(),
                    lessons=num_lessons,
                    now=now,
                )

                # create exams
                utils.create_exams_for_classrooms(
                    classroom=classroom,
                    facility=facility,
                    channels=ChannelMetadata.objects.all(),
                    exams=num_exams,
                    now=now,
                    device_name=device_name,
                )
Beispiel #3
0
    def handle(self, *args, **options):
        # Load in the user data from the csv file to give a predictable source of user data
        data_path = os.path.join(os.path.dirname(__file__), "user_data.csv")
        with io.open(data_path, mode="r", encoding="utf-8") as f:
            user_data = [data for data in csv.DictReader(f)]

        n_users = options["users"]
        n_classes = options["classes"]
        no_onboarding = options["no_onboarding"]
        num_content_items = options["num_content_items"]
        num_lessons = options["num_lessons"]
        num_exams = options["num_exams"]

        # Set the random seed so that all operations will be randomized predictably
        random.seed(options["seed"])

        # Generate data up to the current time
        now = timezone.now()

        facilities = utils.get_or_create_facilities(
            n_facilities=options["facilities"])

        # Device needs to be provisioned before adding superusers
        if no_onboarding:
            logger.info(
                "Provisioning device. Onboarding will be skipped after starting server."
            )
            provision_device()

        for facility in facilities:
            if no_onboarding:
                logger.info(
                    'Creating superuser "superuser" with password "password" at facility {facility}.'
                    .format(facility=facility.name))
                create_superuser(facility=facility)

            classrooms = utils.get_or_create_classrooms(n_classes=n_classes,
                                                        facility=facility)

            # Get all the user data at once so that it is distinct across classrooms
            facility_user_data = random.sample(user_data, n_classes * n_users)

            for i, classroom in enumerate(classrooms):
                classroom_user_data = facility_user_data[i * n_users:(i + 1) *
                                                         n_users]
                users = utils.get_or_create_classroom_users(
                    n_users=n_users,
                    classroom=classroom,
                    user_data=classroom_user_data,
                    facility=facility,
                )

                # Iterate through the slice of the facility_user_data specific to this classroom
                for user, base_data in zip(users, classroom_user_data):
                    # The user data we are fetching from has 'Age' as a characteristic, use this as the "age" of the user
                    # in terms of their content interaction history - older, more content items interacted with!
                    if num_content_items:
                        n_content_items = num_content_items
                    else:
                        n_content_items = int(base_data["Age"])

                    # Loop over all local channels to generate data for each channel
                    for channel in ChannelMetadata.objects.all():
                        utils.add_channel_activity_for_user(
                            n_content_items=n_content_items,
                            channel=channel,
                            user=user,
                            now=now,
                        )

                # create lessons
                utils.create_lessons_for_classroom(
                    classroom=classroom,
                    facility=facility,
                    channels=ChannelMetadata.objects.all(),
                    lessons=num_lessons,
                    now=now,
                )

                # create exams
                utils.create_exams_for_classrooms(
                    classroom=classroom,
                    facility=facility,
                    channels=ChannelMetadata.objects.all(),
                    exams=num_exams,
                    now=now,
                )