196 lines
6.5 KiB
Python
196 lines
6.5 KiB
Python
import queue
|
|
import random
|
|
import re
|
|
import string
|
|
from wonderwords import RandomWord
|
|
|
|
from .text_helper import TextHelper
|
|
|
|
|
|
class ExercisesHelper:
|
|
|
|
@staticmethod
|
|
def divide_number_into_parts(number, parts):
|
|
if number < parts:
|
|
return None
|
|
|
|
part_size = number // parts
|
|
remaining = number % parts
|
|
|
|
q = queue.Queue()
|
|
|
|
for i in range(parts):
|
|
if i < remaining:
|
|
q.put(part_size + 1)
|
|
else:
|
|
q.put(part_size)
|
|
|
|
return q
|
|
|
|
@staticmethod
|
|
def fix_exercise_ids(exercise, start_id):
|
|
# Initialize the starting ID for the first exercise
|
|
current_id = start_id
|
|
|
|
questions = exercise["questions"]
|
|
|
|
# Iterate through questions and update the "id" value
|
|
for question in questions:
|
|
question["id"] = str(current_id)
|
|
current_id += 1
|
|
|
|
return exercise
|
|
|
|
@staticmethod
|
|
def replace_first_occurrences_with_placeholders(text: str, words_to_replace: list, start_id):
|
|
for i, word in enumerate(words_to_replace, start=start_id):
|
|
# Create a case-insensitive regular expression pattern
|
|
pattern = re.compile(r'\b' + re.escape(word) + r'\b', re.IGNORECASE)
|
|
placeholder = '{{' + str(i) + '}}'
|
|
text = pattern.sub(placeholder, text, 1)
|
|
return text
|
|
|
|
@staticmethod
|
|
def replace_first_occurrences_with_placeholders_notes(notes: list, words_to_replace: list, start_id):
|
|
replaced_notes = []
|
|
for i, note in enumerate(notes, start=0):
|
|
word = words_to_replace[i]
|
|
pattern = re.compile(r'\b' + re.escape(word) + r'\b', re.IGNORECASE)
|
|
placeholder = '{{' + str(start_id + i) + '}}'
|
|
note = pattern.sub(placeholder, note, 1)
|
|
replaced_notes.append(note)
|
|
return replaced_notes
|
|
|
|
@staticmethod
|
|
def add_random_words_and_shuffle(word_array, num_random_words):
|
|
r = RandomWord()
|
|
random_words_selected = r.random_words(num_random_words)
|
|
|
|
combined_array = word_array + random_words_selected
|
|
|
|
random.shuffle(combined_array)
|
|
|
|
return combined_array
|
|
|
|
@staticmethod
|
|
def fillblanks_build_solutions_array(words, start_id):
|
|
solutions = []
|
|
for i, word in enumerate(words, start=start_id):
|
|
solutions.append(
|
|
{
|
|
"id": str(i),
|
|
"solution": word
|
|
}
|
|
)
|
|
return solutions
|
|
|
|
@staticmethod
|
|
def remove_excess_questions(questions: [], quantity):
|
|
count_true = 0
|
|
result = []
|
|
|
|
for item in reversed(questions):
|
|
if item.get('solution') == 'true' and count_true < quantity:
|
|
count_true += 1
|
|
else:
|
|
result.append(item)
|
|
|
|
result.reverse()
|
|
return result
|
|
|
|
@staticmethod
|
|
def build_write_blanks_text(questions: [], start_id):
|
|
result = ""
|
|
for i, q in enumerate(questions, start=start_id):
|
|
placeholder = '{{' + str(i) + '}}'
|
|
result = result + q["question"] + placeholder + "\\n"
|
|
return result
|
|
|
|
@staticmethod
|
|
def build_write_blanks_text_form(form: [], start_id):
|
|
result = ""
|
|
replaced_words = []
|
|
for i, entry in enumerate(form, start=start_id):
|
|
placeholder = '{{' + str(i) + '}}'
|
|
# Use regular expression to find the string after ':'
|
|
match = re.search(r'(?<=:)\s*(.*)', entry)
|
|
# Extract the matched string
|
|
original_string = match.group(1)
|
|
# Split the string into words
|
|
words = re.findall(r'\b\w+\b', original_string)
|
|
# Remove words with only one letter
|
|
filtered_words = [word for word in words if len(word) > 1]
|
|
# Choose a random word from the list of words
|
|
selected_word = random.choice(filtered_words)
|
|
pattern = re.compile(r'\b' + re.escape(selected_word) + r'\b', re.IGNORECASE)
|
|
|
|
# Replace the chosen word with the placeholder
|
|
replaced_string = pattern.sub(placeholder, original_string, 1)
|
|
# Construct the final replaced string
|
|
replaced_string = entry.replace(original_string, replaced_string)
|
|
|
|
result = result + replaced_string + "\\n"
|
|
# Save the replaced word or use it as needed
|
|
# For example, you can save it to a file or a list
|
|
replaced_words.append(selected_word)
|
|
return result, replaced_words
|
|
|
|
@staticmethod
|
|
def build_write_blanks_solutions(questions: [], start_id):
|
|
solutions = []
|
|
for i, q in enumerate(questions, start=start_id):
|
|
solution = [q["possible_answers"]] if isinstance(q["possible_answers"], str) else q["possible_answers"]
|
|
|
|
solutions.append(
|
|
{
|
|
"id": str(i),
|
|
"solution": solution
|
|
}
|
|
)
|
|
return solutions
|
|
|
|
@staticmethod
|
|
def build_write_blanks_solutions_listening(words: [], start_id):
|
|
solutions = []
|
|
for i, word in enumerate(words, start=start_id):
|
|
solution = [word] if isinstance(word, str) else word
|
|
|
|
solutions.append(
|
|
{
|
|
"id": str(i),
|
|
"solution": solution
|
|
}
|
|
)
|
|
return solutions
|
|
|
|
@staticmethod
|
|
def answer_word_limit_ok(question):
|
|
# Check if any option in any solution has more than three words
|
|
return not any(
|
|
len(option.split()) > 3
|
|
for solution in question["solutions"]
|
|
for option in solution["solution"]
|
|
)
|
|
|
|
@staticmethod
|
|
def assign_letters_to_paragraphs(paragraphs):
|
|
result = []
|
|
letters = iter(string.ascii_uppercase)
|
|
for paragraph in paragraphs.split("\n\n"):
|
|
if TextHelper.has_x_words(paragraph, 10):
|
|
result.append({'paragraph': paragraph.strip(), 'letter': next(letters)})
|
|
return result
|
|
|
|
@staticmethod
|
|
def contains_empty_dict(arr):
|
|
return any(elem == {} for elem in arr)
|
|
|
|
@staticmethod
|
|
def fix_writing_overall(overall: float, task_response: dict):
|
|
if overall > max(task_response.values()) or overall < min(task_response.values()):
|
|
total_sum = sum(task_response.values())
|
|
average = total_sum / len(task_response.values())
|
|
rounded_average = round(average, 0)
|
|
return rounded_average
|
|
return overall
|