Add ak constraints

This commit is contained in:
Lars Westermann 2019-06-08 22:35:20 +02:00
parent 743e57395a
commit 70e1c2ec26
Signed by: lars.westermann
GPG key ID: 9D417FA5BB9D5E1D
12 changed files with 336 additions and 86 deletions

View file

@ -40,24 +40,61 @@ fun checkConstraints(
errors += ConstraintError("Work group requires accessible, but room does not have one!") errors += ConstraintError("Work group requires accessible, but room does not have one!")
} }
for (constraint in schedule.workGroup.constraints) { for ((type, constraints) in schedule.workGroup.constraints.groupBy { it.type }) {
when (constraint.type) { when (type) {
ConstraintType.OnlyOnDay -> { ConstraintType.OnlyOnDay -> {
if (constraint.number.toInt() != schedule.day) { val onlyOnDay = constraints.map { it.day == schedule.day }
errors += ConstraintError("Work group requires day ${constraint.number}, but is on ${schedule.day}!") if (!onlyOnDay.any()) {
val dayList = constraints.mapNotNull { it.day }.distinct().sorted()
errors += ConstraintError("Work group requires days $dayList, but is on ${schedule.day}!")
} }
} }
ConstraintType.NotOnDay -> {
val notOnDay = constraints.map { it.day == schedule.day }
if (notOnDay.any()) {
val dayList = constraints.mapNotNull { it.day }.distinct().sorted()
errors += ConstraintError("Work group requires not days $dayList, but is on ${schedule.day}!")
}
}
ConstraintType.OnlyBeforeTime -> {
for (it in constraints) {
if (it.time == null) continue
if (it.day == null) {
if (it.time > schedule.time) {
errors += ConstraintError("Work group requires before time ${it.time}, but is on ${schedule.time}!")
}
} else {
if (it.day == schedule.day && it.time > schedule.time) {
errors += ConstraintError("Work group requires before time ${it.time} on day ${it.day}, but is on ${schedule.time}!")
}
}
}
}
ConstraintType.OnlyAfterTime -> { ConstraintType.OnlyAfterTime -> {
if (constraint.number.toInt() > schedule.time) { for (it in constraints) {
errors += ConstraintError("Work group requires time after ${constraint.number}, but is on ${schedule.time}!") if (it.time == null) continue
if (it.day == null) {
if (it.time < schedule.time) {
errors += ConstraintError("Work group requires after time ${it.time}, but is on ${schedule.time}!")
}
} else {
if (it.day == schedule.day && it.time < schedule.time) {
errors += ConstraintError("Work group requires after time ${it.time} on day ${it.day}, but is on ${schedule.time}!")
} }
} }
}
}
ConstraintType.NotAtSameTime -> { ConstraintType.NotAtSameTime -> {
val start = schedule.getAbsoluteStartTime() val start = schedule.getAbsoluteStartTime()
val end = schedule.getAbsoluteEndTime() val end = schedule.getAbsoluteEndTime()
for (constraint in constraints) {
for (s in against) { for (s in against) {
if ( if (
s.workGroup.id == constraint.number && s.workGroup.id == constraint.workGroup &&
start <= s.getAbsoluteEndTime() && start <= s.getAbsoluteEndTime() &&
s.getAbsoluteStartTime() <= end s.getAbsoluteStartTime() <= end
) { ) {
@ -65,11 +102,14 @@ fun checkConstraints(
} }
} }
} }
}
ConstraintType.OnlyAfterWorkGroup -> { ConstraintType.OnlyAfterWorkGroup -> {
val start = schedule.getAbsoluteStartTime() val start = schedule.getAbsoluteStartTime()
for (constraint in constraints) {
for (s in against) { for (s in against) {
if ( if (
s.workGroup.id == constraint.number && s.workGroup.id == constraint.workGroup &&
s.getAbsoluteEndTime() > start s.getAbsoluteEndTime() > start
) { ) {
errors += ConstraintError("Work group requires after ${s.workGroup.name}!") errors += ConstraintError("Work group requires after ${s.workGroup.name}!")
@ -78,6 +118,7 @@ fun checkConstraints(
} }
} }
} }
}
map[schedule.id] = errors map[schedule.id] = errors
} }

View file

@ -5,9 +5,40 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
data class Constraint( data class Constraint(
val type: ConstraintType, val type: ConstraintType,
val number: Long val day: Int? = null,
val time: Int? = null,
val workGroup: Long? = null
) )
enum class ConstraintType { enum class ConstraintType {
OnlyOnDay, OnlyAfterTime, NotAtSameTime, OnlyAfterWorkGroup
/**
* Requires day, permits time and workGroup.
*/
OnlyOnDay,
/**
* Requires day, permits time and workGroup.
*/
NotOnDay,
/**
* Requires time, optionally allows day, permits workGroup.
*/
OnlyAfterTime,
/**
* Requires time, optionally allows day, permits workGroup.
*/
OnlyBeforeTime,
/**
* Requires workGroup, permits day and time.
*/
NotAtSameTime,
/**
* Requires workGroup, permits day and time.
*/
OnlyAfterWorkGroup
} }

View file

@ -18,6 +18,7 @@ data class WorkGroup(
val accessible: Boolean, val accessible: Boolean,
val length: Int, val length: Int,
val language: Language, val language: Language,
val leader: List<String>,
val constraints: List<Constraint>, val constraints: List<Constraint>,
override val createdAt: Long = 0, override val createdAt: Long = 0,
override val updateAt: Long = 0 override val updateAt: Long = 0

View file

@ -51,6 +51,44 @@ fun initWorkGroupConstraints() {
}.html) }.html)
} }
} }
addList.textView("Add not on day") {
onClick {
constraints.appendChild(View.wrap(createHtmlView<HTMLDivElement>()) {
classList += "input-group"
html.appendChild(TextView("Not day").apply {
classList += "form-btn"
onClick { this@wrap.html.remove() }
}.html)
html.appendChild(InputView(InputType.NUMBER).apply {
classList += "form-control"
html.name = "constraint-not-on-day-${index++}"
min = -1337.0
max = 1337.0
}.html)
}.html)
}
}
addList.textView("Add only before time") {
onClick {
constraints.appendChild(View.wrap(createHtmlView<HTMLDivElement>()) {
classList += "input-group"
html.appendChild(TextView("Before time").apply {
classList += "form-btn"
onClick { this@wrap.html.remove() }
}.html)
html.appendChild(InputView(InputType.TEXT).apply {
classList += "form-control"
html.name = "constraint-only-before-time-day-${index++}"
}.html)
html.appendChild(InputView(InputType.NUMBER).apply {
classList += "form-control"
html.name = "constraint-only-before-time-${index++}"
min = -1337.0
max = 133700.0
}.html)
}.html)
}
}
addList.textView("Add only after time") { addList.textView("Add only after time") {
onClick { onClick {
constraints.appendChild(View.wrap(createHtmlView<HTMLDivElement>()) { constraints.appendChild(View.wrap(createHtmlView<HTMLDivElement>()) {
@ -59,6 +97,10 @@ fun initWorkGroupConstraints() {
classList += "form-btn" classList += "form-btn"
onClick { this@wrap.html.remove() } onClick { this@wrap.html.remove() }
}.html) }.html)
html.appendChild(InputView(InputType.TEXT).apply {
classList += "form-control"
html.name = "constraint-only-after-time-day-${index++}"
}.html)
html.appendChild(InputView(InputType.NUMBER).apply { html.appendChild(InputView(InputType.NUMBER).apply {
classList += "form-control" classList += "form-control"
html.name = "constraint-only-after-time-${index++}" html.name = "constraint-only-after-time-${index++}"
@ -125,7 +167,6 @@ fun initWorkGroupConstraints() {
} }
} }
console.log(constraints)
for (child in constraints.children.iterator()) { for (child in constraints.children.iterator()) {
console.log(child) console.log(child)
if (child.classList.contains("input-group")) { if (child.classList.contains("input-group")) {

View file

@ -15,7 +15,7 @@ import org.w3c.dom.get
class WorkGroupTableLine(view: HTMLElement) : TableLine(view) { class WorkGroupTableLine(view: HTMLElement) : TableLine(view) {
var lineId = dataset["id"]?.toLongOrNull() ?: -1 private var lineId = dataset["id"]?.toLongOrNull() ?: -1
private val workGroup = private val workGroup =
RepositoryDelegate(WorkGroupRepository, lineId) RepositoryDelegate(WorkGroupRepository, lineId)

View file

@ -12,6 +12,7 @@
margin: 1px; margin: 1px;
transition: border-color $transitionTime; transition: border-color $transitionTime;
color: var(--text-primary-color); color: var(--text-primary-color);
min-width: 0;
&:focus { &:focus {
border-color: var(--primary-color); border-color: var(--primary-color);
@ -41,6 +42,16 @@ select:-moz-focusring {
padding-bottom: 0.3rem; padding-bottom: 0.3rem;
padding-left: 0.2rem; padding-left: 0.2rem;
} }
&:after {
content: attr(data-hint);
position: absolute;
left: 100%;
color: var(--text-secondary-color);
line-height: 2.5rem;
margin-left: 1rem;
width: 100%;
}
} }
.form-switch { .form-switch {
@ -177,7 +188,7 @@ form {
& > * { & > * {
margin-right: 0; margin-right: 0;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-basis: 0;
&:not(:first-child) { &:not(:first-child) {
border-top-left-radius: 0; border-top-left-radius: 0;

View file

@ -90,7 +90,9 @@
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
span { span {
width: 4rem; width: 8rem;
flex-basis: 8rem;
flex-grow: 0;
position: relative; position: relative;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;

View file

@ -29,6 +29,7 @@ object DbWorkGroup : Table() {
val accessible = bool("accessible") val accessible = bool("accessible")
val language = enumeration("language", Language::class) val language = enumeration("language", Language::class)
val leader = text("leader").default("[]")
val length = integer("length") val length = integer("length")
val constraints = text("constraints") val constraints = text("constraints")

View file

@ -12,6 +12,7 @@ import de.kif.common.model.WorkGroup
import de.westermann.kobserve.event.EventHandler import de.westermann.kobserve.event.EventHandler
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.serialization.list import kotlinx.serialization.list
import kotlinx.serialization.serializer
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import java.util.Date import java.util.Date
@ -35,6 +36,7 @@ object WorkGroupRepository : Repository<WorkGroup> {
val accessible = row[DbWorkGroup.accessible] val accessible = row[DbWorkGroup.accessible]
val length = row[DbWorkGroup.length] val length = row[DbWorkGroup.length]
val language = row[DbWorkGroup.language] val language = row[DbWorkGroup.language]
val leader = Message.json.parse(String.serializer().list, row[DbWorkGroup.leader])
val constraints = Message.json.parse(Constraint.serializer().list, row[DbWorkGroup.constraints]) val constraints = Message.json.parse(Constraint.serializer().list, row[DbWorkGroup.constraints])
val createdAt = row[DbWorkGroup.createdAt] val createdAt = row[DbWorkGroup.createdAt]
@ -56,6 +58,7 @@ object WorkGroupRepository : Repository<WorkGroup> {
accessible, accessible,
length, length,
language, language,
leader,
constraints, constraints,
createdAt, createdAt,
updatedAt updatedAt
@ -89,6 +92,7 @@ object WorkGroupRepository : Repository<WorkGroup> {
it[accessible] = model.accessible it[accessible] = model.accessible
it[length] = model.length it[length] = model.length
it[language] = model.language it[language] = model.language
it[leader] = Message.json.stringify(String.serializer().list, model.leader)
it[constraints] = Message.json.stringify(Constraint.serializer().list, model.constraints) it[constraints] = Message.json.stringify(Constraint.serializer().list, model.constraints)
it[createdAt] = now it[createdAt] = now
@ -120,6 +124,7 @@ object WorkGroupRepository : Repository<WorkGroup> {
it[accessible] = model.accessible it[accessible] = model.accessible
it[length] = model.length it[length] = model.length
it[language] = model.language it[language] = model.language
it[leader] = Message.json.stringify(String.serializer().list, model.leader)
it[constraints] = Message.json.stringify(Constraint.serializer().list, model.constraints) it[constraints] = Message.json.stringify(Constraint.serializer().list, model.constraints)
it[updatedAt] = now it[updatedAt] = now

View file

@ -3,15 +3,12 @@ package de.kif.backend.route
import de.kif.backend.authenticateOrRedirect import de.kif.backend.authenticateOrRedirect
import de.kif.backend.repository.TrackRepository import de.kif.backend.repository.TrackRepository
import de.kif.backend.repository.WorkGroupRepository import de.kif.backend.repository.WorkGroupRepository
import de.kif.backend.view.MainTemplate
import de.kif.backend.view.MenuTemplate
import de.kif.backend.view.TableTemplate import de.kif.backend.view.TableTemplate
import de.kif.backend.view.respondMain import de.kif.backend.view.respondMain
import de.kif.common.Search import de.kif.common.Search
import de.kif.common.model.* import de.kif.common.model.*
import io.ktor.application.call import io.ktor.application.call
import io.ktor.html.insert import io.ktor.html.insert
import io.ktor.html.respondHtmlTemplate
import io.ktor.request.receiveParameters import io.ktor.request.receiveParameters
import io.ktor.response.respondRedirect import io.ktor.response.respondRedirect
import io.ktor.routing.Route import io.ktor.routing.Route
@ -23,6 +20,8 @@ import kotlinx.css.Display
import kotlinx.html.* import kotlinx.html.*
import kotlin.collections.set import kotlin.collections.set
private const val separator = "###"
fun Route.workGroup() { fun Route.workGroup() {
get("workgroups") { get("workgroups") {
authenticateOrRedirect(Permission.WORK_GROUP) { user -> authenticateOrRedirect(Permission.WORK_GROUP) { user ->
@ -152,11 +151,7 @@ fun Route.workGroup() {
val tracks = TrackRepository.all() val tracks = TrackRepository.all()
val workGroups = editWorkGroup.constraints.mapNotNull { val workGroups = editWorkGroup.constraints.mapNotNull {
when (it.type) { it.workGroup
ConstraintType.NotAtSameTime -> it.number
ConstraintType.OnlyAfterWorkGroup -> it.number
else -> null
}
}.distinct().associateWith { }.distinct().associateWith {
WorkGroupRepository.get(it)!! WorkGroupRepository.get(it)!!
} }
@ -270,6 +265,24 @@ fun Route.workGroup() {
} }
} }
div("form-group") {
attributes["data-hint"] = "Use '$separator' to separate multiple leaders"
label {
htmlFor = "leader"
+"Leader"
}
input(
name = "leader",
classes = "form-control"
) {
id = "leader"
placeholder = "Leader"
value = editWorkGroup.leader.joinToString(" $separator ")
}
}
div("form-switch-group") { div("form-switch-group") {
div("form-group form-switch") { div("form-group form-switch") {
input( input(
@ -383,22 +396,66 @@ fun Route.workGroup() {
classes = "form-control", classes = "form-control",
type = InputType.number type = InputType.number
) { ) {
value = constraint.number.toString() value = constraint.day.toString()
min = "-1337" min = "-1337"
max = "1337" max = "1337"
} }
} }
ConstraintType.NotOnDay -> {
span("form-btn") {
+"Not day"
}
input(
name = "constraint-not-on-day-$index",
classes = "form-control",
type = InputType.number
) {
value = constraint.day.toString()
min = "-1337"
max = "1337"
}
}
ConstraintType.OnlyBeforeTime -> {
span("form-btn") {
+"Before time"
}
input(
name = "constraint-only-before-time-day-$index",
classes = "form-control"
) {
value = constraint.day?.toString() ?: ""
placeholder = "day"
}
input(
name = "constraint-only-before-time-$index",
classes = "form-control",
type = InputType.number
) {
value = constraint.time.toString()
min = "-1337"
max = "133700"
}
}
ConstraintType.OnlyAfterTime -> { ConstraintType.OnlyAfterTime -> {
span("form-btn") { span("form-btn") {
+"After time" +"After time"
} }
input(
name = "constraint-only-after-time-day-$index",
classes = "form-control"
) {
value = constraint.day?.toString() ?: ""
placeholder = "day"
}
input( input(
name = "constraint-only-after-time-$index", name = "constraint-only-after-time-$index",
classes = "form-control", classes = "form-control",
type = InputType.number type = InputType.number
) { ) {
value = constraint.number.toString() value = constraint.time.toString()
min = "-1337" min = "-1337"
max = "133700" max = "133700"
@ -415,8 +472,8 @@ fun Route.workGroup() {
option { option {
selected = true selected = true
value = constraint.number.toString() value = constraint.workGroup.toString()
+(workGroups[constraint.number]?.name ?: "") +(workGroups[constraint.workGroup!!]?.name ?: "")
} }
} }
} }
@ -431,8 +488,8 @@ fun Route.workGroup() {
option { option {
selected = true selected = true
value = constraint.number.toString() value = constraint.workGroup.toString()
+(workGroups[constraint.number]?.name ?: "") +(workGroups[constraint.workGroup!!]?.name ?: "")
} }
} }
} }
@ -490,24 +547,12 @@ fun Route.workGroup() {
editWorkGroup = editWorkGroup =
editWorkGroup.copy(language = Language.values().find { l -> l.code == it } ?: Language.GERMAN) editWorkGroup.copy(language = Language.values().find { l -> l.code == it } ?: Language.GERMAN)
} }
params["leader"]?.let {
val leader = it.split("\\s*$separator+\\s*".toRegex())
editWorkGroup = editWorkGroup.copy(leader = leader)
}
val constraints = params.mapNotNull { (key, value) -> val constraints = parseConstraintParam(params)
when {
key.startsWith("constraint-only-on-day") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyOnDay, it) }
}
key.startsWith("constraint-only-after-time") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyAfterTime, it) }
}
key.startsWith("constraint-not-at-same-time") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.NotAtSameTime, it) }
}
key.startsWith("constraint-only-after-work-group") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyAfterWorkGroup, it) }
}
else -> null
}
}
editWorkGroup = editWorkGroup.copy(constraints = constraints) editWorkGroup = editWorkGroup.copy(constraints = constraints)
@ -628,6 +673,25 @@ fun Route.workGroup() {
} }
} }
div("form-group") {
attributes["data-hint"] = "Use '$separator' to separate multiple leaders"
label {
htmlFor = "leader"
+"Leader"
}
input(
name = "leader",
classes = "form-control"
) {
id = "leader"
placeholder = "Leader"
value = ""
}
}
div("form-switch-group") { div("form-switch-group") {
div("form-group form-switch") { div("form-group form-switch") {
input( input(
@ -763,29 +827,14 @@ fun Route.workGroup() {
val language = (params["language"] ?: return@post).let { val language = (params["language"] ?: return@post).let {
Language.values().find { l -> l.code == it } ?: Language.GERMAN Language.values().find { l -> l.code == it } ?: Language.GERMAN
} }
val leader = params["leader"]?.split("\\s*$separator+\\s*".toRegex()) ?: return@post
val internet = params["internet"] == "on" val internet = params["internet"] == "on"
val whiteboard = params["whiteboard"] == "on" val whiteboard = params["whiteboard"] == "on"
val blackboard = params["blackboard"] == "on" val blackboard = params["blackboard"] == "on"
val accessible = params["accessible"] == "on" val accessible = params["accessible"] == "on"
val constraints = params.mapNotNull { (key, value) -> val constraints = parseConstraintParam(params)
when {
key.startsWith("constraint-only-on-day") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyOnDay, it) }
}
key.startsWith("constraint-only-after-time") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyAfterTime, it) }
}
key.startsWith("constraint-not-at-same-time") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.NotAtSameTime, it) }
}
key.startsWith("constraint-only-after-work-group") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyAfterWorkGroup, it) }
}
else -> null
}
}
val workGroup = WorkGroup( val workGroup = WorkGroup(
null, null,
@ -801,6 +850,7 @@ fun Route.workGroup() {
accessible = accessible, accessible = accessible,
length = length, length = length,
language = language, language = language,
leader = leader,
constraints = constraints constraints = constraints
) )
@ -820,3 +870,63 @@ fun Route.workGroup() {
} }
} }
} }
private fun parseConstraintParam(params: Map<String, String?>) = params.map { (key, value) ->
val id = key.substringAfterLast("-").toIntOrNull() ?: -1
id to when {
key.startsWith("constraint-only-on-day") -> {
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyOnDay, day = it) }
}
key.startsWith("constraint-not-on-day") -> {
value?.toIntOrNull()?.let { Constraint(ConstraintType.NotOnDay, day = it) }
}
key.startsWith("constraint-only-after-time") -> {
if ("day" in key) {
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyAfterTime, day = it) }
} else {
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyAfterTime, time = it) }
}
}
key.startsWith("constraint-only-before-time") -> {
if ("day" in key) {
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyBeforeTime, day = it) }
} else {
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyBeforeTime, time = it) }
}
}
key.startsWith("constraint-not-at-same-time") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.NotAtSameTime, workGroup = it) }
}
key.startsWith("constraint-only-after-work-group") -> {
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyAfterWorkGroup, workGroup = it) }
}
else -> null
}
}.groupBy({ it.first }) {
it.second
}.mapNotNull { (_, c) ->
when {
c.isEmpty() -> null
c.size == 1 -> c.first()
c.size == 2 -> {
val c1 = c[0] ?: return@mapNotNull null
val c2 = c[1] ?: return@mapNotNull null
when {
c1.type != c2.type -> null
c1.type == ConstraintType.OnlyBeforeTime -> Constraint(
ConstraintType.OnlyBeforeTime,
day = c1.day ?: c2.day,
time = c1.time ?: c2.time
)
c1.type == ConstraintType.OnlyAfterTime -> Constraint(
ConstraintType.OnlyAfterTime,
day = c1.day ?: c2.day,
time = c1.time ?: c2.time
)
else -> null
}
}
else -> null
}
}

