Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions src/main/kotlin/fi/aalto/cs/apluscourses/api/APlusApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@
val UserID: Long,
val Status: String,
val Grade: Int,
val Penalty: Double?
val Penalty: Double?,
val Tags: String //tunnisteet ovat eroteltu pystyviivoilla | api:ssa
)
}

Expand Down Expand Up @@ -286,20 +287,66 @@

@Resource("/submissions/{id}")
class Submission(val id: Long) {
@OptIn(ExperimentalSerializationApi::class)
suspend fun get(project: Project): SubmissionBody {
return CoursesClient.getInstance(project).getBody<Submission, SubmissionBody>(this@Submission)
val json = Json {
ignoreUnknownKeys = true
namingStrategy = JsonNamingStrategy.SnakeCase
}
val noTagJson = json.encodeToString(OuterData(gradingData = null))

Check notice on line 296 in src/main/kotlin/fi/aalto/cs/apluscourses/api/APlusApi.kt

View workflow job for this annotation

GitHub Actions / Inspect code

Redundant value argument

Value argument matches the default value of parameter 'gradingData'
val raw = CoursesClient.getInstance(project).getBody<Submission, RawSubmissionBody>(this@Submission)
var tags: List<String> = emptyList()
val rawGradingData = raw.gradingData?.let {
val potentialRaw = it.gradingData ?: noTagJson
json.decodeFromString<RawGradingData>(potentialRaw)
}
if (rawGradingData != null) {
tags = rawGradingData.submissionTags?.split(",")?.map { it.trim() } ?: emptyList()
}

return SubmissionBody(
feedback = raw.feedback,
htmlUrl = raw.htmlUrl,
status = raw.status,
grade = raw.grade,
latePenaltyApplied = raw.latePenaltyApplied,
submissionTags = tags,
exercise = raw.exercise
)
}

@Serializable
data class RawSubmissionBody(
val feedback: String,
val htmlUrl: String,
val status: String,
val grade: Int,
val latePenaltyApplied: Double?,
val gradingData: OuterData?,
val exercise: SubmissionExercise,
)

@Serializable
data class SubmissionBody(
val feedback: String,
val htmlUrl: String,
val status: String,
val grade: Int,
val latePenaltyApplied: Double?,
val submissionTags: List<String> = emptyList(),
val exercise: SubmissionExercise,
)

@Serializable
data class OuterData(
val gradingData: String? = null,
)

@Serializable
data class RawGradingData(
val submissionTags: String? = "",
)

@Serializable
data class SubmissionExercise(
val id: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ data class Exercise(
* Returns the best submission of this exercise (if one exists).
*/
private fun bestSubmission(): SubmissionResult? {
return submissionResults.find { it.id == bestSubmissionId }
//the best submission is always assumed to be the one returned by api, but if there is another one with equal/higher points and no 'warn', it is treated as the best locally
val best = submissionResults.find { it.id == bestSubmissionId }
return submissionResults.find { !it.hasTag("warn") && it.userPoints >= (best?.userPoints ?: 0) } ?: best
}

fun bestHasWarn(): Boolean {
val bestSubmission = bestSubmission()
return bestSubmission != null && bestSubmission.hasTag("warn")
}

fun isLate(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ data class SubmissionResult(
val maxPoints: Int,
var userPoints: Int,
var latePenalty: Double?,
var tags: List<String>,
var status: Status,
val filesInfo: List<SubmissionFileInfo>,
val submitters: List<Long>?,
Expand All @@ -25,6 +26,10 @@ data class SubmissionResult(
this.status = status
}

fun hasTag(tagSlug: String): Boolean {
return tags.contains(tagSlug)
}

enum class Status {
GRADED,
UNOFFICIAL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ class ExercisesUpdater(
status = SubmissionResult.statusFromString(data?.Status),
filesInfo = emptyList(),
submitters = submitters,
tags = data?.Tags?.split("|")?.map { it.trim() } ?: emptyList()
)
}.toMutableList(),
maxPoints = exercise.maxPoints,
Expand Down Expand Up @@ -272,6 +273,7 @@ class ExercisesUpdater(
submissionResult.updateStatus(submission.status)
submissionResult.userPoints = submission.grade
submissionResult.latePenalty = submission.latePenaltyApplied
submissionResult.tags = submission.submissionTags
Notifier.notify(FeedbackAvailableNotification(submissionResult, exercise, project), project)
fireExerciseUpdated(exercise)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,9 @@ class ExercisesTreeRenderer : NodeRenderer() {
return if (isSubmittable()) baseColor else ColorUtil.withAlpha(baseColor, 0.5)
}

//määrittelee yksittäisen palautksen väriä
private fun submissionResultToColor(submission: SubmissionResult): Color {
return if (submission.userPoints == submission.maxPoints) {
return if (submission.userPoints == submission.maxPoints && !submission.hasTag("warn")) {
JBColor(0x8bc34a, 0x8bc34a)
} else {
JBColor(0xffb74d, 0xffb74d)
Expand Down Expand Up @@ -280,7 +281,7 @@ class ExercisesTreeRenderer : NodeRenderer() {
Status.OPTIONAL_PRACTICE
} else if (exercise.submissionResults.isEmpty()) {
Status.NO_SUBMISSIONS
} else if (exercise.userPoints == exercise.maxPoints) {
} else if (exercise.userPoints == exercise.maxPoints && !exercise.bestHasWarn()) {
Status.FULL_POINTS
} else if (exercise.isLate()) {
Status.LATE
Expand Down
Loading