Source code for exam_generator.classes

"""
This module contains all classes relevant for the exam-generator.
"""

import random
import re

from .customExceptions import *


[docs]class Pool: """ Represents each pool with its corresponding problems. Construction: >>> Pool(name, file_names_tex) :param name: Name of the pool for example: A1, CV21, DV07 :type name: str :param pool_files: All Problem-Solution-file names of the pool :type pool_files: list[str] """ def __init__(self, name, pool_files): """ Creates new pool instance """ self.name = name self.stack_available = [] # [(filename_problem, filename_solution)]; problems that can be chosen from self.stack_pulled = [] # [(filename_problem, filename_solution)]; selected problems for corresponding group self.stack_storage = [] # [(filename_problem, filename_solution)]; problems which were pulled by last group # Creates a list with all problems of required pool problem_regex = re.compile(f"^problem_.+\\.tex$") file_names_pool_problems = [ file for file in pool_files if re.match(problem_regex, file) is not None ] # Checks if problem + solution exists if len(file_names_pool_problems) == 0: raise MissingFileError( f"{errorInfo()} There is no problems available in Pool {self.name}. \ Please ensure there is problem/ solution data for every used pool." ) # Searches solution for problem for file in file_names_pool_problems: file_solution = file.replace("problem", "solution") # Adds problem and solution to stack if file_solution in pool_files: self.stack_available.append((file, file_solution)) else: raise MissingFileError( f"{errorInfo()} File {file_solution} does not exist. \ Please make sure that all your problem files have a corresponding solution file." )
[docs] def pull(self): """ Pulls a random problem + solution from the pool :return: prob_sol :rtype: tuple(str, str) """ if len(self.stack_available) == 0: # Stack with available problems is exhausted # Storage stack is new available stack if len(self.stack_storage) > 0: self.stack_available = self.stack_storage self.stack_storage = [] else: raise CompilingError( f"{errorInfo()} Pool {self.name} is exhausted, problems might repeat within the group. \ Please ensure that your problem/ solution data size is sufficient." ) # Random selection of problems/solution pairs prob_sol = self.stack_available.pop( random.randint(0, len(self.stack_available) - 1) ) # adding name of pool prob_sol = (*prob_sol, self.name) self.stack_pulled.append(prob_sol) return prob_sol
[docs] def discard(self): """ Discards all pulled problems to the discard pile """ self.stack_storage.extend(self.stack_pulled) self.stack_pulled = []
[docs]class TestType: """ Represents all different test types Construction: >>> TestType(name, *pools) :param name: Name of the test type, for example the name of Experiment :type name: str :param pools: Pools belonging to the test type, mind the "*" :type pools: list[pool] """ def __init__(self, name, *pools): """ Creates instance of TestType """ self.name = name # Name of the test type, for example the name of experiment self.pools = pools
# list of pools belonging to the test type from which problems should be selected