Lint: strict mode on; tune detekt thresholds; more decompositions

This commit is contained in:
2026-09-27 22:15:00 +03:00
parent 4a8a10971c
commit a87110580b
8 changed files with 621 additions and 505 deletions

View File

@@ -25,10 +25,16 @@ import ru.ysu.lms.web.api.LabUpdatePayload
import ru.ysu.lms.web.api.LevelAssignPayload
import ru.ysu.lms.web.api.LevelPayload
import ru.ysu.lms.web.api.LevelSavePayload
import ru.ysu.lms.web.api.StudentRowDto
import ru.ysu.lms.web.api.VariantSavePayload
import ru.ysu.lms.web.session.SessionKeys
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
@Controller
@RequestMapping("/admin")
@@ -564,26 +570,19 @@ class AdminController(
var i = 0
while (i < line.length) {
val c = line[i]
if (inQuotes) {
if (c == '"') {
if (i + 1 < line.length && line[i + 1] == '"') {
sb.append('"')
i++
} else {
inQuotes = false
}
} else {
sb.append(c)
when {
inQuotes && c == '"' && i + 1 < line.length && line[i + 1] == '"' -> {
sb.append('"')
i++
}
} else {
when (c) {
'"' -> inQuotes = true
delimiter -> {
out.add(sb.toString())
sb.setLength(0)
}
else -> sb.append(c)
inQuotes && c == '"' -> inQuotes = false
inQuotes -> sb.append(c)
c == '"' -> inQuotes = true
c == delimiter -> {
out.add(sb.toString())
sb.setLength(0)
}
else -> sb.append(c)
}
i++
}
@@ -796,52 +795,62 @@ class AdminController(
val group = api.groupDetail(t, id)
val studentById = group.students.associateBy { it.id }
val labs = api.listLabs(t).filter { lab -> labId == null || lab.id == labId }
val out = java.io.ByteArrayOutputStream()
java.util.zip.ZipOutputStream(out).use { zos ->
java.util.zip.ZipEntry("ОПИСАНИЕ.txt").also {
it.time = 0
zos.putNextEntry(it)
}
zos.write("Архив сдач группы ${group.name} (последние попытки)\n".toByteArray(Charsets.UTF_8))
val bytes = buildGroupArchive(t, group.name, studentById, labs)
return zipAttachment("solutions-${group.name}.zip", bytes)
}
private fun buildGroupArchive(
token: String,
groupName: String,
studentById: Map<String, StudentRowDto>,
labs: List<LabSummaryDto>,
): ByteArray {
val out = ByteArrayOutputStream()
ZipOutputStream(out).use { zos ->
zos.putNextEntry(ZipEntry("ОПИСАНИЕ.txt").apply { time = 0 })
zos.write("Архив сдач группы $groupName (последние попытки)\n".toByteArray(Charsets.UTF_8))
zos.closeEntry()
for (lab in labs) {
val subs = api.labSubmissions(t, lab.id)
for (sub in subs) {
for (sub in api.labSubmissions(token, lab.id)) {
val student = studentById[sub.studentId] ?: continue
val bytes = api.downloadSubmissionAsAdmin(t, sub.id).bytes
java.io.ByteArrayInputStream(bytes).let { src ->
java.util.zip.ZipInputStream(src).use { zin ->
var e = zin.nextEntry
while (e != null) {
if (!e.isDirectory) {
java.util.zip
.ZipEntry(
"ЛР${lab.number}/${student.studentNo}_${student.fullName.replace(
Regex("[\\\\/:*?\"<>|]"),
"_",
)}/${e.name}",
).let { ne ->
ne.time =
0
; zos.putNextEntry(ne)
}
zin.copyTo(zos)
zos.closeEntry()
}
e = zin.nextEntry
}
}
}
val bytes = api.downloadSubmissionAsAdmin(token, sub.id).bytes
appendSubmissionArchive(zos, lab, student, bytes)
}
}
}
val name = "solutions-${group.name}.zip"
val encoded = java.net.URLEncoder.encode(name, java.nio.charset.StandardCharsets.UTF_8)
return out.toByteArray()
}
private fun appendSubmissionArchive(
zos: ZipOutputStream,
lab: LabSummaryDto,
student: StudentRowDto,
submissionZip: ByteArray,
) {
ZipInputStream(ByteArrayInputStream(submissionZip)).use { zin ->
var entry = zin.nextEntry
while (entry != null) {
if (!entry.isDirectory) {
val safeName = student.fullName.replace(Regex("[\\\\/:*?\"<>|]"), "_")
zos.putNextEntry(ZipEntry("ЛР${lab.number}/${student.studentNo}_$safeName/${entry.name}").apply { time = 0 })
zin.copyTo(zos)
zos.closeEntry()
}
entry = zin.nextEntry
}
}
}
private fun zipAttachment(
name: String,
bytes: ByteArray,
): ResponseEntity<ByteArray> {
val encoded = URLEncoder.encode(name, StandardCharsets.UTF_8)
return ResponseEntity
.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''$encoded")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(out.toByteArray())
.body(bytes)
}
@PostMapping("/groups/{id}/publish")