This commit is contained in:
Neha Ranade 2022-01-13 10:30:00 +00:00
Родитель 72407eeba0
Коммит 6a1d592a75
8 изменённых файлов: 375 добавлений и 130 удалений

Просмотреть файл

@ -3,11 +3,10 @@ import * as React from "react";
import {useMemo, useState} from "react";
import {RepositoryContext} from "../context/RepositoryContext";
import { Dropdown, IDropdown } from '@fluentui/react/lib/Dropdown';
import { IStackTokens, Stack } from '@fluentui/react/lib/Stack';
import { parse, GIFTQuestion, TextChoice, TextFormat } from "gift-pegjs";
import { arrayBuffer } from "stream/consumers";
import { XMLParser} from "fast-xml-parser";
import { addConsoleHandler } from "selenium-webdriver/lib/logging";
import { AssessmentAppParserFactory } from "../model/parsers/AssessmentAppParserFactory";
import { Question } from "../model/Question";
import { ParsedQuestionBank } from "../model/parsers/ParsedQuestionBank";
const dropdownStyles = { dropdown: { width: 300 } };
const modalPropsStyles = { main: { maxWidth: 600 } };
@ -119,74 +118,71 @@ export const UploadQuestionBanksComponent = (
return str;
}
const giftFormat = async (rawData:any) => {
// Only MCQ questions for now
// ::title:: -> Question title
// text -> Question text
// [format] -> [html], [plain], [markdown]
const quiz: GIFTQuestion[] = parse(rawData)
console.log(quiz);
const bank = await repositoryContext.createNewQuestionBank({
id: "",
name: "GIFT Question Bank", // We update the name later
description: "",
lastModified: new Date(),
questionIds: [],
assessmentType: "",
});
console.log("Created a new question bank");
// const giftFormat = async (rawData:any) => {
// // Only MCQ and True/False questions supported for now
// const quiz: GIFTQuestion[] = parse(rawData)
// console.log(quiz);
// const bank = await repositoryContext.createNewQuestionBank({
// id: "",
// name: "GIFT Question Bank", // We update the name later
// description: "",
// lastModified: new Date(),
// questionIds: [],
// assessmentType: "",
// });
// console.log("Created a new question bank");
for (let question in quiz){
var q: GIFTQuestion = quiz[question]
if (q.type === "Category"){
await repositoryContext.updateQuestionBankWithName(bank.id, q.title)
}
if (q.type === "MC"){ // multiple choice
// for (let question in quiz){
// var q: GIFTQuestion = quiz[question]
// if (q.type === "Category"){
// await repositoryContext.updateQuestionBankWithName(bank.id, q.title)
// }
// if (q.type === "MC"){ // multiple choice
var choices:TextChoice[] = q.choices;
var answerTexts = Array();
var correctAnswer = 0;
for (var choice in choices){
var details:TextChoice = choices[choice];
answerTexts.push(removeTags(details.text['text']));
if (details.isCorrect){
correctAnswer = +choice; // plus operator converts to number
}
}
var stem:TextFormat = q.stem;
// var choices:TextChoice[] = q.choices;
// var answerTexts = Array();
// var correctAnswer = 0;
// for (var choice in choices){
// var details:TextChoice = choices[choice];
// answerTexts.push(removeTags(details.text['text']));
// if (details.isCorrect){
// correctAnswer = +choice; // plus operator converts to number
// }
// }
// var stem:TextFormat = q.stem;
await repositoryContext.saveNewQuestion(bank.id, {
id: "",
name: removeTags(stem.text),
description: removeTags(stem.text),
lastModified: new Date (),
options: answerTexts,
answer: correctAnswer,
})
// await repositoryContext.saveNewQuestion(bank.id, {
// id: "",
// name: removeTags(stem.text),
// description: removeTags(stem.text),
// lastModified: new Date (),
// options: answerTexts,
// answer: correctAnswer,
// })
}
// }
if (q.type === "TF"){
var stem:TextFormat = q.stem;
var isTrue:boolean = q.isTrue;
await repositoryContext.saveNewQuestion(bank.id, {
id: "",
name: removeTags(stem.text),
description: removeTags(stem.text),
lastModified: new Date (),
options: ["True", "False"],
answer: isTrue?0:1,
})
// if (q.type === "TF"){
// var stem:TextFormat = q.stem;
// var isTrue:boolean = q.isTrue;
// await repositoryContext.saveNewQuestion(bank.id, {
// id: "",
// name: removeTags(stem.text),
// description: removeTags(stem.text),
// lastModified: new Date (),
// options: ["True", "False"],
// answer: isTrue?0:1,
// })
}
// }
}
// }
return true;
// return true;
}
// }
const canvasFormat = async (rawData:any) => {
@ -242,52 +238,6 @@ export const UploadQuestionBanksComponent = (
}
// for (let question in quiz){
// var q: GIFTQuestion = quiz[question]
// if (q.type === "Category"){
// await repositoryContext.updateQuestionBankWithName(bank.id, q.title)
// }
// if (q.type === "MC"){ // multiple choice
// var choices:TextChoice[] = q.choices;
// var answerTexts = Array();
// var correctAnswer = 0;
// for (var choice in choices){
// var details:TextChoice = choices[choice];
// answerTexts.push(removeTags(details.text['text']));
// if (details.isCorrect){
// correctAnswer = +choice; // plus operator converts to number
// }
// }
// var stem:TextFormat = q.stem;
// await repositoryContext.saveNewQuestion(bank.id, {
// id: "",
// name: removeTags(stem.text),
// description: removeTags(stem.text),
// lastModified: new Date (),
// options: answerTexts,
// answer: correctAnswer,
// })
// }
// if (q.type === "TF"){
// var stem:TextFormat = q.stem;
// var isTrue:boolean = q.isTrue;
// await repositoryContext.saveNewQuestion(bank.id, {
// id: "",
// name: removeTags(stem.text),
// description: removeTags(stem.text),
// lastModified: new Date (),
// options: ["True", "False"],
// answer: isTrue?0:1,
// })
// }
// }
return true;
@ -306,29 +256,32 @@ export const UploadQuestionBanksComponent = (
if (!text) {
return;
}
var parserFactory = new AssessmentAppParserFactory(text.toString(), selectedOption.key);
var parser = parserFactory.parser;
parser.parse();
var questionBanks: ParsedQuestionBank[] = parser.questionbanks;
switch(selectedOption.key) {
case "A": {
// opensource curriculum
const rawData = JSON.parse(text.toString());
await openSourceCurriculumJson(rawData);
break;
}
case "B": {
//statements;
const rawData = JSON.parse(text.toString());
await assessmentAppJson(rawData);
break;
}
case "C": {
await giftFormat(text.toString());
break;
}
case "D": {
await canvasFormat(text.toString());
break;
for (let qb_id in questionBanks){
console.log("currenly looking at question bank");
console.log(qb_id);
var questionBank:ParsedQuestionBank = questionBanks[qb_id];
const bank = await repositoryContext.createNewQuestionBank({
id: "",
name: questionBank.questionBankTitle,
description: "",
lastModified: new Date(),
questionIds: [],
assessmentType: "",
});
const questions:Question[] = questionBank.questions;
for (let questionId in questions){
await repositoryContext.saveNewQuestion(bank.id, questions[questionId])
}
}
}
onFinish(true);
setInProgress(false);
}
@ -337,8 +290,8 @@ export const UploadQuestionBanksComponent = (
const dropdownRef = React.createRef<IDropdown>();
const uploadOptions = [
{ key: 'A', text: 'Microsoft Open Source Curriculum JSON'},
{ key: 'B', text: 'Assessment App JSON' },
{ key: 'A', text: 'Assessment App JSON'},
{ key: 'B', text: 'Microsoft Open Source Curriculum JSON ' },
{ key: 'C', text: 'GIFT Export'},
{ key: 'D', text: 'QTI Zip Export' },
];

Просмотреть файл

@ -0,0 +1,40 @@
import { GiftParser } from "./GiftParser";
import { MicrosoftOSCParser } from "./MicrosoftOSCParser";
import { OriginalAppParser } from "./OriginalParser";
import { AssessmentAppParser } from "./Parser";
import { QTIParser } from "./QTIParser";
export class AssessmentAppParserFactory{
// parser!: AssessmentAppParser;
raw:string;
parser!: AssessmentAppParser;
constructor( raw:string, key:string) {
this.raw = raw;
switch(key) {
case "A": {
// opensource curriculum
this.parser = new OriginalAppParser(raw)
break;
}
case "B": {
//statements;
this.parser = new MicrosoftOSCParser(raw)
break;
}
case "C": {
this.parser = new GiftParser(raw)
break;
}
default : {
this.parser = new QTIParser(raw)
break;
}
}
}
}

Просмотреть файл

@ -0,0 +1,59 @@
import { parse, GIFTQuestion, TextChoice, TextFormat } from "gift-pegjs";
import { ParsedQuestionBank } from "./ParsedQuestionBank";
import { AssessmentAppParser } from "./Parser";
import { Question } from "../Question";
// Currently only parses in MCQs and TFs
export class GiftParser extends AssessmentAppParser{
public parse(): void {
var questionBankTitle:string = "Not defined yet";
var questions:Question[] = [];
const quiz: GIFTQuestion[] = parse(this.raw)
for (let question in quiz){
var q: GIFTQuestion = quiz[question]
if (q.type === "Category"){
questionBankTitle = q.title;
}
if (q.type === "MC"){ // multiple choice
var choices:TextChoice[] = q.choices;
var answerTexts = Array();
var correctAnswer = 0;
for (var choice in choices){
var details:TextChoice = choices[choice];
answerTexts.push(this.removeTags(details.text['text']));
if (details.isCorrect){
correctAnswer = +choice; // plus operator converts to number
}
}
var stem:TextFormat = q.stem;
const question: Question = {
id: "",
name: this.removeTags(stem.text),
description: this.removeTags(stem.text),
lastModified: new Date (),
options: answerTexts,
answer: correctAnswer,
}
questions.push(question);
}
}
var qb: ParsedQuestionBank = {
questionBankTitle: questionBankTitle,
questions:questions
};
this.questionbanks.push(qb);
}
}

Просмотреть файл

@ -0,0 +1,62 @@
import { ParsedQuestionBank } from "./ParsedQuestionBank";
import { AssessmentAppParser } from "./Parser";
import { Question } from "../Question";
// Currently only parses in MCQs and TFs
export class MicrosoftOSCParser extends AssessmentAppParser{
public parse(): void {
const rawData = JSON.parse(this.raw);
for (let rawBank of rawData){
for (let rawQuestion of rawBank.quizzes) {
var questions:Question[] = [];
for (let question of rawQuestion.quiz){
var answerTexts = Array();
var correctAnswer = 0;
var counter = 0;
console.log("Read a new question");
console.log(question.questionText);
for (let option of question.answerOptions){
answerTexts.push(option.answerText)
if (option.isCorrect == "true"){
correctAnswer = counter ;
}
counter = counter + 1;
}
const questionToSave: Question = {
id: "",
name: question.questionText,
description: question.questionText,
lastModified: new Date (),
options: answerTexts,
answer: correctAnswer,
}
questions.push(questionToSave);
}
var qb: ParsedQuestionBank = {
questionBankTitle: rawQuestion.title,
questions:questions
};
this.questionbanks.push(qb);
}
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
import { ParsedQuestionBank } from "./ParsedQuestionBank";
import { AssessmentAppParser } from "./Parser";
import { Question } from "../Question";
export class OriginalAppParser extends AssessmentAppParser{
public parse() {
const rawData = JSON.parse(this.raw);
for (let rawBank of rawData) {
var questions:Question[] = [];
for (let rawQuestion of rawBank.questions) {
const question: Question = {
id: "",
name: rawQuestion.name,
description: rawQuestion.description,
lastModified: new Date (),
options: rawQuestion.options,
answer: rawQuestion.answer,
}
questions.push(question);
}
var qb: ParsedQuestionBank = {
questionBankTitle: rawBank.name,
questions:questions
};
this.questionbanks.push(qb);
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
import { Question } from "../Question";
export type ParsedQuestionBank = {
questionBankTitle:string;
questions: Question[];
}

Просмотреть файл

@ -0,0 +1,26 @@
import { ParsedQuestionBank } from "./ParsedQuestionBank";
export class AssessmentAppParser {
raw:string;
questionbanks:ParsedQuestionBank[];
constructor( raw:string) {
this.raw = raw;
this.questionbanks = [];
}
// This method gets overwritten by individual parsers
public parse() {
}
public removeTags(str:string) {
if ((str===null) || (str===''))
return '';
else
str = str.toString();
str = str.replace( /(<([^>]+)>)/ig, '')
str = str.replaceAll('\\n','')
return str;}
}

Просмотреть файл

@ -0,0 +1,66 @@
import { XMLParser} from "fast-xml-parser";
import { ParsedQuestionBank } from "./ParsedQuestionBank";
import { AssessmentAppParser } from "./Parser";
import { Question } from "../Question";
export class QTIParser extends AssessmentAppParser{
options = {
ignoreAttributes:false
};
public parse() {
var questionBankTitle:string = "Not defined yet";
var questions:Question[] = [];
const xmlParser: XMLParser = new XMLParser(this.options);
var parsedInput = xmlParser.parse(this.raw);
var assessment = parsedInput['questestinterop']['assessment'];
questionBankTitle = assessment['@_title'];
var questionsSection = assessment['section']['item']
for (let questionId in questionsSection){
var currQuestion = questionsSection[questionId];
var questionTitle = currQuestion['@_title'];
var qMetaDataField = currQuestion['itemmetadata']['qtimetadata']['qtimetadatafield'];
var metaData = qMetaDataField[0]; // 0 position contains question type
if (metaData['fieldentry'] != 'multiple_choice_question'){
continue; // As we currently only support MCQs
}
var questionText = currQuestion['presentation']['material']['mattext']['#text'];
questionText = this.removeTags(questionText); // Clean any html tags
questionText = questionText.split('\n')[1];
// Get all options
var responseLabels = currQuestion['presentation']['response_lid']['render_choice']['response_label'];
var answerTexts = Array();
var correctAnswer = currQuestion['resprocessing']['respcondition']['conditionvar']['varequal']['#text']
for (let responseId in responseLabels){
var response = responseLabels[responseId];
if (correctAnswer == response['@_ident']){
correctAnswer = responseId;
}
answerTexts.push(this.removeTags(response['material']['mattext']['#text']))
}
// Finally creating the question
const question:Question = {
id: "",
name: questionTitle,
description: questionText,
lastModified: new Date (),
options: answerTexts,
answer: correctAnswer,
}
questions.push(question);
}
var qb: ParsedQuestionBank = {
questionBankTitle: questionBankTitle,
questions:questions
};
this.questionbanks.push(qb);
}
}