Lint: strict mode on; tune detekt thresholds; more decompositions
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user