View file

@ -49,25 +49,31 @@ data class Backup(
suspend fun import(data: String) { suspend fun import(data: String) {
val backup = Message.json.parse(serializer(), data) val backup = Message.json.parse(serializer(), data)
val userMap = backup.users.associateWith { UserRepository.create(it) } backup.users.forEach { UserRepository.create(it) }
val postMap = backup.posts.associateWith { PostRepository.create(it) } backup.posts.forEach { PostRepository.create(it) }
val roomMap = backup.rooms.associateWith { RoomRepository.create(it) } backup.rooms.forEach { RoomRepository.create(it) }
val trackMap = backup.tracks.associateWith { TrackRepository.create(it) } val roomMap = RoomRepository.all().associateWith { it.id!! }
val workGroupMap = backup.workGroups.associateWith {
backup.tracks.forEach { TrackRepository.create(it) }
val trackMap =TrackRepository.all().associateWith { it.id!! }
backup.workGroups.forEach {
var workGroup = it var workGroup = it
val track = workGroup.track val track = workGroup.track
if (track != null) { if (track != null) {
workGroup = workGroup.copy(track = track.copy(id = trackMap[track] ?: return@associateWith -1L)) workGroup = workGroup.copy(track = track.copy(id = trackMap[track] ?: return@forEach))
} }
WorkGroupRepository.create(workGroup) WorkGroupRepository.create(workGroup)
} }
val scheduleMap = backup.schedules.associateWith { val workGroupMap = WorkGroupRepository.all().associateWith { it.id!! }
backup.schedules.forEach {
ScheduleRepository.create( ScheduleRepository.create(
it.copy( it.copy(
room = it.room.copy(id = roomMap[it.room] ?: return@associateWith -1L), room = it.room.copy(id = roomMap[it.room] ?: return@forEach),
workGroup = it.workGroup.copy(id = workGroupMap[it.workGroup] ?: return@associateWith -1L) workGroup = it.workGroup.copy(id = workGroupMap[it.workGroup] ?: return@forEach)
) )
) )
} }

View file

@ -147,6 +147,7 @@ object WikiImporter {
accessible = false, accessible = false,
length = akLength, length = akLength,
language = Language.GERMAN, language = Language.GERMAN,
leader = listOf(who),
constraints = emptyList() constraints = emptyList()
) )
} }