"use strict";

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

var _typeof = require("@babel/runtime/helpers/typeof");

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

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

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

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

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

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

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

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

var _utils = require("./utils");

var _translator = _interopRequireDefault(require("@pie-lib/translator"));

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

var mv = _interopRequireWildcard(require("@pie-framework/math-validation"));

var _excluded = ["extraCSSRules", "responses", "language"];

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

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 translator = _translator["default"].translator;
var log = (0, _debug["default"])('@pie-element:math-inline:controller');

var getResponseCorrectness = function getResponseCorrectness(model, answerItem, isOutcome) {
  var correctResponses = model.responses;
  var isAdvanced = model.responseType === _utils.ResponseTypes.advanced;

  if (!answerItem) {
    return {
      correctness: 'unanswered',
      score: isOutcome ? 0 : '0%',
      correct: false
    };
  }

  var isAnswerCorrect = getIsAnswerCorrect(isAdvanced ? correctResponses : correctResponses.slice(0, 1), answerItem);
  var correctnessObject = {
    correctness: 'incorrect',
    score: isOutcome ? 0 : '0%',
    correct: false
  };

  if (isAnswerCorrect) {
    correctnessObject.correctness = 'correct';
    correctnessObject.score = isOutcome ? 1 : '100%';
    correctnessObject.correct = true;
  }

  return correctnessObject;
};

function getIsAnswerCorrect(correctResponseItems, answerItem) {
  var answerCorrect = false;
  (correctResponseItems || []).forEach(function (correctResponse) {
    if (answerCorrect) return;
    var opts = {
      mode: correctResponse.validation || _defaults["default"].validationDefault
    };

    if (opts.mode === 'literal') {
      opts.literal = {
        allowTrailingZeros: correctResponse.allowTrailingZeros || false,
        ignoreOrder: correctResponse.ignoreOrder || false
      };
    }

    var acceptedValues = [correctResponse.answer].concat(Object.keys(correctResponse.alternates || {}).map(function (alternateId) {
      return correctResponse.alternates[alternateId];
    }));

    for (var i = 0; i < acceptedValues.length; i++) {
      try {
        if (mv.latexEqual(answerItem, acceptedValues[i], opts)) {
          answerCorrect = true;
          break;
        }
      } catch (e) {
        log('Parse failure when evaluating math', acceptedValues[i], answerItem, e);
        continue;
      }
    }
  });
  return answerCorrect;
}

var getCorrectness = function getCorrectness(question, env, session, isOutcome) {
  if (env.mode === 'evaluate') {
    return getResponseCorrectness(question, question.responseType === _utils.ResponseTypes.advanced ? session && session.completeAnswer || '' : session && session.response, isOutcome);
  }

  return undefined;
};

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

var outcome = function outcome(question, session, env) {
  return new Promise(function (resolve) {
    if (env.mode !== 'evaluate') {
      resolve({
        score: undefined,
        completed: undefined
      });
    } else {
      if (!session || (0, _isEmpty["default"])(session)) {
        resolve({
          score: 0,
          empty: true
        });
      } else {
        var correctness = getCorrectness(question, env, session, true);
        resolve({
          score: correctness.score
        });
      }
    }
  });
};

exports.outcome = outcome;

var normalize = function normalize(question) {
  // making sure that defaults are set
  if (!(0, _isEmpty["default"])(question.responses)) {
    question.responses = question.responses.map(function (correctResponse) {
      return _objectSpread(_objectSpread({}, correctResponse), {}, {
        validation: correctResponse.validation || question.validationDefault,
        allowTrailingZeros: correctResponse.allowTrailingZeros || question.allowTrailingZerosDefault,
        ignoreOrder: correctResponse.ignoreOrder || question.ignoreOrderDefault
      });
    });
  }

  return _objectSpread(_objectSpread({}, _defaults["default"]), question);
};

exports.normalize = normalize;

var model = function model(question, session, env) {
  return new Promise(function (resolve) {
    var _config$responses;

    var normalizedQuestion = normalize(question);
    var correctness = getCorrectness(normalizedQuestion, env, session);
    var extraCSSRules = normalizedQuestion.extraCSSRules,
        responses = normalizedQuestion.responses,
        language = normalizedQuestion.language,
        config = (0, _objectWithoutProperties2["default"])(normalizedQuestion, _excluded);
    config.responses = config.responseType === _utils.ResponseTypes.simple ? responses.slice(0, 1) : responses;
    var feedback = env.mode === 'evaluate' && normalizedQuestion.feedbackEnabled ? (0, _feedback.getActualFeedbackForCorrectness)(correctness === null || correctness === void 0 ? void 0 : correctness.correctness, normalizedQuestion.feedback) : undefined;
    var out = {
      extraCSSRules: extraCSSRules,
      config: config,
      correctness: correctness,
      feedback: feedback,
      disabled: env.mode !== 'gather',
      view: env.mode === 'view'
    };
    var note = normalizedQuestion.note || translator.t('mathInline.primaryCorrectWithAlternates', {
      lng: language
    });
    var showNote = (config === null || config === void 0 ? void 0 : (_config$responses = config.responses) === null || _config$responses === void 0 ? void 0 : _config$responses.length) > 1 || ((config === null || config === void 0 ? void 0 : config.responses) || []).some(function (response) {
      return response.validation === 'symbolic' || Object.keys(response.alternates || {}).length > 0;
    });

    if (env.mode === 'evaluate') {
      out.correctResponse = {};
      out.config.showNote = showNote;
      out.config.note = note;
    } else {
      out.config.responses = [];
      out.config.showNote = false;
    }

    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;
      out.config.rationale = null;
      out.config.teacherInstructions = null;
    }

    out.config.env = env;
    out.config.prompt = normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null;
    out.language = language;
    log('out: ', out);
    resolve(out);
  });
};

