ivprogAssessment.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { IVProgParser } from "./../ast/ivprogParser";
  2. import { SemanticAnalyser } from "./../processor/semantic/semanticAnalyser";
  3. import { IVProgProcessor } from "./../processor/ivprogProcessor";
  4. import { InputTest } from "./../util/inputTest";
  5. import { OutputTest } from "./../util/outputTest";
  6. import * as LocalizedStringsService from "../services/localizedStringsService";
  7. import { Decimal } from 'decimal.js';
  8. import { Config } from "../util/config";
  9. const LocalizedStrings = LocalizedStringsService.getInstance();
  10. export class IVProgAssessment {
  11. constructor (textCode, testCases, domConsole) {
  12. this.textCode = textCode;
  13. this.testCases = testCases;
  14. this.domConsole = domConsole;
  15. }
  16. runTest () {
  17. try {
  18. // try and show error messages through domconsole
  19. const parser = IVProgParser.createParser(this.textCode);
  20. const semantic = new SemanticAnalyser(parser.parseTree());
  21. const validTree = semantic.analyseTree();
  22. // loop test cases and show messages through domconsole
  23. const partialTests = this.testCases.map( (t, name) => {
  24. return this.partialEvaluateTestCase(new IVProgProcessor(validTree), t.input, t.output, name);
  25. });
  26. const testResult = partialTests.reduce((acc, curr) => acc.then(curr), Promise.resolve(0));
  27. return testResult.then(total => Promise.resolve(total / this.testCases.length))
  28. .catch(err => {
  29. this.domConsole.err("Erro durante a execução do programa");// try and show error messages through domconsole
  30. this.domConsole.err(err.message);
  31. return Promise.resolve(0);
  32. });
  33. } catch (error) {
  34. this.domConsole.err("Erro durante a execução do programa");// try and show error messages through domconsole
  35. this.domConsole.err(error.message);
  36. return Promise.resolve(0);
  37. }
  38. }
  39. evaluateTestCase (prog, inputList, outputList, name, accumulator) {
  40. const outerThis = this;
  41. const input = new InputTest(inputList);
  42. const output = new OutputTest();
  43. prog.registerInput(input);
  44. prog.registerOutput(output);
  45. const startTime = Date.now()
  46. return prog.interpretAST().then( _ => {
  47. const millis = Date.now() - startTime;
  48. if (input.inputList.length !== input.index) {
  49. outerThis.showErrorMessage('test_case_few_reads', name+1);
  50. outerThis.showMessage('test_case_duration', millis);
  51. return Promise.resolve(accumulator + 1 * (input.index/inputList.length));
  52. } else if (output.list.length < outputList.length) {
  53. outerThis.showErrorMessage('test_case_failed', name + 1, inputList.join(','),
  54. outputList.join(','), output.list.join(','));
  55. outerThis.showMessage('test_case_duration', millis);
  56. return Promise.resolve(accumulator + 1 * (output.list.length/outputList.length));
  57. } else if (output.list.length > outputList.length) {
  58. outerThis.showErrorMessage('test_case_failed', name + 1, inputList.join(','),
  59. outputList.join(','), output.list.join(','));
  60. outerThis.showMessage('test_case_duration', millis);
  61. return Promise.resolve(accumulator + 1 * (outputList.length/output.list.length));
  62. } else {
  63. const isOk = outerThis.checkOutput(output.list, outputList);
  64. if(!isOk) {
  65. outerThis.showErrorMessage('test_case_failed', name + 1, inputList.join(','),
  66. outputList.join(','), output.list.join(','));
  67. outerThis.showMessage('test_case_duration', millis);
  68. return Promise.resolve(accumulator);
  69. } else {
  70. outerThis.showMessage('test_case_success', name + 1);
  71. outerThis.showMessage('test_case_duration', millis);
  72. return Promise.resolve(accumulator + 1);
  73. }
  74. }
  75. }).catch( error => {
  76. outerThis.showErrorMessage('test_case_failed_exception', name + 1, error.message);
  77. return Promise.resolve(accumulator);
  78. });
  79. }
  80. partialEvaluateTestCase (prog, inputList, outputList, name) {
  81. return this.evaluateTestCase.bind(this, prog, inputList, outputList, name);
  82. }
  83. checkOutput (aList, bList) {
  84. for (let i = 0; i < aList.length; i++) {
  85. const outValue = aList[i];
  86. let castNumberA = parseFloat(outValue);
  87. if(!Number.isNaN(castNumberA)) {
  88. let castNumberB = parseFloat(bList[i]);
  89. if(Number.isNaN(castNumberB)) {
  90. return false;
  91. }
  92. castNumberA = new Decimal(castNumberA);
  93. castNumberB = new Decimal(castNumberB);
  94. const decimalPlaces = Math.min(castNumberB.dp(), Config.decimalPlaces);
  95. Decimal.set({ rounding: Decimal.ROUND_FLOOR});
  96. castNumberA = new Decimal(castNumberA.toFixed(decimalPlaces));
  97. castNumberB = new Decimal(castNumberB.toFixed(decimalPlaces));
  98. const aEqualsB = castNumberA.eq(castNumberB);
  99. Decimal.set({ rounding: Decimal.ROUND_HALF_UP});
  100. if (!aEqualsB) {
  101. return false;
  102. }
  103. } else if(outValue != bList[i]) {
  104. return false;
  105. }
  106. }
  107. return true;
  108. }
  109. showErrorMessage (errorID, ...args) {
  110. this.domConsole.err(LocalizedStrings.getError(errorID, args));
  111. }
  112. showMessage (msgID, ...args) {
  113. this.domConsole.info(LocalizedStrings.getMessage(msgID, args));
  114. }
  115. }