Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Zitrone44 committed Dec 11, 2024
2 parents 8b7b8e1 + 82283c7 commit 269575c
Show file tree
Hide file tree
Showing 64 changed files with 8,705 additions and 1,506 deletions.
28 changes: 14 additions & 14 deletions .github/workflows/check-fbs-python-module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ jobs:
echo "::add-matcher::.github/problem-matchers/python.json"
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- name: Install and configure Poetry
uses: snok/install-poetry@v1
- name: Install library
run: poetry install --no-interaction
- run: |
poetry run pylint api --msg-template='${{ inputs.working-directory }}/{path}:{line}:{column}: {msg_id}: {msg} ({symbol})'
name: Run Pylint
id: pylint
- run: |
poetry run black --check --verbose --diff api
name: Run Black
# Run Step even if pylint was not successfull
if: ${{ success() || steps.pylint.conclusion == 'failure' }}
# - run: |
# poetry run pylint api --msg-template='${{ inputs.working-directory }}/{path}:{line}:{column}: {msg_id}: {msg} ({symbol})'
# name: Run Pylint
# id: pylint
# - run: |
# poetry run black --check --verbose --diff api
# name: Run Black
# # Run Step even if pylint was not successfull
# if: ${{ success() || steps.pylint.conclusion == 'failure' }}

