Skip to content

Commit

Permalink
Merge pull request #838 from luechtdiode/feature/cleanups
Browse files Browse the repository at this point in the history
Feature/cleanups
  • Loading branch information
luechtdiode authored Mar 3, 2024
2 parents 53ef802 + 9e6c27a commit dadf617
Show file tree
Hide file tree
Showing 25 changed files with 299 additions and 79 deletions.
2 changes: 2 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ ENTRYPOINT [ "java", "-cp", ".:app.jar:libs/*" \
, "--add-opens=java.base/sun.util.calendar=ALL-UNNAMED" \
, "-XX:+UseZGC" \
, "-XX:+ZGenerational" \
, "-XX:MaxRAMPercentage=75.0" \
, "-XX:+ExitOnOutOfMemoryError" \
, "-XshowSettings:vm -version" \
, "ch.seidel.kutu.KuTuServer"]
3 changes: 2 additions & 1 deletion newclient/resultcatcher/src/app/services/backend.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,8 @@ export class BackendService extends WebsocketService {
next: (data) => {
this.steps = data;
if (this._step < data[0]) {
this._step = data[0]
this._step = data[0];
this.loadWertungen();
}
},
error: this.standardErrorHandler
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>ch.seidel</groupId>
<artifactId>KuTu</artifactId>
<version>2.3.8</version>
<version>2.3.9</version>

<inceptionYear>2014</inceptionYear>

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@

<body>
<app-root></app-root>
<script src="runtime.558ba81ba4f74808.js" type="module"></script><script src="polyfills.04266a2a1c92f89b.js" type="module"></script><script src="main.911883d362ae1303.js" type="module"></script></body>
<script src="runtime.558ba81ba4f74808.js" type="module"></script><script src="polyfills.04266a2a1c92f89b.js" type="module"></script><script src="main.90253aff127136dc.js" type="module"></script></body>

</html>
1 change: 1 addition & 0 deletions src/main/resources/app/main.90253aff127136dc.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/main/resources/app/main.911883d362ae1303.js

This file was deleted.

5 changes: 5 additions & 0 deletions src/main/scala/ch/seidel/kutu/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ object Config extends KuTuSSLContext {
}

val bestenlisteSchwellwert: Double = if (config.hasPath("app.bestenlisteSchwellwert")) config.getDouble("app.bestenlisteSchwellwert") else 9.0

val donationLink: String = if (config.hasPath("X_DONATION_LINK")) config.getString("X_DONATION_LINK") else ""
val donationPrice: String = if (config.hasPath("X_DONATION_PRICE")) config.getString("X_DONATION_PRICE") else ""
val donationDonationBegin: String = if (config.hasPath("X_DONATION_BEGIN")) config.getString("X_DONATION_BEGIN") else ""

private val jwtConfig = config.getConfig("jwt")
private val appRemoteConfig = config.getConfig("app.remote")

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/ch/seidel/kutu/KuTuApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ object KuTuApp extends JFXApp3 with KutuService with JsonSupport with JwtSupport
})
}

