"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createCorrectResponseSession = void 0;
exports.createDefaultModel = createDefaultModel;
exports.validate = exports.outcome = exports.normalizeSession = exports.normalize = exports.model = exports.getPartialScore = exports.getCorrectness = void 0;

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _debug = _interopRequireDefault(require("debug"));

var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));

var _feedback = require("@pie-lib/pie-toolbox/feedback");

var _controllerUtils = require("@pie-lib/pie-toolbox/controller-utils");

var _defaults = _interopRequireDefault(require("./defaults"));

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

var log = (0, _debug["default"])('@pie-element:select-text:controller');

var equalTokens = function equalTokens() {
  var token1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  var token2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  return (token1 === null || token1 === void 0 ? void 0 : token1.start) === (token2 === null || token2 === void 0 ? void 0 : token2.start) && (token1 === null || token1 === void 0 ? void 0 : token1.end) === (token2 === null || token2 === void 0 ? void 0 : token2.end) || // this case is used for the cases when the token's start & end were recalculated
  (token1 === null || token1 === void 0 ? void 0 : token1.start) === (token2 === null || token2 === void 0 ? void 0 : token2.oldStart) && (token1 === null || token1 === void 0 ? void 0 : token1.end) === (token2 === null || token2 === void 0 ? void 0 : token2.oldEnd);
};

var normalizeTokens = function normalizeTokens() {
  var tokens = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  var selectedTokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  var evaluateMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  return (tokens || []).map(function (token) {
    var isCorrect = !!token.correct; // search if correct token is missing from session

    var isMissing = isCorrect && !(selectedTokens || []).find(function (selectedToken) {
      return equalTokens(token, selectedToken);
    });
    return _objectSpread(_objectSpread({}, token), {}, {
      correct: evaluateMode ? isCorrect : undefined,
      isMissing: evaluateMode ? isMissing : undefined
    });
  });
};

var getCorrectness = function getCorrectness(tokens, selected) {
  var correct = tokens.filter(function (t) {
    return t.correct === true;
  });

  if (correct.length === 0) {
    return 'unknown';
  }

  var correctSelected = getCorrectSelected(tokens, selected);

  if (correctSelected.length === selected.length) {
    if (correctSelected.length === correct.length) {
      return 'correct';
    } else if (correctSelected.length > 0) {
      return 'partially-correct';
    }
  }

  if (correctSelected.length > 0) {
    return 'partially-correct';
  }

  return 'incorrect';
};

exports.getCorrectness = getCorrectness;

var getCorrectSelected = function getCorrectSelected(tokens, selected) {
  return (selected || []).filter(function (s) {
    return tokens.findIndex(function (token) {
      return token.correct && equalTokens(token, s);
    }) !== -1;
  });
};

var getPartialScore = function getPartialScore(question, session, totalCorrect) {
  if (!session || (0, _isEmpty["default"])(session)) {
    return 0;
  }

  var correctCount = getCorrectSelected(question.tokens, session.selectedTokens).length;
  var correctTokens = (question.tokens || []).filter(function (t) {
    return t.correct === true;
  });
  var extraSelected = session.selectedTokens ? session.selectedTokens.length > correctTokens.length : 0;
  var incorrectCount = extraSelected ? session.selectedTokens && session.selectedTokens.length - correctCount : 0;
  var count = correctCount - incorrectCount;
  var positiveCount = count < 0 ? 0 : count;
  return totalCorrect.length ? parseFloat((positiveCount / totalCorrect.length).toFixed(2)) : 0;
};

exports.getPartialScore = getPartialScore;

var outcome = function outcome(question, session, env) {
  return new Promise(function (resolve) {
    if (!session || (0, _isEmpty["default"])(session)) {
      resolve({
        score: 0,
        empty: true
      });
    }

    session = normalizeSession(session);

    if (env.mode !== 'evaluate') {
      resolve({
        score: undefined,
        completed: undefined
      });
    } else {
      var enabled = _controllerUtils.partialScoring.enabled(question, env, true);

      var totalCorrect = question.tokens.filter(function (t) {
        return t.correct;
      });
      var score = getPartialScore(question, session, totalCorrect);
      resolve({
        score: enabled ? score : score === 1 ? 1 : 0
      });
    }
  });
};

exports.outcome = outcome;

