如何使用 SCORM 和 React 计算总分?

how to calculate total score with SCORM and React?

关于SCORM实现的例子很少,所以我有点迷茫。我需要根据 3 个问题获得学生分数。我真的不明白我在做什么。我知道我可能需要一个像 calculateScore() 这样的函数。不过,SCORM 把我搞糊涂了。我使用 SCORMCLOUD 进行测试,但每次我想测试一些东西时我都会重新上传构建..

APP.js

function App() {
  Scorm.init();

  const [learnerName, setLearnerName] = useState(`${Scorm.getLearnerName()}`);
  const [assessment, setAssessment] = useState([]);

  const finish = () => {
    Scorm.finish();
  };

  const updateAssesment = (correct, response) => {
    setAssessment(assessment.concat([correct]));
    Scorm.submitMCQ(correct, response);
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Learner name={learnerName} />
      </header>
      <main>
        <Mcq result={updateAssesment.bind()} question="What is 10 * 10?" correctAnswer={0} answers={["100", "20"]} />
        <Mcq
          result={updateAssesment.bind()}
          question="What is the capital of Spain?"
          correctAnswer={2}
          answers={["Barcelona", "Lisbon", "Madrid"]}
        />
        <Mcq
          result={updateAssesment.bind()}
          question="Which US President's office commissioned the creation of SCORM?"
          correctAnswer={3}
          answers={["Donald Trump", "Barack Obama", "Ronald Reagan", "Bill Clinton"]}
        />
        <CompleteButton completeActivity={finish.bind()} />
      </main>
    </div>
  );
}
export default App;

SCORM.js

import { SCORM } from "pipwerks-scorm-api-wrapper";

let Scorm = {
  init() {
    SCORM.init();
  },

  getLearnerName() {
    return SCORM.get("cmi.core.student_name");
  },

  submitMCQ(correct, response) {
    let nextIndex = SCORM.get("cmi.interactions._count", true);
    SCORM.set("cmi.interactions." + nextIndex + ".id", "round_" + nextIndex);
    SCORM.set("cmi.interactions." + nextIndex + ".type", "choice");
    SCORM.set("cmi.interactions." + nextIndex + ".student_response", response);
    SCORM.set("cmi.interactions." + nextIndex + ".result", correct);
  },

  calculateScore() {
    //something here??
    SCORM.set("cmi.core.score.raw", "0");
    SCORM.set("cmi.core.score.max", "100");
    SCORM.set("cmi.core.score.min", "0");
  },

  finish() {
    alert("you have finished!");
    SCORM.set("cmi.core.lesson_status", "completed");
    SCORM.save();
    SCORM.quit();
  },
};

export default Scorm;

MCQ 组件

export default function Mcq(props) {
  const [selectedOption, setSelectedOption] = useState(0);
  const [answered, setAnswered] = useState(false);

  const handleOptionChange = (changeEvent) => {
    setSelectedOption(Number(changeEvent.target.value));
  };
  const renderAnswers = () => {
    return props.answers.map(function (answer, index) {
      return (
        <div className="answer" key={index}>
          <input type="radio" value={index} checked={selectedOption === index} onChange={handleOptionChange} />
          <label>{answer}</label>
        </div>
      );
    });
  };
  const handleFormSubmit = (formSubmitEvent) => {
    formSubmitEvent.preventDefault();
    setAnswered(true);
    props.result(selectedOption === props.correctAnswer, props.answers[selectedOption]);
  };
  const currentState = () => {
    if (!answered) {
      return (
        <form onSubmit={handleFormSubmit.bind(this)}>
          {renderAnswers()}
          <button className="btn btn-default" type="submit">
            Submit
          </button>
        </form>
      );
    } else {
      return <div>{checkCorrectAnswer()}</div>;
    }
  };
  const checkCorrectAnswer = () => {
    if (selectedOption === props.correctAnswer) {
      return `yes, ${props.answers[props.correctAnswer]} is the correct answer.`;
    } else {
      return `You answered ${props.answers[selectedOption]}. Sorry, but the correct answer is ${
        props.answers[props.correctAnswer]
      }.`;
    }
  };

  return (
    <div className="Mcq">
      <p>{props.question}</p>
      {currentState()}
    </div>
  );
}

你的问题有点令人费解。 SCORM 是 API 将两件事联系在一起:

  • 学习内容,通常采用一个或多个所谓的 SCO 的形式(即 HTML 包含与 SCORM JS 对话的资产的文件 API)
  • LMS 服务于学习内容并提供 SCORM JS API 实例

看起来你正在尝试创建学习内容,尽管你提供了一种更改学习者姓名的方法,这是 JS 提供的只读数据 API。

如果这就是您想要做的,那么 SCORM 不会告诉您分数,而是您自己。根据您的代码,我猜您希望每个问题在回答正确的情况下都值得多分(或至少只有一分),并且分数应基于该问题和问题总数。

由于您已经将所有答案存储在 cmi.interactions 中,您可以先尝试获取互动次数(即答案)。这会告诉您答案总数,因此会告诉您最大分数,或 cmi.core.score.max.

因为如果你做一个简单的计数而不是更复杂的事情,比如选择不正确的选择的负分,最低可能的分数是零分,那么 cmi.core.score.min 将是 0

cmi.core.score.raw就是总分,也就是正确答案的个数。你可以通过遍历你之前设置的 cmi.interactions.n.result 的值来得到这个(n 是零和 cmi.interactions._count 之间的索引,并且只计算 result"correct").

但是请注意,submitMCQ 应将 cmi.interactions.n.result 设置为 "correct""incorrect" 而不是 truefalse。否则,符合标准的 LMS 将拒绝该值作为无效值(这不会引发异常,而是设置一个错误标志,您必须明确检查,因为 SCORM 很奇怪)。

我设计了 SCOBot Content API 来帮助解决其中的一些问题,如果您想试一试的话。至少如果您厌倦了尝试查找所有个人电话。

它添加了额外的包装来管理总交互/评分计算,因此您无需编写所有额外的管理。

https://github.com/cybercussion/SCOBot/blob/e67239c36fdc104be9d29b0810815f9b3175c831/QUnit-Tests/js/scorm/SCOBot.js#L841

还有示例分组,这样您只需定义一次,它就会处理 - https://github.com/cybercussion/SCOBot/wiki/SCORM-SCOBot-Documentation#set-interaction

有许多配置设置可以将项目的 'bot' 部分变为 on/off 等...

QUnit 测试也写在测试目录中,其中显示了几个 interactions/objectives 和其他调用。 https://github.com/cybercussion/SCOBot/blob/e67239c36fdc104be9d29b0810815f9b3175c831/QUnit-Tests/js/test/scobot-prod.js#L252

我还将它设计为独立于 1.2 / 2004 工作,因此您使用的是一组命名空间。而且不必记住所有版本差异。

本项目开源,免费use/test出。最新版本将其从 jQuery 中分离出来,因此它有自己的事件系统和实用程序。如果你使用像 Angular 这样的东西,你可能必须使用 NgZone,React 我想你可能没问题。如果您 运行 遇到问题请告诉我。