import StringDiff from "./../../util/string_diff"; import { LocalizedStrings } from './../../services/localizedStringsService' export class OutputAssessmentResult { static get PAGE_TEMPLATE () { return ` :assessment-result: `; } static get DETAIL_TEMPLATE () { return `

:test-name:

:time-label:: :time:ms

:grade-label:: :grade:%

:input-label:

:output-label:

:output-result:
`; } static get OUPUT_TABLE_TEMPLATE () { return `
:results:
:expected-label: :generated-label: :result-label:
`; } static get OUTPUT_TEMPLATE () { return `$0 $1 $2`; } static get EMPTY_OUTPUT_TEMPLATE () { return `
$0
`; } static get FAILED_TEMPLATE () { return `

$0

`; } static get INPUT_INFO_TEMPLATE () { return `$1`; } // Status code - it is not grade related! // 0 - Succesful execution // 1 - failed execution constructor (name, status, inputs, result, store, time, error_msg = '') { this.name = name; this.status = status; this.inputs = inputs; this.results = result; this.store = store; this.time = time; this.error_msg = error_msg; } get grade () { if(this.results == null) { return 0; } return this.results.reduce((prev, val) => prev + val.grade, 0) / this.results.length; } prepareResults () { let template = OutputAssessmentResult.DETAIL_TEMPLATE; const grade = (this.grade * 100).toFixed(2); const time = this.time || "-"; template = template.replace(':test-name:', LocalizedStrings.getUI('assessment-detail-title', [this.name + 1])); template = template.replace(':time-label:', LocalizedStrings.getUI('assessment-detail-time-label')); template = template.replace(':time:', time); template = template.replace(':grade-label:', LocalizedStrings.getUI('assessment-detail-grade-label')); template = template.replace(':grade:', grade); const input_spans = this.prepareInputList(this.inputs); template = template.replace(':input-label:', LocalizedStrings.getUI('assessment-detail-input-label')); template = template.replace(':input-list:', input_spans); template = template.replace(':output-label:', LocalizedStrings.getUI('assessment-detail-output-label')); if(this.status == 0) { const output_rows = this.results.map(result => { if(result.type == "string") { return this.formatString(result); } else if (result.type == "number") { return this.formatNumber(result); } else { return this.formatBool(result); } }, this); template = template.replace(':output-result:', this.prepareOutputTable(output_rows)); } else { let failed_text = OutputAssessmentResult.FAILED_TEMPLATE; failed_text = failed_text.replace("$0", this.error_msg); template = template.replace(":output-result:", failed_text); } return template; } prepareInputList (input_list) { const list = input_list.map(input => { let template = OutputAssessmentResult.INPUT_INFO_TEMPLATE; template = template.replace("$1", input.value); if(input.read) { template = template.replace("$0", "assessment-input-read"); } else { template = template.replace("$0", "assessment-input-unread"); } return template; }, this); return list.join(LocalizedStrings.getUI('text_join_assessment_outputs')); } prepareOutputTable (output_rows) { let template = OutputAssessmentResult.OUPUT_TABLE_TEMPLATE; template = template.replace(':expected-label:', LocalizedStrings.getUI('assessment-detail-expected-label')); template = template.replace(':generated-label:', LocalizedStrings.getUI('assessment-detail-generated-label')); template = template.replace(':result-label:', LocalizedStrings.getUI('assessment-detail-result-label')); template = template.replace(':results:', output_rows.join('')); return template; } generateOutput () { const assessment_result = this.prepareResults(); let page = OutputAssessmentResult.PAGE_TEMPLATE; page = page.replace(':assessment-result:', assessment_result); page = page.replace(/(\r|\n|\t)/gm,'').replace(/> *<'); return page; } formatNumber (result) { const result_class = result.grade == 1 ? 'assessment-number-result' : 'assessment-number-result-failed'; let template = this.formatOutput('assessment-number-expected', 'assessment-number-generated', result_class, result); return template } formatBool (result) { const result_class = result.grade == 1 ? 'assessment-bool-result' : 'assessment-bool-result-failed'; let template = this.formatOutput('assessment-bool-expected', 'assessment-bool-generated', result_class, result); return template } formatOutput (expected_class, generated_class, result_class, result) { let template = OutputAssessmentResult.OUTPUT_TEMPLATE; template = template.replace(":class-expected:", expected_class); template = template.replace(":class-generated:", generated_class); template = template.replace(":class-result:", result_class); let expected_tmpl = result.expected; let generated_tmpl = result.generated; if(expected_tmpl == null) { expected_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0', LocalizedStrings.getMessage('assessment-empty-expected-tooltip')); } else if(generated_tmpl == null) { generated_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0', LocalizedStrings.getMessage('assessment-empty-generated-tooltip')); } template = template.replace("$0", expected_tmpl); template = template.replace("$1", generated_tmpl); const final_result = result.grade == 1 ? "✓" : "✗" template = template.replace("$2", final_result); return template } formatString (result) { const expected_class = 'assessment-string-expected'; const generated_class = 'assessment-string-generated'; //const result_class = 'assessment-string-result'; let template = OutputAssessmentResult.OUTPUT_TEMPLATE; template = template.replace(":class-expected:", expected_class); template = template.replace(":class-generated:", generated_class); //template = template.replace(":class-result:", result_class); const g_string = result.generated || ""; const e_string = result.expected || ""; // console.log("generated: ", g_string,"expected: ", e_string); let g_string_tmpl = g_string; let e_string_tmpl = e_string; if(result.generated == null) { g_string_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0', LocalizedStrings.getMessage('assessment-empty-generated-tooltip')); } else if (result.expected == null) { e_string_tmpl = OutputAssessmentResult.EMPTY_OUTPUT_TEMPLATE.replace('$0', LocalizedStrings.getMessage('assessment-empty-expected-tooltip')); } template = template.replace("$0", e_string_tmpl); template = template.replace("$1", g_string_tmpl); if(result.grade == 1) { template = template.replace("$2", "✓"); template = template.replace(":class-result:", 'assessment-string-result'); } else { const diff = StringDiff(g_string, e_string); // console.log(diff); const diff_vec = diff.map(part => this.getDiffStringStyle(part[1], part[0]), this); const diff_string = diff_vec.reduce((prev, actual) => prev + actual, ""); template = template.replace("$2", "" + diff_string); template = template.replace(":class-result:", "assessment-string-diff"); } return template; } getDiffStringStyle (text, action) { const template = "$1" // Fix missing whitespace when its a single element text = text.replace(/\s/g," "); switch(action) { case StringDiff.INSERT: return template.replace("$0", "stringdiff-insert").replace("$1", text); case StringDiff.DELETE: return template.replace("$0", "stringdiff-delete").replace("$1", text); case StringDiff.EQUAL: return template.replace("$0", "stringdiff-equal").replace("$1", text); } } }