function createDefaultModel() {
  var model = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  return new Promise(function (resolve) {
    resolve(_objectSpread(_objectSpread({}, _defaults["default"]), model));
  });
}

var normalizeSession = function normalizeSession(session) {
  return _objectSpread({
    selectedTokens: []
  }, session);
};

exports.normalizeSession = normalizeSession;

var normalize = function normalize(question) {
  return _objectSpread({
    feedbackEnabled: false,
    rationaleEnabled: true,
    promptEnabled: true,
    teacherInstructionsEnabled: true,
    studentInstructionsEnabled: true
  }, question);
};

exports.normalize = normalize;

var model = function model(question, session, env) {
  session = session || {
    selectedToken: []
  };
  session.selectedTokens = session.selectedTokens || [];
  var normalizedQuestion = normalize(question);
  return new Promise(function (resolve) {
    log('[model]', 'normalizedQuestion: ', normalizedQuestion);
    log('[model]', 'session: ', session);
    var tokens = normalizeTokens(normalizedQuestion.tokens, session.selectedTokens, env.mode === 'evaluate');
    log('[model] tokens:', tokens);
    var correctness = env.mode === 'evaluate' ? getCorrectness(normalizedQuestion.tokens, session.selectedTokens) : undefined;
    var fb = env.mode === 'evaluate' && normalizedQuestion.feedbackEnabled ? (0, _feedback.getFeedbackForCorrectness)(correctness, normalizedQuestion.feedback) : Promise.resolve(undefined);
    fb.then(function (feedback) {
      var out = {
        tokens: tokens,
        highlightChoices: normalizedQuestion.highlightChoices,
        prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,
        text: normalizedQuestion.text,
        disabled: env.mode !== 'gather',
        maxSelections: normalizedQuestion.maxSelections,
        correctness: correctness,
        env: env,
        feedback: feedback,
        incorrect: env.mode === 'evaluate' ? correctness !== 'correct' : undefined,
        language: normalizedQuestion.language
      };

      if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
        out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;
        out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;
      } else {
        out.rationale = null;
        out.teacherInstructions = null;
      }

      resolve(out);
    });
  });
};

exports.model = model;

var createCorrectResponseSession = function createCorrectResponseSession(question, env) {
  return new Promise(function (resolve) {
    if (env.mode !== 'evaluate' && env.role === 'instructor') {
      var tokens = question.tokens;
      var selectedTokens = tokens.filter(function (t) {
        return t.correct;
      });
      resolve({
        id: '1',
        selectedTokens: selectedTokens
      });
    } else {
      resolve(null);
    }
  });
}; // remove all html tags


exports.createCorrectResponseSession = createCorrectResponseSession;

var getInnerText = function getInnerText(html) {
  return (html || '').replaceAll(/<[^>]*>/g, '');
}; // remove all html tags except img and iframe


var getContent = function getContent(html) {
  return (html || '').replace(/(<(?!img|iframe)([^>]+)>)/gi, '');
};

var validate = function validate() {
  var model = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var tokens = model.tokens;
  var _config$minTokens = config.minTokens,
      minTokens = _config$minTokens === void 0 ? 2 : _config$minTokens,
      maxTokens = config.maxTokens,
      maxSelections = config.maxSelections;
  var errors = {};
  var nbOfTokens = (tokens || []).length;
  ['teacherInstructions', 'prompt', 'rationale'].forEach(function (field) {
    var _config$field;

    if ((_config$field = config[field]) !== null && _config$field !== void 0 && _config$field.required && !getContent(model[field])) {
      errors[field] = 'This field is required.';
    }
  });
  var nbOfSelections = (tokens || []).reduce(function (acc, token) {
    return token.correct ? acc + 1 : acc;
  }, 0);

  if (nbOfTokens < minTokens) {
    errors.tokensError = "There should be at least ".concat(minTokens, " tokens defined.");
  } else if (nbOfTokens > maxTokens) {
    errors.tokensError = "No more than ".concat(maxTokens, " tokens should be defined.");
  }

  if (nbOfSelections < 1) {
    errors.selectionsError = 'There should be at least 1 token selected.';
  } else if (nbOfSelections > maxSelections) {
    errors.selectionsError = "No more than ".concat(maxSelections, " tokens should be selected.");
  }

  return errors;
};

exports.validate = validate;
//# sourceMappingURL=index.js.map