diff --git a/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/controller/CheckerConfigurationController.scala b/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/controller/CheckerConfigurationController.scala index ff847b9e7..d8e79cbab 100644 --- a/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/controller/CheckerConfigurationController.scala +++ b/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/controller/CheckerConfigurationController.scala @@ -92,10 +92,10 @@ class CheckerConfigurationController { case (Some(checkerType), Some(ord), Some(checkerTypeInformation)) => (checkerTypeInformation.retrive("showHints").asBool(), checkerTypeInformation.retrive("showHintsAt").asInt(), checkerTypeInformation.retrive("showExtendedHints").asBool(), - checkerTypeInformation.retrive("showExtendedHintsAt").asInt()) match { - case (Some(showHints), Some(showHintsAt), Some(showExtendedHints), Some(showExtendedHintsAt)) => + checkerTypeInformation.retrive("showExtendedHintsAt").asInt(), checkerTypeInformation.retrive("disableDistance").asBool()) match { + case (Some(showHints), Some(showHintsAt), Some(showExtendedHints), Some(showExtendedHintsAt), Some(disableDistance)) => val cc = CheckrunnerConfiguration(checkerType, ord, checkerTypeInformation = - Some(SqlCheckerInformation("", showHints, showHintsAt, showExtendedHints, showExtendedHintsAt))) + Some(SqlCheckerInformation("", showHints, showHintsAt, showExtendedHints, showExtendedHintsAt, disableDistance))) notifyChecker(tid, cc) val ccc = this.ccs.create(cid, tid, cc) notifyChecker(tid, ccc) @@ -139,10 +139,10 @@ class CheckerConfigurationController { case (Some(checkerType), Some(ord), Some(checkerTypeInformation)) => (checkerTypeInformation.retrive("showHints").asBool(), checkerTypeInformation.retrive("showHintsAt").asInt(), checkerTypeInformation.retrive("showExtendedHints").asBool(), - checkerTypeInformation.retrive("showExtendedHintsAt").asInt()) match { - case (Some(showHints), Some(showHintsAt), Some(showExtendedHints), Some(showExtendedHintsAt)) => + checkerTypeInformation.retrive("showExtendedHintsAt").asInt(), checkerTypeInformation.retrive("disableDistance").asBool()) match { + case (Some(showHints), Some(showHintsAt), Some(showExtendedHints), Some(showExtendedHintsAt), Some(disableDistance)) => val cc = CheckrunnerConfiguration(checkerType, ord, checkerTypeInformation = - Some(SqlCheckerInformation("", showHints, showHintsAt, showExtendedHints, showExtendedHintsAt))) + Some(SqlCheckerInformation("", showHints, showHintsAt, showExtendedHints, showExtendedHintsAt, disableDistance))) notifyChecker(tid, cc) this.ccs.update(cid, tid, ccid, cc) case _ => throw new BadRequestException("Malformed checker type information") diff --git a/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/model/CheckerTypeInformation.scala b/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/model/CheckerTypeInformation.scala index 77cd09b8c..89c6858ed 100644 --- a/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/model/CheckerTypeInformation.scala +++ b/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/model/CheckerTypeInformation.scala @@ -12,7 +12,7 @@ object CheckerTypeInformation { val obj = new JSONObject(json) obj.getString("type") match { case "sqlCheckerInformation" => SqlCheckerInformation (obj.getString ("solution"), obj.getBoolean ("showHints"), - obj.getInt ("showHintsAt"), obj.getBoolean ("showExtendedHints"), obj.getInt ("showExtendedHintsAt") ) + obj.getInt ("showHintsAt"), obj.getBoolean ("showExtendedHints"), obj.getInt ("showExtendedHintsAt"), obj.getBoolean("disableDistance") ) case _ => throw new IllegalArgumentException() } } @@ -32,6 +32,7 @@ object CheckerTypeInformation { .put("showHintsAt", sobj.showHintsAt) .put("showExtendedHints", sobj.showExtendedHints) .put("showExtendedHintsAt", sobj.showExtendedHintsAt) + .put("disableDistance", sobj.disableDistance) .toString case _ => throw new IllegalArgumentException() @@ -57,5 +58,6 @@ case class SqlCheckerInformation( showHints: Boolean, showHintsAt: Int, showExtendedHints: Boolean, - showExtendedHintsAt: Int + showExtendedHintsAt: Int, + disableDistance: Boolean, ) extends CheckerTypeInformation diff --git a/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/services/checker/SqlCheckerRemoteCheckerService.scala b/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/services/checker/SqlCheckerRemoteCheckerService.scala index 57c5c6e96..f5e4c9305 100644 --- a/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/services/checker/SqlCheckerRemoteCheckerService.scala +++ b/modules/fbs-core/api/src/main/scala/de/thm/ii/fbs/services/checker/SqlCheckerRemoteCheckerService.scala @@ -133,7 +133,7 @@ class SqlCheckerRemoteCheckerService(@Value("${services.masterRunner.insecure}") formatLegacy(hints, query) } } - if (query.distance.isPresent) { + if (!sci.disableDistance && query.distance.isPresent) { val steps = Math.round(query.distance.get / 50) if (steps == 0) { hints ++= "Du bist ganz nah an der Lösung, es sind nur noch kleine Änderung notwendig.\n" @@ -192,7 +192,7 @@ class SqlCheckerRemoteCheckerService(@Value("${services.masterRunner.insecure}") val passed = submission.results.headOption.exists(result => result.exitCode == 0) new ObjectMapper().createObjectNode() .put("passed", passed) - .put("isSol", false) + .put("isSol", !checker.checkerTypeInformation.get.asInstanceOf[SqlCheckerInformation].disableDistance) .put("userId", submission.userID.get) .put("cid", task.courseID) .put("tid", checker.taskId) diff --git a/modules/fbs-core/web/src/app/dialogs/new-checker-dialog/new-checker-dialog.component.html b/modules/fbs-core/web/src/app/dialogs/new-checker-dialog/new-checker-dialog.component.html index 0d6f50a02..bf32c8014 100644 --- a/modules/fbs-core/web/src/app/dialogs/new-checker-dialog/new-checker-dialog.component.html +++ b/modules/fbs-core/web/src/app/dialogs/new-checker-dialog/new-checker-dialog.component.html @@ -95,6 +95,16 @@
{{ activeTab.errorMsg }}+ diff --git a/modules/fbs-sql-checker/api/datatypes.py b/modules/fbs-sql-checker/api/datatypes.py index 3f2301acb..25f294bd1 100644 --- a/modules/fbs-sql-checker/api/datatypes.py +++ b/modules/fbs-sql-checker/api/datatypes.py @@ -76,6 +76,7 @@ class Result: statement: str = "" time: str = "" passed: bool = False + is_solution: bool = False parsable: bool = False closest_solution: str = "" min_distance: int = 0 @@ -92,6 +93,7 @@ def from_submission(cls, submission: Submission) -> Self: attempt=submission.attempt, statement=submission.submission, time=datetime.now(UTC).isoformat(), + is_solution=submission.is_solution and submission.passed, ) @classmethod @@ -123,6 +125,7 @@ def to_db_dict(self): "statement": self.statement, "passed": self.passed, "parsable": self.parsable, + "isSolution": self.is_solution, "time": self.time, "usedSolutionId": self.closest_solution, "distance": self.min_distance, @@ -134,7 +137,6 @@ def to_db_dict(self): @typechecked class LegacyResult(Result): task_nr: int = 0 - is_sol: bool = False tables_right: bool = False sel_attributes_right: bool = False pro_attributes_right: bool = False @@ -154,7 +156,7 @@ def to_db_dict(self): "statement": self.statement, "queryRight": self.passed, "parsable": self.parsable, - "isSolution": self.is_sol, + "isSolution": self.is_solution, "tablesRight": self.tables_right, "selAttributesRight": self.sel_attributes_right, "proAttributesRight": self.pro_attributes_right, diff --git a/modules/fbs-sql-checker/api/main.py b/modules/fbs-sql-checker/api/main.py index 8b7d7dddb..5e7925b27 100755 --- a/modules/fbs-sql-checker/api/main.py +++ b/modules/fbs-sql-checker/api/main.py @@ -1,6 +1,7 @@ # main.py """System module.""" +import json import sys # pylint: disable=W0611 import requests # pylint: disable=W0611 @@ -10,7 +11,7 @@ from api.distance.distance_calc import GetDistanceCalculator from api.query_processor import QueryProcessorV2 from api.datatypes import Submission -from api.solution_fetcher import NearestSolutionFetcher +from api.solution_fetcher import NearestSolutionFetcher, FirstSolutionFetcher # The following Code is for productive purposes @@ -21,12 +22,14 @@ "zu analysierende JSON aufgerufen werden soll." ) else: + answer = requests.get(sys.argv[1], verify=False, timeout=60) + submission = Submission.from_dict(answer.json()) storage = MongoDataStore.connect(sys.argv[2]) qp = QueryProcessorV2( SqlparseComparator(), NearestSolutionFetcher(storage, GetDistanceCalculator()), ) - answer = requests.get(sys.argv[1], verify=False, timeout=60) - result = qp.process(Submission.from_dict(answer.json())) + result = qp.process(submission) + print("storing", result.to_db_dict()) storage.store("Queries", result.to_db_dict()) diff --git a/modules/fbs-sql-checker/api/query_processor.py b/modules/fbs-sql-checker/api/query_processor.py index 583a14ee9..a5e2977fb 100755 --- a/modules/fbs-sql-checker/api/query_processor.py +++ b/modules/fbs-sql-checker/api/query_processor.py @@ -56,27 +56,24 @@ def __init__( def process(self, submission: Submission) -> Result: result = ResultV2.from_submission(submission) - if not (submission.is_solution or submission.passed): - solution, distance = self._solution_fetcher.fetch_solution( - submission.task_id, submission + solution, distance = self._solution_fetcher.fetch_solution( + submission.task_id, submission + ) + if solution is None and result.is_solution: + sqlparse.parse(submission.submission) + result.passed = True + result.parsable = True + return result + try: + result.errors = self._comparator.compare( + solution.statement, submission.submission ) - try: - result.errors = self._comparator.compare( - solution.statement, submission.submission - ) - result.passed = len(result.errors) == 0 - result.closest_solution = solution.uuid - result.min_distance = distance - result.parsable = True - except Exception as e: - logger.exception(e) - else: - try: - sqlparse.parse(submission.submission) - result.parsable = True - except Exception as e: - pass - result.passed = result.parsable + result.passed = len(result.errors) == 0 + result.closest_solution = solution.uuid + result.min_distance = distance + result.parsable = True + except Exception as e: + logger.exception(e) return result diff --git a/modules/fbs-sql-checker/api/solution_fetcher.py b/modules/fbs-sql-checker/api/solution_fetcher.py index 5316e1885..c6273d4a6 100644 --- a/modules/fbs-sql-checker/api/solution_fetcher.py +++ b/modules/fbs-sql-checker/api/solution_fetcher.py @@ -1,6 +1,6 @@ import math from abc import ABCMeta, abstractmethod -from typing import Tuple +from typing import Tuple, Optional from api.data_store import DataStore from api.distance.distance_calc import DistanceCalculator @@ -11,7 +11,7 @@ class SolutionFetcher(metaclass=ABCMeta): @abstractmethod def fetch_solution( self, task_id: int, submission: Submission - ) -> Tuple[Result, float]: + ) -> Tuple[Optional[Result], float]: pass @@ -21,11 +21,12 @@ def __init__(self, datastore: DataStore): def fetch_solution( self, task_id: int, submission: Submission - ) -> Tuple[Result, float]: + ) -> Tuple[Optional[Result], float]: + solution = self._datastore.query("Queries", {"taskId": task_id, "isSolution": True}) + if len(solution) == 0: + return None, 0.0 return ( - Result.from_db_dict( - self._datastore.query("Queries", {"taskId": task_id, "passed": True}) - ), + Result.from_db_dict(solution[0]), 1.0, ) @@ -39,7 +40,7 @@ def fetch_solution( self, task_id: int, submission: Submission ) -> Tuple[Result, float]: solutions = self._datastore.query( - "Queries", {"taskId": task_id, "passed": True} + "Queries", {"taskId": task_id, "isSolution": True} ) solutions = [Result.from_db_dict(solution) for solution in solutions] min_distance = math.inf