Revert "Fix the unpredictable order randomization issue with randomized content blocks"
This commit is contained in:
@@ -154,40 +154,37 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
"""
|
||||
rand = random.Random()
|
||||
|
||||
selected_keys = set(tuple(k) for k in selected) # set of (block_type, block_id) tuples assigned to this student
|
||||
selected = set(tuple(k) for k in selected) # set of (block_type, block_id) tuples assigned to this student
|
||||
|
||||
# Determine which of our children we will show:
|
||||
valid_block_keys = set([(c.block_type, c.block_id) for c in children])
|
||||
|
||||
# Remove any selected blocks that are no longer valid:
|
||||
invalid_block_keys = (selected_keys - valid_block_keys)
|
||||
invalid_block_keys = (selected - valid_block_keys)
|
||||
if invalid_block_keys:
|
||||
selected_keys -= invalid_block_keys
|
||||
selected -= invalid_block_keys
|
||||
|
||||
# If max_count has been decreased, we may have to drop some previously selected blocks:
|
||||
overlimit_block_keys = set()
|
||||
if len(selected_keys) > max_count:
|
||||
num_to_remove = len(selected_keys) - max_count
|
||||
overlimit_block_keys = set(rand.sample(selected_keys, num_to_remove))
|
||||
selected_keys -= overlimit_block_keys
|
||||
if len(selected) > max_count:
|
||||
num_to_remove = len(selected) - max_count
|
||||
overlimit_block_keys = set(rand.sample(selected, num_to_remove))
|
||||
selected -= overlimit_block_keys
|
||||
|
||||
# Do we have enough blocks now?
|
||||
num_to_add = max_count - len(selected_keys)
|
||||
num_to_add = max_count - len(selected)
|
||||
|
||||
added_block_keys = None
|
||||
if num_to_add > 0:
|
||||
# We need to select [more] blocks to display to this user:
|
||||
pool = valid_block_keys - selected_keys
|
||||
pool = valid_block_keys - selected
|
||||
if mode == "random":
|
||||
num_to_add = min(len(pool), num_to_add)
|
||||
added_block_keys = set(rand.sample(pool, num_to_add))
|
||||
# We now have the correct n random children to show for this user.
|
||||
else:
|
||||
raise NotImplementedError("Unsupported mode.")
|
||||
selected_keys |= added_block_keys
|
||||
|
||||
if any([invalid_block_keys, overlimit_block_keys, added_block_keys]):
|
||||
selected = selected_keys
|
||||
selected |= added_block_keys
|
||||
|
||||
return {
|
||||
'selected': selected,
|
||||
@@ -267,15 +264,19 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
|
||||
def selected_children(self):
|
||||
"""
|
||||
Returns a list() of block_ids indicating which of the possible children
|
||||
Returns a set() of block_ids indicating which of the possible children
|
||||
have been selected to display to the current user.
|
||||
|
||||
This reads and updates the "selected" field, which has user_state scope.
|
||||
|
||||
Note: the return value (self.selected) contains block_ids. To get
|
||||
Note: self.selected and the return value contain block_ids. To get
|
||||
actual BlockUsageLocators, it is necessary to use self.children,
|
||||
because the block_ids alone do not specify the block type.
|
||||
"""
|
||||
if hasattr(self, "_selected_set"):
|
||||
# Already done:
|
||||
return self._selected_set # pylint: disable=access-member-before-definition
|
||||
|
||||
block_keys = self.make_selection(self.selected, self.children, self.max_count, "random") # pylint: disable=no-member
|
||||
|
||||
# Publish events for analytics purposes:
|
||||
@@ -287,13 +288,13 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
self._publish_event,
|
||||
)
|
||||
|
||||
if any(block_keys[changed] for changed in ('invalid', 'overlimit', 'added')):
|
||||
# Save our selections to the user state, to ensure consistency:
|
||||
selected = list(block_keys['selected'])
|
||||
random.shuffle(selected)
|
||||
self.selected = selected # TODO: this doesn't save from the LMS "Progress" page.
|
||||
# Save our selections to the user state, to ensure consistency:
|
||||
selected = block_keys['selected']
|
||||
self.selected = list(selected) # TODO: this doesn't save from the LMS "Progress" page.
|
||||
# Cache the results
|
||||
self._selected_set = selected # pylint: disable=attribute-defined-outside-init
|
||||
|
||||
return self.selected
|
||||
return selected
|
||||
|
||||
def _get_selected_child_blocks(self):
|
||||
"""
|
||||
|
||||
@@ -269,8 +269,9 @@ class LibraryContentModuleTestMixin(object):
|
||||
Helper method that changes the max_count of self.lc_block, refreshes
|
||||
children, and asserts that the number of selected children equals the count provided.
|
||||
"""
|
||||
# Construct the XModule for the descriptor, if not present already present pylint: disable=protected-access
|
||||
self.lc_block._xmodule
|
||||
# Clear the cache (only needed because we skip saving/re-loading the block) pylint: disable=protected-access
|
||||
if hasattr(self.lc_block._xmodule, '_selected_set'):
|
||||
del self.lc_block._xmodule._selected_set
|
||||
self.lc_block.max_count = count
|
||||
selected = self.lc_block.get_child_descriptors()
|
||||
self.assertEqual(len(selected), count)
|
||||
@@ -393,6 +394,8 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
|
||||
# Now increase max_count so that one more child will be added:
|
||||
self.lc_block.max_count = 2
|
||||
# Clear the cache (only needed because we skip saving/re-loading the block) pylint: disable=protected-access
|
||||
del self.lc_block._xmodule._selected_set
|
||||
children = self.lc_block.get_child_descriptors()
|
||||
self.assertEqual(len(children), 2)
|
||||
child, new_child = children if children[0].location == child.location else reversed(children)
|
||||
@@ -472,6 +475,8 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
self.lc_block.get_child_descriptors() # This line is needed in the test environment or the change has no effect
|
||||
self.publisher.reset_mock() # Clear the "assigned" event that was just published.
|
||||
self.lc_block.max_count = 0
|
||||
# Clear the cache (only needed because we skip saving/re-loading the block) pylint: disable=protected-access
|
||||
del self.lc_block._xmodule._selected_set
|
||||
|
||||
# Check that the event says that one block was removed, leaving no blocks left:
|
||||
children = self.lc_block.get_child_descriptors()
|
||||
@@ -489,6 +494,8 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
# Start by assigning two blocks to the student:
|
||||
self.lc_block.get_child_descriptors() # This line is needed in the test environment or the change has no effect
|
||||
self.lc_block.max_count = 2
|
||||
# Clear the cache (only needed because we skip saving/re-loading the block) pylint: disable=protected-access
|
||||
del self.lc_block._xmodule._selected_set
|
||||
initial_blocks_assigned = self.lc_block.get_child_descriptors()
|
||||
self.assertEqual(len(initial_blocks_assigned), 2)
|
||||
self.publisher.reset_mock() # Clear the "assigned" event that was just published.
|
||||
@@ -502,6 +509,8 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
self.library.children = [keep_block_lib_usage_key]
|
||||
self.store.update_item(self.library, self.user_id)
|
||||
self.lc_block.refresh_children()
|
||||
# Clear the cache (only needed because we skip saving/re-loading the block) pylint: disable=protected-access
|
||||
del self.lc_block._xmodule._selected_set
|
||||
|
||||
# Check that the event says that one block was removed, leaving one block left:
|
||||
children = self.lc_block.get_child_descriptors()
|
||||
|
||||
Reference in New Issue
Block a user