from mirth import ability_mle

from lib.irt.models.base import *

class Rasch(Base):

  def result(self):
    # contains the primary Rasch function, determining the probably of an inidividual
    # that an individual at a certain theta would get a particular question correct
    # https://edres.org/irt/baker/chapter6.pdf
    return (1 / (1 + self.e(-1 * (self.theta - self.b_param))))

  @classmethod
  def ability_estimate(self, items) -> float:
    # responses are mapped into a matrix, where each row and item
    # and each column is an exam form result
    # we'll likely have to change this to something more robust
    # when we get into more complex response types
    responses = np.array([[int(item.response)] for item in items])
    # the difficulty (b param) for each item is in an ordered list
    difficulty = np.array([item.b_param for item in items])
    # the package currently utilizes a fixed a param (discrimination)
    discrimination = np.linspace(1, 1, len(difficulty))
    # there are many methodologies to calculate ability from a data set of responses
    # this is what our client currently uses but we should expand this to allow for
    # switching between methodologies when needed
    # it also currrently only does a single ability estimation
    # at some point we can also accommodate batch ability estimates if need be
    return ability_mle(responses, difficulty, discrimination).tolist()[0]