def makeFindDuplicteAthletes = makeMenuAction("Doppelt erfasste Athleten finden ...") { (caption, action) =>
private def makeFindDuplicteAthletes = makeMenuAction("Doppelt erfasste Athleten finden ...") { (caption, action) =>
implicit val e = action
KuTuApp.invokeAsyncWithBusyIndicator(caption) {
Future {
Expand All @@ -788,7 +788,7 @@ object KuTuApp extends JFXApp3 with KutuService with JsonSupport with JwtSupport
.map { sn => if (sn.isMasculin == sn.isFeminin) athlet.geschlecht else if (sn.isMasculin) "M" else "W" }
.getOrElse("X")

val likeFinder = findAthleteLike(new java.util.ArrayList[MatchCode]) _
val likeFinder = findAthleteLike(cache = new java.util.ArrayList[MatchCode], exclusive = true) _
for {
athleteView <- selectAthletesView
athlete = athleteView.toAthlet
Expand Down
14 changes: 13 additions & 1 deletion src/main/scala/ch/seidel/kutu/KuTuServer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,18 @@ object KuTuServer extends App with KuTuAppHTTPServer with AuthSupport with Hashi
super.shutDown("KuTuServer")
}

KuTuMailerActor.send(SimpleMail("Server-Startup Mailsend-Test", "Mailsender has been started up", s"${KuTuMailerActor.props().args(2)}@${KuTuMailerActor.props().args(3)}")).onComplete {
logger.info("initial cleanup athletes ...")
val cleanedAthletes = markAthletesInactiveOlderThan(3)
logger.info("initial cleanup clubs ...")
val cleanedClubs = cleanUnusedClubs()

KuTuMailerActor.send(SimpleMail("Server-Startup Mailsend-Test", s"""
Mailsender of ${KuTuMailerActor.mailSenderAppName} has been started up.

$cleanedAthletes have been archived.
${cleanedClubs.size} Cleaned Clubs:
${cleanedClubs.mkString("\n ")}
""", s"${KuTuMailerActor.props().args(2)}@${KuTuMailerActor.props().args(3)}")).onComplete {
println("test sendmail completed")
println(_)
}
Expand All @@ -46,6 +57,7 @@ object KuTuServer extends App with KuTuAppHTTPServer with AuthSupport with Hashi

case s: String if (s.endsWith("cleanathletes")) =>
markAthletesInactiveOlderThan(3)
cleanUnusedClubs()
println("done")
true

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/ch/seidel/kutu/akka/AthletIndexActor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ class AthletIndexActor extends Actor with JsonSupport with KutuService {
case ResyncIndex =>
log.info("Resync Athlet Index ...")
invalidateIndex()
sender() ! AthletLikeFound(Athlet(), findAthleteLike(index)(Athlet()))
sender() ! AthletLikeFound(Athlet(), findAthleteLike(index, exclusive = false)(Athlet()))
log.info("ResyncIndex Athlet Index finished")

case FindAthletLike(athlet) =>
sender() ! AthletLikeFound(athlet, findAthleteLike(index)(athlet))
sender() ! AthletLikeFound(athlet, findAthleteLike(index, exclusive = false)(athlet))
case SaveAthlet(athlet) => mcOfId(athlet.id) match {
case None =>
invalidateIndex()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ import ch.seidel.kutu.data.ResourceExchanger
import ch.seidel.kutu.domain._
import ch.seidel.kutu.http.Core.system
import ch.seidel.kutu.http.{EnrichedJson, JsonSupport}
import ch.seidel.kutu.renderer.RiegenBuilder
import ch.seidel.kutu.renderer.{MailTemplates, RiegenBuilder}
import io.prometheus.client
import io.prometheus.client.{Collector, CollectorRegistry}
import org.slf4j.LoggerFactory
import spray.json._

import java.time.{LocalDate, LocalDateTime, LocalTime}
import java.util.UUID
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.DurationInt
Expand Down Expand Up @@ -53,6 +54,8 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
private val wkPgmId = wettkampf.programmId
private val isDNoteUsed = wkPgmId != 20 && wkPgmId != 1
private val snapShotInterval = 100
private val donationDonationBegin = if (Config.donationDonationBegin.nonEmpty) LocalDate.parse(Config.donationDonationBegin) else LocalDate.of(2000,1,1)
private val donationActiv = donationDonationBegin.before(wettkampf.datum) && Config.donationLink.nonEmpty && Config.donationPrice.nonEmpty

private var wsSend: Map[Option[String], List[ActorRef]] = Map.empty
private var deviceWebsocketRefs: Map[String, ActorRef] = Map.empty
Expand Down Expand Up @@ -116,8 +119,8 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
state = state.updated(evt, isDNoteUsed)
if (!recoveryMode && lastSequenceNr % snapShotInterval == 0 && lastSequenceNr != 0) {
val criteria = SnapshotSelectionCriteria.Latest
saveSnapshot(state)
deleteSnapshots(criteria)
saveSnapshot(state)
deleteMessages(criteria.maxSequenceNr)
}
!state.equals(stateBefore)
Expand Down Expand Up @@ -254,7 +257,9 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
ref ! NewLastResults(state.lastWertungen, state.lastBestenResults)

// system actions
case KeepAlive => wsSend.flatMap(_._2).foreach(ws => ws ! TextMessage("keepAlive"))
case KeepAlive =>
wsSend.flatMap(_._2).foreach(ws => ws ! TextMessage("keepAlive"))
checkDonation()

case MessageAck(txt) => if (txt.equals("keepAlive")) handleKeepAliveAck() else println(txt)

Expand All @@ -268,7 +273,10 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
context.system.scheduler.scheduleOnce(30.second, self, TryStop)

case TryStop =>
if (state.startedDurchgaenge.isEmpty && wsSend.isEmpty) handleStop()
if (state.startedDurchgaenge.isEmpty &&
wsSend.isEmpty &&
(LocalDate.now().before(wettkampf.datum) || LocalDate.now().minusDays(2).after(wettkampf.datum))
) handleStop()

case Terminated(stoppedWebsocket) =>
context.unwatch(stoppedWebsocket)
Expand Down Expand Up @@ -300,6 +308,28 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
case _ =>
}

private def checkDonation(): Unit = {
if (donationActiv && LocalDateTime.of(wettkampf.datum, LocalTime.of(7, 0, 0)).plusDays(2).isBefore(LocalDateTime.now()) && !state.completedflags.exists {
case DonationMailSent(_, _, _, wkid) if wkid == this.wettkampfUUID => true
case _ => false
}) {
val teilnehmer = getAllKandidatenWertungen(UUID.fromString(wettkampfUUID))
val results = teilnehmer.flatMap(k => k.wertungen.map(w => w.resultat.endnote)).sum
if (results > 0 && teilnehmer.size > 10) {
val price = BigDecimal(Config.donationPrice)
val donationLink = Config.donationLink
KuTuMailerActor.send(
MailTemplates.createDonateMail(wettkampf, donationLink, teilnehmer.size, price)
)
handleEvent(DonationMailSent(teilnehmer.size, price, donationLink, wettkampfUUID))
saveSnapshot(state)
} else {
handleEvent(DonationMailSent(0, BigDecimal(0), "", wettkampfUUID))
saveSnapshot(state)
}
}
}

private def cleanupWebsocketRefs(stoppedWebsocket: ActorRef): Unit = {
deviceWebsocketRefs = deviceWebsocketRefs.filter(x => x._2 != stoppedWebsocket)
val durchgaenge = wsSend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ sealed trait RegistrationEvent extends RegistrationProtokoll

case class CompetitionCreated(wettkampfUUID: String, link: String) extends RegistrationAction
case class ApproveEMail(wettkampfUUID: String, mail: String) extends RegistrationAction
case class EMailApproved(message: String) extends RegistrationEvent
case class EMailApproved(message: String, success: Boolean) extends RegistrationEvent
case class RegistrationChanged(wettkampfUUID: String) extends RegistrationAction

case class RegistrationResync(wettkampfUUID: String) extends RegistrationAction
Expand Down Expand Up @@ -128,12 +128,17 @@ class CompetitionRegistrationClientActor(wettkampfUUID: String) extends Persiste
case ApproveEMail(_, mail) =>
val notificationEMail = readWettkampf(wettkampfUUID).notificationEMail
if (notificationEMail.equals(mail)) {
syncState = syncState.approved
sender() ! EMailApproved(s"EMail ${mail} erfolgreich verifiziert")
log.info(s"EMail approved ${mail}")
if (!syncState.emailApproved) {
syncState = syncState.approved
sender() ! EMailApproved(s"EMail ${mail} erfolgreich verifiziert", success = true)
log.info(s"EMail approved ${mail}")
} else {
sender() ! EMailApproved(s"EMail ${mail} wurde bereits verifiziert", success = true)
log.info(s"EMail ${mail} was already approved")
}
}
else {
sender() ! EMailApproved(s"EMail ${mail} nicht erfolgreich verifiziert.")
sender() ! EMailApproved(s"EMail ${mail} nicht erfolgreich verifiziert.", success = false)
log.info(s"EMail not approved ${mail} - not matching with competitions notificationEMail: $notificationEMail")
}

Expand Down
21 changes: 15 additions & 6 deletions src/main/scala/ch/seidel/kutu/akka/CompetitionState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ case class CompetitionState (
lastWertungen: Map[String, WertungContainer] = Map.empty,
bestenResults: Map[String, WertungContainer] = Map.empty,
lastBestenResults: Map[String, WertungContainer] = Map.empty,
lastSequenceId: Long = Long.MinValue
lastSequenceId: Long = Long.MinValue,
completedflags: List[KutuAppEvent] = List.empty
) {

def updated(event: KutuAppEvent, isDNoteUsed: Boolean): CompetitionState = event match {
Expand All @@ -26,7 +27,8 @@ case class CompetitionState (
.filter(fds => encodeURIComponent(fds.durchgang) != encodeURIComponent(eventDurchgangStarted.durchgang)),
finishedDurchgaenge - eventDurchgangStarted.durchgang,
startStopEvents :+ eventDurchgangStarted,
lastWertungen, bestenResults, lastBestenResults, lastSequenceId
lastWertungen, bestenResults, lastBestenResults, lastSequenceId,
completedflags
)
}

Expand All @@ -39,7 +41,8 @@ case class CompetitionState (
finishedDurchgangSteps,
finishedDurchgaenge + eventDurchgangFinished.durchgang,
startStopEvents :+ eventDurchgangFinished,
Map.empty, bestenResults, lastBestenResults, lastSequenceId
Map.empty, bestenResults, lastBestenResults, lastSequenceId,
completedflags
)
}

Expand All @@ -55,17 +58,22 @@ case class CompetitionState (
finishedDurchgangSteps + fds,
finishedDurchgaenge,
startStopEvents,
lastWertungen, bestenResults, lastBestenResults, lastSequenceId
lastWertungen, bestenResults, lastBestenResults, lastSequenceId,
completedflags
)

case dms: DonationMailSent =>
copy(completedflags = completedflags :+ dms)

case _: DurchgangStepFinished =>
if (lastWertungen.nonEmpty) {
CompetitionState(
startedDurchgaenge,
finishedDurchgangSteps,
finishedDurchgaenge,
startStopEvents,
Map.empty, Map.empty, bestenResults, lastSequenceId
Map.empty, Map.empty, bestenResults, lastSequenceId,
completedflags
)
} else {
this
Expand Down Expand Up @@ -97,7 +105,8 @@ case class CompetitionState (
finishedDurchgaenge,
startStopEvents,
lastWertungen.updated(wertungContainer.wertung.wettkampfdisziplinId.toString(), wertungContainer),
putBestenResult(wertungContainer), lastBestenResults, lastSequenceId + 1
putBestenResult(wertungContainer), lastBestenResults, lastSequenceId + 1,
completedflags
)

}
3 changes: 2 additions & 1 deletion src/main/scala/ch/seidel/kutu/akka/KuTuMailerActor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,14 @@ class KuTuMailerActor(smtpHost: String, smtpPort: Int, smtpUsername: String, smt

object KuTuMailerActor {
private var customMailer: Option[CustomMailer] = None;
val mailSenderAppName = Config.config.getString("app.smtpsender.appname")

def props(): Props = {
if (isSMTPConfigured) {
Props(classOf[KuTuMailerActor],
Config.config.getString("X_SMTP_HOST"), Config.config.getInt("X_SMTP_PORT"),
Config.config.getString("X_SMTP_USERNAME"), Config.config.getString("X_SMTP_DOMAIN"),
Config.config.getString("X_SMTP_PASSWORD"), Config.config.getString("app.smtpsender.appname"), customMailer
Config.config.getString("X_SMTP_PASSWORD"), mailSenderAppName, customMailer
)
} else {
Props(classOf[KuTuMailerActor],
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/ch/seidel/kutu/akka/Messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ case class AthletMovedInWettkampf(athlet: AthletView, wettkampfUUID: String, pgm
case class AthletsAddedToWettkampf(athlet: List[AthletView], wettkampfUUID: String, pgmId: Long, team: Int) extends KutuAppEvent
case class DurchgangChanged(durchgang: String, wettkampfUUID: String, athlet: AthletView) extends KutuAppEvent
case class ScoresPublished(scoreId: String, title: String, query: String, published: Boolean, wettkampfUUID: String) extends KutuAppEvent
case class DonationMailSent(teilnehmer: Int, price: BigDecimal, donationLink: String, wettkampfUUID: String) extends KutuAppEvent
case class GeraeteRiegeList(list: List[GeraeteRiege], wettkampfUUID: String) extends KutuAppEvent

case class NewLastResults(results: Map[String, WertungContainer], lastTopResults: Map[String, WertungContainer]) extends KutuAppEvent
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/ch/seidel/kutu/data/ResourceExchanger.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ object ResourceExchanger extends KutuService with RiegenBuilder {
case Some(v) => findVereinLike(Verein(id = 0, name = v.name, verband = None))
case _ => None
}
val mappedAthlet = findAthleteLike(cache, wettkampf)(athlet.toAthlet.copy(id = 0, verein = mappedverein))
val mappedAthlet = findAthleteLike(cache, wettkampf, exclusive = false)(athlet.toAthlet.copy(id = 0, verein = mappedverein))
val mappedAthletView = athlet.updatedWith(mappedAthlet)
mappedAthletView
}
Expand Down Expand Up @@ -238,7 +238,7 @@ object ResourceExchanger extends KutuService with RiegenBuilder {
val cache = new java.util.ArrayList[MatchCode]()
val athletInstanceCandidates = mappedAthletes.map { imported =>
val (csvId, importathlet) = imported
val candidate = findAthleteLike(cache)(importathlet)
val candidate = findAthleteLike(cache, exclusive = false)(importathlet)

if (candidate.id > 0) {
importathlet.gebdat match {
Expand Down
Loading

0 comments on commit dadf617

Please sign in to comment.