test:
name: Test
Expand All @@ -48,10 +48,10 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- name: Install and configure Poetry
uses: snok/install-poetry@v1
- name: Install library
run: poetry install --no-interaction --only dev
- name: Run unittest
run: poetry run python -m unittest
run: poetry install --no-interaction
# - name: Run unittest
# run: poetry run python -m unittest
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ services:
environment:
POSTGRES_PASSWORD: SqfyBWhiFGr7FK60cVR2rel
PGDATA: /var/lib/postgresql/data/pgdata
ports:
- 5432:5432
volumes:
- ./data/postgres2:/var/lib/postgresql/data
networks:
Expand Down Expand Up @@ -213,6 +215,7 @@ services:
SQL_PLAYGROUND_SHARE_PSQL_SERVER_URL: jdbc:postgresql://psql-sharing:5432/?allowMultiQueries=true
SQL_PLAYGROUND_SHARE_PSQL_SERVER_PASSWORD: R!7pWqY@K5zE3Xt&g9L1MfD
SQL_PLAYGROUND_SHARE_PSQL_SERVER_USERNAME: postgres
RUNNER_DOCKER_DISABLE_REMOVE: "true"
volumes:
- /tmp/feebi:/dockertemp # A temp dir where docker image stores task submissions temporarily
- /var/run/docker.sock:/var/run/docker.sock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class HomeController {
* Forward every access that is not defined to the index page.
* @return Forward undefined access to index.
*/
@RequestMapping(value = Array("/courses", "/sqlplayground", "/analytics", "/modelling", "/kanban")) // TODO: Remove as soon as possible
@RequestMapping(value = Array("/courses", "/sqlplayground", "/analytics", "/modelling", "/kanban", "/sci-check")) // TODO: Remove as soon as possible
def redirectRoot: String = "forward:/"

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
Expand All @@ -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()
Expand All @@ -57,5 +58,6 @@ case class SqlCheckerInformation(
showHints: Boolean,
showHintsAt: Int,
showExtendedHints: Boolean,
showExtendedHintsAt: Int
showExtendedHintsAt: Int,
disableDistance: Boolean,
) extends CheckerTypeInformation
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package de.thm.ii.fbs.model

import java.util
import java.util.Optional

case class SQLCheckerQuery(id: String, taskNumber: String, statement: String, queryRight: Boolean, parsable: Boolean,
case class SQLCheckerError(expected: String, got: String, trace: util.List[String])

case class SQLCheckerQuery(id: String, taskNumber: String, statement: String, parsable: Boolean,
queryRight: Optional[Boolean], passed: Optional[Boolean],
tablesRight: Optional[Boolean], proAttributesRight: Optional[Boolean], selAttributesRight: Optional[Boolean],
stringsRight: Optional[Boolean], orderByRight: Optional[Boolean], groupByRight: Optional[Boolean],
joinsRight: Optional[Boolean], wildcards: Optional[Boolean], userId: Int, attempt: Int)
joinsRight: Optional[Boolean], wildcards: Optional[Boolean], distance: Optional[Int], userId: Int, attempt: Int,
version: Optional[String], errors: util.List[SQLCheckerError],
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper}
import de.thm.ii.fbs.model
import de.thm.ii.fbs.model.checker.{RunnerRequest, SqlCheckerState, SqlCheckerSubmission, User}
import de.thm.ii.fbs.model.task.Task
import de.thm.ii.fbs.model.{CheckrunnerConfiguration, SqlCheckerInformation, Submission => FBSSubmission}
import de.thm.ii.fbs.model.{CheckrunnerConfiguration, SQLCheckerQuery, SqlCheckerInformation, Submission => FBSSubmission}
import de.thm.ii.fbs.services.checker.`trait`._
import de.thm.ii.fbs.services.persistence._
import de.thm.ii.fbs.services.persistence.storage.StorageService
Expand All @@ -14,8 +14,10 @@ import org.springframework.beans.factory.annotation.{Autowired, Value}
import org.springframework.stereotype.Service

import java.util.UUID
import java.util.Optional
import java.util.concurrent.ConcurrentHashMap
import scala.collection.mutable
import scala.jdk.CollectionConverters._

object SqlCheckerRemoteCheckerService {
private val isCheckerRun = new ConcurrentHashMap[Int, SqlCheckerState.Value]()
Expand Down Expand Up @@ -81,15 +83,13 @@ class SqlCheckerRemoteCheckerService(@Value("${services.masterRunner.insecure}")
resultText: String, extInfo: String): Unit = {
SqlCheckerRemoteCheckerService.isCheckerRun.getOrDefault(submission.id, SqlCheckerState.Runner) match {
case SqlCheckerState.Runner =>
SqlCheckerRemoteCheckerService.isCheckerRun.put(submission.id, SqlCheckerState.Checker)
this.notify(task.id, submission.id, checkerConfiguration, userService.find(submission.userID.get).get)
if (exitCode == 2 && hintsEnabled(checkerConfiguration)) {
SqlCheckerRemoteCheckerService.isCheckerRun.put(submission.id, SqlCheckerState.Checker)
if (extInfo != null) {
SqlCheckerRemoteCheckerService.extInfo.put(submission.id, extInfo)
}
this.notify(task.id, submission.id, checkerConfiguration, userService.find(submission.userID.get).get)
} else {
SqlCheckerRemoteCheckerService.isCheckerRun.put(submission.id, SqlCheckerState.Ignore)
this.notify(task.id, submission.id, checkerConfiguration, userService.find(submission.userID.get).get)
SqlCheckerRemoteCheckerService.isCheckerRun.put(submission.id, SqlCheckerState.Ignore)
super.handle(submission, checkerConfiguration, task, exitCode, resultText, extInfo)
}
Expand All @@ -109,57 +109,90 @@ class SqlCheckerRemoteCheckerService(@Value("${services.masterRunner.insecure}")
case Some(sci: SqlCheckerInformation) =>
val hints = new mutable.StringBuilder()
val attempts = submissionService.getAll(userID, task.courseID, task.id).length
sqlCheckerService.getQuery(task.id, userID) match {
sqlCheckerService.getQuery(submission.id) match {
case Some(query) =>
if (!query.parsable) {
hints ++= "Abfrage nicht parsbar\n"
hints ++= "genaues Feedback nicht verfügbar\n"
} else {
if (sci.showHints && sci.showHintsAt <= attempts) {
if (!query.tablesRight.get) {
hints ++= "falsche Tabellen verwendet\n"
}
if (!query.selAttributesRight.get) {
hints ++= "falsche Where-Attribute verwendet\n"
}
if (!query.proAttributesRight.get) {
hints ++= "falsche Select-Attribute verwendet\n"
}
if (!query.stringsRight.get) {
if (!query.wildcards.get) {
hints ++= "falsche Zeichenketten verwendet, bitte auch die Wildcards prüfen\n"
} else {
hints ++= "falsche Zeichenketten verwendet\n"
}
}
if (!query.orderByRight.get) {
hints ++= "falsche Order By verwendet\n"
}
if (!query.groupByRight.get) {
hints ++= "falsche Group By verwendet\n"
}
if (!query.joinsRight.get) {
hints ++= "falsche Joins verwendet\n"
}
}
if (sci.showExtendedHints && sci.showExtendedHintsAt <= attempts) {
//ToDo
}
formatHint(sci, hints, attempts, query)
}
(if (query.queryRight) 0 else 1, hints.toString())
(if (Optional.ofNullable(query.queryRight)
.or(() => Optional.ofNullable(query.passed)).flatMap(a => a).get()) {0} else {1}, hints.toString())
case _ => (3, "sql-checker hat kein Abfrageobjekt zurückgegeben")
}
case _ => (2, "Ungültige Checker-Typ-Informationen")
}
super.handle(submission, checkerConfiguration, task, exitCode, resultText, extInfo)
}

private def formatHint(sci: SqlCheckerInformation, hints: StringBuilder, attempts: Int, query: SQLCheckerQuery): Unit = {
if (sci.showHints && sci.showHintsAt <= attempts) {
if (query.version == Optional.of("v2")) {
formatV2(hints, query)
} else {
formatLegacy(hints, query)
}
}
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"
} else {
hints ++= "Es sind "
hints ++= steps.toString
hints ++= " Änderungen erforderlich, um Deine Lösung an die nächstgelegene Musterlösung anzupassen.\n"
}
}
if (sci.showExtendedHints && sci.showExtendedHintsAt <= attempts) {
//ToDo
}
}

private def formatV2(hints: StringBuilder, query: SQLCheckerQuery): Unit = {
for (error <- query.errors.asScala) {
hints ++= "Mistake in "
hints ++= error.trace.asScala.mkString(", ")
hints ++= " where "
hints ++= error.got
hints ++= "\n\n"
}
}

private def formatLegacy(hints: StringBuilder, query: SQLCheckerQuery): Unit = {
if (!query.tablesRight.get) {
hints ++= "falsche Tabellen verwendet\n"
}
if (!query.selAttributesRight.get) {
hints ++= "falsche Where-Attribute verwendet\n"
}
if (!query.proAttributesRight.get) {
hints ++= "falsche Select-Attribute verwendet\n"
}
if (!query.stringsRight.get) {
if (!query.wildcards.get) {
hints ++= "falsche Zeichenketten verwendet, bitte auch die Wildcards prüfen\n"
} else {
hints ++= "falsche Zeichenketten verwendet\n"
}
}
if (!query.orderByRight.get) {
hints ++= "falsche Order By verwendet\n"
}
if (!query.groupByRight.get) {
hints ++= "falsche Group By verwendet\n"
}
if (!query.joinsRight.get) {
hints ++= "falsche Joins verwendet\n"
}
}

def formatSubmission(submission: FBSSubmission, checker: CheckrunnerConfiguration, solution: String): Any = {
val task = taskService.getOne(checker.taskId).get
val attempts = submissionService.getAll(submission.userID.get, task.courseID, checker.taskId).length
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ class SQLCheckerService {
mongodbTemplate.upsert(query, solution, SolutionCollectionName)
}

def getQuery(taskNumber: Int, userId: Int): Option[SQLCheckerQuery] = {
def getQuery(submissionId: Int): Option[SQLCheckerQuery] = {
val query = new Query()
query.`with`(Sort.by(Sort.Direction.DESC, "$natural"))
query.addCriteria(where("taskNumber").is(taskNumber))
query.addCriteria(where("submissionId").is(submissionId))

Option(mongodbTemplate.findOne(query, classOf[SQLCheckerQuery], QueryCollectionName))
}
Expand Down
7 changes: 7 additions & 0 deletions modules/fbs-core/web/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { AnalyticsToolComponent } from "./page-components/analytics-tool/analyti
import { FbsModellingComponent } from "./page-components/fbs-modelling/fbs-modelling.component";
import { GroupDetailComponent } from "./page-components/group-detail/group-detail.component";
import { FbsKanbanComponent } from "./page-components/fbs-kanban/fbs-kanban.component";
import { FbsSciCheckComponent } from "./page-components/fbs-sci-check/fbs-sci-check.component";

const routes: Routes = [
{ path: "login", component: LoginComponent },
Expand Down Expand Up @@ -115,6 +116,12 @@ const routes: Routes = [
component: FbsKanbanComponent,
canActivate: [AuthGuard],
},
// Sci-Check
{
path: "sci-check",
component: FbsSciCheckComponent,
canActivate: [AuthGuard],
},
// Admin
{
path: "admin/user-management",
Expand Down
2 changes: 2 additions & 0 deletions modules/fbs-core/web/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ import { GroupPreviewComponent } from "./page-components/group-preview/group-pre
import { GroupDetailComponent } from "./page-components/group-detail/group-detail.component";
import { GroupDeregisterDialogComponent } from "./dialogs/group-deregister-dialog/group-deregister-dialog.component";
import { FbsKanbanComponent } from "./page-components/fbs-kanban/fbs-kanban.component";
import { FbsSciCheckComponent } from "./page-components/fbs-sci-check/fbs-sci-check.component";

@Injectable()
export class ApiURIHttpInterceptor implements HttpInterceptor {
Expand Down Expand Up @@ -232,6 +233,7 @@ export const httpInterceptorProviders = [
GroupDetailComponent,
GroupDeregisterDialogComponent,
FbsKanbanComponent,
FbsSciCheckComponent,
],
imports: [
BrowserModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ <h4>
</mat-form-field>
</div>
</div>
<div>
<mat-checkbox
formControlName="disableDistance"
value="false"
(change)="showHintsEvent(checkerForm.value)"
>{{
"dialog.checker.new.disable-distance" | i18nextEager
}}</mat-checkbox
>
</div>
</div>
</form>
<mat-dialog-actions class="actions">
Expand Down
Loading

0 comments on commit 269575c

Please sign in to comment.