UNPKG

course-renderer

Version:

Manages CA School Courses file system storage and HTML conversion

152 lines (151 loc) 5.84 kB
"use strict"; /** * @module answer-generator */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs-extra"); const yaml = require("js-yaml"); const path = require("path"); const _ = require("lodash"); const replaceExtension = require('replace-ext'); const { promisify } = require('util'); const read = promisify(fs.readFile); const append = promisify(fs.appendFile); const statFile = promisify(fs.stat); const access = promisify(fs.access); const readDir = promisify(fs.readdir); /** * answerGenerator - Generates an answer.yml file for each course */ function answerGenerator(tokens, courseDest, courseSource, callback) { return __awaiter(this, void 0, void 0, function* () { const pathSep = path.sep; const output = path.resolve(courseDest, 'answer.yml'); let answerOutput = {}; try { let mapping; try { yield access(path.resolve(courseSource, 'mapping.json'), fs.constants.F_OK); mapping = JSON.parse(yield read(path.resolve(courseSource, 'mapping.json'), 'utf-8')); } catch (e) { mapping = {}; } yield createTokensAnswer(tokens, answerOutput, courseSource, mapping); if (!_.isEmpty(answerOutput)) { yield append(output, yaml.safeDump(answerOutput)); } callback(null, tokens); } catch (e) { callback(e); } }); } exports.answerGenerator = answerGenerator; function createTokensAnswer(tokens, answerOutput, courseSource, mapping) { return __awaiter(this, void 0, void 0, function* () { for (let token of tokens) { if (token.children instanceof Array) { yield createTokensAnswer(token.children, answerOutput, courseSource, mapping); } else if (token.type && token.type !== 'text' && token.type !== 'REPL') { const answer = createTokenAnswer(token); if (token.type === 'CR') { answer.hint = yield getQuestionHint(courseSource, answer.answer, token.id); } else if (token.type === 'MS') { // Sort MS answer just in case the authors did not sort the answer on the annotation. The reader is expecting a sorted answer const answers = answer.answer.split(','); answers.sort((a, b) => { return a - b; }); answer.answer = answers.join(','); } delete token.answer; if (mapping[token.id]) { answer.provisionedId = mapping[token.id]; 1; } answerOutput[token.id] = answer; } } }); } function createTokenAnswer(token) { return { text: token.content, chapter: token.chapter, answer: token.answer, type: token.type }; } function readHintFile(hintFile) { return __awaiter(this, void 0, void 0, function* () { try { return yield read(hintFile, 'utf-8'); } catch (e) { console.log(e); throw new Error(`Unable to read Proof file ${hintFile}: ${e.message}`); } }); } function hintFileExists(hintFile) { return __awaiter(this, void 0, void 0, function* () { try { const stat = yield statFile(hintFile); return true; } catch (e) { return false; } }); } function readHintDirectory(hintDirectory) { return __awaiter(this, void 0, void 0, function* () { try { const files = yield readDir(hintDirectory); if (files.length == 0) { throw new Error(`Hint directory ${hintDirectory} is empty`); } const hints = []; for (let i = 0; i < files.length; i++) { const file = path.resolve(hintDirectory, files[i]); const content = yield read(file, 'utf-8'); hints.push({ fileName: files[i], answer: content }); } return hints; } catch (e) { throw e; } }); } function getQuestionHint(source, answerPath, id) { return __awaiter(this, void 0, void 0, function* () { let hintFile = path.resolve(source, answerPath.replace(/^tests/, 'answers')); if (yield hintFileExists(hintFile)) { const fileName = path.basename(hintFile); return [{ fileName: fileName, answer: yield readHintFile(hintFile) }]; } else if (yield hintFileExists(replaceExtension(hintFile, ''))) { hintFile = replaceExtension(hintFile, ''); const fileName = path.basename(hintFile); return [{ fileName: fileName, answer: yield readHintFile(hintFile) }]; } else { // Assume the hint is in a directory const hintPath = path.resolve(path.dirname(path.resolve(source, answerPath.replace(/^tests/, 'answers'))), id); return yield readHintDirectory(hintPath); } }); }