exports.model = model;

var escape = function escape(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}; // $& means the whole matched string


var simpleSessionResponse = function simpleSessionResponse(question) {
  return new Promise(function (resolve) {
    var responses = question.responses,
        id = question.id;

    var _ref = responses && responses.length ? responses[0] : {},
        answer = _ref.answer;

    resolve({
      id: id,
      response: answer || '',
      completeAnswer: answer || ''
    });
  });
}; // use this for items like E672793


var removeTrailingEscape = function removeTrailingEscape(str) {
  return str.endsWith('\\') ? str.slice(0, -1) : str;
};

var advancedSessionResponse = function advancedSessionResponse(question) {
  return new Promise(function (resolve) {
    var responses = question.responses,
        id = question.id;

    var _ref2 = responses && responses.length ? responses[0] : {},
        answer = _ref2.answer;

    if (!answer) {
      resolve({
        id: id,
        answers: {},
        completeAnswer: ''
      });
      return;
    }

    try {
      var e = question.expression;
      var RESPONSE_TOKEN = /\\{\\{\s*response\s*\\}\\}/g;
      var o = escape(e).split(RESPONSE_TOKEN);
      var to = o.map(function (t) {
        return t === '' ? t : t.replace(/\s+/g, function () {
          return '\\s*';
        });
      });
      var tt = to.join('(.*)');
      var m = answer.match(new RegExp(tt));
      var count = o.length - 1;

      if (!m) {
        resolve({
          id: id,
          answers: {},
          completeAnswer: answer
        }); // eslint-disable-next-line no-console

        console.log("can not find match: ".concat(o, " in ").concat(answer));
        return;
      }

      m.shift();
      var answers = {};

      for (var i = 0; i < count; i++) {
        answers["r".concat(i + 1)] = {
          value: removeTrailingEscape(m[i].trim())
        };
      }

      resolve({
        id: id,
        answers: answers,
        completeAnswer: answer
      });
    } catch (e) {
      resolve({
        id: id,
        answers: {},
        completeAnswer: answer
      }); // eslint-disable-next-line no-console

      console.error(e.toString());
    }
  });
};

var createCorrectResponseSession = function createCorrectResponseSession(question, env) {
  if (env.mode === 'evaluate' || env.role !== 'instructor') {
    // eslint-disable-next-line no-console
    console.error('can not create correct response session if mode is evaluate or role is not instructor');
    return Promise.resolve(null);
  }

  if ((question.responseType || '').toLowerCase() === 'simple') {
    return simpleSessionResponse(question, env);
  } else {
    return advancedSessionResponse(question, env);
  }
}; // remove all html tags


exports.createCorrectResponseSession = createCorrectResponseSession;

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


var getContent = function getContent(html) {
  return (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/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 _model$expression = model.expression,
      expression = _model$expression === void 0 ? '' : _model$expression,
      responses = model.responses,
      responseType = model.responseType;
  var maxResponseAreas = config.maxResponseAreas;
  var responsesErrors = {};
  var errors = {};
  ['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.';
    }
  });
  (responses || []).forEach(function (response, index) {
    var answer = response.answer;
    var reversedAlternates = (0, _toConsumableArray2["default"])(Object.entries(response.alternates || {})).reverse();
    var alternatesErrors = {};
    var responseError = {};

    if (answer === '') {
      responseError.answer = 'Content should not be empty.';
    }

    reversedAlternates.forEach(function (_ref3, index) {
      var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
          key = _ref4[0],
          value = _ref4[1];

      if (value === '') {
        alternatesErrors[key] = 'Content should not be empty.';
      } else {
        var identicalAnswer = answer === value || reversedAlternates.slice(index + 1).some(function (_ref5) {
          var _ref6 = (0, _slicedToArray2["default"])(_ref5, 2),
              val = _ref6[1];

          return val === value;
        });

        if (identicalAnswer) {
          alternatesErrors[key] = 'Content should be unique.';
        }
      }
    });

    if (!(0, _isEmpty["default"])(responseError) || !(0, _isEmpty["default"])(alternatesErrors)) {
      responsesErrors[index] = _objectSpread(_objectSpread({}, responseError), alternatesErrors);
    }
  });

  if (responseType === 'Advanced Multi') {
    var nbOfResponseAreas = (expression.match(/\{\{response\}\}/g) || []).length;

    if (nbOfResponseAreas > maxResponseAreas) {
      errors.responseAreasError = "No more than ".concat(maxResponseAreas, " response areas should be defined.");
    } else if (nbOfResponseAreas < 1) {
      errors.responseAreasError = 'There should be at least 1 response area defined.';
    }
  }

  if (!(0, _isEmpty["default"])(responsesErrors)) {
    errors.responsesErrors = responsesErrors;
  }

  return errors;
};

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