From 6716d7e4025a9f73df06e8bb20b602b08b30c7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Lamy?= Date: Wed, 25 Dec 2024 10:45:38 -0500 Subject: [PATCH] baseline: copyright and source cleanup --- fixcopyright.sh | 116 +++++ owlcms/src/main/java/app/owlcms/AppShell.java | 6 + owlcms/src/main/java/app/owlcms/Main.java | 199 ++++---- .../java/app/owlcms/apputils/AccessUtils.java | 2 +- .../apputils/ClientMultipartFormPost.java | 2 +- .../java/app/owlcms/apputils/DebugUtils.java | 2 +- .../app/owlcms/apputils/JpaJsonConverter.java | 6 + .../apputils/LogbackConfigReloader.java | 105 +++-- .../owlcms/apputils/NotificationUtils.java | 2 +- .../java/app/owlcms/apputils/SoundUtils.java | 2 +- .../apputils/queryparameters/BaseContent.java | 9 +- .../queryparameters/DisplayParameters.java | 6 +- .../DisplayParametersReader.java | 12 +- .../queryparameters/FOPParameters.java | 2 +- .../queryparameters/FOPParametersReader.java | 30 +- .../queryparameters/ParameterReader.java | 12 +- .../queryparameters/ResultsParameters.java | 14 +- .../ResultsParametersReader.java | 6 + .../queryparameters/SoundParameters.java | 54 ++- .../SoundParametersReader.java | 48 +- .../queryparameters/TopParameters.java | 6 + .../queryparameters/TopParametersReader.java | 6 + .../owlcms/components/ConfirmationDialog.java | 8 +- .../GroupCategorySelectionMenu.java | 149 +++--- .../owlcms/components/GroupSelectionMenu.java | 19 +- .../app/owlcms/components/JXLSDownloader.java | 17 +- .../app/owlcms/components/NavigationPage.java | 2 +- .../elements/AthleteTimerElement.java | 29 +- .../components/elements/BeepElement.java | 2 +- .../elements/BreakTimerElement.java | 60 ++- .../components/elements/DecisionElement.java | 2 +- .../elements/JuryDisplayDecisionElement.java | 2 +- .../elements/LazyDownloadButton.java | 39 +- .../components/elements/PlatesElement.java | 37 +- .../components/elements/SoundEnabler.java | 6 +- .../components/elements/TimerElement.java | 15 +- .../elements/unload/UnloadEvent.java | 17 +- .../elements/unload/UnloadListener.java | 2 +- .../elements/unload/UnloadObserver.java | 28 +- .../components/fields/CategoryGridField.java | 6 +- .../components/fields/CategoryListField.java | 2 +- .../components/fields/DurationField.java | 2 +- .../owlcms/components/fields/GridField.java | 2 +- .../components/fields/LocalDateField.java | 2 +- .../components/fields/LocalDateTimeField.java | 2 +- .../fields/LocalDateTimePicker.java | 2 +- .../fields/LocalizedDecimalField.java | 2 +- .../fields/LocalizedIntegerField.java | 2 +- .../fields/ValidationTextField.java | 6 +- .../components/fields/ValidationUtils.java | 9 +- .../components/fields/WrappedTextField.java | 17 +- .../app/owlcms/data/agegroup/AgeGroup.java | 82 ++-- .../agegroup/AgeGroupDefinitionReader.java | 81 ++-- .../data/agegroup/AgeGroupRepository.java | 124 +++-- .../agegroup/AssignedAthletesException.java | 6 + .../owlcms/data/agegroup/Championship.java | 82 ++-- .../data/agegroup/ChampionshipType.java | 6 + .../java/app/owlcms/data/athlete/Athlete.java | 397 ++++++++-------- .../data/athlete/AthleteRepository.java | 210 ++++----- .../java/app/owlcms/data/athlete/Gender.java | 6 +- .../owlcms/data/athlete/LiftDefinition.java | 12 +- .../app/owlcms/data/athlete/LiftInfo.java | 2 +- .../data/athlete/RuleViolationException.java | 33 +- .../app/owlcms/data/athlete/XAthlete.java | 61 ++- .../athleteSort/AbstractLifterComparator.java | 428 +++++++++--------- .../data/athleteSort/AthleteSorter.java | 94 ++-- .../data/athleteSort/LiftOrderComparator.java | 2 +- .../athleteSort/LiftTimeStampComparator.java | 6 +- .../athleteSort/MultiCategoryRankSetter.java | 14 +- .../data/athleteSort/OverallRankSetter.java | 8 +- .../app/owlcms/data/athleteSort/Ranking.java | 73 +-- .../athleteSort/RegistrationBWComparator.java | 2 +- .../RegistrationExportComparator.java | 2 +- .../RegistrationOrderComparator.java | 2 +- .../StartNumberOrderComparator.java | 2 +- .../athleteSort/TeamPointsComparator.java | 2 +- .../athleteSort/TeamPointsPComparator.java | 2 +- .../athleteSort/TeamRankingComparator.java | 2 +- .../athleteSort/WinningOrderComparator.java | 103 +++-- .../app/owlcms/data/category/Category.java | 271 +++++------ .../data/category/CategoryRankingHolder.java | 18 +- .../data/category/CategoryRepository.java | 78 ++-- .../app/owlcms/data/category/IRankHolder.java | 2 +- .../owlcms/data/category/Participation.java | 26 +- .../owlcms/data/category/ParticipationId.java | 2 +- .../RegistrationPreferenceComparator.java | 2 +- .../owlcms/data/category/RobiCategories.java | 11 +- .../owlcms/data/competition/Competition.java | 2 +- .../competition/CompetitionRepository.java | 2 +- .../data/competition/DebuggingTextField.java | 2 +- .../java/app/owlcms/data/config/Config.java | 4 +- .../owlcms/data/config/ConfigRepository.java | 2 +- .../data/export/AthleteSessionDataReader.java | 86 ++-- .../owlcms/data/export/CompetitionData.java | 18 +- .../app/owlcms/data/group/AgeGroupInfo.java | 42 +- .../data/group/AgeGroupInfoFactory.java | 33 +- .../java/app/owlcms/data/group/BWCatInfo.java | 16 +- .../app/owlcms/data/group/DisplayGroup.java | 6 + .../java/app/owlcms/data/group/Group.java | 325 +++++++------ .../owlcms/data/group/GroupRepository.java | 2 +- .../app/owlcms/data/jpa/BenchmarkData.java | 5 +- .../java/app/owlcms/data/jpa/DemoData.java | 16 +- .../data/jpa/HikariDataSourcePoolDetail.java | 52 ++- .../java/app/owlcms/data/jpa/JPAService.java | 66 ++- .../data/jpa/LocalDateAttributeConverter.java | 2 +- .../jpa/LocalDateTimeAttributeConverter.java | 2 +- .../data/jpa/LocaleAttributeConverter.java | 2 +- .../data/jpa/PersistenceUnitInfoImpl.java | 2 +- .../java/app/owlcms/data/jpa/ProdData.java | 2 +- .../app/owlcms/data/platform/Platform.java | 95 ++-- .../data/platform/PlatformRepository.java | 2 +- .../records/FederationStructureReader.java | 6 +- .../app/owlcms/data/records/RecordConfig.java | 6 + .../data/records/RecordDefinitionReader.java | 8 +- .../app/owlcms/data/records/RecordEvent.java | 76 ++-- .../app/owlcms/data/records/RecordFilter.java | 10 +- .../app/owlcms/data/scoring/AgeFactors.java | 21 +- .../java/app/owlcms/data/scoring/GAMX.java | 11 +- .../java/app/owlcms/data/scoring/QPoints.java | 33 +- .../data/scoring/SinclairCoefficients.java | 26 +- .../main/java/app/owlcms/data/team/ITeam.java | 2 +- .../main/java/app/owlcms/data/team/Team.java | 41 +- .../owlcms/data/team/TeamResultsTreeData.java | 2 +- .../data/team/TeamSelectionTreeData.java | 2 +- .../app/owlcms/data/team/TeamTreeItem.java | 2 +- .../displays/athletecard/AthleteCard.java | 2 +- .../attemptboard/AbstractAttemptBoard.java | 7 +- .../displays/attemptboard/AttemptBoard.java | 2 +- .../attemptboard/BrandedAttemptBoard.java | 2 +- .../displays/attemptboard/DecisionBoard.java | 2 +- .../displays/options/DisplayOptions.java | 2 +- .../displays/scoreboard/CurrentAthlete.java | 13 +- .../owlcms/displays/scoreboard/Results.java | 122 ++--- .../displays/scoreboard/ResultsJury.java | 8 +- .../scoreboard/ResultsLiftingOrder.java | 6 + .../displays/scoreboard/ResultsMedals.java | 228 +++++----- .../scoreboard/ResultsMultiRanks.java | 2 +- .../displays/scoreboard/ResultsNoLeaders.java | 2 +- .../scoreboard/ResultsRankingOrder.java | 6 + .../displays/scoreboard/ResultsRankings.java | 8 +- .../app/owlcms/displays/top/AbstractTop.java | 20 +- .../app/owlcms/displays/top/TopSinclair.java | 2 +- .../app/owlcms/displays/top/TopTeams.java | 2 +- .../owlcms/displays/top/TopTeamsSinclair.java | 2 +- .../displays/video/StreamingEventMonitor.java | 2 +- .../displays/video/StylesDirSelection.java | 6 + .../owlcms/endpoints/CompetitionExport.java | 10 +- .../owlcms/endpoints/SimulationServlet.java | 10 +- .../app/owlcms/fieldofplay/CountdownType.java | 6 + .../java/app/owlcms/fieldofplay/FOPError.java | 2 +- .../java/app/owlcms/fieldofplay/FOPEvent.java | 31 +- .../java/app/owlcms/fieldofplay/FOPState.java | 5 +- .../app/owlcms/fieldofplay/FieldOfPlay.java | 306 +++++++------ .../app/owlcms/fieldofplay/IBreakTimer.java | 2 +- .../app/owlcms/fieldofplay/IProxyTimer.java | 2 +- .../app/owlcms/fieldofplay/LiftOrderInfo.java | 29 +- .../fieldofplay/LiftOrderReconstruction.java | 2 +- .../owlcms/fieldofplay/ProxyAthleteTimer.java | 118 ++--- .../owlcms/fieldofplay/ProxyBreakTimer.java | 46 +- .../java/app/owlcms/init/InitialData.java | 2 +- .../owlcms/init/MoquetteAuthenticator.java | 6 + .../java/app/owlcms/init/OwlcmsFactory.java | 40 +- .../java/app/owlcms/init/OwlcmsSession.java | 140 +++--- .../java/app/owlcms/jetty/EmbeddedJetty.java | 108 ++--- .../app/owlcms/monitors/EventForwarder.java | 144 +++--- .../java/app/owlcms/monitors/IUnregister.java | 6 + .../java/app/owlcms/monitors/MQTTMonitor.java | 128 +++--- .../java/app/owlcms/monitors/OBSMonitor.java | 2 +- .../nui/crudui/OwlcmsComboBoxProvider.java | 2 +- .../nui/crudui/OwlcmsCrudFormFactory.java | 23 +- .../app/owlcms/nui/crudui/OwlcmsCrudGrid.java | 20 +- .../owlcms/nui/crudui/OwlcmsGridLayout.java | 2 +- .../nui/displays/AbstractDisplayPage.java | 6 + .../displays/DisplayNavigationContent.java | 8 +- .../app/owlcms/nui/displays/SoundEntries.java | 6 + .../nui/displays/VideoNavigationContent.java | 2 +- .../AbstractAttemptBoardPage.java | 9 +- .../AthleteFacingAttemptBoardPage.java | 6 + .../AthleteFacingDecisionBoardPage.java | 6 + .../PublicFacingAttemptBoardPage.java | 8 +- .../PublicFacingDecisionBoardPage.java | 6 + .../AbstractResultsDisplayPage.java | 9 +- .../scoreboards/CurrentAthletePage.java | 12 +- .../scoreboards/JuryScoreboardPage.java | 8 +- .../nui/displays/scoreboards/MedalsPage.java | 6 + .../scoreboards/PublicMultiRanksPage.java | 12 +- .../scoreboards/PublicNoLeadersPage.java | 7 +- .../scoreboards/PublicRankingOrderPage.java | 36 +- .../scoreboards/PublicScoreboardPage.java | 78 ++-- .../displays/scoreboards/RankingsPage.java | 6 + .../scoreboards/WarmupLiftingOrderPage.java | 8 +- .../scoreboards/WarmupMultiRanksPage.java | 8 +- .../scoreboards/WarmupNoLeadersPage.java | 10 +- .../scoreboards/WarmupRankingOrderPage.java | 8 +- .../scoreboards/WarmupScoreboardPage.java | 16 +- .../nui/displays/top/TopSinclairPage.java | 26 +- .../owlcms/nui/displays/top/TopTeamsPage.java | 33 +- .../displays/top/TopTeamsSinclairPage.java | 33 +- .../app/owlcms/nui/home/DisplayLoginView.java | 6 + .../nui/home/HomeNavigationContent.java | 44 +- .../nui/home/InfoNavigationContent.java | 2 +- .../java/app/owlcms/nui/home/LoginView.java | 12 +- .../owlcms/nui/lifting/AnnouncerContent.java | 96 ++-- .../nui/lifting/AthleteCardFormFactory.java | 31 +- .../app/owlcms/nui/lifting/JuryContent.java | 4 +- .../app/owlcms/nui/lifting/JuryDialog.java | 46 +- .../nui/lifting/LiftingNavigationContent.java | 76 ++-- .../owlcms/nui/lifting/MarshallContent.java | 56 +-- .../owlcms/nui/lifting/NextAthleteAble.java | 12 +- .../app/owlcms/nui/lifting/TCContent.java | 32 +- .../owlcms/nui/lifting/TimekeeperContent.java | 2 +- .../owlcms/nui/lifting/UIEventProcessor.java | 9 +- .../owlcms/nui/lifting/WeighinContent.java | 172 ++++--- .../nui/preparation/AgeGroupContent.java | 20 +- .../AgeGroupEditingFormFactory.java | 51 +-- .../AgeGroupsFileUploadDialog.java | 2 +- .../nui/preparation/CompetitionContent.java | 2 +- .../CompetitionEditingFormFactory.java | 30 +- .../owlcms/nui/preparation/ConfigContent.java | 2 +- .../preparation/ConfigEditingFormFactory.java | 50 +- .../owlcms/nui/preparation/DocsContent.java | 18 +- .../nui/preparation/DocumentsContent.java | 46 +- .../owlcms/nui/preparation/DocumentsGrid.java | 28 +- .../preparation/EditChampionshipsDialog.java | 21 +- .../nui/preparation/JsonUploadDialog.java | 2 +- .../LocalOverrideUploadDialog.java | 2 +- .../NRegistrationFileUploadDialog.java | 15 +- .../nui/preparation/PlatformContent.java | 2 +- .../PlatformEditingFormFactory.java | 2 +- .../preparation/PreCompetitionTemplates.java | 57 +-- .../PreparationNavigationContent.java | 15 +- .../RecordConfigEditingFormFactory.java | 8 +- .../nui/preparation/RecordsContent.java | 2 +- .../nui/preparation/RegistrationContent.java | 189 ++++---- .../nui/preparation/SessionContent.java | 4 +- .../SessionEditingFormFactory.java | 2 +- .../owlcms/nui/preparation/SessionGrid.java | 63 +-- .../TeamItemSelectionFormFactory.java | 2 +- .../nui/preparation/TeamSelectionContent.java | 18 +- .../TemplateSelectionFormFactory.java | 110 ++--- .../owlcms/nui/preparation/ZipFileField.java | 2 +- .../app/owlcms/nui/referee/RefContent.java | 12 +- .../owlcms/nui/results/IFilterCascade.java | 27 +- .../owlcms/nui/results/PackageContent.java | 6 +- .../nui/results/ResultsNavigationContent.java | 12 +- .../nui/results/SessionImportContent.java | 27 +- .../nui/results/SessionResultsContent.java | 26 +- .../results/SessionResultsUploadDialog.java | 2 +- .../nui/results/SessionSelectionGrid.java | 29 +- .../results/TeamItemResultsFormFactory.java | 2 +- .../nui/results/TeamResultsContent.java | 2 +- .../nui/results/TeamTreeItemCrudGrid.java | 2 +- .../owlcms/nui/shared/AthleteCrudGrid.java | 2 +- .../owlcms/nui/shared/AthleteGridContent.java | 142 +++--- .../nui/shared/BaseNavigationContent.java | 33 +- .../app/owlcms/nui/shared/BreakDialog.java | 2 +- .../owlcms/nui/shared/BreakManagement.java | 201 ++++---- .../owlcms/nui/shared/ContentWrapping.java | 2 +- .../owlcms/nui/shared/CustomFormFactory.java | 11 +- .../nui/shared/DownloadButtonFactory.java | 87 ++-- .../app/owlcms/nui/shared/HasBoardMode.java | 8 +- .../owlcms/nui/shared/IAthleteEditing.java | 2 +- .../NAthleteRegistrationFormFactory.java | 102 ++--- .../app/owlcms/nui/shared/NavigationPage.java | 2 +- .../app/owlcms/nui/shared/OwlcmsContent.java | 2 +- .../app/owlcms/nui/shared/OwlcmsLayout.java | 6 + .../owlcms/nui/shared/OwlcmsLayoutAware.java | 7 +- .../nui/shared/RequireDisplayLogin.java | 2 +- .../app/owlcms/nui/shared/RequireLogin.java | 2 +- .../nui/shared/SafeEventBusRegistration.java | 2 +- .../simulation/CompetitionSimulator.java | 31 +- .../app/owlcms/simulation/FOPSimulator.java | 10 +- .../src/main/java/app/owlcms/sound/Sound.java | 2 +- .../main/java/app/owlcms/sound/Speakers.java | 2 +- .../java/app/owlcms/sound/SunFileReader.java | 36 +- .../src/main/java/app/owlcms/sound/Tone.java | 2 +- .../java/app/owlcms/sound/WaveFileFormat.java | 2 +- .../java/app/owlcms/sound/WaveFileReader.java | 32 +- .../IRegistrationFileProcessor.java | 6 + .../app/owlcms/spreadsheet/JXLSCardsDocs.java | 17 +- .../owlcms/spreadsheet/JXLSCardsWeighIn.java | 3 +- .../spreadsheet/JXLSCategoriesListDocs.java | 2 +- .../spreadsheet/JXLSCompetitionBook.java | 61 ++- .../owlcms/spreadsheet/JXLSExportRecords.java | 111 +++-- .../app/owlcms/spreadsheet/JXLSJurySheet.java | 50 +- .../owlcms/spreadsheet/JXLSMedalSchedule.java | 56 +-- .../owlcms/spreadsheet/JXLSMedalsSheet.java | 10 +- .../owlcms/spreadsheet/JXLSRegistration.java | 2 +- .../JXLSRegistrationEmptyExport.java | 2 +- .../owlcms/spreadsheet/JXLSResultSheet.java | 5 +- .../owlcms/spreadsheet/JXLSSBDEExport.java | 2 +- .../spreadsheet/JXLSStartingListDocs.java | 10 +- .../owlcms/spreadsheet/JXLSTimingStats.java | 12 +- .../owlcms/spreadsheet/JXLSWeighInSheet.java | 22 +- .../owlcms/spreadsheet/JXLSWinningSheet.java | 39 +- .../spreadsheet/JXLSWorkbookStreamSource.java | 12 +- .../java/app/owlcms/spreadsheet/MAthlete.java | 52 ++- .../NRegistrationFileProcessor.java | 36 +- .../ORegistrationFileProcessor.java | 6 + .../java/app/owlcms/spreadsheet/PAthlete.java | 118 ++--- .../java/app/owlcms/spreadsheet/RAthlete.java | 156 +++---- .../app/owlcms/spreadsheet/RCompetition.java | 6 +- .../java/app/owlcms/spreadsheet/RGroup.java | 2 +- .../spreadsheet/XLSXAgeGroupsExport.java | 6 + .../spreadsheet/XLSXWorkbookStreamSource.java | 6 +- .../java/app/owlcms/uievents/AppEvent.java | 6 + .../app/owlcms/uievents/BreakDisplay.java | 4 +- .../java/app/owlcms/uievents/BreakType.java | 17 +- .../app/owlcms/uievents/CeremonyType.java | 2 +- .../owlcms/uievents/DecisionEventType.java | 2 +- .../uievents/JuryDeliberationEventType.java | 2 +- .../java/app/owlcms/uievents/UIEvent.java | 98 ++-- .../css/grid/interfaces/MinMaxUnit.java | 4 +- .../interfaces/TemplateRowsAndColsUnit.java | 3 +- .../appreciated/css/grid/sizes/Length.java | 4 +- .../appreciated/css/grid/sizes/MinMax.java | 3 +- .../github/appreciated/layout/AreaLayout.java | 6 +- .../layout/FlexibleGridLayout.java | 20 +- .../github/appreciated/layout/GridLayout.java | 22 +- .../owlcms/data/jpa/BenchmarkDataTest.java | 6 + .../java/app/owlcms/tests/AgeFactorsTest.java | 6 + .../test/java/app/owlcms/tests/AllTests.java | 2 +- .../app/owlcms/tests/AthleteSorterTest.java | 2 +- .../java/app/owlcms/tests/AthleteTest.java | 2 +- .../tests/FederationStructureReaderTest.java | 2 +- .../test/java/app/owlcms/tests/GAMXTest.java | 6 + .../app/owlcms/tests/ICountDownTimer.java | 2 +- .../owlcms/tests/JSONExportImportTest.java | 6 + .../app/owlcms/tests/LiftDefinitionTest.java | 2 +- .../tests/LiftingOrderReconstructionTest.java | 2 +- .../app/owlcms/tests/MockCountdownTimer.java | 2 +- .../java/app/owlcms/tests/MovingDownTest.java | 2 +- .../tests/RecordDefinitionReaderTest.java | 2 +- .../RegistrationOrderComparatorTest.java | 2 +- .../owlcms/tests/RegistrationReaderTest.java | 2 +- .../app/owlcms/tests/ResourceWalkerTest.java | 2 +- .../app/owlcms/tests/RobiCategoriesTest.java | 2 +- .../test/java/app/owlcms/tests/TestData.java | 2 +- .../app/owlcms/tests/TwoMinutesRuleTest.java | 2 +- .../src/main/java/playwright/RunResults.java | 2 +- .../queryparameters/DisplayParameters.java | 2 +- .../queryparameters/FOPParameters.java | 2 +- .../fields/LocalizedDecimalField.java | 2 +- .../component/fields/ValidationTextField.java | 2 +- .../component/fields/WrappedTextField.java | 2 +- .../elements/AthleteTimerElementPR.java | 2 +- .../elements/BreakTimerElementPR.java | 2 +- .../elements/DecisionElementPR.java | 2 +- .../owlcms/components/elements/IFopName.java | 2 +- .../components/elements/TimerElementPR.java | 2 +- .../elements/unload/UnloadEventPR.java | 2 +- .../elements/unload/UnloadListenerPR.java | 2 +- .../elements/unload/UnloadObserverPR.java | 2 +- .../displays/options/DisplayOptions.java | 2 +- .../owlcms/displays/scoreboard/ResultsPR.java | 2 +- .../java/app/owlcms/init/OwlcmsSession.java | 2 +- .../java/app/owlcms/prutils/DebugUtils.java | 2 +- .../prutils/SafeEventBusRegistrationPR.java | 2 +- .../java/app/owlcms/prutils/SoundUtils.java | 2 +- .../publicresults/ConfigReceiverServlet.java | 2 +- .../DecisionReceiverServlet.java | 2 +- .../owlcms/publicresults/ExpiredServlet.java | 2 +- .../java/app/owlcms/publicresults/Main.java | 2 +- .../app/owlcms/publicresults/MainView.java | 2 +- .../publicresults/TimerReceiverServlet.java | 2 +- .../publicresults/UpdateReceiverServlet.java | 2 +- .../ui/parameters/DarkModeParameters.java | 2 +- .../ui/parameters/QueryParameterReader.java | 2 +- .../app/owlcms/uievents/BreakTimerEvent.java | 2 +- .../java/app/owlcms/uievents/BreakType.java | 2 +- .../app/owlcms/uievents/CeremonyType.java | 2 +- .../app/owlcms/uievents/DecisionEvent.java | 2 +- .../owlcms/uievents/DecisionEventType.java | 2 +- .../java/app/owlcms/uievents/TimerEvent.java | 2 +- .../java/app/owlcms/uievents/UpdateEvent.java | 2 +- .../main/java/app/owlcms/i18n/Translator.java | 2 +- .../app/owlcms/servlet/EmbeddedJetty.java | 6 + .../java/app/owlcms/servlet/FileServlet.java | 2 +- .../app/owlcms/servlet/JettyErrorHandler.java | 2 +- .../servlet/StopProcessingException.java | 6 + .../main/java/app/owlcms/utils/CSSUtils.java | 6 + .../java/app/owlcms/utils/DateTimeUtils.java | 2 +- .../java/app/owlcms/utils/DelayTimer.java | 6 + .../app/owlcms/utils/IPInterfaceUtils.java | 2 +- .../main/java/app/owlcms/utils/IdUtils.java | 2 +- .../java/app/owlcms/utils/LambdaUtils.java | 2 +- .../java/app/owlcms/utils/LoggerUtils.java | 2 +- .../java/app/owlcms/utils/MemTempUtils.java | 2 +- .../java/app/owlcms/utils/OwlcmsLicense.java | 6 + .../java/app/owlcms/utils/ProcessUtils.java | 6 + .../java/app/owlcms/utils/ProxyUtils.java | 2 +- .../main/java/app/owlcms/utils/Resource.java | 2 +- .../java/app/owlcms/utils/ResourceWalker.java | 2 +- .../java/app/owlcms/utils/StartupUtils.java | 2 +- .../java/app/owlcms/utils/TimeZoneUtils.java | 2 +- .../main/java/app/owlcms/utils/URLUtils.java | 2 +- .../main/java/app/owlcms/utils/ZipUtils.java | 2 +- 397 files changed, 5181 insertions(+), 4694 deletions(-) create mode 100644 fixcopyright.sh diff --git a/fixcopyright.sh b/fixcopyright.sh new file mode 100644 index 0000000000..8e28748332 --- /dev/null +++ b/fixcopyright.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +# Define the copyright notice +copyright_notice='/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/' + +# List of files to update (add your file paths here) +files=( +./owlcms/src/main/java/app/owlcms/AppShell.java +./owlcms/src/main/java/app/owlcms/apputils/JpaJsonConverter.java +./owlcms/src/main/java/app/owlcms/apputils/LogbackConfigReloader.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/BaseContent.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParametersReader.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/ParameterReader.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/ResultsParameters.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/ResultsParametersReader.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/SoundParameters.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/SoundParametersReader.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParameters.java +./owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParametersReader.java +./owlcms/src/main/java/app/owlcms/components/GroupCategorySelectionMenu.java +./owlcms/src/main/java/app/owlcms/components/GroupSelectionMenu.java +./owlcms/src/main/java/app/owlcms/data/agegroup/AssignedAthletesException.java +./owlcms/src/main/java/app/owlcms/data/agegroup/ChampionshipType.java +./owlcms/src/main/java/app/owlcms/data/athleteSort/Ranking.java +./owlcms/src/main/java/app/owlcms/data/export/AthleteSessionDataReader.java +./owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfo.java +./owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfoFactory.java +./owlcms/src/main/java/app/owlcms/data/group/BWCatInfo.java +./owlcms/src/main/java/app/owlcms/data/group/DisplayGroup.java +./owlcms/src/main/java/app/owlcms/data/jpa/HikariDataSourcePoolDetail.java +./owlcms/src/main/java/app/owlcms/data/records/RecordConfig.java +./owlcms/src/main/java/app/owlcms/data/records/RecordFilter.java +./owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsJury.java +./owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsLiftingOrder.java +./owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankingOrder.java +./owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankings.java +./owlcms/src/main/java/app/owlcms/displays/top/AbstractTop.java +./owlcms/src/main/java/app/owlcms/displays/video/StylesDirSelection.java +./owlcms/src/main/java/app/owlcms/fieldofplay/CountdownType.java +./owlcms/src/main/java/app/owlcms/init/MoquetteAuthenticator.java +./owlcms/src/main/java/app/owlcms/jetty/EmbeddedJetty.java +./owlcms/src/main/java/app/owlcms/monitors/IUnregister.java +./owlcms/src/main/java/app/owlcms/monitors/MQTTMonitor.java +./owlcms/src/main/java/app/owlcms/nui/displays/AbstractDisplayPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AbstractAttemptBoardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingAttemptBoardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingDecisionBoardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingAttemptBoardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingDecisionBoardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/AbstractResultsDisplayPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/CurrentAthletePage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/JuryScoreboardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/MedalsPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicMultiRanksPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicNoLeadersPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicRankingOrderPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicScoreboardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/RankingsPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupLiftingOrderPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupMultiRanksPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupNoLeadersPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupRankingOrderPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupScoreboardPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/SoundEntries.java +./owlcms/src/main/java/app/owlcms/nui/displays/top/TopSinclairPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/top/TopTeamsPage.java +./owlcms/src/main/java/app/owlcms/nui/displays/top/TopTeamsSinclairPage.java +./owlcms/src/main/java/app/owlcms/nui/home/DisplayLoginView.java +./owlcms/src/main/java/app/owlcms/nui/lifting/NextAthleteAble.java +./owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsGrid.java +./owlcms/src/main/java/app/owlcms/nui/preparation/PreCompetitionTemplates.java +./owlcms/src/main/java/app/owlcms/nui/preparation/RecordConfigEditingFormFactory.java +./owlcms/src/main/java/app/owlcms/nui/preparation/SessionGrid.java +./owlcms/src/main/java/app/owlcms/nui/results/IFilterCascade.java +./owlcms/src/main/java/app/owlcms/nui/results/SessionSelectionGrid.java +./owlcms/src/main/java/app/owlcms/nui/shared/HasBoardMode.java +./owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayout.java +./owlcms/src/main/java/app/owlcms/spreadsheet/IRegistrationFileProcessor.java +./owlcms/src/main/java/app/owlcms/spreadsheet/MAthlete.java +./owlcms/src/main/java/app/owlcms/spreadsheet/NRegistrationFileProcessor.java +./owlcms/src/main/java/app/owlcms/spreadsheet/ORegistrationFileProcessor.java +./owlcms/src/main/java/app/owlcms/spreadsheet/XLSXAgeGroupsExport.java +./owlcms/src/main/java/app/owlcms/uievents/AppEvent.java +./owlcms/src/test/java/app/owlcms/data/jpa/BenchmarkDataTest.java +./owlcms/src/test/java/app/owlcms/tests/AgeFactorsTest.java +./owlcms/src/test/java/app/owlcms/tests/GAMXTest.java +./owlcms/src/test/java/app/owlcms/tests/JSONExportImportTest.java +./publicresults/src/main/java/app/owlcms/apputils/queryparameters/ContentParameters.java +./publicresults/src/main/java/app/owlcms/displays/scoreboard/HasBoardMode.java +./publicresults/src/main/java/app/owlcms/prutils/CountdownTimer.java +./publicresults/src/main/java/app/owlcms/prutils/SessionCleanup.java +./publicresults/src/main/java/app/owlcms/publicresults/AppShell.java +./publicresults/src/main/java/app/owlcms/publicresults/Traceable.java +./shared/src/main/java/app/owlcms/servlet/EmbeddedJetty.java +./shared/src/main/java/app/owlcms/servlet/StopProcessingException.java +./shared/src/main/java/app/owlcms/utils/CSSUtils.java +./shared/src/main/java/app/owlcms/utils/DelayTimer.java +./shared/src/main/java/app/owlcms/utils/OwlcmsLicense.java +./shared/src/main/java/app/owlcms/utils/ProcessUtils.java +) + +# Add the copyright notice to each file +for file in "${files[@]}"; do + if [ -f "$file" ]; then + # Add the copyright notice at the top of the file + echo "$copyright_notice" | cat - "$file" > temp && mv temp "$file" + echo "Updated: $file" + else + echo "File not found: $file" + fi +done diff --git a/owlcms/src/main/java/app/owlcms/AppShell.java b/owlcms/src/main/java/app/owlcms/AppShell.java index 8a42eadd51..d3a7c119af 100644 --- a/owlcms/src/main/java/app/owlcms/AppShell.java +++ b/owlcms/src/main/java/app/owlcms/AppShell.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms; import org.eclipse.jetty.io.EofException; diff --git a/owlcms/src/main/java/app/owlcms/Main.java b/owlcms/src/main/java/app/owlcms/Main.java index 12bfbc3620..e5d631be4a 100644 --- a/owlcms/src/main/java/app/owlcms/Main.java +++ b/owlcms/src/main/java/app/owlcms/Main.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -97,6 +97,23 @@ public void onSessionLoopError(Throwable error) { private static InitialData initialData; public static String mqttStartup; private static Integer demoResetDelay; + private static Server mqttBroker; + + public static EmbeddedJetty doRun() { + EmbeddedJetty embeddedJetty = new EmbeddedJetty(null, "owlcms") + .setStartLogger(logger) + .setInitConfig(Main::initConfig) + .setInitData(Main::initData); + Thread server = new Thread(() -> { + try { + embeddedJetty.run(serverPort, "/"); + } catch (Exception e) { + logger.error("cannot start server {}\\n{}", e, LoggerUtils.stackTrace(e)); + } + }); + server.start(); + return embeddedJetty; + } public static Logger getStartupLogger() { String name = Main.class.getName() + ".startup"; @@ -135,17 +152,8 @@ public static void initData() { } // initialization, don't push out to browsers OwlcmsFactory.initDefaultFOP(); - - signalDatabaseReady(); - } - private static void signalDatabaseReady() { - try { - logger.info("Data initialized."); - OwlcmsFactory.countDownLatch(); - } catch (InterruptedException e) { - LoggerUtils.logError(logger, e, false); - } + signalDatabaseReady(); } public static void injectSuppliers() { @@ -158,9 +166,8 @@ public static void injectSuppliers() { /** * The main method. * - * Start a web server and do all the required initializations for the application If running normally, we run until - * killed. If running as a public demo, we sleep for awhile, and then exit. Some external mechanism such as - * Kubernetes will notice and restart another instance. + * Start a web server and do all the required initializations for the application If running normally, we run until killed. If running as a public demo, we + * sleep for awhile, and then exit. Some external mechanism such as Kubernetes will notice and restart another instance. * * @param args the arguments * @throws Exception the exception @@ -173,7 +180,7 @@ public static void main(String... args) throws Exception { } init(); - //CountDownLatch latch = OwlcmsFactory.getInitializationLatch(); + // CountDownLatch latch = OwlcmsFactory.getInitializationLatch(); // restart automatically forever if running as public demo while (true) { @@ -187,27 +194,76 @@ public static void main(String... args) throws Exception { } - public static EmbeddedJetty doRun() { - EmbeddedJetty embeddedJetty = new EmbeddedJetty(null, "owlcms") - .setStartLogger(logger) - .setInitConfig(Main::initConfig) - .setInitData(Main::initData); - Thread server = new Thread(() -> { - try { - embeddedJetty.run(serverPort, "/"); - } catch (Exception e) { - logger.error("cannot start server {}\\n{}", e, LoggerUtils.stackTrace(e)); + @SuppressWarnings("deprecation") + public static void startMQTT() { + Config conf = Config.getCurrent(); + Boolean mqttInternal = conf.getMqttInternal(); + if (mqttInternal == null) { + conf.setMqttInternal(true); + Config.setCurrent(conf); + } else { + // conf.setMqttInternal(true); + // Config.setCurrent(conf); + if (!mqttInternal) { + logger.info("MQTT server disabled using database configuration"); + return; } - }); - server.start(); - return embeddedJetty; + } + + mqttStartup = Long.toString(System.currentTimeMillis()); + final IConfig mqttConfig = new MemoryConfig(new Properties()); + Config.getCurrent().setMqttConfig(mqttConfig); + mqttConfig.setProperty(IConfig.ALLOW_ANONYMOUS_PROPERTY_NAME, + Boolean.toString(Config.getCurrent().getParamMqttUserName() == null)); + mqttConfig.setProperty(IConfig.AUTHENTICATOR_CLASS_NAME, "app.owlcms.init.MoquetteAuthenticator"); + mqttConfig.setProperty(IConfig.PORT_PROPERTY_NAME, Config.getCurrent().getParamMqttPort()); + mqttConfig.setProperty(IConfig.BUFFER_FLUSH_MS_PROPERTY_NAME, Integer.toString(0)); + mqttConfig.setProperty(IConfig.PERSISTENCE_ENABLED_PROPERTY_NAME, Boolean.FALSE.toString()); + // this should be in memory, but the DATA_PATH_PROPERTY_NAME does not work with a virtual file system + mqttConfig.setProperty(IConfig.DATA_PATH_PROPERTY_NAME, "mqttData"); + new File(mqttConfig.getProperty(IConfig.DATA_PATH_PROPERTY_NAME)).mkdirs(); + + mqttBroker = new Server(); + List userHandlers = Collections.singletonList(new PublisherListener()); + + if (Config.getCurrent().getParamMqttServer() != null && !Config.getCurrent().getParamMqttServer().isBlank()) { + logger.info("MQTT Server overridden by environment or system parameter, not starting embedded MQTT"); + return; + } + if (!Config.getCurrent().getParamMqttInternal()) { + logger.info("Internal MQTT server not enabled, skipping"); + return; + } + if (Config.getCurrent().getMqttInternal() == null) { + // default should be true if not set previously + Config.getCurrent().setMqttInternal(true); + } + + try { + long now = System.currentTimeMillis(); + logger.info("starting MQTT broker."); + mqttBroker.startServer(mqttConfig, userHandlers); + logger.info("started MQTT broker ({} ms).", System.currentTimeMillis() - now); + + // Bind a shutdown hook + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + logger.info("Stopping broker"); + mqttBroker.stopServer(); + logger.info("Broker stopped"); + })); + } catch (Exception e) { + logger.error("could not start server", e.toString(), e.getCause()); + } + } + + public static void stopMQTT() { + mqttBroker.stopServer(); } /** * Prepare owlcms * - * Reads configuration options, injects data, initializes singletons and configurations. The embedded web server can - * then be started. + * Reads configuration options, injects data, initializes singletons and configurations. The embedded web server can then be started. * * Sample command line to run on port 80 and in demo mode (automatically generated fake data, in-memory database) * @@ -224,13 +280,13 @@ protected static void init() throws IOException, ParseException { SLF4JBridgeHandler.install(); // disable poixml warning StartupUtils.disableWarning(); - + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - System.out.println("Caught " + e); - e.printStackTrace(); - } + @Override + public void uncaughtException(Thread t, Throwable e) { + System.out.println("Caught " + e); + e.printStackTrace(); + } }); // read command-line and environment variable parameters @@ -290,7 +346,7 @@ private static void injectData(InitialData data, break; case BENCHMARK: BenchmarkData.insertInitialData( - EnumSet.of(ChampionshipType.IWF, ChampionshipType.MASTERS)); + EnumSet.of(ChampionshipType.IWF, ChampionshipType.MASTERS)); break; } } else { @@ -420,74 +476,15 @@ private static void parseConfig() { masters = StartupUtils.getBooleanParam("masters"); } - - private static Server mqttBroker; - - @SuppressWarnings("deprecation") - public static void startMQTT() { - Config conf = Config.getCurrent(); - Boolean mqttInternal = conf.getMqttInternal(); - if (mqttInternal == null) { - conf.setMqttInternal(true); - Config.setCurrent(conf); - } else { - // conf.setMqttInternal(true); - // Config.setCurrent(conf); - if (!mqttInternal) { - logger.info("MQTT server disabled using database configuration"); - return; - } - } - - mqttStartup = Long.toString(System.currentTimeMillis()); - final IConfig mqttConfig = new MemoryConfig(new Properties()); - Config.getCurrent().setMqttConfig(mqttConfig); - mqttConfig.setProperty(IConfig.ALLOW_ANONYMOUS_PROPERTY_NAME, - Boolean.toString(Config.getCurrent().getParamMqttUserName() == null)); - mqttConfig.setProperty(IConfig.AUTHENTICATOR_CLASS_NAME, "app.owlcms.init.MoquetteAuthenticator"); - mqttConfig.setProperty(IConfig.PORT_PROPERTY_NAME, Config.getCurrent().getParamMqttPort()); - mqttConfig.setProperty(IConfig.BUFFER_FLUSH_MS_PROPERTY_NAME, Integer.toString(0)); - mqttConfig.setProperty(IConfig.PERSISTENCE_ENABLED_PROPERTY_NAME, Boolean.FALSE.toString()); - // this should be in memory, but the DATA_PATH_PROPERTY_NAME does not work with a virtual file system - mqttConfig.setProperty(IConfig.DATA_PATH_PROPERTY_NAME, "mqttData"); - new File(mqttConfig.getProperty(IConfig.DATA_PATH_PROPERTY_NAME)).mkdirs(); - - mqttBroker = new Server(); - List userHandlers = Collections.singletonList(new PublisherListener()); - - if (Config.getCurrent().getParamMqttServer() != null && !Config.getCurrent().getParamMqttServer().isBlank()) { - logger.info("MQTT Server overridden by environment or system parameter, not starting embedded MQTT"); - return; - } - if (!Config.getCurrent().getParamMqttInternal()) { - logger.info("Internal MQTT server not enabled, skipping"); - return; - } - if (Config.getCurrent().getMqttInternal() == null) { - // default should be true if not set previously - Config.getCurrent().setMqttInternal(true); - } + private static void signalDatabaseReady() { try { - long now = System.currentTimeMillis(); - logger.info("starting MQTT broker."); - mqttBroker.startServer(mqttConfig, userHandlers); - logger.info("started MQTT broker ({} ms).", System.currentTimeMillis() - now); - - // Bind a shutdown hook - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - logger.info("Stopping broker"); - mqttBroker.stopServer(); - logger.info("Broker stopped"); - })); - } catch (Exception e) { - logger.error("could not start server", e.toString(), e.getCause()); + logger.info("Data initialized."); + OwlcmsFactory.countDownLatch(); + } catch (InterruptedException e) { + LoggerUtils.logError(logger, e, false); } } - - public static void stopMQTT() { - mqttBroker.stopServer(); - } private static void warnAndExit(Integer demoResetDelay, EmbeddedJetty server) throws InterruptedException { diff --git a/owlcms/src/main/java/app/owlcms/apputils/AccessUtils.java b/owlcms/src/main/java/app/owlcms/apputils/AccessUtils.java index db605bf4a2..9fce54e300 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/AccessUtils.java +++ b/owlcms/src/main/java/app/owlcms/apputils/AccessUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/apputils/ClientMultipartFormPost.java b/owlcms/src/main/java/app/owlcms/apputils/ClientMultipartFormPost.java index 28c2a027cf..088ad71e6c 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/ClientMultipartFormPost.java +++ b/owlcms/src/main/java/app/owlcms/apputils/ClientMultipartFormPost.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * original code from * https://stackoverflow.com/questions/2469451/upload-files-from-java-client-to-a-http-server diff --git a/owlcms/src/main/java/app/owlcms/apputils/DebugUtils.java b/owlcms/src/main/java/app/owlcms/apputils/DebugUtils.java index 7312986c8b..4ddedef511 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/DebugUtils.java +++ b/owlcms/src/main/java/app/owlcms/apputils/DebugUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/apputils/JpaJsonConverter.java b/owlcms/src/main/java/app/owlcms/apputils/JpaJsonConverter.java index db40c6b30b..e600cffa5e 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/JpaJsonConverter.java +++ b/owlcms/src/main/java/app/owlcms/apputils/JpaJsonConverter.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.apputils; import java.io.IOException; diff --git a/owlcms/src/main/java/app/owlcms/apputils/LogbackConfigReloader.java b/owlcms/src/main/java/app/owlcms/apputils/LogbackConfigReloader.java index 27772d4002..df3fb21bac 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/LogbackConfigReloader.java +++ b/owlcms/src/main/java/app/owlcms/apputils/LogbackConfigReloader.java @@ -1,4 +1,11 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.apputils; + import java.net.URL; import org.slf4j.LoggerFactory; @@ -8,55 +15,55 @@ import ch.qos.logback.core.joran.spi.JoranException; public class LogbackConfigReloader { - private static final String[] CONFIG_FILES = { - "logback.xml", - "logback-test.xml" - }; + private static final String[] CONFIG_FILES = { + "logback.xml", + "logback-test.xml" + }; public static void reloadLogbackConfiguration() { - LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); - - try { - URL configUrl = findLogbackConfigurationUrl(); - - if (configUrl == null) { - System.err.println("No Logback configuration file found"); - return; - } - - // Reset the current configuration - loggerContext.reset(); - - // Create a new configurator - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(loggerContext); - - // Reconfigure using the original configuration URL - configurator.doConfigure(configUrl); - - System.out.println("Logback configuration reloaded from: " + configUrl); - - } catch (JoranException e) { - System.err.println("Error reloading Logback configuration: " + e.getMessage()); - } - } - - private static URL findLogbackConfigurationUrl() { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - - // Check system property first - String explicitConfigFile = System.getProperty("logback.configurationFile"); - if (explicitConfigFile != null) { - return classLoader.getResource(explicitConfigFile); - } - - // Try predefined list of configuration files - for (String configFile : CONFIG_FILES) { - URL url = classLoader.getResource(configFile); - if (url != null) { - return url; - } - } - return null; - } + LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); + + try { + URL configUrl = findLogbackConfigurationUrl(); + + if (configUrl == null) { + System.err.println("No Logback configuration file found"); + return; + } + + // Reset the current configuration + loggerContext.reset(); + + // Create a new configurator + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + + // Reconfigure using the original configuration URL + configurator.doConfigure(configUrl); + + System.out.println("Logback configuration reloaded from: " + configUrl); + + } catch (JoranException e) { + System.err.println("Error reloading Logback configuration: " + e.getMessage()); + } + } + + private static URL findLogbackConfigurationUrl() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + // Check system property first + String explicitConfigFile = System.getProperty("logback.configurationFile"); + if (explicitConfigFile != null) { + return classLoader.getResource(explicitConfigFile); + } + + // Try predefined list of configuration files + for (String configFile : CONFIG_FILES) { + URL url = classLoader.getResource(configFile); + if (url != null) { + return url; + } + } + return null; + } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/apputils/NotificationUtils.java b/owlcms/src/main/java/app/owlcms/apputils/NotificationUtils.java index 85410e75ba..4ae70861e9 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/NotificationUtils.java +++ b/owlcms/src/main/java/app/owlcms/apputils/NotificationUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/apputils/SoundUtils.java b/owlcms/src/main/java/app/owlcms/apputils/SoundUtils.java index cdcfb965d9..d83e45cdb8 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/SoundUtils.java +++ b/owlcms/src/main/java/app/owlcms/apputils/SoundUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/BaseContent.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/BaseContent.java index 1f349f1d1c..f12ff8feba 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/BaseContent.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/BaseContent.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.apputils.queryparameters; import java.util.List; @@ -19,7 +25,6 @@ public class BaseContent extends VerticalLayout implements FOPParametersReader, SoundParameters { final static Logger logger = (Logger) LoggerFactory.getLogger(BaseContent.class); - protected FieldOfPlay fop; private Group group; private Location location; @@ -29,7 +34,7 @@ public class BaseContent extends VerticalLayout implements FOPParametersReader, private String routeParameter; private boolean silenced; private boolean downSilenced; - + public BaseContent() { OwlcmsFactory.waitDBInitialized(); } diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java index edf9bbde1c..888b12528d 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -11,8 +11,8 @@ import ch.qos.logback.classic.Logger; /** - * Navigating to a component that implements this interface will trigger the setParameter method. The setParameter - * method will invoke readParams method to actually process the query parameter. + * Navigating to a component that implements this interface will trigger the setParameter method. The setParameter method will invoke readParams method to + * actually process the query parameter. * * Display pages extend an abstract class that stores all the options. * diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParametersReader.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParametersReader.java index 45fc4328f6..0984bd0db6 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParametersReader.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/DisplayParametersReader.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.apputils.queryparameters; import java.net.URLDecoder; @@ -141,11 +147,9 @@ public default Map> readParams(Location location, /* * Process query parameters * - * Note: what Vaadin calls a parameter is in the REST style, actually part of the URL path. We use the old-style - * Query parameters for our purposes. + * Note: what Vaadin calls a parameter is in the REST style, actually part of the URL path. We use the old-style Query parameters for our purposes. * - * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin. flow.router.BeforeEvent, - * java.lang.String) + * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin. flow.router.BeforeEvent, java.lang.String) */ @Override public default void setParameter(BeforeEvent event, @OptionalParameter String routeParameter) { diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java index fa83d9c4a4..4938aa567b 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParametersReader.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParametersReader.java index 3fcfadfae7..c122077021 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParametersReader.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/FOPParametersReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -36,8 +36,8 @@ public interface FOPParametersReader extends ParameterReader, FOPParameters { final Logger logger = (Logger) LoggerFactory.getLogger(FOPParametersReader.class); /** - * @see app.owlcms.apputils.queryparameters.ParameterReader#doUpdateUrlLocation(com.vaadin.flow.component.UI, - * com.vaadin.flow.router.Location, java.util.Map) + * @see app.owlcms.apputils.queryparameters.ParameterReader#doUpdateUrlLocation(com.vaadin.flow.component.UI, com.vaadin.flow.router.Location, + * java.util.Map) */ @Override public default void doUpdateUrlLocation(UI ui, Location location, Map> queryParameterMap) { @@ -64,8 +64,7 @@ public default boolean isIgnoreGroupFromURL() { } /** - * @see app.owlcms.apputils.queryparameters.ParameterReader#readParams(com.vaadin.flow.router.Location, - * java.util.Map) + * @see app.owlcms.apputils.queryparameters.ParameterReader#readParams(com.vaadin.flow.router.Location, java.util.Map) */ @Override @SuppressWarnings("null") @@ -86,11 +85,10 @@ public default Map> readParams(Location location, Map> parameters, String parameter, String value) { @@ -195,8 +189,8 @@ public default void updateParam(Map> parameters, String par } /** - * @see app.owlcms.apputils.queryparameters.ParameterReader#updateURLLocation(com.vaadin.flow.component.UI, - * com.vaadin.flow.router.Location, java.lang.String, java.lang.String) + * @see app.owlcms.apputils.queryparameters.ParameterReader#updateURLLocation(com.vaadin.flow.component.UI, com.vaadin.flow.router.Location, + * java.lang.String, java.lang.String) */ @Override public default void updateURLLocation(UI ui, Location location, String parameter, String value) { diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/ParameterReader.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/ParameterReader.java index 20185083e0..adb0d3ea7c 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/ParameterReader.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/ParameterReader.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.apputils.queryparameters; import java.util.List; @@ -73,14 +79,12 @@ public default Map> removeDefaultValues(Map> readParams(Location location, @Override public void setShowInitialDialog(boolean b); - public default void switchDownMode(boolean silent, boolean updateURL) { - setDownSilenced(silent); - if (updateURL) { - updateURLLocation(getLocationUI(), getLocation(), DOWNSILENT, silent ? "true" : "false"); - } - } - - public default void switchLiveLightsMode(Component component, boolean liveLights, boolean updateURL) { - setLiveLights(liveLights); - if (updateURL) { - updateURLLocation(getLocationUI(), getLocation(), LIVE_LIGHTS, liveLights ? "true" : "false"); - } - } - - public default void switchStartOrderMode(Component component, boolean startOrder, boolean updateURL) { - setStartOrder(startOrder); + public default void switchCenteringMode(Component component, boolean centerNotification, boolean updateURL) { + setCenterNotifications(centerNotification); if (updateURL) { - updateURLLocation(getLocationUI(), getLocation(), START_ORDER, startOrder ? "true" : "false"); + updateURLLocation(getLocationUI(), getLocation(), CENTER_NOTIFICATIONS, centerNotification ? "true" : "false"); } } - + public default void switchDeclarationsMode(Component component, boolean showDeclarations, boolean updateURL) { setDeclarations(showDeclarations); if (updateURL) { @@ -132,10 +124,10 @@ public default void switchDeclarationsMode(Component component, boolean showDecl } } - public default void switchCenteringMode(Component component, boolean centerNotification, boolean updateURL) { - setCenterNotifications(centerNotification); + public default void switchDownMode(boolean silent, boolean updateURL) { + setDownSilenced(silent); if (updateURL) { - updateURLLocation(getLocationUI(), getLocation(), CENTER_NOTIFICATIONS, centerNotification ? "true" : "false"); + updateURLLocation(getLocationUI(), getLocation(), DOWNSILENT, silent ? "true" : "false"); } } @@ -154,6 +146,13 @@ public default void switchImmediateDecisionMode(Component component, boolean b, } } + public default void switchLiveLightsMode(Component component, boolean liveLights, boolean updateURL) { + setLiveLights(liveLights); + if (updateURL) { + updateURLLocation(getLocationUI(), getLocation(), LIVE_LIGHTS, liveLights ? "true" : "false"); + } + } + public default void switchSingleRefereeMode(Component component, boolean b, boolean updateURL) { setSingleReferee(b); if (updateURL) { @@ -175,4 +174,11 @@ public default void switchSoundMode(boolean silent, boolean updateURL) { public default void switchSoundMode(Component target, boolean silent, boolean updateURL) { switchSoundMode(silent, updateURL); } + + public default void switchStartOrderMode(Component component, boolean startOrder, boolean updateURL) { + setStartOrder(startOrder); + if (updateURL) { + updateURLLocation(getLocationUI(), getLocation(), START_ORDER, startOrder ? "true" : "false"); + } + } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParameters.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParameters.java index b49e5eb778..46cea1cd4b 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParameters.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParameters.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.apputils.queryparameters; public interface TopParameters extends DisplayParameters, ResultsParameters { diff --git a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParametersReader.java b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParametersReader.java index 5738b2e096..4c9dc1f614 100644 --- a/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParametersReader.java +++ b/owlcms/src/main/java/app/owlcms/apputils/queryparameters/TopParametersReader.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.apputils.queryparameters; import java.util.List; diff --git a/owlcms/src/main/java/app/owlcms/components/ConfirmationDialog.java b/owlcms/src/main/java/app/owlcms/components/ConfirmationDialog.java index 18fb3ecbfc..df0c47a8be 100644 --- a/owlcms/src/main/java/app/owlcms/components/ConfirmationDialog.java +++ b/owlcms/src/main/java/app/owlcms/components/ConfirmationDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -41,8 +41,8 @@ public ConfirmationDialog(String title, String question, String confirmation, Ru Button confirmButton = new Button(Translator.translate("Confirm"), event -> { if (pAction != null) { pAction.run(); - } else if (action != null) { - action.run(); + } else if (this.action != null) { + this.action.run(); } if (confirmation != null) { Notification.show(confirmation); @@ -65,7 +65,7 @@ public ConfirmationDialog(String title, String question, String confirmation, Ru } public Runnable getAction() { - return action; + return this.action; } public void setAction(Runnable action) { diff --git a/owlcms/src/main/java/app/owlcms/components/GroupCategorySelectionMenu.java b/owlcms/src/main/java/app/owlcms/components/GroupCategorySelectionMenu.java index 6f059a6c49..76cd23811e 100644 --- a/owlcms/src/main/java/app/owlcms/components/GroupCategorySelectionMenu.java +++ b/owlcms/src/main/java/app/owlcms/components/GroupCategorySelectionMenu.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.components; import java.util.HashMap; @@ -53,6 +59,8 @@ public interface TriConsumer { private FieldOfPlay fop; private TriConsumer whenChecked; private TriConsumer whenUnselected; + boolean subMenuLoaded = false; + Map> medalCategoriesPerGroup = new HashMap<>(); public GroupCategorySelectionMenu(List groups, FieldOfPlay fop, TriConsumer whenChecked, @@ -64,77 +72,6 @@ public GroupCategorySelectionMenu(List groups, FieldOfPlay fop, this.whenUnselected = whenUnselected; } - @Override - protected void onAttach(AttachEvent attachEvent) { - subMenuLoaded = false; - init(groups, fop, whenChecked, whenUnselected, this.getUI().get()); - } - - public void recompute() { - UI ui = this.getUI().get(); - this.removeAll(); - subMenuLoaded = false; - init(this.groups, this.fop, this.whenChecked, this.whenUnselected, ui); - } - - public void setIncludeNotCompleted(Boolean value) { - this.includeNotCompleted = value; - } - - @SuppressWarnings("unused") - private String describedName(Group g) { - String desc = g.getDescription(); - if (desc == null || desc.isBlank()) { - return g.getName(); - } else { - return g.getName() + " - " + g.getDescription(); - } - } - - private Set getAllCategories(Group g) { - TreeMap> medals = Competition.getCurrent().getMedals(g, false); - return medals.keySet(); - } - - private Set getFinishedCategories(Group g) { - Set finishedCategories = new TreeSet<>(); - TreeMap> medals = Competition.getCurrent().getMedals(g, true); - finishedCategories = medals.keySet(); - return finishedCategories; - } - - boolean subMenuLoaded = false; - Map> medalCategoriesPerGroup = new HashMap<>(); - - private void init(List groups, FieldOfPlay fop, TriConsumer whenChecked, - TriConsumer whenUnselected, UI ui) { - - MenuItem item; - String menuTitle = Translator.translate("Group") + "/" + Translator.translate("Category") + "\u2003\u25bc"; - this.setId("sessionDropDown"); - item = this.addItem(menuTitle); - this.addThemeVariants(MenuBarVariant.LUMO_SMALL, MenuBarVariant.LUMO_PRIMARY); - this.setEnabled(false); - - if (!subMenuLoaded) { - medalCategoriesPerGroup.clear(); - new Thread(() -> { - for (Group g : groups) { - Set categories = this.includeNotCompleted ? getAllCategories(g) : getFinishedCategories(g); - if (!categories.isEmpty()) { - medalCategoriesPerGroup.put(g, categories); - } - } - subMenuLoaded = true; - ui.access(() -> { - fillMenu(groups, medalCategoriesPerGroup, fop, whenChecked, whenUnselected, item, menuTitle); - this.setEnabled(true); - }); - }).start(); - } - - } - public void fillMenu(List groups, Map> medalCategoriesPerGroup, FieldOfPlay fop, TriConsumer whenChecked, TriConsumer whenUnselected, MenuItem item, String menuTitle) { @@ -156,7 +93,7 @@ public void fillMenu(List groups, Map> medalCategories } subItem.getElement().setAttribute("style", "margin: 0px; padding: 0px"); - logger.debug("***medal categories {}", categories); + this.logger.debug("***medal categories {}", categories); for (String c : categories) { Category cat = CategoryRepository.findByCode(c); @@ -195,6 +132,74 @@ public void fillMenu(List groups, Map> medalCategories item.setEnabled(true); } + public void recompute() { + UI ui = this.getUI().get(); + this.removeAll(); + this.subMenuLoaded = false; + init(this.groups, this.fop, this.whenChecked, this.whenUnselected, ui); + } + + public void setIncludeNotCompleted(Boolean value) { + this.includeNotCompleted = value; + } + + @Override + protected void onAttach(AttachEvent attachEvent) { + this.subMenuLoaded = false; + init(this.groups, this.fop, this.whenChecked, this.whenUnselected, this.getUI().get()); + } + + @SuppressWarnings("unused") + private String describedName(Group g) { + String desc = g.getDescription(); + if (desc == null || desc.isBlank()) { + return g.getName(); + } else { + return g.getName() + " - " + g.getDescription(); + } + } + + private Set getAllCategories(Group g) { + TreeMap> medals = Competition.getCurrent().getMedals(g, false); + return medals.keySet(); + } + + private Set getFinishedCategories(Group g) { + Set finishedCategories = new TreeSet<>(); + TreeMap> medals = Competition.getCurrent().getMedals(g, true); + finishedCategories = medals.keySet(); + return finishedCategories; + } + + private void init(List groups, FieldOfPlay fop, TriConsumer whenChecked, + TriConsumer whenUnselected, UI ui) { + + MenuItem item; + String menuTitle = Translator.translate("Group") + "/" + Translator.translate("Category") + "\u2003\u25bc"; + this.setId("sessionDropDown"); + item = this.addItem(menuTitle); + this.addThemeVariants(MenuBarVariant.LUMO_SMALL, MenuBarVariant.LUMO_PRIMARY); + this.setEnabled(false); + + if (!this.subMenuLoaded) { + this.medalCategoriesPerGroup.clear(); + new Thread(() -> { + for (Group g : groups) { + Set categories = this.includeNotCompleted ? getAllCategories(g) : getFinishedCategories(g); + if (!categories.isEmpty()) { + this.medalCategoriesPerGroup.put(g, categories); + } + } + this.subMenuLoaded = true; + ui.access(() -> { + fillMenu(groups, this.medalCategoriesPerGroup, fop, whenChecked, whenUnselected, item, menuTitle); + this.setEnabled(true); + }); + }).start(); + } + + } + private void setChecked(MenuItem menuItem, SubMenu subMenu, boolean checked) { for (MenuItem item : subMenu.getItems()) { item.setChecked(false); diff --git a/owlcms/src/main/java/app/owlcms/components/GroupSelectionMenu.java b/owlcms/src/main/java/app/owlcms/components/GroupSelectionMenu.java index 24ff38d202..5f4ae7f5b0 100644 --- a/owlcms/src/main/java/app/owlcms/components/GroupSelectionMenu.java +++ b/owlcms/src/main/java/app/owlcms/components/GroupSelectionMenu.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.components; import java.util.List; @@ -58,9 +64,9 @@ public GroupSelectionMenu(List groups, Group curGroup, FieldOfPlay fop2, MenuItem subItem = subMenu.addItem( describedName(g), e -> { - if (!e.isFromClient()) { - return; - } + if (!e.isFromClient()) { + return; + } whenChecked.accept(g); if (currentlyChecked[0] != null) { currentlyChecked[0].setChecked(false); @@ -93,9 +99,9 @@ public GroupSelectionMenu(List groups, Group curGroup, FieldOfPlay fop2, hl.setAlignItems(Alignment.CENTER); MenuItem item3 = subMenu.addItem(hl, e -> { - if (!e.isFromClient()) { - return; - } + if (!e.isFromClient()) { + return; + } if (currentlyChecked[0] != null) { currentlyChecked[0].setChecked(false); } @@ -124,5 +130,4 @@ private String describedName(Group g) { } } - } diff --git a/owlcms/src/main/java/app/owlcms/components/JXLSDownloader.java b/owlcms/src/main/java/app/owlcms/components/JXLSDownloader.java index a83c752904..d80ce180c9 100644 --- a/owlcms/src/main/java/app/owlcms/components/JXLSDownloader.java +++ b/owlcms/src/main/java/app/owlcms/components/JXLSDownloader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -154,16 +154,15 @@ public Button createDownloadButton() { } /** - * Deprecated because the time stamp in the file name is determined when the download button - * is created, and not when the file is downloaded. - * + * Deprecated because the time stamp in the file name is determined when the download button is created, and not when the file is downloaded. + * * Use LazyDownloadButton instead. - * + * * @param tooltipText * @return */ - //@Deprecated - //TODO remove use of createImmediateDownloadButton + // @Deprecated + // TODO remove use of createImmediateDownloadButton public Anchor createImmediateDownloadButton(String... tooltipText) { this.xlsWriter = this.streamSourceSupplier.get(); Supplier supplier = () -> getTargetFileName(); @@ -237,9 +236,9 @@ private Dialog createDialog() { this.logger.debug("(2) template as set {}", this.templateNameGetter.apply(current)); this.xlsWriter = this.streamSourceSupplier.get(); - this.logger.debug("(2) xlsWriter dialog {} {}", xlsWriter, dialog); + this.logger.debug("(2) xlsWriter dialog {} {}", this.xlsWriter, this.dialog); if (this.xlsWriter == null) { - UI.getCurrent().access(() -> dialog.close()); + UI.getCurrent().access(() -> this.dialog.close()); return; } this.logger.debug("(2) xlsWriter {} {}", this.xlsWriter.getClass().getSimpleName(), diff --git a/owlcms/src/main/java/app/owlcms/components/NavigationPage.java b/owlcms/src/main/java/app/owlcms/components/NavigationPage.java index bac1f4575d..f3358217d9 100644 --- a/owlcms/src/main/java/app/owlcms/components/NavigationPage.java +++ b/owlcms/src/main/java/app/owlcms/components/NavigationPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/elements/AthleteTimerElement.java b/owlcms/src/main/java/app/owlcms/components/elements/AthleteTimerElement.java index 401410a9b3..f12f3b03d2 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/AthleteTimerElement.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/AthleteTimerElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -91,7 +91,6 @@ public void clientInitialWarning(String fopName) { @ClientCallable public void clientSyncTime(String fopName) { if (!Config.getCurrent().featureSwitch("oldTimers")) { - return; } // timer should only get explicit changes // OwlcmsSession.withFop(fop -> { @@ -225,6 +224,19 @@ public void slaveStopTimer(UIEvent.StopTime e) { doStopTimer(milliseconds); } + public void syncWithFop(FieldOfPlay fop) { + init(fop.getName()); + // sync with current status of FOP + IProxyTimer athleteTimer = getFopTimer(fop); + if (athleteTimer != null) { + if (athleteTimer.isRunning()) { + doStartTimer(athleteTimer.liveTimeRemaining(), isSilenced() || fop.isEmitSoundsOnServer()); + } else { + doSetTimer(athleteTimer.getTimeRemaining()); + } + } + } + @Override public void syncWithFopTimer(FieldOfPlay fop) { // only used by break timer @@ -264,17 +276,4 @@ protected void onAttach(AttachEvent attachEvent) { }); } - public void syncWithFop(FieldOfPlay fop) { - init(fop.getName()); - // sync with current status of FOP - IProxyTimer athleteTimer = getFopTimer(fop); - if (athleteTimer != null) { - if (athleteTimer.isRunning()) { - doStartTimer(athleteTimer.liveTimeRemaining(), isSilenced() || fop.isEmitSoundsOnServer()); - } else { - doSetTimer(athleteTimer.getTimeRemaining()); - } - } - } - } diff --git a/owlcms/src/main/java/app/owlcms/components/elements/BeepElement.java b/owlcms/src/main/java/app/owlcms/components/elements/BeepElement.java index c2b5d81d4b..9cd1b6280b 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/BeepElement.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/BeepElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-Fran�ois Lamy + * Copyright © 2009-present Jean-Fran�ois Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/elements/BreakTimerElement.java b/owlcms/src/main/java/app/owlcms/components/elements/BreakTimerElement.java index f741c44f19..e63ffeb9fa 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/BreakTimerElement.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/BreakTimerElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -119,7 +119,6 @@ public void clientTimeOver(String fopName) { @ClientCallable public void clientTimerStarting(String fopName, double remainingTime, double lateMillis, String from) { if (!Config.getCurrent().featureSwitch("oldTimers")) { - return; } // logger.debug("timer {} starting on client: remaining = {}, late={}, roundtrip={}", from, remainingTime, // lateMillis, delta(lastStartMillis)); @@ -135,7 +134,6 @@ public void clientTimerStarting(String fopName, double remainingTime, double lat @ClientCallable public void clientTimerStopped(String fopName, double remainingTime, String from) { if (!Config.getCurrent().featureSwitch("oldTimers")) { - return; } // do not stop the server-side timer, otherwise we create an infinite loop. } @@ -200,38 +198,38 @@ public void slaveSwitchGroup(UIEvent.SwitchGroup e) { @Override public void syncWithFopTimer(FieldOfPlay fop) { - //OwlcmsSession.withFop(fop -> { - init(fop.getName()); - // sync with current status of FOP - IProxyTimer breakTimer = getFopTimer(fop); - if (breakTimer != null) { - if (this.uiEventLogger.isDebugEnabled()) { - this.uiEventLogger.debug("&&& breakTimerElement sync running {} indefinite {}", - breakTimer.isRunning(), - breakTimer.isIndefinite()); - } - if (breakTimer.isRunning()) { - if (breakTimer.isIndefinite()) { - if (this.uiEventLogger.isDebugEnabled()) { - this.uiEventLogger.debug("&&& indefinite {}", breakTimer.liveTimeRemaining()); - } - doStartTimer(null, fop.isEmitSoundsOnServer()); - } else { - if (this.uiEventLogger.isDebugEnabled()) { - this.uiEventLogger.debug("&&& live {}", breakTimer.liveTimeRemaining()); - } - doStartTimer(breakTimer.liveTimeRemaining(), isSilenced() || fop.isEmitSoundsOnServer()); + // OwlcmsSession.withFop(fop -> { + init(fop.getName()); + // sync with current status of FOP + IProxyTimer breakTimer = getFopTimer(fop); + if (breakTimer != null) { + if (this.uiEventLogger.isDebugEnabled()) { + this.uiEventLogger.debug("&&& breakTimerElement sync running {} indefinite {}", + breakTimer.isRunning(), + breakTimer.isIndefinite()); + } + if (breakTimer.isRunning()) { + if (breakTimer.isIndefinite()) { + if (this.uiEventLogger.isDebugEnabled()) { + this.uiEventLogger.debug("&&& indefinite {}", breakTimer.liveTimeRemaining()); } + doStartTimer(null, fop.isEmitSoundsOnServer()); } else { - doSetTimer(null); - // if (breakTimer.isIndefinite()) { - // doSetTimer(null); - // } else { - // doSetTimer(breakTimer.getTimeRemainingAtLastStop()); - // } + if (this.uiEventLogger.isDebugEnabled()) { + this.uiEventLogger.debug("&&& live {}", breakTimer.liveTimeRemaining()); + } + doStartTimer(breakTimer.liveTimeRemaining(), isSilenced() || fop.isEmitSoundsOnServer()); } + } else { + doSetTimer(null); + // if (breakTimer.isIndefinite()) { + // doSetTimer(null); + // } else { + // doSetTimer(breakTimer.getTimeRemainingAtLastStop()); + // } } - //}); + } + // }); } @Override diff --git a/owlcms/src/main/java/app/owlcms/components/elements/DecisionElement.java b/owlcms/src/main/java/app/owlcms/components/elements/DecisionElement.java index 64608d89a9..c29cc60aca 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/DecisionElement.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/DecisionElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-Fran�ois Lamy + * Copyright © 2009-present Jean-Fran�ois Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/elements/JuryDisplayDecisionElement.java b/owlcms/src/main/java/app/owlcms/components/elements/JuryDisplayDecisionElement.java index 8ad48e7645..388bcf18d9 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/JuryDisplayDecisionElement.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/JuryDisplayDecisionElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/elements/LazyDownloadButton.java b/owlcms/src/main/java/app/owlcms/components/elements/LazyDownloadButton.java index 42796908ce..c647dab79e 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/LazyDownloadButton.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/LazyDownloadButton.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -33,8 +33,7 @@ import ch.qos.logback.classic.Logger; /** - * Extension of anchor, that will display a vaadin button as clickable instance to initiate a download. The download - * content is generated at click time. + * Extension of anchor, that will display a vaadin button as clickable instance to initiate a download. The download content is generated at click time. * * @author Stefan Uebe * @implNote Copied from https://github.com/stefanuebe/vaadin-lazy-download-button @@ -48,8 +47,7 @@ public static class DownloadStartsEvent extends ComponentEventtrue if the event originated from the client @@ -104,12 +102,11 @@ public LazyDownloadButton(String text, Component icon, InputStreamFactory inputS * The third parameter is a callback, that is used to generate the download file name *

*

- * The fourth parameter is a callback to generate the input stream sent to the client. This callback will be called - * in a separate thread (so that the UI thread is not blocked). + * The fourth parameter is a callback to generate the input stream sent to the client. This callback will be called in a separate thread (so that the UI + * thread is not blocked). *

*

- * You can add an additional listener using {@link #addDownloadStartsListener(ComponentEventListener)} for when the - * download starts + * You can add an additional listener using {@link #addDownloadStartsListener(ComponentEventListener)} for when the download starts *

* * @param text button text @@ -157,10 +154,10 @@ public LazyDownloadButton(String text, Component icon, Supplier pFileNam try { InputStream inputStream = getInputStreamCallback().createInputStream(); optionalUI.ifPresent(ui -> ui.access(() -> { - if (notification != null) { - notification.open(); + if (this.notification != null) { + this.notification.open(); } - + StreamResource href = new StreamResource(getFileNameCallback().get(), () -> inputStream); href.setCacheTime(0); this.anchor.setHref(href); @@ -171,7 +168,7 @@ public LazyDownloadButton(String text, Component icon, Supplier pFileNam this.anchor.getElement().callJsFunction("click"); })); } catch (Exception e) { - if (! (e instanceof StopProcessingException)) { + if (!(e instanceof StopProcessingException)) { throw new RuntimeException(e); } } @@ -201,6 +198,10 @@ public InputStreamFactory getInputStreamCallback() { return this.inputStreamCallback; } + public Notification getNotification() { + return this.notification; + } + public void setFileNameCallback(Supplier fileNameCallback) { this.fileNameCallback = fileNameCallback; } @@ -209,6 +210,10 @@ public void setInputStreamCallback(InputStreamFactory inputStreamCallback) { this.inputStreamCallback = inputStreamCallback; } + public void setNotification(Notification notification) { + this.notification = notification; + } + @Override protected void onDetach(DetachEvent detachEvent) { if (this.anchor != null) { @@ -220,12 +225,4 @@ protected void onDetach(DetachEvent detachEvent) { }); } } - - public Notification getNotification() { - return notification; - } - - public void setNotification(Notification notification) { - this.notification = notification; - } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/components/elements/PlatesElement.java b/owlcms/src/main/java/app/owlcms/components/elements/PlatesElement.java index e14ccd0a94..3e9cad4d58 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/PlatesElement.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/PlatesElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -46,9 +46,9 @@ public void computeImageArea(FieldOfPlay fop, boolean showCaption) { final int barWeight = fop.getBarWeight(); this.setWeight(currentAthlete.getNextAttemptRequestedWeight()); final String caption = Translator.translate("Kg", this.getWeight()); - //logger.debug("caption {}",caption); + // logger.debug("caption {}",caption); - //logger.debug("before createImageArea save, platform identity={} 5kg={}",System.identityHashCode(fop.getPlatform()), fop.getPlatform().getNbB_5()); + // logger.debug("before createImageArea save, platform identity={} 5kg={}",System.identityHashCode(fop.getPlatform()), fop.getPlatform().getNbB_5()); createImageArea(fop, barWeight, (showCaption ? caption : "")); } @@ -63,7 +63,7 @@ public void computeImageArea(FieldOfPlay fop, boolean showCaption) { private int addPlates(Integer availablePlates, String style, double plateWeight, FieldOfPlay fop, boolean outline) { int subtractedWeight = 0; - //logger.debug("adding plates {} {} {} {} -- {}", availablePlates, style, getWeight(), plateWeight, LoggerUtils.whereFrom()); + // logger.debug("adding plates {} {} {} {} -- {}", availablePlates, style, getWeight(), plateWeight, LoggerUtils.whereFrom()); while (availablePlates > 0 && this.getWeight() >= plateWeight) { NativeLabel plate = new NativeLabel(); plate.setSizeUndefined(); @@ -104,14 +104,13 @@ private int addPlates(Integer availablePlates, String style, double plateWeight, return subtractedWeight; } - /** * @param platform * @param barWeight * @param caption */ private void createImageArea(FieldOfPlay fop, final Integer barWeight, final String caption) { - ui.access(() -> { + this.ui.access(() -> { this.removeAll(); Platform platform = fop.getPlatform(); boolean outline = caption != null && !caption.isBlank(); @@ -121,7 +120,7 @@ private void createImageArea(FieldOfPlay fop, final Integer barWeight, final Str // compute the bar and collar first. } - //logger.debug("barWeight {}",barWeight); + // logger.debug("barWeight {}",barWeight); int nonBarWeight = this.getWeight() - barWeight; addPlates(1, "bar", barWeight, fop, outline); @@ -132,12 +131,12 @@ private void createImageArea(FieldOfPlay fop, final Integer barWeight, final Str if (nonBarWeight >= 0) { addPlates(1, "barInner", 0, fop, outline); - //logger.debug("barWeight = {} nonBarWeight = {}", barWeight, nonBarWeight); + // logger.debug("barWeight = {} nonBarWeight = {}", barWeight, nonBarWeight); // make sure that large 5 and large 2.5 are only used when warranted // (must not require manual intervention if they are available) -// if (platform.getNbL_2_5() > 0 && nonBarWeight < 10 || platform.getNbL_5() > 0 && nonBarWeight < 15) { -// useCollar = false; -// } + // if (platform.getNbL_2_5() > 0 && nonBarWeight < 10 || platform.getNbL_5() > 0 && nonBarWeight < 15) { + // useCollar = false; + // } if (useCollar) { // we take off the collar weight because we need to // wait before showing the collar. @@ -152,24 +151,24 @@ private void createImageArea(FieldOfPlay fop, final Integer barWeight, final Str subtractedWeight += addPlates(platform.getNbL_15(), "L_15", 2 * 15, fop, outline); subtractedWeight += addPlates(platform.getNbL_10(), "L_10", 2 * 10, fop, outline); - //logger.debug("1 subtractedWeight {} nonBarWeight {}", subtractedWeight, nonBarWeight); + // logger.debug("1 subtractedWeight {} nonBarWeight {}", subtractedWeight, nonBarWeight); if (subtractedWeight == 0 && nonBarWeight >= 10) { // we have not used a large plate subtractedWeight += addPlates(platform.getNbL_5(), "L_5", 2 * 5, fop, outline); } - //logger.debug("2 subtractedWeight {} nonBarWeight {}", subtractedWeight, nonBarWeight); + // logger.debug("2 subtractedWeight {} nonBarWeight {}", subtractedWeight, nonBarWeight); if (subtractedWeight == 0 && nonBarWeight >= 5) { // we have not used a large plate subtractedWeight += addPlates(platform.getNbL_2_5(), "L_2_5", 2 * 2.5, fop, outline); } - - //logger.debug("3 subtractedWeight {} nonBarWeight {}", subtractedWeight, nonBarWeight); - + + // logger.debug("3 subtractedWeight {} nonBarWeight {}", subtractedWeight, nonBarWeight); + // add the small plates addPlates(platform.getNbS_5(), "S_5", 2 * 5, fop, outline); addPlates(platform.getNbS_2_5(), "S_2_5", 2 * 2.5, fop, outline); - + // collar is depicted here if (useCollar) { this.setWeight(this.getWeight() + 5); @@ -186,11 +185,11 @@ private void createImageArea(FieldOfPlay fop, final Integer barWeight, final Str } private int getWeight() { - return weight; + return this.weight; } private void setWeight(int weight) { - //logger.debug("weight = {} -- {}", weight, LoggerUtils.whereFrom()); + // logger.debug("weight = {} -- {}", weight, LoggerUtils.whereFrom()); this.weight = weight; } diff --git a/owlcms/src/main/java/app/owlcms/components/elements/SoundEnabler.java b/owlcms/src/main/java/app/owlcms/components/elements/SoundEnabler.java index 02282c5efa..9d90693e7d 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/SoundEnabler.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/SoundEnabler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -18,8 +18,8 @@ /** * Button that triggers an initSounds document event that causes components to initialize their sounds. * - * iOS in particular is stringent about requiring that sounds be played in response to a user interaction. Once a sound - * has been played once, it can be played again without user intervention + * iOS in particular is stringent about requiring that sounds be played in response to a user interaction. Once a sound has been played once, it can be played + * again without user intervention * * @author jflamy * diff --git a/owlcms/src/main/java/app/owlcms/components/elements/TimerElement.java b/owlcms/src/main/java/app/owlcms/components/elements/TimerElement.java index 46ef6d57c7..c2246daa1d 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/TimerElement.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/TimerElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-Fran�ois Lamy + * Copyright © 2009-present Jean-Fran�ois Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -74,8 +74,7 @@ public TimerElement() { abstract public void clientInitialWarning(String fopName); /** - * Client requests that the server send back the remaining time. Intended to be used after client has been hidden - * and is made visible again. + * Client requests that the server send back the remaining time. Intended to be used after client has been hidden and is made visible again. */ @AllowInert @ClientCallable @@ -110,7 +109,7 @@ public boolean isServerSound() { } public void setSilenced(boolean b) { - //this.logger.debug("======= {} silenced = {} from {}", this.getClass().getSimpleName(), b, LoggerUtils.stackTrace()); + // this.logger.debug("======= {} silenced = {} from {}", this.getClass().getSimpleName(), b, LoggerUtils.stackTrace()); this.silenced = b; } @@ -228,10 +227,10 @@ protected void onAttach(AttachEvent attachEvent) { @Override protected void onDetach(DetachEvent detachEvent) { -// // tell the javascript to stay quiet -// setSilenced(true); -// setTimerElement(null); -// getElement().setProperty("silent", true); + // // tell the javascript to stay quiet + // setSilenced(true); + // setTimerElement(null); + // getElement().setProperty("silent", true); } protected void setIndefinite(boolean indefinite) { diff --git a/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadEvent.java b/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadEvent.java index ab5a78043d..37c43984bc 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadEvent.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadEvent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -9,8 +9,7 @@ import com.vaadin.flow.component.ComponentEvent; /** - * Server-side event class associated with {@code beforeunload} event happening in the client-side. Can optionally - * prompt the user before leaving the page. + * Server-side event class associated with {@code beforeunload} event happening in the client-side. Can optionally prompt the user before leaving the page. * * @author miki * @since 2020-04-29 @@ -21,12 +20,10 @@ public class UnloadEvent extends ComponentEvent { private final boolean becauseOfQuerying; /** - * Creates a new event using the given source and indicator whether the event originated from the client side or the - * server side. + * Creates a new event using the given source and indicator whether the event originated from the client side or the server side. * * @param source the source component - * @param attempted when {@code true}, the event is fired in response to querying before unloading; {@code false} - * otherwise. + * @param attempted when {@code true}, the event is fired in response to querying before unloading; {@code false} otherwise. */ public UnloadEvent(UnloadObserver source, boolean attempted) { super(source, true); @@ -34,11 +31,9 @@ public UnloadEvent(UnloadObserver source, boolean attempted) { } /** - * Checks whether or not the event has been fired in response to querying the user on {@code beforeunload} browser - * event. + * Checks whether or not the event has been fired in response to querying the user on {@code beforeunload} browser event. * - * @return {@code true} when event is in response to querying the user on {@code beforeunload}, {@code false} - * otherwise. + * @return {@code true} when event is in response to querying the user on {@code beforeunload}, {@code false} otherwise. */ public boolean isBecauseOfQuerying() { return this.becauseOfQuerying; diff --git a/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadListener.java b/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadListener.java index cb326d1304..b70818d3f3 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadListener.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadListener.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadObserver.java b/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadObserver.java index 91df513618..eee47f27d4 100644 --- a/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadObserver.java +++ b/owlcms/src/main/java/app/owlcms/components/elements/unload/UnloadObserver.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-Fran�ois Lamy + * Copyright © 2009-present Jean-Fran�ois Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -18,15 +18,13 @@ /** * Server-side component that listens to {@code beforeunload} events. Based on - * the code by Kaspar - * Scherrer and Stuart Robinson. This component will broadcast events on {@code beforeunload} event in the browser. - * If {@link #isQueryingOnUnload()} is {@code true}, before the event the user will be prompted about leaving the page. - * However, there is no way to find out what the user selected. If {@link #isQueryingOnUnload()} is {@code false}, the - * event on the server will be called just before the page is unloaded. Note that the component must be present in the - * DOM structure in the browser for the event to be received on the server. + * the code by Kaspar Scherrer and Stuart Robinson. This + * component will broadcast events on {@code beforeunload} event in the browser. If {@link #isQueryingOnUnload()} is {@code true}, before the event the user + * will be prompted about leaving the page. However, there is no way to find out what the user selected. If {@link #isQueryingOnUnload()} is {@code false}, the + * event on the server will be called just before the page is unloaded. Note that the component must be present in the DOM structure in the browser for the + * event to be received on the server. * - * Warning: this class is a {@link UI}-scoped; the class is final, the constructors are private and there is at most one - * instance per UI. + * Warning: this class is a {@link UI}-scoped; the class is final, the constructors are private and there is at most one instance per UI. * * Warning: when the page is unloaded, the UI instance should be removed to prevent memory leaks. See {@link #remove()}. * @@ -68,8 +66,7 @@ public static UnloadObserver get(boolean queryingOnUnload) { } /** - * Cleans up the thread-local variable. This method is called automatically when the component receives - * {@code unload} event. + * Cleans up the thread-local variable. This method is called automatically when the component receives {@code unload} event. */ public static void remove() { UI current = UI.getCurrent(); @@ -110,8 +107,8 @@ public Registration addUnloadListener(UnloadListener listener) { /** * Returns whether or not querying on document unload will happen. * - * @return {@code true} when unloading the document from browser window results in showing a browser-native - * confirmation dialog and notifying {@link UnloadListener}s; {@code false} otherwise. + * @return {@code true} when unloading the document from browser window results in showing a browser-native confirmation dialog and notifying + * {@link UnloadListener}s; {@code false} otherwise. */ public boolean isQueryingOnUnload() { return this.queryingOnUnload; @@ -120,9 +117,8 @@ public boolean isQueryingOnUnload() { /** * Controls whether or not there should be querying when the document is going to be unloaded. * - * @param queryingOnUnload When {@code true}, {@link UnloadListener}s registered through - * {@link #addUnloadListener(UnloadListener)} will be notified and document unloading can be - * prevented. When {@code false}, nothing will happen when the document gets unloaded. + * @param queryingOnUnload When {@code true}, {@link UnloadListener}s registered through {@link #addUnloadListener(UnloadListener)} will be notified and + * document unloading can be prevented. When {@code false}, nothing will happen when the document gets unloaded. */ public void setQueryingOnUnload(boolean queryingOnUnload) { if (queryingOnUnload != this.queryingOnUnload) { diff --git a/owlcms/src/main/java/app/owlcms/components/fields/CategoryGridField.java b/owlcms/src/main/java/app/owlcms/components/fields/CategoryGridField.java index f6d43f63f7..42a15dd76a 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/CategoryGridField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/CategoryGridField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -143,7 +143,7 @@ private void populateGrid(VerticalLayout catGrid2, List presentationCa .withStatusLabel(this.validationStatus).bind("qualifyingTotal"); catBinder.setBean(pc); hl.add(qualTotField); - + Button delete = new Button(Translator.translate("Delete")); delete.addClassName("delete"); delete.addClickListener(e -> { @@ -157,7 +157,7 @@ private void populateGrid(VerticalLayout catGrid2, List presentationCa updateValue(); }); delete.getStyle().set("margin-left", "2em"); - + if (pc.getMaximumWeight() <= 998) { hl.add(delete); } diff --git a/owlcms/src/main/java/app/owlcms/components/fields/CategoryListField.java b/owlcms/src/main/java/app/owlcms/components/fields/CategoryListField.java index ac58186c32..bceadf8e67 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/CategoryListField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/CategoryListField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/DurationField.java b/owlcms/src/main/java/app/owlcms/components/fields/DurationField.java index 175f96525b..2eb580b97e 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/DurationField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/DurationField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/GridField.java b/owlcms/src/main/java/app/owlcms/components/fields/GridField.java index 43832fc879..840f36fda1 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/GridField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/GridField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/LocalDateField.java b/owlcms/src/main/java/app/owlcms/components/fields/LocalDateField.java index 246971121e..6d7990be87 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/LocalDateField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/LocalDateField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimeField.java b/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimeField.java index f7e07d172d..206ae2f4e6 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimeField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimeField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimePicker.java b/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimePicker.java index 43808dcc62..8a54e5a0da 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimePicker.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/LocalDateTimePicker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/LocalizedDecimalField.java b/owlcms/src/main/java/app/owlcms/components/fields/LocalizedDecimalField.java index 900d2e8341..f5842d6c59 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/LocalizedDecimalField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/LocalizedDecimalField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/LocalizedIntegerField.java b/owlcms/src/main/java/app/owlcms/components/fields/LocalizedIntegerField.java index 5736584bc4..b76fbacc48 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/LocalizedIntegerField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/LocalizedIntegerField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/components/fields/ValidationTextField.java b/owlcms/src/main/java/app/owlcms/components/fields/ValidationTextField.java index 501c6f3f15..90cb5e090f 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/ValidationTextField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/ValidationTextField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -11,8 +11,8 @@ /** * Absolutely horrible workaround for validations. * - * Validations in user mode correctly sets the invalid flag, but something unknown causes a second property change event - * to be triggered, which resets the invalid indicator on the text field.¸ + * Validations in user mode correctly sets the invalid flag, but something unknown causes a second property change event to be triggered, which resets the + * invalid indicator on the text field.¸ * * We have no idea why that is. * diff --git a/owlcms/src/main/java/app/owlcms/components/fields/ValidationUtils.java b/owlcms/src/main/java/app/owlcms/components/fields/ValidationUtils.java index a2dcdcc0f2..67b71fe5b7 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/ValidationUtils.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/ValidationUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -44,9 +44,8 @@ public static Validator checkUsingException(SerializablePredicate guar } /** - * Builds a validator out of a conditional function and an error message If the function returns true, the validator - * returns {@code Result.ok()}; if it returns false or throws an exception, {@code Result.error()} is returned with - * the message from the exception using getLocalizedMessage(). + * Builds a validator out of a conditional function and an error message If the function returns true, the validator returns {@code Result.ok()}; if it + * returns false or throws an exception, {@code Result.error()} is returned with the message from the exception using getLocalizedMessage(). * * @param the value type * @param guard the function used to validate, not null @@ -91,7 +90,7 @@ public static Validator checkUsingException2(SerializablePredicate gua } }; } - + public static Validator nonNullValidator(String errorMessage) { return (value, context) -> { if (value != null) { diff --git a/owlcms/src/main/java/app/owlcms/components/fields/WrappedTextField.java b/owlcms/src/main/java/app/owlcms/components/fields/WrappedTextField.java index 31ffcd9352..feef175ff5 100644 --- a/owlcms/src/main/java/app/owlcms/components/fields/WrappedTextField.java +++ b/owlcms/src/main/java/app/owlcms/components/fields/WrappedTextField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -24,8 +24,8 @@ /** * Common base for creating fields that parse text to obtain a value. * - * Subclasses define a converter and a renderer. This parent class uses a TextField to display and read the - * corresponding text. Typical use of a subclass of this class is as follows + * Subclasses define a converter and a renderer. This parent class uses a TextField to display and read the corresponding text. Typical use of a subclass of + * this class is as follows * *
  * LocalDateField f = ((LocalDateField) field);
@@ -33,8 +33,8 @@
  * binder.forField(f).withValidator(fv).bind(property);
  * 
* - * In the example, validator fv is the most basic validation -- the content of the field was syntactically legal and was - * converted successfully into a value. Additional semantic validations can of course be chained after fv. + * In the example, validator fv is the most basic validation -- the content of the field was syntactically legal and was converted successfully into a value. + * Additional semantic validations can of course be chained after fv. * * @author Jean-François Lamy * @@ -189,10 +189,9 @@ protected void logConversionError(String e) { /** * Keep parsing result for use during validation. * - * Binder validates converted values, it does not convert again from the field content. So if an ill-formed syntax - * is used, the field value is not updated, and the original valid value is still present. So no error is shown to - * the user. In order to show the error, we memorize the last parsing status and we systematically use the - * {@link #formatValidation(Locale)} validator when binding a field. + * Binder validates converted values, it does not convert again from the field content. So if an ill-formed syntax is used, the field value is not updated, + * and the original valid value is still present. So no error is shown to the user. In order to show the error, we memorize the last parsing status and we + * systematically use the {@link #formatValidation(Locale)} validator when binding a field. * * @param valid * @param locale diff --git a/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroup.java b/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroup.java index 86674e1bc9..72d1e297c1 100644 --- a/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroup.java +++ b/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroup.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -242,6 +242,14 @@ public String getAgeDivision() { return this.ageDivision; } + @Transient + @JsonIgnore + public String getAgeFirstSortCode() { + String core = scoreCodeCore(); + String result = core + "_" + this.gender.ordinal(); + return result; + } + @JsonIgnore public List getAllCategories() { return this.categories; @@ -318,6 +326,15 @@ public Gender getGender() { return this.gender; } + @Transient + @JsonIgnore + public String getGenderFirstSortCode() { + // all women before all men + String core = scoreCodeCore(); + String result = this.gender.ordinal() + "_" + core; + return result; + } + public Long getId() { return this.id; } @@ -424,6 +441,19 @@ public void removeCategory(Category category) { } } + public String scoreCodeCore() { + // younger group firsts (max age) + // 15-20 should come before 17-20 (min age) + // but 85-999 must come before 0-999 + // then with categories before no categories (score medals last within an age range) + Integer maxAge2 = this.getMaxAge(); + Integer minAge2 = this.getMinAge(); + String core = String.format("%03d", maxAge2) + + "_" + String.format("%03d", maxAge2 >= 900 ? maxAge2 : minAge2) + + "_" + String.format("%03d", 999 - this.getCategories().size()); + return core; + } + public void setActive(boolean active) { this.active = active; } @@ -432,6 +462,11 @@ public void setAgeDivision(String ageDivision) { this.ageDivision = ageDivision; } + @Transient + @JsonIgnore + public void setAgeFirstSortCode(String ignored) { + } + public void setAlreadyGendered(boolean b) { this.alreadyGendered = b; } @@ -463,6 +498,11 @@ public void setGender(Gender gender) { this.gender = gender; } + @Transient + @JsonIgnore + public void setGenderFirstSortCode(String ignored) { + } + public void setKey(String key) { // do nothing, this is to fool Json deserialization. } @@ -498,44 +538,4 @@ private String getTranslatedCode(String code2) { // return translatedCode != null ? translatedCode : code2; return code2; } - - @Transient - @JsonIgnore - public String getAgeFirstSortCode() { - String core = scoreCodeCore(); - String result = core + "_" + gender.ordinal(); - return result; - } - - @Transient - @JsonIgnore - public void setAgeFirstSortCode(String ignored) { - } - - @Transient - @JsonIgnore - public String getGenderFirstSortCode() { - // all women before all men - String core = scoreCodeCore(); - String result = gender.ordinal() + "_" + core; - return result; - } - - public String scoreCodeCore() { - // younger group firsts (max age) - // 15-20 should come before 17-20 (min age) - // but 85-999 must come before 0-999 - // then with categories before no categories (score medals last within an age range) - Integer maxAge2 = this.getMaxAge(); - Integer minAge2 = this.getMinAge(); - String core = String.format("%03d", maxAge2) - + "_" + String.format("%03d", maxAge2 >= 900 ? maxAge2 : minAge2) - + "_" + String.format("%03d", 999-this.getCategories().size()); - return core; - } - - @Transient - @JsonIgnore - public void setGenderFirstSortCode(String ignored) { - } } diff --git a/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupDefinitionReader.java b/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupDefinitionReader.java index ae8c103986..06145dc0f6 100644 --- a/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupDefinitionReader.java +++ b/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupDefinitionReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -42,6 +42,7 @@ public class AgeGroupDefinitionReader { private static final String AGE_GROUP_SCORING_HEADER = "agegroupscoring"; private static Logger logger = (Logger) LoggerFactory.getLogger(AgeGroupDefinitionReader.class); + static DataFormatter formatter = new DataFormatter(); public static void doInsertRobiAndAgeGroups(InputStream ageGroupStream) { Logger mainLogger = Main.getStartupLogger(); @@ -226,46 +227,6 @@ static void createAgeGroups(Workbook workbook, Map templates, }); } - private static void reportError(int iRow, int iColumn, String cellValue, Exception e) { - String msg = MessageFormat.format( - "cannot process cell {0} (content = \"{1}\") {2}", - cellName(iColumn, iRow), cellValue, e); - logger.error(msg); - if (UI.getCurrent() != null) { - NotificationUtils.errorNotification(msg); - } - } - - static DataFormatter formatter = new DataFormatter(); - - private static boolean getSafeBooleanValue(Cell cell) { - try { - return cell.getBooleanCellValue(); - } catch (IllegalStateException e) { - if (cell.getCellType() == CellType.NUMERIC) { - String strValue = formatter.formatCellValue(cell); - return strValue.equalsIgnoreCase("true"); - } else { - logger.error("cannot extract string from cell {}", cell.getAddress()); - throw new IllegalStateException("cannot extract boolean from cell " + cell.getAddress()); - } - } - } - - private static String safeGetTextValue(Cell cell) { - try { - return cell.getStringCellValue(); - } catch (IllegalStateException e) { - if (cell.getCellType() == CellType.NUMERIC) { - String strValue = formatter.formatCellValue(cell); - return strValue; - } else { - logger.error("cannot extract string from cell {}", cell.getAddress()); - throw new IllegalStateException("cannot extract string from cell " + cell.getAddress()); - } - } - } - static void doInsertRobiAndAgeGroups(EnumSet forcedInsertion, String localizedFileName) { Logger mainLogger = Main.getStartupLogger(); Map templates = loadRobi(mainLogger); @@ -288,6 +249,20 @@ private static InputStream findAgeGroupFile(String localizedFileName, Logger mai return ageGroupStream; } + private static boolean getSafeBooleanValue(Cell cell) { + try { + return cell.getBooleanCellValue(); + } catch (IllegalStateException e) { + if (cell.getCellType() == CellType.NUMERIC) { + String strValue = formatter.formatCellValue(cell); + return strValue.equalsIgnoreCase("true"); + } else { + logger.error("cannot extract string from cell {}", cell.getAddress()); + throw new IllegalStateException("cannot extract boolean from cell " + cell.getAddress()); + } + } + } + private static void loadAgeGroupStream(EnumSet forcedInsertion, String localizedName, Logger mainLogger, Map templates, InputStream localizedResourceAsStream1) { @@ -319,4 +294,28 @@ private static Map loadRobi(Logger mainLogger) { return templates; } + private static void reportError(int iRow, int iColumn, String cellValue, Exception e) { + String msg = MessageFormat.format( + "cannot process cell {0} (content = \"{1}\") {2}", + cellName(iColumn, iRow), cellValue, e); + logger.error(msg); + if (UI.getCurrent() != null) { + NotificationUtils.errorNotification(msg); + } + } + + private static String safeGetTextValue(Cell cell) { + try { + return cell.getStringCellValue(); + } catch (IllegalStateException e) { + if (cell.getCellType() == CellType.NUMERIC) { + String strValue = formatter.formatCellValue(cell); + return strValue; + } else { + logger.error("cannot extract string from cell {}", cell.getAddress()); + throw new IllegalStateException("cannot extract string from cell " + cell.getAddress()); + } + } + } + } diff --git a/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupRepository.java b/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupRepository.java index 4523e0236c..8d82d6cca6 100644 --- a/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupRepository.java +++ b/owlcms/src/main/java/app/owlcms/data/agegroup/AgeGroupRepository.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -65,10 +65,9 @@ public static AgeGroup add(AgeGroup ageGroup) { return nAgeGroup; } - public static List allChampionshipsForAllAgeGroups() { + public static List allActiveChampionshipsNames(boolean activeOnly) { List ageGroups = JPAService.runInTransaction((em) -> { TypedQuery q = em.createQuery( - // "select ag from Participation p join p.category c join c.ageGroup ag", "select ag from AgeGroup ag", AgeGroup.class); List resultSet = q.getResultList(); @@ -76,20 +75,21 @@ public static List allChampionshipsForAllAgeGroups() { }); TreeSet ts = new TreeSet<>(); for (AgeGroup ag : ageGroups) { - if (ag.computeChampionshipName() != null && !ag.computeChampionshipName().isBlank()) { - ts.add(ag.computeChampionshipName() + "¤" + ag.getAgeDivision()); - } else if (ag.getAgeDivision() != null) { - ts.add(ag.getAgeDivision()); - } else { - logger.error("{} {} {}", ag.getId(), ag.code, ag.computeChampionshipName(), ag.getCategoriesAsString()); + if (!activeOnly || ag.isActive()) { + if (ag.computeChampionshipName() != null && !ag.computeChampionshipName().isBlank()) { + ts.add(ag.computeChampionshipName()); + } else { + ts.add(ag.getAgeDivision()); + } } } return new ArrayList<>(ts); } - public static List allActiveChampionshipsNames(boolean activeOnly) { + public static List allChampionshipsForAllAgeGroups() { List ageGroups = JPAService.runInTransaction((em) -> { TypedQuery q = em.createQuery( + // "select ag from Participation p join p.category c join c.ageGroup ag", "select ag from AgeGroup ag", AgeGroup.class); List resultSet = q.getResultList(); @@ -97,12 +97,12 @@ public static List allActiveChampionshipsNames(boolean activeOnly) { }); TreeSet ts = new TreeSet<>(); for (AgeGroup ag : ageGroups) { - if (!activeOnly || ag.isActive()) { - if (ag.computeChampionshipName() != null && !ag.computeChampionshipName().isBlank()) { - ts.add(ag.computeChampionshipName()); - } else { - ts.add(ag.getAgeDivision()); - } + if (ag.computeChampionshipName() != null && !ag.computeChampionshipName().isBlank()) { + ts.add(ag.computeChampionshipName() + "¤" + ag.getAgeDivision()); + } else if (ag.getAgeDivision() != null) { + ts.add(ag.getAgeDivision()); + } else { + logger.error("{} {} {}", ag.getId(), ag.code, ag.computeChampionshipName(), ag.getCategoriesAsString()); } } return new ArrayList<>(ts); @@ -283,26 +283,6 @@ public static AgeGroup doFindByName(String name, EntityManager em) { return ag; } - private static AgeGroup fixAg(AgeGroup ag) { - if (ag.getChampionshipType() == ChampionshipType.MASTERS) { - ag.setAlreadyGendered(true); - } - if (ag.getCode().startsWith("!")) { - ag.setCode(ag.getCode().substring(1)); - ag.setAlreadyGendered(true); - } - return ag; - } - - // /** - // * @return active categories - // */ - // private static List findActive() { - // List findFiltered = findFiltered((String) null, (Gender) null, (Championship) null, (Integer) null, - // true, -1, -1); - // return findFiltered.stream().map(ag -> fixAg(ag)).collect(Collectors.toList()); - // } - public static List findActiveAndUsedAgeGroupNames(Championship championship) { return JPAService.runInTransaction((em) -> { if (championship == null) { @@ -322,6 +302,15 @@ public static List findActiveAndUsedAgeGroupNames(Championship champions }); } + // /** + // * @return active categories + // */ + // private static List findActive() { + // List findFiltered = findFiltered((String) null, (Gender) null, (Championship) null, (Integer) null, + // true, -1, -1); + // return findFiltered.stream().map(ag -> fixAg(ag)).collect(Collectors.toList()); + // } + /** * Fetch all age groups present in the current group * @@ -458,7 +447,7 @@ public static void reloadDefinitions(String localizedFileName) { * * @param AgeGroup the group * @return the group - * @throws AssignedAthletesException + * @throws AssignedAthletesException */ public static AgeGroup save(AgeGroup ageGroup) throws AssignedAthletesException { AgeGroup existing = JPAService.runInTransaction(em -> { @@ -471,24 +460,23 @@ public static AgeGroup save(AgeGroup ageGroup) throws AssignedAthletesException return ag; }); - boolean needCleanUp = - !ageGroup.getCode().equals(existing.getCode()) - || !ageGroup.getMinAge().equals(existing.getMinAge()) + boolean needCleanUp = !ageGroup.getCode().equals(existing.getCode()) + || !ageGroup.getMinAge().equals(existing.getMinAge()) || !ageGroup.getMaxAge().equals(existing.getMaxAge()) || ageGroup.getGender() != existing.getGender() || existing.reassignmentHashCode() != ageGroup.reassignmentHashCode(); - ; - List assignedAthletes = AthleteRepository.findAthletesForAgeGroup(ageGroup); - + + List assignedAthletes = AthleteRepository.findAthletesForAgeGroup(ageGroup); + if (needCleanUp) { - boolean empty = assignedAthletes.isEmpty(); + boolean empty = assignedAthletes.isEmpty(); Boolean forceSave = ageGroup.getForceSave(); - //logger.debug("empty {} needCleanup {} isForcedSave {}", empty, needCleanUp, forceSave); + // logger.debug("empty {} needCleanup {} isForcedSave {}", empty, needCleanUp, forceSave); if (!empty && forceSave == null) { - logger.info("athletes present in age group {} need confirmation", ageGroup); - throw new AssignedAthletesException(); - } - + logger.info("athletes present in age group {} need confirmation", ageGroup); + throw new AssignedAthletesException(); + } + if (forceSave != null && !forceSave) { logger.info("not saving age group {}", ageGroup); return ageGroup; @@ -522,7 +510,20 @@ public static AgeGroup save(AgeGroup ageGroup) throws AssignedAthletesException return nAgeGroup; } + } + public static void updateExistingChampionships() { + JPAService.runInTransaction(em -> { + List ags = doFindAll(em); + for (AgeGroup a : ags) { + if (a.computeChampionshipName() == null || a.computeChampionshipName().isBlank()) { + a.setChampionshipName(a.getAgeDivision()); + } + em.merge(a); + } + em.flush(); + return null; + }); } static void cascadeCategoryRemoval(EntityManager em, AgeGroup mAgeGroup, Category nc) { @@ -654,20 +655,6 @@ private static void cleanUpExisting() { }); } - public static void updateExistingChampionships() { - JPAService.runInTransaction(em -> { - List ags = doFindAll(em); - for (AgeGroup a : ags) { - if (a.computeChampionshipName() == null || a.computeChampionshipName().isBlank()) { - a.setChampionshipName(a.getAgeDivision()); - } - em.merge(a); - } - em.flush(); - return null; - }); - } - @SuppressWarnings("unchecked") private static List doFindAll(EntityManager em) { return em.createQuery("select c from AgeGroup c order by c.ageDivision,c.minAge,c.maxAge").getResultList(); @@ -707,6 +694,17 @@ private static String filteringWhere(String name, Championship championship, Int } } + private static AgeGroup fixAg(AgeGroup ag) { + if (ag.getChampionshipType() == ChampionshipType.MASTERS) { + ag.setAlreadyGendered(true); + } + if (ag.getCode().startsWith("!")) { + ag.setCode(ag.getCode().substring(1)); + ag.setAlreadyGendered(true); + } + return ag; + } + private static void setFilteringParameters(String name, Gender gender, Championship championship, Integer age, Boolean active, Query query) { if (name != null && name.trim().length() > 0) { diff --git a/owlcms/src/main/java/app/owlcms/data/agegroup/AssignedAthletesException.java b/owlcms/src/main/java/app/owlcms/data/agegroup/AssignedAthletesException.java index a9d30e22f9..9c6a85abe7 100644 --- a/owlcms/src/main/java/app/owlcms/data/agegroup/AssignedAthletesException.java +++ b/owlcms/src/main/java/app/owlcms/data/agegroup/AssignedAthletesException.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.agegroup; @SuppressWarnings("serial") diff --git a/owlcms/src/main/java/app/owlcms/data/agegroup/Championship.java b/owlcms/src/main/java/app/owlcms/data/agegroup/Championship.java index b39ab5a760..8d0fb90292 100644 --- a/owlcms/src/main/java/app/owlcms/data/agegroup/Championship.java +++ b/owlcms/src/main/java/app/owlcms/data/agegroup/Championship.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -55,6 +55,17 @@ public class Championship implements Comparable { return compare; }; + public static Championship addChampionship(String nameString, ChampionshipType u2) { + Championship championship = allChampionshipsMap.get(nameString.toLowerCase()); + if (championship == null) { + Championship newChampionship = new Championship(nameString, u2); + allChampionshipsMap.put(nameString.toLowerCase(), + newChampionship); + return newChampionship; + } + return championship; + } + /** * Find all. * @@ -105,17 +116,6 @@ public static List findAll() { return allChampionshipsList; } - public static Championship addChampionship(String nameString, ChampionshipType u2) { - Championship championship = allChampionshipsMap.get(nameString.toLowerCase()); - if (championship == null) { - Championship newChampionship = new Championship(nameString, u2); - allChampionshipsMap.put(nameString.toLowerCase(), - newChampionship); - return newChampionship; - } - return championship; - } - public static List findAllUsed(boolean activeOnly) { var results = new ArrayList(); findAll(); @@ -142,21 +142,39 @@ static public Championship getChampionshipFromName(String name) { return value; } + public static Map getMap() { + return allChampionshipsMap; + } + public static Championship of(String championshipName) { if (allChampionshipsMap == null) { findAll(); } if (championshipName == null) { - return new Championship("",ChampionshipType.U); + return new Championship("", ChampionshipType.U); } return allChampionshipsMap.get(championshipName.toLowerCase()); } + public static Championship ofType(ChampionshipType t) { + // return first championship of the type + // we use reverse order to get Open and Senior and U20 first. + Optional found = allChampionshipsMap.values().stream().sorted(Comparator.reverseOrder()).filter(v -> v.getType() == t).findFirst(); + return found.isPresent() ? found.get() : null; + } + + public static void remove(Championship c) { + allChampionshipsMap.remove(c.name.toLowerCase()); + } + public static void reset() { allChampionshipsMap = null; findAll(); } + public static void update(Championship c) { + } + private String name; private ChampionshipType type; @@ -192,42 +210,24 @@ public boolean isDefault() { return this.getType() == ChampionshipType.DEFAULT; } - public void setType(ChampionshipType type) { - this.type = type; - } - - public String translate() { - String tr = Translator.translateOrElseNull("Championship." + getName(), OwlcmsSession.getLocale()); - return tr != null ? tr : getName(); - } - - @Override - public String toString() { - return "Championship [name=" + name + ", type=" + type + "]"; - } - - public static Map getMap() { - return allChampionshipsMap; - } - - public static void update(Championship c) { - } - public void setName(String name) { allChampionshipsMap.remove(this.name.toLowerCase()); this.name = name; allChampionshipsMap.put(this.name.toLowerCase(), this); } - public static void remove(Championship c) { - allChampionshipsMap.remove(c.name.toLowerCase()); + public void setType(ChampionshipType type) { + this.type = type; } - public static Championship ofType(ChampionshipType t) { - // return first championship of the type - // we use reverse order to get Open and Senior and U20 first. - Optional found = allChampionshipsMap.values().stream().sorted(Comparator.reverseOrder()).filter(v -> v.getType() == t).findFirst(); - return found.isPresent() ? found.get() : null; + @Override + public String toString() { + return "Championship [name=" + this.name + ", type=" + this.type + "]"; + } + + public String translate() { + String tr = Translator.translateOrElseNull("Championship." + getName(), OwlcmsSession.getLocale()); + return tr != null ? tr : getName(); } } diff --git a/owlcms/src/main/java/app/owlcms/data/agegroup/ChampionshipType.java b/owlcms/src/main/java/app/owlcms/data/agegroup/ChampionshipType.java index 6c093e1c77..a28fbef5e6 100644 --- a/owlcms/src/main/java/app/owlcms/data/agegroup/ChampionshipType.java +++ b/owlcms/src/main/java/app/owlcms/data/agegroup/ChampionshipType.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.agegroup; public enum ChampionshipType { diff --git a/owlcms/src/main/java/app/owlcms/data/athlete/Athlete.java b/owlcms/src/main/java/app/owlcms/data/athlete/Athlete.java index 02eb618b30..c4af728460 100644 --- a/owlcms/src/main/java/app/owlcms/data/athlete/Athlete.java +++ b/owlcms/src/main/java/app/owlcms/data/athlete/Athlete.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -109,8 +109,6 @@ @JsonIgnoreProperties(ignoreUnknown = true, value = { "hibernateLazyInitializer", "logger" }) @JsonPropertyOrder({ "id", "participations", "category" }) public class Athlete { - @Transient - protected final Logger logger = (Logger) LoggerFactory.getLogger(Athlete.class); @Transient @JsonIgnore private static QPoints qPoints = new QPoints(2023); @@ -279,6 +277,8 @@ public static int zeroIfInvalid(String value) { } } + @Transient + protected final Logger logger = (Logger) LoggerFactory.getLogger(Athlete.class); /** * We cannot always rely on the session to be present and give us a valid Fop. LoadGroup should set the Fop. */ @@ -546,6 +546,27 @@ public void clearLifts() { } } + /** + * Gets the custom score. + * + * @return the custom score + */ + @Transient + @JsonIgnore + public Double computedCategoryScore() { + AgeGroup ageGroup = getAgeGroup(); + if (ageGroup == null) { + return 0.0; + } + Ranking scoringSystem = ageGroup.getComputedScoringSystem(); + // logger.debug("{} {} {}", this.getLastName(), scoringSystem, Ranking.getRankingValue(this, scoringSystem)); + if (scoringSystem != null) { + return Ranking.getRankingValue(this, scoringSystem); + } else { + return 0.0; + } + } + public void computeMainAndEligibleCategories() { Double weight = this.getBodyWeight(); Integer age = this.getAge(); @@ -572,6 +593,31 @@ public void computeMainAndEligibleCategories() { } } + /** + * for an Athlete, this will be the participation to the registration category + * + * for a PAthlete, this will be the participation to the PAthlete's category. A PAthlete only has one registration. + */ + public void computeMainRankings() { + // needs to be called in setParticipations and setCategory. + Participation curRankings = null; + List participations2 = getParticipations(); + // logger.trace("athlete {} category {} participations {}", this, category, + // participations2); + for (Participation eligible : participations2) { + Category eligibleCat = eligible.getCategory(); + if (this.category != null && eligibleCat != null) { + String eligibleCode = eligibleCat.getComputedCode(); + String catCode = this.category.getComputedCode(); + if (StringUtils.equals(eligibleCode, catCode)) { + curRankings = eligible; + break; + } + } + } + setMainRankings(curRankings); + } + /** * used for jury overrides and for testing * @@ -633,7 +679,7 @@ public void enforceCategoryIsEligible() { } } setCategory(matchingEligible); - logger.trace("category {} {} matching eligible {} {}", this.category, + this.logger.trace("category {} {} matching eligible {} {}", this.category, System.identityHashCode(this.category), matchingEligible, System.identityHashCode(matchingEligible)); } @@ -697,7 +743,7 @@ public Integer getActualLift(int liftNo) { String value = getActualLiftStringOrElseNull(liftNo); return value == null ? 0 : Integer.valueOf(value); } catch (NumberFormatException e) { - LoggerUtils.logError(logger, e); + LoggerUtils.logError(this.logger, e); return 0; } } @@ -709,7 +755,7 @@ public Integer getActualLiftOrNull(int liftNo) { String value = getActualLiftStringOrElseNull(liftNo); return value == null ? null : Integer.valueOf(value); } catch (NumberFormatException e) { - LoggerUtils.logError(logger, e); + LoggerUtils.logError(this.logger, e); return null; } } @@ -869,24 +915,6 @@ public String getAllCategoriesAsString() { } } - @Transient - @JsonIgnore - public String getSortedCategoriesAsString() { - String eligiblesAsString = this.getParticipations().stream() - .sorted((a, b) -> a.getCategory().getMedalingSortCode().compareTo(b.getCategory().getMedalingSortCode())) - .map(p -> { - String catName = p.getCategory().getDisplayName(); - return catName + (!p.getTeamMember() ? RAthlete.NoTeamMarker : ""); - }) - .collect(Collectors.joining(";")); - return eligiblesAsString; - } - - @Transient - @JsonIgnore - public void setSortedCategoriesAsString() { - } - /** * Number of attempt 1..3, relative to current lift * @@ -1149,20 +1177,6 @@ public String getCategoryCode() { return this.category != null ? this.getCategory().getCode() : "-"; } - @Transient - @JsonIgnore - public String getCategorySortCode() { - // TODO: something that reflects age boundaries then weight, considering no-age and no-weight score based. - // maybe championship age-low age-high body-low body-high - Category sortCategory = getMainRankings().getCategory(); - String sortCode = sortCategory != null ? sortCategory.getSortCode() : "-"; - // logger.debug("a {} category {} sortCode {}", getAbbreviatedName(), getCategory(), sortCategory.getSortCode()); - return sortCode; - } - - public void setCategoryScoreCode(String unused) { - } - @Transient @JsonIgnore public Boolean getCategoryFinished() { @@ -1173,8 +1187,14 @@ public Boolean getCategoryFinished() { @Transient @JsonIgnore - public Boolean isCategoryFinished() { - return getCategoryFinished(); + public Double getCategoryScore() { + Double computedScore = computedCategoryScore(); + // logger.debug("{} getCategoryScore {}", this.getClass().getSimpleName(), this.getCategoryCode(), computedScore); + return computedScore; + } + + public int getCategoryScoreRank() { + return (getMainRankings() != null ? getMainRankings().getCategoryScoreRank() : -1); } /** @@ -1213,6 +1233,17 @@ public Double getCategorySinclair() { return getSinclair(categoryWeight); } + @Transient + @JsonIgnore + public String getCategorySortCode() { + // TODO: something that reflects age boundaries then weight, considering no-age and no-weight score based. + // maybe championship age-low age-high body-low body-high + Category sortCategory = getMainRankings().getCategory(); + String sortCode = sortCategory != null ? sortCategory.getSortCode() : "-"; + // logger.debug("a {} category {} sortCode {}", getAbbreviatedName(), getCategory(), sortCategory.getSortCode()); + return sortCode; + } + /** * Gets the sinclair factor. * @@ -1527,6 +1558,22 @@ public int getCombinedRank() { return this.combinedRank; } + public Ranking getComputedScoringSystem() { + var category2 = this.getCategory(); + if (category2 == null) { + return Ranking.TOTAL; + } + var group2 = category2.getAgeGroup(); + if (group2 == null) { + return Ranking.TOTAL; + } + var css = group2.getComputedScoringSystem(); + if (css == null) { + return Ranking.TOTAL; + } + return css; + } + @Transient @JsonIgnore public int getCumulativeAttemptProgression(int attempt) { @@ -1657,35 +1704,6 @@ public Double getCustomScore() { return this.customScore; } - @Transient - @JsonIgnore - public Double getCategoryScore() { - Double computedScore = computedCategoryScore(); - // logger.debug("{} getCategoryScore {}", this.getClass().getSimpleName(), this.getCategoryCode(), computedScore); - return computedScore; - } - - /** - * Gets the custom score. - * - * @return the custom score - */ - @Transient - @JsonIgnore - public Double computedCategoryScore() { - AgeGroup ageGroup = getAgeGroup(); - if (ageGroup == null) { - return 0.0; - } - Ranking scoringSystem = ageGroup.getComputedScoringSystem(); - // logger.debug("{} {} {}", this.getLastName(), scoringSystem, Ranking.getRankingValue(this, scoringSystem)); - if (scoringSystem != null) { - return Ranking.getRankingValue(this, scoringSystem); - } else { - return 0.0; - } - } - /** * Gets the display category. * @@ -1718,7 +1736,7 @@ public Set getEligibleCategories() { List cats = getParticipations().stream() .map(p -> p.getCategory()) .sorted(Category.medalingComparator()) - //.peek(c -> logger.debug("{} {}", c, c.getMedalingSortCode())) + // .peek(c -> logger.debug("{} {}", c, c.getMedalingSortCode())) .toList(); s.addAll(cats); return s; @@ -1997,7 +2015,7 @@ public Integer getLiftOrderRank() { @Transient @JsonIgnore public Logger getLogger() { - return logger; + return this.logger; } /** @@ -2027,31 +2045,6 @@ public Participation getMainRankings() { return this.mainRankings; } - /** - * for an Athlete, this will be the participation to the registration category - * - * for a PAthlete, this will be the participation to the PAthlete's category. A PAthlete only has one registration. - */ - public void computeMainRankings() { - // needs to be called in setParticipations and setCategory. - Participation curRankings = null; - List participations2 = getParticipations(); - // logger.trace("athlete {} category {} participations {}", this, category, - // participations2); - for (Participation eligible : participations2) { - Category eligibleCat = eligible.getCategory(); - if (this.category != null && eligibleCat != null) { - String eligibleCode = eligibleCat.getComputedCode(); - String catCode = this.category.getComputedCode(); - if (StringUtils.equals(eligibleCode, catCode)) { - curRankings = eligible; - break; - } - } - } - setMainRankings(curRankings); - } - /** * Get the age group. mastersAgeGroup is a misnomer. * @@ -2294,6 +2287,16 @@ public int getqAgeRank() { return this.qAgeRank; } + @Transient + @JsonIgnore + public Float getQMastersFactor() { + final Integer birthDate1 = getYearOfBirth(); + if (birthDate1 == null) { + return 0.0F; + } + return qPoints.getAgeGenderCoefficient(YEAR - birthDate1, getGender()); + } + @Transient @JsonIgnore public Double getqPoints() { @@ -2406,6 +2409,10 @@ public Integer getRequestedWeightForAttempt(int attempt) { return 0; } + public String getRequiredInitialAttempts() { + return Integer.toString(Math.round(this.getEntryTotal() - getStartingTotalMargin(this.getCategory(), this.getEntryTotal()))); + } + /** * Gets the robi. In a multiple age group competition, the Robi shown in the final package will depend on the age group * @@ -2588,16 +2595,6 @@ public Float getSmhfFactor() { } return sinclairProperties2020.getAgeGenderCoefficient(YEAR - birthDate1, getGender()); } - - @Transient - @JsonIgnore - public Float getQMastersFactor() { - final Integer birthDate1 = getYearOfBirth(); - if (birthDate1 == null) { - return 0.0F; - } - return qPoints.getAgeGenderCoefficient(YEAR - birthDate1, getGender()); - } /** * Gets the smm. @@ -2891,6 +2888,19 @@ public int getSnatchTotal() { return snatchTotal; } + @Transient + @JsonIgnore + public String getSortedCategoriesAsString() { + String eligiblesAsString = this.getParticipations().stream() + .sorted((a, b) -> a.getCategory().getMedalingSortCode().compareTo(b.getCategory().getMedalingSortCode())) + .map(p -> { + String catName = p.getCategory().getDisplayName(); + return catName + (!p.getTeamMember() ? RAthlete.NoTeamMarker : ""); + }) + .collect(Collectors.joining(";")); + return eligiblesAsString; + } + /** * Gets the start number. * @@ -3037,10 +3047,6 @@ public int getTotalRank() { return (getMainRankings() != null ? getMainRankings().getTotalRank() : -1); } - public int getCategoryScoreRank() { - return (getMainRankings() != null ? getMainRankings().getCategoryScoreRank() : -1); - } - /** * Gets the year of birth. * @@ -3074,6 +3080,12 @@ public boolean isATeamMember() { return isEligibleForTeamRanking(); } + @Transient + @JsonIgnore + public Boolean isCategoryFinished() { + return getCategoryFinished(); + } + public boolean isCheckTiming() { return this.checkTiming; } @@ -3282,7 +3294,7 @@ public void removeEligibleCategory(Category category) { Category category2 = participation.getCategory(); boolean categoryEqual = sameCategory(category, category2); if (athleteEqual && categoryEqual) { - logger.trace("removeCategory removing {} {}", category, participation); + this.logger.trace("removeCategory removing {} {}", category, participation); iterator.remove(); if (category2 != null) { category2.getParticipations().remove(participation); @@ -3290,7 +3302,7 @@ public void removeEligibleCategory(Category category) { participation.setAthlete(null); participation.setCategory(null); } else { - logger.trace("removeCategory skipping {} {} {} {} {}", this, athleteEqual, participation, category, + this.logger.trace("removeCategory skipping {} {} {} {} {}", this, athleteEqual, participation, category, categoryEqual); } } @@ -3389,6 +3401,15 @@ public void setCategoryFinished(Boolean done) { // no-op, computed. } + public void setCategoryScoreCode(String unused) { + } + + @Transient + @JsonIgnore + public void setCategoryScoreRank(int ignored) { + // ignored. computed property. setter needed for beans introspection. + } + public void setCatSinclairRank(int i) { this.catSinclairRank = i; } @@ -3604,6 +3625,11 @@ public void setCleanJerk3ActualLift(String cleanJerk3ActualLift) { cleanJerk3ActualLift); } + /* + * General event framework: we implement the com.vaadin.event.MethodEventSource interface which defines how a notifier can call a method on a listener to + * signal that an event has occurred, and how the listener can register/unregister itself. + */ + /** * Sets the clean jerk 3 automatic progression. * @@ -3633,11 +3659,6 @@ public void setCleanJerk3Change1(String cleanJerk3Change1) { cleanJerk3Change1); } - /* - * General event framework: we implement the com.vaadin.event.MethodEventSource interface which defines how a notifier can call a method on a listener to - * signal that an event has occurred, and how the listener can register/unregister itself. - */ - /** * Sets the clean jerk 3 change 2. * @@ -3865,6 +3886,13 @@ public void setGroup(Group group) { this.group = group; } + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + /** * Sets the last name. * @@ -3896,6 +3924,10 @@ public void setLotNumber(Integer lotNumber) { this.lotNumber = lotNumber; } + public void setMainRankings(Participation mainRankings) { + this.mainRankings = mainRankings; + } + /** * Sets the membership. * @@ -4301,6 +4333,11 @@ public void setSnatchRank(int ignored) { // ignored. computed property. setter needed for beans introspection. } + @Transient + @JsonIgnore + public void setSortedCategoriesAsString() { + } + public void setStartingTotalViolation(boolean startingTotalViolation) { this.startingTotalViolation = startingTotalViolation; } @@ -4422,12 +4459,6 @@ public void setTotalRank(int ignored) { // ignored. computed property. setter needed for beans introspection. } - @Transient - @JsonIgnore - public void setCategoryScoreRank(int ignored) { - // ignored. computed property. setter needed for beans introspection. - } - public void setValidation(boolean validation) { this.validation = validation; } @@ -4538,6 +4569,27 @@ public void validateActualLift(int curLift, String automaticProgression, String } } + // @SuppressWarnings("unused") + // private Long getCopyId() { + // return copyId; + // } + + // @SuppressWarnings("unused") + // private Integer getDeclaredAndActuallyAttempted(Integer... items) { + // int lastIndex = items.length - 1; + // if (items.length == 0) { + // return 0; + // } + // while (lastIndex >= 0) { + // if (items[lastIndex] > 0) { + // // if went down from declared weight, then return lower weight + // return (items[lastIndex] < items[0] ? items[lastIndex] : items[0]); + // } + // lastIndex--; + // } + // return 0; + // } + public boolean validateCleanJerk1ActualLift(String cleanJerk1ActualLift) throws RuleViolationException { validateActualLift(3, getCleanJerk1AutomaticProgression(), this.cleanJerk1Declaration, this.cleanJerk1Change1, this.cleanJerk1Change2, cleanJerk1ActualLift); @@ -4565,6 +4617,17 @@ public boolean validateCleanJerk1Change2(String cleanJerk1Change2) throws RuleVi return true; } + // /** + // * Null-safe comparison for longs. + // * + // * @param o1 + // * @param o2 + // * @return + // */ + // private boolean LongEquals(Long o1, Long o2) { + // return o1 == o2 || o1 != null && o2 != null && o1.longValue() == (o2.longValue()); + // } + public boolean validateCleanJerk1Declaration(String cleanJerk1Declaration) throws RuleViolationException { // not always true. Can violate moving down rules validateDeclaration(3, "0", cleanJerk1Declaration, this.cleanJerk1Change1, @@ -4572,27 +4635,6 @@ public boolean validateCleanJerk1Declaration(String cleanJerk1Declaration) throw return true; } - // @SuppressWarnings("unused") - // private Long getCopyId() { - // return copyId; - // } - - // @SuppressWarnings("unused") - // private Integer getDeclaredAndActuallyAttempted(Integer... items) { - // int lastIndex = items.length - 1; - // if (items.length == 0) { - // return 0; - // } - // while (lastIndex >= 0) { - // if (items[lastIndex] > 0) { - // // if went down from declared weight, then return lower weight - // return (items[lastIndex] < items[0] ? items[lastIndex] : items[0]); - // } - // lastIndex--; - // } - // return 0; - // } - public boolean validateCleanJerk2ActualLift(String cleanJerk2ActualLift) throws RuleViolationException { validateActualLift(4, getCleanJerk2AutomaticProgression(), this.cleanJerk2Declaration, this.cleanJerk2Change1, this.cleanJerk2Change2, cleanJerk2ActualLift); @@ -4611,17 +4653,6 @@ public boolean validateCleanJerk2Change2(String cleanJerk2Change2) throws RuleVi return true; } - // /** - // * Null-safe comparison for longs. - // * - // * @param o1 - // * @param o2 - // * @return - // */ - // private boolean LongEquals(Long o1, Long o2) { - // return o1 == o2 || o1 != null && o2 != null && o1.longValue() == (o2.longValue()); - // } - public boolean validateCleanJerk2Declaration(String cleanJerk2Declaration) throws RuleViolationException { validateDeclaration(4, getCleanJerk2AutomaticProgression(), cleanJerk2Declaration, this.cleanJerk2Change1, this.cleanJerk2Change2, this.cleanJerk2ActualLift); @@ -4898,13 +4929,13 @@ private void checkAttemptVsLiftOrderReference(int curLift, int newVal, LiftOrder if (checkedLift_1 < currentLiftNo_1) { // we are checking an earlier attempt of the athlete (e.g. when loading the // athlete card) - logger.debug("ignoring lift {} {}", checkedLift_1, currentLiftNo_1); + this.logger.debug("ignoring lift {} {}", checkedLift_1, currentLiftNo_1); return; } else { - logger.debug("checking lift {} {}", checkedLift_1, currentLiftNo_1); + this.logger.debug("checking lift {} {}", checkedLift_1, currentLiftNo_1); } - logger.debug("referenceAttempt {} reference weight {} curLift {} currentLiftNo {}", referenceAttemptNo_1, + this.logger.debug("referenceAttempt {} reference weight {} curLift {} currentLiftNo {}", referenceAttemptNo_1, referenceWeight, curLift, currentLiftNo_1); // Careful: do not mix one-based numbers with zero-based numbers. if (referenceAttemptNo_1 <= 3 && currentLiftNo_1 == 4) { @@ -4992,10 +5023,10 @@ private void checkChangeVsTimer(int curLift, String declaration, String change1, int clock = getFop().getAthleteTimer().liveTimeRemaining(); if (!this.isSameAthleteAs(owner)) { // clock is not running for us - logger.debug("NOT owning clock"); + this.logger.debug("NOT owning clock"); doCheckChangeNotOwningTimer(declaration, change1, change2, getFop(), clock, initialTime); } else { - logger.debug("OWNING clock"); + this.logger.debug("OWNING clock"); doCheckChangeOwningTimer(declaration, change1, change2, getFop(), clock, initialTime); } @@ -5009,7 +5040,7 @@ private void checkDeclarationWasMade(int curLift, String declaration) { int clock = getFop().getAthleteTimer().liveTimeRemaining(); if (declaration == null || declaration.isBlank()) { // there was no declaration made in time - logger./**/warn("{}{} change without declaration (not owning clock)", OwlcmsSession.getFopLoggingName(), + this.logger./**/warn("{}{} change without declaration (not owning clock)", OwlcmsSession.getFopLoggingName(), this.getShortName()); throw new RuleViolationException.MustDeclareFirst(this, clock); } @@ -5130,10 +5161,10 @@ private void doCheckChangeNotOwningTimer(String declaration, String change1, Str int clock, int initialTime) { if ((declaration != null && !declaration.isBlank()) && (change1 == null || change1.isBlank()) && (change2 == null || change2.isBlank())) { - logger.trace("{}{} declaration accepted (not owning clock)", OwlcmsSession.getFopLoggingName(), + this.logger.trace("{}{} declaration accepted (not owning clock)", OwlcmsSession.getFopLoggingName(), this.getShortName()); } else { - logger.trace("{}{} change accepted (not owning clock)", OwlcmsSession.getFopLoggingName(), + this.logger.trace("{}{} change accepted (not owning clock)", OwlcmsSession.getFopLoggingName(), this.getShortName()); } } @@ -5146,20 +5177,20 @@ private void doCheckChangeOwningTimer(String declaration, String change1, String if ((change1 == null || change1.isBlank()) && (change2 == null || change2.isBlank())) { // validate declaration if (clock < initialTime - 30000) { - logger./**/warn("{}{} late declaration denied ({})", OwlcmsSession.getFopLoggingName(), + this.logger./**/warn("{}{} late declaration denied ({})", OwlcmsSession.getFopLoggingName(), this.getShortName(), clock / 1000.0); throw new RuleViolationException.LateDeclaration(this, clock); } - logger.debug("{}{}valid declaration", OwlcmsSession.getFopLoggingName(), this.getShortName(), + this.logger.debug("{}{}valid declaration", OwlcmsSession.getFopLoggingName(), this.getShortName(), clock / 1000.0); } else { if (clock < 30000) { - logger./**/warn("{}{} late change denied after final warning ({})", OwlcmsSession.getFopLoggingName(), + this.logger./**/warn("{}{} late change denied after final warning ({})", OwlcmsSession.getFopLoggingName(), this.getShortName(), clock / 1000.0); throw new RuleViolationException.MustChangeBeforeFinalWarning(this, clock); } - logger.debug("{}change before final warning", OwlcmsSession.getFopLoggingName(), clock); + this.logger.debug("{}change before final warning", OwlcmsSession.getFopLoggingName(), clock); } } @@ -5474,7 +5505,7 @@ private boolean isSameAthleteAs(Athlete other) { && Integer.compare(this.getLotNumber(), other.getLotNumber()) == 0; boolean strong = Long.compare(this.getId(), other.getId()) == 0; if (weak && !strong) { - logger.error("same athlete, different ids {} ", this); + this.logger.error("same athlete, different ids {} ", this); } return weak; @@ -5572,13 +5603,6 @@ private void setFullBirthDateFromYear(Integer yearOfBirth) { } } - /** - * @param id the id to set - */ - public void setId(Long id) { - this.id = id; - } - /** * Compute the Sinclair formula given its parameters. * @@ -5616,10 +5640,6 @@ private int startingTotalDelta(Integer snatch1Request, Integer cleanJerk1Request return missing; } - public String getRequiredInitialAttempts() { - return Integer.toString(Math.round(this.getEntryTotal() - getStartingTotalMargin(this.getCategory(), this.getEntryTotal()))); - } - /** * @param curLift * @param actualLift @@ -5684,7 +5704,7 @@ private void validateChange2(int curLift, String automaticProgression, String de } catch (RuleViolationException e) { rethrow(e); } catch (Exception e) { - logger.error("{}", LoggerUtils.exceptionMessage(e)); + this.logger.error("{}", LoggerUtils.exceptionMessage(e)); throw new RuntimeException(e); } this.timingLogger.info("validateChange2 {}ms {} {}", System.currentTimeMillis() - start, curLift, @@ -5723,21 +5743,4 @@ private void validateDeclaration(int curLift, String automaticProgression, Strin this.timingLogger.info("validateDeclaration {}ms {} {}", System.currentTimeMillis() - start, curLift, LoggerUtils.whereFrom()); } - - public void setMainRankings(Participation mainRankings) { - this.mainRankings = mainRankings; - } - - public Ranking getComputedScoringSystem() { - var category2 = this.getCategory(); - if (category2 == null) - return Ranking.TOTAL; - var group2 = category2.getAgeGroup(); - if (group2 == null) - return Ranking.TOTAL; - var css = group2.getComputedScoringSystem(); - if (css == null) - return Ranking.TOTAL; - return css; - } } diff --git a/owlcms/src/main/java/app/owlcms/data/athlete/AthleteRepository.java b/owlcms/src/main/java/app/owlcms/data/athlete/AthleteRepository.java index feb0097f7a..dd300b59ea 100644 --- a/owlcms/src/main/java/app/owlcms/data/athlete/AthleteRepository.java +++ b/owlcms/src/main/java/app/owlcms/data/athlete/AthleteRepository.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -40,6 +40,27 @@ public class AthleteRepository { static { logger.setLevel(Level.INFO); } + public static Set allUnfinishedCategories; + + public static Set allUnfinishedCategories() { + Set unfinishedCategories = new HashSet<>(); + List ranked = findAll(); + if (ranked == null || ranked.isEmpty()) { + return Set.of(); + } + for (Athlete a : ranked) { + // logger.debug("unfinishedCategories *** athlete {}",a); + if (!a.isDone()) { + // logger.debug("{}", a, a.getCleanJerk3ActualLift()); + for (Participation p : a.getParticipations()) { + unfinishedCategories.add(p.getCategory().getCode()); + } + } + } + logger.debug("unfinishedCategories2 {}", unfinishedCategories); + setAllUnfinishedCategories(unfinishedCategories); + return unfinishedCategories; + } public static void assignCategoryRanks() { JPAService.runInTransaction(em -> { @@ -62,12 +83,14 @@ public static void assignStartNumbers(Group group) { return currentGroupAthletes; }); } - + /** * Assign start numbers to the list of Athletes. - *

Ordering of the initial list is preserved. - *

Assumption: Athletes should come from a single session. - * + *

+ * Ordering of the initial list is preserved. + *

+ * Assumption: Athletes should come from a single session. + * * @param athletes */ public static void assignStartNumbers(List athletes) { @@ -231,6 +254,16 @@ public static List findAllTeams() { }); } + public static List findAthletesForAgeGroup(AgeGroup ag) { + return JPAService.runInTransaction((em) -> { + TypedQuery q = em.createQuery( + "select distinct a from Athlete a join a.participations p join p.category c join c.ageGroup ag where ag.id = :agId", + Athlete.class); + q.setParameter("agId", ag.getId()); + return q.getResultList(); + }); + } + /** * Fetch all athletes needed for leader board * @@ -247,22 +280,12 @@ public static List findAthletesForCategory(Category c) { }); } - public static List findAthletesNoCategory() { - return JPAService.runInTransaction((em) -> { - TypedQuery q = em.createQuery( - "select distinct a from Athlete a left outer join a.participations p where p is null", - Athlete.class); - return q.getResultList(); - }); - } - public static List findAthletesForGlobalRanking(EntityManager emgr, Group g) { return doFindAthletesForGlobalRanking(g, emgr, true); } /** - * Fetch all athletes and participations for the categories present in the group. If group is null, all athletes and - * their participations. + * Fetch all athletes and participations for the categories present in the group. If group is null, all athletes and their participations. * * @param g * @param onlyWeighedIn @@ -275,6 +298,15 @@ public static List findAthletesForGlobalRanking(Group g, boolean onlyWe }); } + public static List findAthletesNoCategory() { + return JPAService.runInTransaction((em) -> { + TypedQuery q = em.createQuery( + "select distinct a from Athlete a left outer join a.participations p where p is null", + Athlete.class); + return q.getResultList(); + }); + } + public static Athlete findById(long id) { return JPAService.runInTransaction(em -> { return getById(id, em); @@ -300,6 +332,13 @@ public static List findFiltered(String lastName, Group group, Category }); } + public static Set getAllUnfinishedCategories() { + if (allUnfinishedCategories == null) { + allUnfinishedCategories(); + } + return allUnfinishedCategories; + } + /** * Gets the by id. * @@ -315,6 +354,26 @@ public static Athlete getById(Long id, EntityManager em) { return (Athlete) query.getResultList().stream().findFirst().orElse(null); } + public static Set keepOnlyFinishedCategoryAthletes(Collection athletes) { + Set unfinishedCategories = new HashSet<>(); + Set finishedCategoryAthletes = new HashSet<>(); + for (Athlete a : athletes) { + if (a.getSnatch3AsInteger() == null || a.getSnatch3ActualLift().isBlank() + || a.getCleanJerk3AsInteger() == null || a.getCleanJerk3ActualLift().isBlank()) { + for (Participation p : a.getParticipations()) { + unfinishedCategories.add(p.getCategory().getCode()); + } + } + } + // logger.debug("unfinishedCategories1 {}",unfinishedCategories); + for (Athlete a : athletes) { + if (!unfinishedCategories.contains(a.getCategory().getCode())) { + finishedCategoryAthletes.add(a); + } + } + return finishedCategoryAthletes; + } + /** * Use the athlete bodyweight (or presumed body weight if weigh-in has not taken place) to determine category. */ @@ -364,22 +423,44 @@ public static Athlete save(Athlete athlete) { }); } + public static void setAllUnfinishedCategories(Set allUnfinishedCategories) { + AthleteRepository.allUnfinishedCategories = allUnfinishedCategories; + } + + public static Set unfinishedCategories(List ranked) { + Set unfinishedCategories = new HashSet<>(); + if (ranked == null || ranked.isEmpty()) { + return Set.of(); + } + for (Athlete a : ranked) { + // logger.debug("unfinishedCategories *** athlete {}",a); + if (!a.isDone()) { + // logger.debug("{}", a, a.getCleanJerk3ActualLift()); + for (Participation p : a.getParticipations()) { + unfinishedCategories.add(p.getCategory().getCode()); + } + } + } + // logger.debug("unfinishedCategories2 {}",unfinishedCategories); + return unfinishedCategories; + } + private static List doFindAthletesForGlobalRanking(Group g, EntityManager em, boolean onlyWeighedIn) { String onlyCategoriesFromCurrentGroup = ""; - + // only consider weighed-in athletes from the current session. - // once we have the categories from that query, we will find other athetes in other sessions, and + // once we have the categories from that query, we will find other athetes in other sessions, and // we will use the onlyWeighedIn flag on that second result. if (g != null) { String categoriesFromCurrentGroup = "select distinct c2 from Athlete b join b.group g join b.participations p join p.category c2 where g.id = :groupId"; onlyCategoriesFromCurrentGroup = " join p.category c where exists (" + categoriesFromCurrentGroup + " and c2.code = c.code and b.bodyWeight > 0.01)"; - -// // following 4 lines are a trace, disable when confirmed. -// TypedQuery q2 = em.createQuery(categoriesFromCurrentGroup, Category.class); -// q2.setParameter("groupId", g.getId()); -// List q2Results = q2.getResultList(); -// logger.info("categories for currentGroup {}",q2Results); + + // // following 4 lines are a trace, disable when confirmed. + // TypedQuery q2 = em.createQuery(categoriesFromCurrentGroup, Category.class); + // q2.setParameter("groupId", g.getId()); + // List q2Results = q2.getResultList(); + // logger.info("categories for currentGroup {}",q2Results); } Query q = em.createQuery( "select distinct a, p from Athlete a join fetch a.participations p" @@ -493,85 +574,4 @@ private static void setFilteringParameters(String lastName, Group group, Categor } } - public static Set keepOnlyFinishedCategoryAthletes(Collection athletes) { - Set unfinishedCategories = new HashSet<>(); - Set finishedCategoryAthletes = new HashSet<>(); - for (Athlete a : athletes) { - if (a.getSnatch3AsInteger() == null || a.getSnatch3ActualLift().isBlank() - || a.getCleanJerk3AsInteger() == null || a.getCleanJerk3ActualLift().isBlank()) { - for (Participation p: a.getParticipations()) { - unfinishedCategories.add(p.getCategory().getCode()); - } - } - } - //logger.debug("unfinishedCategories1 {}",unfinishedCategories); - for (Athlete a : athletes) { - if (!unfinishedCategories.contains(a.getCategory().getCode())) { - finishedCategoryAthletes.add(a); - } - } - return finishedCategoryAthletes; - } - - public static Set unfinishedCategories(List ranked) { - Set unfinishedCategories = new HashSet<>(); - if (ranked == null || ranked.isEmpty()) { - return Set.of(); - } - for (Athlete a : ranked) { - //logger.debug("unfinishedCategories *** athlete {}",a); - if (!a.isDone()) { - //logger.debug("{}", a, a.getCleanJerk3ActualLift()); - for (Participation p: a.getParticipations()) { - unfinishedCategories.add(p.getCategory().getCode()); - } - } - } - //logger.debug("unfinishedCategories2 {}",unfinishedCategories); - return unfinishedCategories; - } - - public static Set allUnfinishedCategories; - - public static Set allUnfinishedCategories() { - Set unfinishedCategories = new HashSet<>(); - List ranked = findAll(); - if (ranked == null || ranked.isEmpty()) { - return Set.of(); - } - for (Athlete a : ranked) { - //logger.debug("unfinishedCategories *** athlete {}",a); - if (!a.isDone()) { - //logger.debug("{}", a, a.getCleanJerk3ActualLift()); - for (Participation p: a.getParticipations()) { - unfinishedCategories.add(p.getCategory().getCode()); - } - } - } - logger.debug("unfinishedCategories2 {}",unfinishedCategories); - setAllUnfinishedCategories(unfinishedCategories); - return unfinishedCategories; - } - - public static Set getAllUnfinishedCategories() { - if (allUnfinishedCategories == null) { - allUnfinishedCategories(); - } - return allUnfinishedCategories; - } - - public static void setAllUnfinishedCategories(Set allUnfinishedCategories) { - AthleteRepository.allUnfinishedCategories = allUnfinishedCategories; - } - - public static List findAthletesForAgeGroup(AgeGroup ag) { - return JPAService.runInTransaction((em) -> { - TypedQuery q = em.createQuery( - "select distinct a from Athlete a join a.participations p join p.category c join c.ageGroup ag where ag.id = :agId", - Athlete.class); - q.setParameter("agId", ag.getId()); - return q.getResultList(); - }); - } - } diff --git a/owlcms/src/main/java/app/owlcms/data/athlete/Gender.java b/owlcms/src/main/java/app/owlcms/data/athlete/Gender.java index d4ce7ffd72..b6fcea5187 100644 --- a/owlcms/src/main/java/app/owlcms/data/athlete/Gender.java +++ b/owlcms/src/main/java/app/owlcms/data/athlete/Gender.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -48,7 +48,7 @@ public String asPublicGenderCode() { throw new IllegalStateException(); } } - + public String getTranslatedGenderCode() { switch (this) { case F: @@ -59,7 +59,7 @@ public String getTranslatedGenderCode() { throw new IllegalStateException(); } } - + public void setTranslatedGenderCode(String ignored) { // do nothing, for bean introspection } diff --git a/owlcms/src/main/java/app/owlcms/data/athlete/LiftDefinition.java b/owlcms/src/main/java/app/owlcms/data/athlete/LiftDefinition.java index 2407f1b903..9b539f2f67 100644 --- a/owlcms/src/main/java/app/owlcms/data/athlete/LiftDefinition.java +++ b/owlcms/src/main/java/app/owlcms/data/athlete/LiftDefinition.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -18,16 +18,14 @@ * * Used to avoid repetitive error-prone boiler-plate code. * - * LiftDefinition ls1 = liftDefinitions[0] contains a {@link #LiftDefinition(int, Stage)} with a list of getters and a - * list of setters, one for each Change (AUTOMATIC, DECLARATION, etc.). + * LiftDefinition ls1 = liftDefinitions[0] contains a {@link #LiftDefinition(int, Stage)} with a list of getters and a list of setters, one for each Change + * (AUTOMATIC, DECLARATION, etc.). * * There is a LiftDefinition for each lift, in the array {@link #lifts} * - * ls1.stage returns Stage.SNATCH ls1.getters[1] is a reference to Athlete.getSnatch1Declaration, so that - * Method.invoke(ls1.getters[1]) returns the value. + * ls1.stage returns Stage.SNATCH ls1.getters[1] is a reference to Athlete.getSnatch1Declaration, so that Method.invoke(ls1.getters[1]) returns the value. * - * It is also possible to iterate over the athlete's card by using the changeGetters[lifts][changes] methods (and the - * corresponding changeSetters). + * It is also possible to iterate over the athlete's card by using the changeGetters[lifts][changes] methods (and the corresponding changeSetters). * * @author Jean-François Lamy * diff --git a/owlcms/src/main/java/app/owlcms/data/athlete/LiftInfo.java b/owlcms/src/main/java/app/owlcms/data/athlete/LiftInfo.java index b31cfddcd2..52bac40ced 100644 --- a/owlcms/src/main/java/app/owlcms/data/athlete/LiftInfo.java +++ b/owlcms/src/main/java/app/owlcms/data/athlete/LiftInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athlete/RuleViolationException.java b/owlcms/src/main/java/app/owlcms/data/athlete/RuleViolationException.java index c10d205632..da68469e81 100644 --- a/owlcms/src/main/java/app/owlcms/data/athlete/RuleViolationException.java +++ b/owlcms/src/main/java/app/owlcms/data/athlete/RuleViolationException.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -26,9 +26,8 @@ public static class AttemptNumberTooLow extends RuleViolationException { /** * Athlete cannot move down to same weight as someone with a higher attempt number. * - * Athlete A on first attempt requests more than an athlete on second attempt. Then A wants to move down to that - * B weight. Cannot, because lower attempt number must lift first. This would give A unfair rest if A could lift - * after B. + * Athlete A on first attempt requests more than an athlete on second attempt. Then A wants to move down to that B weight. Cannot, because lower attempt + * number must lift first. This would give A unfair rest if A could lift after B. * * @param requestedWeight * @param startNumber @@ -85,12 +84,11 @@ public LateDeclaration(Athlete requestingAthlete, int clock) { public static class LiftedEarlier extends RuleViolationException { /** - * Athlete cannot move down the weight on the bar was already taken by someone who lifted later on the previous - * attempt. + * Athlete cannot move down the weight on the bar was already taken by someone who lifted later on the previous attempt. * - * Athlete A lifted on first attempt, then B, due to the requested weight. A requests higher than B on second - * attempt. A cannot move down to B's requested weight after B attempts, as this makes A lift out of order -- By - * rule, A must come before B if they both attempt the same weight at the same attempt. + * Athlete A lifted on first attempt, then B, due to the requested weight. A requests higher than B on second attempt. A cannot move down to B's + * requested weight after B attempts, as this makes A lift out of order -- By rule, A must come before B if they both attempt the same weight at the + * same attempt. * * @param requestedWeight * @param referenceAthlete @@ -105,8 +103,8 @@ public LiftedEarlier(Athlete requestingAthlete, Integer requestedWeight, Athlete public static class LiftValueNotWhatWasRequested extends RuleViolationException { /** - * When correcting an error manually (athlete on platform was not the one called), the value entered for the - * lift must match the last declaration or change + * When correcting an error manually (athlete on platform was not the one called), the value entered for the lift must match the last declaration or + * change * * @param curLift * @param actualLift @@ -123,11 +121,10 @@ public LiftValueNotWhatWasRequested(Athlete requestingAthlete, int curLift, Stri public static class LotNumberTooHigh extends RuleViolationException { /** - * This rule is there as precaution when weigh-in officials forgot to attribute start numbers. Athlete cannot - * move down because same weight was attempted by an athlete with lower start number. + * This rule is there as precaution when weigh-in officials forgot to attribute start numbers. Athlete cannot move down because same weight was + * attempted by an athlete with lower start number. * - * On first lift, start number 1 cannot request higher than start 2 and, after 2 has been called, move down to - * same weight (lifting out of order). + * On first lift, start number 1 cannot request higher than start 2 and, after 2 has been called, move down to same weight (lifting out of order). * * @param requestedWeight * @param referenceLotNumber @@ -188,8 +185,7 @@ public static class StartNumberTooHigh extends RuleViolationException { /** * Athlete cannot move down because same weight was attempted by an athlete with lower start number. * - * On first lift, start number 1 cannot request higher than start 2 and, after 2 has been called, move down to - * same weight (lifting out of order). + * On first lift, start number 1 cannot request higher than start 2 and, after 2 has been called, move down to same weight (lifting out of order). * * @param requestedWeight * @param referenceStartNumber @@ -220,8 +216,7 @@ public static class WeightBelowAlreadyLifted extends RuleViolationException { /** * Another athlete has already lifted more than what is requested. * - * Bar cannot go down in weight. Unless error occurred, in which case T.O. can use "force as current lifter" to - * disable validation. + * Bar cannot go down in weight. Unless error occurred, in which case T.O. can use "force as current lifter" to disable validation. * * @param requestedWeight * @param startNumber diff --git a/owlcms/src/main/java/app/owlcms/data/athlete/XAthlete.java b/owlcms/src/main/java/app/owlcms/data/athlete/XAthlete.java index 6c26d633e4..6dac5a50e9 100644 --- a/owlcms/src/main/java/app/owlcms/data/athlete/XAthlete.java +++ b/owlcms/src/main/java/app/owlcms/data/athlete/XAthlete.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -233,6 +233,15 @@ public Category getCategory() { return this.a.getCategory(); } + /** + * @return + * @see app.owlcms.data.athlete.Athlete#computedCategoryScore() + */ + @Override + public Double getCategoryScore() { + return this.a.getCategoryScore(); + } + /** * @return * @see app.owlcms.data.athlete.Athlete#getCategorySinclair() @@ -564,15 +573,6 @@ public Double getCustomScore() { return this.a.getCustomScore(); } - /** - * @return - * @see app.owlcms.data.athlete.Athlete#computedCategoryScore() - */ - @Override - public Double getCategoryScore() { - return this.a.getCategoryScore(); - } - /** * @return * @see app.owlcms.data.athlete.Athlete#getDisplayCategory() @@ -806,6 +806,16 @@ public LocalDateTime getPreviousLiftTime() { return this.a.getPreviousLiftTime(); } + @Override + public Double getQAge() { + return this.a.getQAge(); + } + + @Override + public int getqAgeRank() { + return this.a.getqAgeRank(); + } + /** * @return * @see app.owlcms.data.athlete.Athlete#getQualifyingTotal() @@ -931,11 +941,6 @@ public Integer getSinclairRank() { return this.a.getSinclairRank(); } - @Override - public Double getSmhfForDelta() { - return this.a.getSmhfForDelta(); - } - /** * @return * @see app.owlcms.data.athlete.Athlete#getSmhf() @@ -944,22 +949,17 @@ public Double getSmhfForDelta() { public Double getSmhf() { return this.a.getSmhf(); } - + @Override - public Double getQAge() { - return this.a.getQAge(); + public Double getSmhfForDelta() { + return this.a.getSmhfForDelta(); } @Override public int getSmhfRank() { return this.a.getSmhfRank(); } - - @Override - public int getqAgeRank() { - return this.a.getqAgeRank(); - } - + /** * @return * @see app.owlcms.data.athlete.Athlete#getSnatch1ActualLift() @@ -1799,6 +1799,11 @@ public void setPresumedCategory(Category category) { super.setPresumedCategory(category); } + @Override + public void setqAgeRank(int i) { + this.a.setqAgeRank(i); + } + /** * @param qualifyingTotal * @see app.owlcms.data.athlete.Athlete#setQualifyingTotal(java.lang.Integer) @@ -1830,11 +1835,6 @@ public void setSinclairRank(Integer sinclairRank) { public void setSmhfRank(int i) { this.a.setSmhfRank(i); } - - @Override - public void setqAgeRank(int i) { - this.a.setqAgeRank(i); - } /** * @param snatch1ActualLift @@ -2236,8 +2236,7 @@ public String toStringRanks() { * @param change1 * @param change2 * @param actualLift - * @see app.owlcms.data.athlete.Athlete#validateActualLift(int, java.lang.String, java.lang.String, - * java.lang.String, java.lang.String, java.lang.String) + * @see app.owlcms.data.athlete.Athlete#validateActualLift(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ @Override public void validateActualLift(int curLift, String automaticProgression, String declaration, String change1, diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/AbstractLifterComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/AbstractLifterComparator.java index 17890eeba1..26c332b82f 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/AbstractLifterComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/AbstractLifterComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -28,6 +28,10 @@ */ public class AbstractLifterComparator { protected final static Logger logger = LoggerFactory.getLogger(AbstractLifterComparator.class); + public static NaturalOrderComparator noc = new NaturalOrderComparator<>(); + public static Comparator athleteSessionComparator = (lifter1, lifter2) -> { + return Group.weighinTimeComparator.compare(lifter1, lifter2); + }; /** * Compare category. @@ -44,7 +48,140 @@ public static int compareBWCategory(Athlete lifter1, Athlete lifter2) { return ObjectUtils.compare(bwCat1, bwCat2, true); } - public static NaturalOrderComparator noc = new NaturalOrderComparator<>(); + public static void doTraceComparison(String where, Object o1, Object v1, Object o2, Object v2, int compare) { + // if (logger.isTraceEnabled()) { + logger./**/warn("{} {}={} {} {}={} {}", where, o1.toString(), v1, (compare < 0 ? " < " : (compare == 0 ? "=" : " > ")), + o2.toString(), v2, + LoggerUtils.whereFrom(1)); + // } + } + + public static void traceComparison(String where, Athlete lifter1, Object v1, Athlete lifter2, Object v2, int compare) { + if (logger.isTraceEnabled()) { + logger./**/warn("{} {}={} {} {}={} {}", where, lifter1.getLastName(), v1, (compare < 0 ? " < " : (compare == 0 ? "=" : " > ")), + lifter2.getLastName(), v2, + LoggerUtils.whereFrom()); + } + } + + public static void traceComparison(String where, Object o1, Object value1, Object o2, Object value2, int compare) { + if (logger.isTraceEnabled()) { + logger./**/warn("{} {}={} {} {}={} {}", where, o1.toString(), value1, (compare < 0 ? " < " : (compare == 0 ? "=" : " > ")), + o2.toString(), value2, + LoggerUtils.whereFrom()); + } + } + + /** + * Compare first name. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + static int compareFirstName(Athlete lifter1, Athlete lifter2) { + String lifter1Value = lifter1.getFirstName(); + String lifter2Value = lifter2.getFirstName(); + return ObjectUtils.compare(lifter1Value, lifter2Value, true); + } + + /** + * Compare group weigh in time. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + + static int compareGroupWeighInTime(Athlete lifter1, Athlete lifter2) { + return Group.weighinTimeComparator.compare(lifter1, lifter2); + } + + /** + * Compare last name. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + static int compareLastName(Athlete lifter1, Athlete lifter2) { + String lifter1Value = lifter1.getLastName(); + String lifter2Value = lifter2.getLastName(); + return ObjectUtils.compare(lifter1Value, lifter2Value, true); + } + + /** + * Compare last successful lift time. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + static int compareLastSuccessfulLiftTime(Athlete lifter1, Athlete lifter2) { + LocalDateTime lifter1Value = lifter1.getLastSuccessfulLiftTime(); + LocalDateTime lifter2Value = lifter2.getLastSuccessfulLiftTime(); + // safe to compare, no nulls. + return lifter1Value.compareTo(lifter2Value); + } + + /** + * Compare lift type. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + static int compareLiftType(Athlete lifter1, Athlete lifter2) { + // snatch comes before clean and jerk + Integer lifter1Value = lifter1.getAttemptsDone(); + Integer lifter2Value = lifter2.getAttemptsDone(); + if (lifter1Value < 3) { + lifter1Value = 0; + } else { + lifter1Value = 1; + } + if (lifter2Value < 3) { + lifter2Value = 0; + } else { + lifter2Value = 1; + } + return lifter1Value.compareTo(lifter2Value); + } + + /** + * Compare lot number. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + static int compareLotNumber(Athlete lifter1, Athlete lifter2) { + Integer lifter1Value = lifter1.getLotNumber(); + Integer lifter2Value = lifter2.getLotNumber(); + if (lifter1Value == null && lifter2Value == null) { + return 0; + } + if (lifter1Value == null) { + return -1; + } + if (lifter2Value == null) { + return 1; + } + return lifter1Value.compareTo(lifter2Value); + } + + /** + * Compare category. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + static int comparePresumedCategory(Athlete lifter1, Athlete lifter2) { + String lifter1Value = lifter1.getPresumedOpenCategoryString(); + String lifter2Value = lifter2.getPresumedOpenCategoryString(); + return ObjectUtils.compare(lifter1Value, lifter2Value, true); + } /** * Compare age group. @@ -56,33 +193,33 @@ public static int compareBWCategory(Athlete lifter1, Athlete lifter2) { int compareAgeGroup(Athlete lifter1, Athlete lifter2) { AgeGroup lifter1Value = lifter1.getAgeGroup(); AgeGroup lifter2Value = lifter2.getAgeGroup(); - + if (lifter1Value == null || lifter2Value == null) { return ObjectUtils.compare(lifter1Value, lifter2Value, true); } - + int compare; compare = ObjectUtils.compare(lifter1Value.getGender(), lifter2Value.getGender(), true); if (compare != 0) { return compare; } - -// // force U, JR, SR order -// if (lifter1Value.getCode().startsWith("U") && !lifter2Value.getCode().startsWith("U")) { -// return -1; -// } else if (!lifter1Value.getCode().startsWith("U") && lifter2Value.getCode().startsWith("U")) { -// return 1; -// } else if (lifter1Value.getCode().startsWith("JR") && !lifter2Value.getCode().startsWith("JR")) { -// return -1; -// } else if (!lifter1Value.getCode().startsWith("JR") && lifter2Value.getCode().startsWith("JR")) { -// return 1; -// } else if (lifter1Value.getCode().startsWith("SR") && !lifter2Value.getCode().startsWith("SR")) { -// return -1; -// } else if (!lifter1Value.getCode().startsWith("SR") && lifter2Value.getCode().startsWith("SR")) { -// return 1; -// } else { - return ObjectUtils.compare(lifter1Value.getMaxAge(), lifter2Value.getMaxAge(), true); -// } + + // // force U, JR, SR order + // if (lifter1Value.getCode().startsWith("U") && !lifter2Value.getCode().startsWith("U")) { + // return -1; + // } else if (!lifter1Value.getCode().startsWith("U") && lifter2Value.getCode().startsWith("U")) { + // return 1; + // } else if (lifter1Value.getCode().startsWith("JR") && !lifter2Value.getCode().startsWith("JR")) { + // return -1; + // } else if (!lifter1Value.getCode().startsWith("JR") && lifter2Value.getCode().startsWith("JR")) { + // return 1; + // } else if (lifter1Value.getCode().startsWith("SR") && !lifter2Value.getCode().startsWith("SR")) { + // return -1; + // } else if (!lifter1Value.getCode().startsWith("SR") && lifter2Value.getCode().startsWith("SR")) { + // return 1; + // } else { + return ObjectUtils.compare(lifter1Value.getMaxAge(), lifter2Value.getMaxAge(), true); + // } } /** @@ -276,19 +413,6 @@ int compareCustomScore(Athlete lifter1, Athlete lifter2) { } return lifter1Value.compareTo(lifter2Value); } - - int compareScore(Athlete lifter1, Athlete lifter2) { - Double lifter1Value = lifter1.getCategoryScore(); - Double lifter2Value = lifter2.getCategoryScore(); - final Double notScored = 0D; - if (lifter1Value == null) { - lifter1Value = notScored; - } - if (lifter2Value == null) { - lifter2Value = notScored; - } - return lifter1Value.compareTo(lifter2Value); - } /** * Compare lot number. @@ -304,8 +428,8 @@ int compareEntryTotal(Athlete lifter1, Athlete lifter2) { } /** - * Comparer les totaux des leveurs, si ils ont terminé tous leurs essais. Le leveur ayant terminé va après, de - * manière à ce le premier à lever soit toujours toujours le premier dans la liste. + * Comparer les totaux des leveurs, si ils ont terminé tous leurs essais. Le leveur ayant terminé va après, de manière à ce le premier à lever soit toujours + * toujours le premier dans la liste. * * @param lifter1 the lifter 1 * @param lifter2 the lifter 2 @@ -331,19 +455,6 @@ int compareFinalResults(Athlete lifter1, Athlete lifter2) { } - /** - * Compare first name. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - static int compareFirstName(Athlete lifter1, Athlete lifter2) { - String lifter1Value = lifter1.getFirstName(); - String lifter2Value = lifter2.getFirstName(); - return ObjectUtils.compare(lifter1Value, lifter2Value, true); - } - /** * Compare forced as first. * @@ -396,11 +507,6 @@ int compareGender(Athlete lifter1, Athlete lifter2) { return ObjectUtils.compare(gender1, gender2, true); } - - public static Comparator athleteSessionComparator = (lifter1, lifter2) -> { - return Group.weighinTimeComparator.compare(lifter1, lifter2); - }; - /** * Compare group. * @@ -436,107 +542,8 @@ int compareGroupPlatform(Athlete lifter1, Athlete lifter2) { } /** - * Compare group weigh in time. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - - static int compareGroupWeighInTime(Athlete lifter1, Athlete lifter2) { - return Group.weighinTimeComparator.compare(lifter1, lifter2); - } - - /** - * Compare last name. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - static int compareLastName(Athlete lifter1, Athlete lifter2) { - String lifter1Value = lifter1.getLastName(); - String lifter2Value = lifter2.getLastName(); - return ObjectUtils.compare(lifter1Value, lifter2Value, true); - } - - /** - * Compare last successful lift time. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - static int compareLastSuccessfulLiftTime(Athlete lifter1, Athlete lifter2) { - LocalDateTime lifter1Value = lifter1.getLastSuccessfulLiftTime(); - LocalDateTime lifter2Value = lifter2.getLastSuccessfulLiftTime(); - // safe to compare, no nulls. - return lifter1Value.compareTo(lifter2Value); - } - - /** - * Compare lift type. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - static int compareLiftType(Athlete lifter1, Athlete lifter2) { - // snatch comes before clean and jerk - Integer lifter1Value = lifter1.getAttemptsDone(); - Integer lifter2Value = lifter2.getAttemptsDone(); - if (lifter1Value < 3) { - lifter1Value = 0; - } else { - lifter1Value = 1; - } - if (lifter2Value < 3) { - lifter2Value = 0; - } else { - lifter2Value = 1; - } - return lifter1Value.compareTo(lifter2Value); - } - - /** - * Compare lot number. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - static int compareLotNumber(Athlete lifter1, Athlete lifter2) { - Integer lifter1Value = lifter1.getLotNumber(); - Integer lifter2Value = lifter2.getLotNumber(); - if (lifter1Value == null && lifter2Value == null) { - return 0; - } - if (lifter1Value == null) { - return -1; - } - if (lifter2Value == null) { - return 1; - } - return lifter1Value.compareTo(lifter2Value); - } - - /** - * Compare category. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - static int comparePresumedCategory(Athlete lifter1, Athlete lifter2) { - String lifter1Value = lifter1.getPresumedOpenCategoryString(); - String lifter2Value = lifter2.getPresumedOpenCategoryString(); - return ObjectUtils.compare(lifter1Value, lifter2Value, true); - } - - /** - * Compare absolute value of attempts prior to attempt "startingFrom" Start comparing attempted weights at - * "startingFrom". If attempted weight differ, smallest attempted weight comes first. If attempted weights are same, - * go back one attempt and keep comparing. + * Compare absolute value of attempts prior to attempt "startingFrom" Start comparing attempted weights at "startingFrom". If attempted weight differ, + * smallest attempted weight comes first. If attempted weights are same, go back one attempt and keep comparing. * * startingFrom is exclusive endingWith is inclusive, and is used to the previous attempts. * @@ -672,8 +679,7 @@ int comparePreviousLiftOrderExceptAtEnd(Athlete lifter1, Athlete lifter2) { } /** - * Determine who lifted first if both athletes are at same attempt and requesting same weight. Smaller previous - * attempt means lifted first. + * Determine who lifted first if both athletes are at same attempt and requesting same weight. Smaller previous attempt means lifted first. * * @param lifter1 the lifter 1 * @param lifter2 the lifter 2 @@ -740,6 +746,36 @@ int compareProgression(Athlete lifter1, Athlete lifter2) { } } + /** + * Compare Q-masters. + * + * @param lifter1 the lifter 1 + * @param lifter2 the lifter 2 + * @return the int + */ + int compareQAge(Athlete lifter1, Athlete lifter2) { + Gender gender = lifter1.getGender(); + if (gender == null) { + return -1; + } + int compare = gender.compareTo(lifter2.getGender()); + if (compare != 0) { + return compare; + } + + Double lifter1Value = lifter1.getQAge(); + Double lifter2Value = lifter2.getQAge(); + final Double notWeighed = 0D; + if (lifter1Value == null) { + lifter1Value = notWeighed; + } + if (lifter2Value == null) { + lifter2Value = notWeighed; + } + // bigger sinclair comes first + return -lifter1Value.compareTo(lifter2Value); + } + /** * Compare registration category. * @@ -816,6 +852,19 @@ int compareRobi(Athlete lifter1, Athlete lifter2) { return -lifter1Value.compareTo(lifter2Value); } + int compareScore(Athlete lifter1, Athlete lifter2) { + Double lifter1Value = lifter1.getCategoryScore(); + Double lifter2Value = lifter2.getCategoryScore(); + final Double notScored = 0D; + if (lifter1Value == null) { + lifter1Value = notScored; + } + if (lifter2Value == null) { + lifter2Value = notScored; + } + return lifter1Value.compareTo(lifter2Value); + } + /** * Compare sinclair. * @@ -876,36 +925,6 @@ int compareSinclairForDelta(Athlete lifter1, Athlete lifter2) { return -lifter1Value.compareTo(lifter2Value); } - /** - * Compare smm. - * - * @param lifter1 the lifter 1 - * @param lifter2 the lifter 2 - * @return the int - */ - int compareSmhfForDelta(Athlete lifter1, Athlete lifter2) { - Gender gender = lifter1.getGender(); - if (gender == null) { - return -1; - } - int compare = gender.compareTo(lifter2.getGender()); - if (compare != 0) { - return compare; - } - - Double lifter1Value = lifter1.getSmhfForDelta(); - Double lifter2Value = lifter2.getSmhfForDelta(); - final Double notWeighed = 0D; - if (lifter1Value == null) { - lifter1Value = notWeighed; - } - if (lifter2Value == null) { - lifter2Value = notWeighed; - } - // bigger sinclair comes first - return -lifter1Value.compareTo(lifter2Value); - } - /** * Compare SM(H)F. * @@ -935,15 +954,15 @@ int compareSmhf(Athlete lifter1, Athlete lifter2) { // bigger sinclair comes first return -lifter1Value.compareTo(lifter2Value); } - + /** - * Compare Q-masters. + * Compare smm. * * @param lifter1 the lifter 1 * @param lifter2 the lifter 2 * @return the int */ - int compareQAge(Athlete lifter1, Athlete lifter2) { + int compareSmhfForDelta(Athlete lifter1, Athlete lifter2) { Gender gender = lifter1.getGender(); if (gender == null) { return -1; @@ -953,8 +972,8 @@ int compareQAge(Athlete lifter1, Athlete lifter2) { return compare; } - Double lifter1Value = lifter1.getQAge(); - Double lifter2Value = lifter2.getQAge(); + Double lifter1Value = lifter1.getSmhfForDelta(); + Double lifter2Value = lifter2.getSmhfForDelta(); final Double notWeighed = 0D; if (lifter1Value == null) { lifter1Value = notWeighed; @@ -1001,29 +1020,4 @@ int compareTotal(Athlete lifter1, Athlete lifter2) { return lifter1Value.compareTo(lifter2Value); } - public static void traceComparison(String where, Athlete lifter1, Object v1, Athlete lifter2, Object v2, int compare) { - if (logger.isTraceEnabled()) { - logger./**/warn("{} {}={} {} {}={} {}", where, lifter1.getLastName(), v1, (compare < 0 ? " < " : (compare == 0 ? "=" : " > ")), - lifter2.getLastName(), v2, - LoggerUtils.whereFrom()); - } - } - - public static void doTraceComparison(String where, Object o1, Object v1, Object o2, Object v2, int compare) { - //if (logger.isTraceEnabled()) { - logger./**/warn("{} {}={} {} {}={} {}", where, o1.toString(), v1, (compare < 0 ? " < " : (compare == 0 ? "=" : " > ")), - o2.toString(), v2, - LoggerUtils.whereFrom(1)); - //} - } - - public static void traceComparison(String where, Object o1, Object value1, Object o2, Object value2, int compare) { - if (logger.isTraceEnabled()) { - logger./**/warn("{} {}={} {} {}={} {}", where, o1.toString(), value1, (compare < 0 ? " < " : (compare == 0 ? "=" : " > ")), - o2.toString(), value2, - LoggerUtils.whereFrom()); - } - } - - } diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/AthleteSorter.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/AthleteSorter.java index b977da8125..d6de37cc6f 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/AthleteSorter.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/AthleteSorter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -85,18 +85,6 @@ public static List assignCategoryRanks(EntityManager em, Group g) { return impactedAthletes; } - public static List fetchForCategoryRanks(EntityManager em, Group g) { - List impactedAthletes; - if (g != null) { - impactedAthletes = AthleteRepository.findAthletesForGlobalRanking(em, g); - // logger.debug"all athletes in group's categories {}", impactedAthletes); - } else { - impactedAthletes = AthleteRepository.doFindAllByGroupAndWeighIn(em, null, true, null); - // logger.debug("all athletes in all groups {}", impactedAthletes); - } - return impactedAthletes; - } - /** * Assign ranks within each category, for all athletes in categories present in group. Returns the list of these athletes (i.e. not only these in group g) * @@ -192,24 +180,6 @@ public static void assignOverallRanksAndPoints(List sortedList, Ranking } } - /** - * Assign start numbers to athletes. - * - * @param sortedList the sorted list - */ - public static void doAssignStartNumbers(List sortedList) { - int rank = 1; - for (Athlete curLifter : sortedList) { - Double bodyWeight = curLifter.getBodyWeight(); - if (bodyWeight != null && bodyWeight > 0.0D) { - curLifter.setStartNumber(rank); - rank++; - } else { - curLifter.setStartNumber(0); - } - } - } - /** * Compute the number of lifts already done. During snatch, exclude cj * @@ -263,6 +233,24 @@ static public List displayOrderCopy(List toBeSorted) { return sorted; } + /** + * Assign start numbers to athletes. + * + * @param sortedList the sorted list + */ + public static void doAssignStartNumbers(List sortedList) { + int rank = 1; + for (Athlete curLifter : sortedList) { + Double bodyWeight = curLifter.getBodyWeight(); + if (bodyWeight != null && bodyWeight > 0.0D) { + curLifter.setStartNumber(rank); + rank++; + } else { + curLifter.setStartNumber(0); + } + } + } + /** * Assign lot numbers at random. * @@ -276,6 +264,18 @@ static public List drawLots(List toBeShuffled) { return shuffled; } + public static List fetchForCategoryRanks(EntityManager em, Group g) { + List impactedAthletes; + if (g != null) { + impactedAthletes = AthleteRepository.findAthletesForGlobalRanking(em, g); + // logger.debug"all athletes in group's categories {}", impactedAthletes); + } else { + impactedAthletes = AthleteRepository.doFindAllByGroupAndWeighIn(em, null, true, null); + // logger.debug("all athletes in all groups {}", impactedAthletes); + } + return impactedAthletes; + } + /** * Gets the rank. * @@ -648,6 +648,22 @@ public static TopScore topScore(List sortedAthletes, int nbAthletes) { } } + public static List updateEligibleCategoryRanks(List absoluteOrderList, Ranking rankingType, Category category) { + List newList = new ArrayList<>(); + MultiCategoryRankSetter rt = new MultiCategoryRankSetter(); + for (Athlete curLifter : absoluteOrderList) { + final double rankingValue = Ranking.getRankingValue(curLifter, rankingType); + // we must update the original participations attached to the original athlete, on all updates. + Athlete realAthlete = ((PAthlete) curLifter)._getAthlete(); + Participation participation = rt.increment(realAthlete, rankingType, rankingValue, category); + PAthlete e = new PAthlete(participation); + // logger.debug("new PAthlete realAthlete={} _getAthlete={}", System.identityHashCode(realAthlete), System.identityHashCode(e._getAthlete())); + // Competition.dumpAthlete("realAthlete", realAthlete); + newList.add(e); + } + return newList; + } + /** * Assign ranks, sequentially. * @@ -665,22 +681,6 @@ private static void assignEligibleCategoryRanks(List absoluteOrderList, } } - public static List updateEligibleCategoryRanks(List absoluteOrderList, Ranking rankingType, Category category) { - List newList = new ArrayList(); - MultiCategoryRankSetter rt = new MultiCategoryRankSetter(); - for (Athlete curLifter : absoluteOrderList) { - final double rankingValue = Ranking.getRankingValue(curLifter, rankingType); - // we must update the original participations attached to the original athlete, on all updates. - Athlete realAthlete = ((PAthlete) curLifter)._getAthlete(); - Participation participation = rt.increment(realAthlete, rankingType, rankingValue, category); - PAthlete e = new PAthlete(participation); - // logger.debug("new PAthlete realAthlete={} _getAthlete={}", System.identityHashCode(realAthlete), System.identityHashCode(e._getAthlete())); - // Competition.dumpAthlete("realAthlete", realAthlete); - newList.add(e); - } - return newList; - } - /** * @param curLifter * @param rankingType diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftOrderComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftOrderComparator.java index e15873b282..b9cebcf870 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftOrderComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftOrderComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftTimeStampComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftTimeStampComparator.java index cf0f187aa6..e0e11ac580 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftTimeStampComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/LiftTimeStampComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -11,8 +11,8 @@ import app.owlcms.data.athlete.Athlete; /** - * This comparator is used to highlight the athletes that have lifted recently, and are likely to request changes to the - * automatic progression. It simply sorts according to time stamp, if available. Else lot number is used. + * This comparator is used to highlight the athletes that have lifted recently, and are likely to request changes to the automatic progression. It simply sorts + * according to time stamp, if available. Else lot number is used. * * @author jflamy * diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/MultiCategoryRankSetter.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/MultiCategoryRankSetter.java index 8ab2cf1c03..7ce1eebcfc 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/MultiCategoryRankSetter.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/MultiCategoryRankSetter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -43,7 +43,8 @@ public Participation increment(Athlete a, Ranking r, double rankingValue, Catego Participation participation = a.getMainRankings(); int rank = eligible ? (rankingValue == 0 ? 0 : ++this.rank) : -1; - // logger.debug("c {} r {} -- a {}/{} v {} z {} e {} rank={} {}", participationCategory, r, a.getAbbreviatedName(), System.identityHashCode(a), rankingValue, zero, eligible, rank, ""); // LoggerUtils.stackTrace()); + // logger.debug("c {} r {} -- a {}/{} v {} z {} e {} rank={} {}", participationCategory, r, a.getAbbreviatedName(), System.identityHashCode(a), + // rankingValue, zero, eligible, rank, ""); // LoggerUtils.stackTrace()); switch (r) { case SNATCH: case CLEANJERK: @@ -106,7 +107,8 @@ private Participation doCategoryBasedRankings(Athlete a, Ranking r, Category cat this.snatchRank = this.snatchRank + 1; p.setSnatchRank(this.snatchRank); curRankings.setSnatchRank(this.snatchRank); - // logger.debug("setting snatch rank {} {} {} p={} a={}", a, curCat, snatchRank, System.identityHashCode(p), System.identityHashCode(p.getAthlete())); + // logger.debug("setting snatch rank {} {} {} p={} a={}", a, curCat, snatchRank, System.identityHashCode(p), + // System.identityHashCode(p.getAthlete())); } else { p.setSnatchRank(a.isEligibleForIndividualRanking() ? 0 : -1); // logger.debug("skipping snatch rank {} {} {}", a, curCat, this.snatchRank); @@ -120,7 +122,8 @@ private Participation doCategoryBasedRankings(Athlete a, Ranking r, Category cat this.cjRank = this.cjRank + 1; p.setCleanJerkRank(this.cjRank); curRankings.setCleanJerkRank(this.cjRank); - // logger.debug("setting clean&jerk rank {} {} {} p {} a {}", a, curCat, cjRank, System.identityHashCode(p), // System.identityHashCode(p.getAthlete())); + // logger.debug("setting clean&jerk rank {} {} {} p {} a {}", a, curCat, cjRank, System.identityHashCode(p), // + // System.identityHashCode(p.getAthlete())); } else { p.setCleanJerkRank(a.isEligibleForIndividualRanking() ? 0 : -1); // logger.debug("skipping clean&jerk rank {} {} {}", a, curCat, 0); @@ -134,7 +137,8 @@ private Participation doCategoryBasedRankings(Athlete a, Ranking r, Category cat this.totalRank = this.totalRank + 1; p.setTotalRank(this.totalRank); curRankings.setTotalRank(this.totalRank); - // logger.debug("setting total rank {} {} {} p {} a {}", a, curCat, totalRank, System.identityHashCode(p), // System.identityHashCode(p.getAthlete())); + // logger.debug("setting total rank {} {} {} p {} a {}", a, curCat, totalRank, System.identityHashCode(p), // + // System.identityHashCode(p.getAthlete())); } else { p.setTotalRank(a.isEligibleForIndividualRanking() ? 0 : -1); diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/OverallRankSetter.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/OverallRankSetter.java index 9a59695a2c..8dafb86c4d 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/OverallRankSetter.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/OverallRankSetter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -54,9 +54,9 @@ public void increment(Athlete a, Ranking r, boolean eligible, boolean zero) { } private int incrementRank(Ranking ranking) { - rank++; - //logger.debug("incrementing ranking {} to {}", ranking, rank); - return rank; + this.rank++; + // logger.debug("incrementing ranking {} to {}", ranking, rank); + return this.rank; } } diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/Ranking.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/Ranking.java index 348976f3af..9c35a49ff3 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/Ranking.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/Ranking.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.athleteSort; import java.util.ArrayList; @@ -18,36 +24,46 @@ */ public enum Ranking { // category values - SNATCH("Sn",false), - CLEANJERK("CJ",false), - TOTAL("Tot",false), - CUSTOM("Cus",false), // modified total / custom score (e.g. technical merit for kids competition) - SNATCH_CJ_TOTAL("Combined",false), // sum of all three point scores - CATEGORY_SCORE("SCORE",false), // copy of TOTAL, CUSTOM or any of the global scoring systems if used to award category medals + SNATCH("Sn", false), + CLEANJERK("CJ", false), + TOTAL("Tot", false), + CUSTOM("Cus", false), // modified total / custom score (e.g. technical merit for kids competition) + SNATCH_CJ_TOTAL("Combined", false), // sum of all three point scores + CATEGORY_SCORE("SCORE", false), // copy of TOTAL, CUSTOM or any of the global scoring systems if used to award category medals // global scoring systems - BW_SINCLAIR("Sinclair",true), // normal Sinclair - CAT_SINCLAIR("CatSinclair",true), // legacy Quebec federation, Sinclair computed at category boundary - SMM("Smm",true), // Legacy name, kept for import/export backward compatibility Sinclair Meltzer Huebner Faber - ROBI("Robi",true), // IWF ROBI - QPOINTS("QPoints",true), // Huebner QPoints. - GAMX("GAMX",true), // Global Adjusted Mixed (Huebner) - AGEFACTORS("QYouth",true), - QAGE("QMasters",true), // QPoints * SMHF age factors + BW_SINCLAIR("Sinclair", true), // normal Sinclair + CAT_SINCLAIR("CatSinclair", true), // legacy Quebec federation, Sinclair computed at category boundary + SMM("Smm", true), // Legacy name, kept for import/export backward compatibility Sinclair Meltzer Huebner Faber + ROBI("Robi", true), // IWF ROBI + QPOINTS("QPoints", true), // Huebner QPoints. + GAMX("GAMX", true), // Global Adjusted Mixed (Huebner) + AGEFACTORS("QYouth", true), + QAGE("QMasters", true), // QPoints * SMHF age factors ; - + public static Map rankingByReportingName = new HashMap<>(); static { for (Ranking r : Ranking.values()) { rankingByReportingName.put(r.reportingName.toLowerCase(), r); rankingByReportingName.put(r.name().toLowerCase(), r); - + } rankingByReportingName.put("smhf", SMM); } - static Logger logger = (Logger) LoggerFactory.getLogger(Ranking.class); + public static String formatScoreboardRank(Integer total) { + if (total == null || total == 0) { + return "-"; + } else if (total == -1) { + // invited lifter, not eligible. + return Translator.translate("Results.Extra/Invited"); + } else { + return total.toString(); + } + } + public static int getRanking(Athlete curLifter, Ranking rankingType) { Integer value = null; if (rankingType == null) { @@ -175,7 +191,7 @@ public static double getRankingValue(Athlete curLifter, Ranking rankingType) { return d != null ? d : 0D; } - public static String getScoringTitle(Ranking rankingType) { + public static String getScoringExplanation(Ranking rankingType) { if (rankingType == null || rankingType == Ranking.CATEGORY_SCORE) { return Translator.translate("Score"); } @@ -190,13 +206,13 @@ public static String getScoringTitle(Ranking rankingType) { case AGEFACTORS: case QAGE: case TOTAL: - return Translator.translate("Ranking." + rankingType); + return Translator.translate("RankingExplanation." + rankingType); default: throw new UnsupportedOperationException("not a score ranking " + rankingType); } } - public static String getScoringExplanation(Ranking rankingType) { + public static String getScoringTitle(Ranking rankingType) { if (rankingType == null || rankingType == Ranking.CATEGORY_SCORE) { return Translator.translate("Score"); } @@ -211,7 +227,7 @@ public static String getScoringExplanation(Ranking rankingType) { case AGEFACTORS: case QAGE: case TOTAL: - return Translator.translate("RankingExplanation." + rankingType); + return Translator.translate("Ranking." + rankingType); default: throw new UnsupportedOperationException("not a score ranking " + rankingType); } @@ -226,7 +242,7 @@ public static List scoringSystems() { private boolean medalScore; /** - * @param medalScore + * @param medalScore * @param reportingInfoName the name of the beans used for Excel reporting */ Ranking(String reportingName, boolean medalScore) { @@ -246,19 +262,8 @@ public String getWReportingName() { return "w" + this.reportingName; } - public static String formatScoreboardRank(Integer total) { - if (total == null || total == 0) { - return "-"; - } else if (total == -1) { - // invited lifter, not eligible. - return Translator.translate("Results.Extra/Invited"); - } else { - return total.toString(); - } - } - public boolean isMedalScore() { - return medalScore; + return this.medalScore; } public void setMedalScore(boolean medalScore) { diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationBWComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationBWComparator.java index 48b438b029..aa10010d57 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationBWComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationBWComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationExportComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationExportComparator.java index 1e5176b17d..9d455efa58 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationExportComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationExportComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationOrderComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationOrderComparator.java index ec19160087..8304fe19a8 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationOrderComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/RegistrationOrderComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/StartNumberOrderComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/StartNumberOrderComparator.java index b972c083a7..d6ad382b9b 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/StartNumberOrderComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/StartNumberOrderComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsComparator.java index 25c9ecf0c9..8068012f2d 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsPComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsPComparator.java index 16a6a69e03..b0afca789f 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsPComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamPointsPComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamRankingComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamRankingComparator.java index 0c26ec1e16..27b4182ad4 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamRankingComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/TeamRankingComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/athleteSort/WinningOrderComparator.java b/owlcms/src/main/java/app/owlcms/data/athleteSort/WinningOrderComparator.java index 7191f2f9ad..1b08317251 100644 --- a/owlcms/src/main/java/app/owlcms/data/athleteSort/WinningOrderComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/athleteSort/WinningOrderComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -82,6 +82,20 @@ public int compare(Athlete lifter1, Athlete lifter2) { return 0; } + public int compareAgeAdjustedTotal(Athlete lifter1, Athlete lifter2) { + Double lifter1Value = lifter1.getAgeAdjustedTotal(); + Double lifter2Value = lifter2.getAgeAdjustedTotal(); + final Double notWeighed = 0D; + if (lifter1Value == null) { + lifter1Value = notWeighed; + } + if (lifter2Value == null) { + lifter2Value = notWeighed; + } + // bigger adjusted total comes first + return -lifter1Value.compareTo(lifter2Value); + } + /** * Determine who ranks first on AgeFactor-adjusted total. * @@ -104,20 +118,6 @@ public int compareAgeAdjustedTotalOrder(Athlete lifter1, Athlete lifter2) { return tieBreak(lifter1, lifter2, true); } - public int compareAgeAdjustedTotal(Athlete lifter1, Athlete lifter2) { - Double lifter1Value = lifter1.getAgeAdjustedTotal(); - Double lifter2Value = lifter2.getAgeAdjustedTotal(); - final Double notWeighed = 0D; - if (lifter1Value == null) { - lifter1Value = notWeighed; - } - if (lifter2Value == null) { - lifter2Value = notWeighed; - } - // bigger adjusted total comes first - return -lifter1Value.compareTo(lifter2Value); - } - /** * Determine who ranks first. the Athlete who reached total first is ranked first. * @@ -201,32 +201,6 @@ public int compareCustomResultOrder(Athlete lifter1, Athlete lifter2, boolean ig return tieBreak(lifter1, lifter2, Competition.getCurrent().isUseOldBodyWeightTieBreak()); } - public int compareScoreResultOrder(Athlete lifter1, Athlete lifter2, boolean ignoreCategories) { - int compare = 0; - - if (!ignoreCategories) { - compare = ObjectUtils.compare(lifter1.getCategory(), lifter2.getCategory(), true); - traceComparison("!ignoreCategories", lifter1, lifter2, compare); - if (compare != 0) { - return compare; - } - } - - compare = compareScore(lifter1, lifter2); - traceComparison("score", lifter1, lifter2, compare); - if (compare != 0) { - return -compare; // we want reverse order - smaller comes after - } - - compare = compareTotal(lifter1, lifter2); - traceComparison("total", lifter1, lifter2, compare); - if (compare != 0) { - return -compare; // we want reverse order - smaller comes after - } - - return tieBreak(lifter1, lifter2, Competition.getCurrent().isUseOldBodyWeightTieBreak()); - } - /** * Determine who ranks first on GAMX points. * @@ -258,23 +232,19 @@ public int compareGamxResultOrder(Athlete lifter1, Athlete lifter2) { * @param lifter2 the lifter 2 * @return the int */ - public int compareQPointsResultOrder(Athlete lifter1, Athlete lifter2) { + public int compareQAgeResultOrder(Athlete lifter1, Athlete lifter2) { int compare = 0; compare = ObjectUtils.compare(lifter1.getGender(), lifter2.getGender()); if (compare != 0) { return compare; } - if (Config.getCurrent().featureSwitch("interimScores")) { - compare = compareQPointsForDelta(lifter1, lifter2); - } else { - compare = compareQPoints(lifter1, lifter2); - } + compare = compareQAge(lifter1, lifter2); traceComparison("qPoints", lifter1, lifter2, compare); if (compare != 0) { return compare; } compare = compareBodyWeight(lifter1, lifter2); - traceComparison("qpoints compareBodyWeight", lifter1, lifter2, compare); + traceComparison("qage compareBodyWeight", lifter1, lifter2, compare); return compare; // smaller Athlete wins } @@ -285,19 +255,23 @@ public int compareQPointsResultOrder(Athlete lifter1, Athlete lifter2) { * @param lifter2 the lifter 2 * @return the int */ - public int compareQAgeResultOrder(Athlete lifter1, Athlete lifter2) { + public int compareQPointsResultOrder(Athlete lifter1, Athlete lifter2) { int compare = 0; compare = ObjectUtils.compare(lifter1.getGender(), lifter2.getGender()); if (compare != 0) { return compare; } - compare = compareQAge(lifter1, lifter2); + if (Config.getCurrent().featureSwitch("interimScores")) { + compare = compareQPointsForDelta(lifter1, lifter2); + } else { + compare = compareQPoints(lifter1, lifter2); + } traceComparison("qPoints", lifter1, lifter2, compare); if (compare != 0) { return compare; } compare = compareBodyWeight(lifter1, lifter2); - traceComparison("qage compareBodyWeight", lifter1, lifter2, compare); + traceComparison("qpoints compareBodyWeight", lifter1, lifter2, compare); return compare; // smaller Athlete wins } @@ -326,6 +300,32 @@ public int compareRobiResultOrder(Athlete lifter1, Athlete lifter2) { return compare; // smaller Athlete wins } + public int compareScoreResultOrder(Athlete lifter1, Athlete lifter2, boolean ignoreCategories) { + int compare = 0; + + if (!ignoreCategories) { + compare = ObjectUtils.compare(lifter1.getCategory(), lifter2.getCategory(), true); + traceComparison("!ignoreCategories", lifter1, lifter2, compare); + if (compare != 0) { + return compare; + } + } + + compare = compareScore(lifter1, lifter2); + traceComparison("score", lifter1, lifter2, compare); + if (compare != 0) { + return -compare; // we want reverse order - smaller comes after + } + + compare = compareTotal(lifter1, lifter2); + traceComparison("total", lifter1, lifter2, compare); + if (compare != 0) { + return -compare; // we want reverse order - smaller comes after + } + + return tieBreak(lifter1, lifter2, Competition.getCurrent().isUseOldBodyWeightTieBreak()); + } + /** * Determine who ranks first on Sinclair points. * @@ -514,7 +514,6 @@ int compareQPoints(Athlete lifter1, Athlete lifter2) { // traceComparison("qpoints", lifter1, lifter2, compare); return compare; } - /** * Compare Q-Points. diff --git a/owlcms/src/main/java/app/owlcms/data/category/Category.java b/owlcms/src/main/java/app/owlcms/data/category/Category.java index b6ec07c3e0..a31d65abeb 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/Category.java +++ b/owlcms/src/main/java/app/owlcms/data/category/Category.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -69,6 +69,47 @@ public class Category implements Serializable, Comparable, Cloneable { public final static Double ROBI_B = 3.321928095; @Transient final private static Logger logger = (Logger) LoggerFactory.getLogger(Category.class); + public static Comparator specificityComparator = (a, b) -> { + if (a == null || b == null) { + return ObjectUtils.compare(a, b, true); + } + var aAgeGroup = a.getAgeGroup(); + var bAgeGroup = b.getAgeGroup(); + if (aAgeGroup == null || bAgeGroup == null) { + return ObjectUtils.compare(aAgeGroup, bAgeGroup, true); + } + int compare; + + compare = ObjectUtils.compare(aAgeGroup.getGender(), bAgeGroup.getGender()); + if (compare != 0) { + return compare; + } + + int aDelta = aAgeGroup.getMaxAge() - aAgeGroup.getMinAge(); + int bDelta = bAgeGroup.getMaxAge() - bAgeGroup.getMinAge(); + compare = Integer.compare(aDelta, bDelta); + if (compare != 0) { + return compare; + } + + // military masters 35-39 with no bw categories will be less specific than masters 35-39 + int aCatNum = aAgeGroup.getCategories().size(); + int bCatNum = bAgeGroup.getCategories().size(); + // more categories comes first + compare = -Integer.compare(aCatNum, bCatNum); + + return compare; + }; + + public static String codeFromName(String catName) { + Category cat = CategoryRepository.codeFromName(catName); + return cat != null ? cat.getCode() : null; + } + + public static Comparator medalingComparator() { + return (a, b) -> ObjectUtils.compare(a.getMedalingSortCode(), b.getMedalingSortCode()); + } + /** The maximum weight. */ Double maximumWeight; // exclusive /** The minimum weight. */ @@ -79,7 +120,6 @@ public class Category implements Serializable, Comparable, Cloneable { @JoinColumn(name = "agegroup_id") @JsonIdentityReference(alwaysAsId = true) private AgeGroup ageGroup; - // combines age group and bw category (which includes gender). private String code; @Enumerated(EnumType.STRING) @@ -170,34 +210,6 @@ public int compareTo(Category o) { return compare; } - public static Comparator specificityComparator = (a, b) -> { - if (a == null || b == null) - return ObjectUtils.compare(a, b, true); - var aAgeGroup = a.getAgeGroup(); - var bAgeGroup = b.getAgeGroup(); - if (aAgeGroup == null || bAgeGroup == null) - return ObjectUtils.compare(aAgeGroup, bAgeGroup, true); - int compare; - - compare = ObjectUtils.compare(aAgeGroup.getGender(), bAgeGroup.getGender()); - if (compare != 0) - return compare; - - int aDelta = aAgeGroup.getMaxAge() - aAgeGroup.getMinAge(); - int bDelta = bAgeGroup.getMaxAge() - bAgeGroup.getMinAge(); - compare = Integer.compare(aDelta, bDelta); - if (compare != 0) - return compare; - - // military masters 35-39 with no bw categories will be less specific than masters 35-39 - int aCatNum = aAgeGroup.getCategories().size(); - int bCatNum = bAgeGroup.getCategories().size(); - // more categories comes first - compare = -Integer.compare(aCatNum, bCatNum); - - return compare; - }; - public String dump() { return "Category [code=" + this.code + ", name=" + getSafeName() + ", minimumWeight=" + this.minimumWeight + ", maximumWeight=" @@ -271,62 +283,6 @@ public String getCodeLimitString() { } } - @Transient - @JsonIgnore - public String getSortCodeLimitString() { - if (this.id == null || this.maximumWeight == null - || this.maximumWeight - Math.round(this.maximumWeight) > 0.1) { - String val = "temp_" + this.minimumWeight + "_" + this.maximumWeight; - return val; - } - if (this.maximumWeight > 130) { - return "999"; - } else { - return String.format("%03d", (int) (Math.round(this.maximumWeight))); - } - } - - @JsonIgnore - @Transient - public String getSortCode() { - String agName = (this.ageGroup != null ? this.ageGroup.getName() : ""); - - String result; - if (agName == null || agName.isEmpty()) { - String catName = "zzzz" + "_" + getGender() + getSortCodeLimitString(); - result = catName; - } else { - result = this.ageGroup.getCode() + "_" + getGender() + getSortCodeLimitString(); - } - // logger.debug("Category {} sort code {}", this, result); - return result; - } - - @JsonIgnore - @Transient - public String getMedalingSortCode() { - String agName = (this.ageGroup != null ? this.ageGroup.getName() : ""); - - String result; - if (agName == null || agName.isEmpty()) { - String catName = "zzzz" + "_" + getGender() + getSortCodeLimitString(); - result = catName; - } else { - result = this.ageGroup.getAgeFirstSortCode() + "_" + getSortCodeLimitString(); - } - //logger.debug("Category {} sort code {}", this, result); - return result; - } - - public static Comparator medalingComparator() { - return (a,b) -> ObjectUtils.compare(a.getMedalingSortCode(), b.getMedalingSortCode()); - } - - @JsonIgnore - @Transient - public void setMedalingSortCode() { - } - @JsonIgnore @Transient public String getComputedCode() { @@ -358,20 +314,6 @@ public String getDisplayName() { return result.trim(); } - @JsonIgnore - @Transient - ChampionshipType getChampionshipType() { - ChampionshipType championshipType = this.ageGroup != null ? ageGroup.getChampionshipType() : null; - return championshipType; - } - - @JsonIgnore - @Transient - private boolean isAlreadyGendered() { - boolean alreadyGendered = this.ageGroup != null ? ageGroup.isAlreadyGendered() : false; - return alreadyGendered; - } - /** * Gets the gender. * @@ -422,6 +364,22 @@ public Double getMaximumWeight() { return this.maximumWeight; } + @JsonIgnore + @Transient + public String getMedalingSortCode() { + String agName = (this.ageGroup != null ? this.ageGroup.getName() : ""); + + String result; + if (agName == null || agName.isEmpty()) { + String catName = "zzzz" + "_" + getGender() + getSortCodeLimitString(); + result = catName; + } else { + result = this.ageGroup.getAgeFirstSortCode() + "_" + getSortCodeLimitString(); + } + // logger.debug("Category {} sort code {}", this, result); + return result; + } + /** * Gets the minimum weight. * @@ -431,6 +389,36 @@ public Double getMinimumWeight() { return this.minimumWeight; } + public String getName() { + return this.name; + } + + @JsonIgnore + @Transient + public String getNameWithAgeGroup() { + String agName = (this.ageGroup != null ? this.ageGroup.getName() : ""); + String catName = getLimitString(); + String result; + if (agName == null || agName.isEmpty()) { + result = getTranslatedGender() + " " + catName; + } else { + result = agName + " " + catName; + } + return result.trim(); + } + + @JsonIgnore + public List getParticipations() { + return this.participations; + } + + /** + * @return the qualifyingTotal + */ + public int getQualifyingTotal() { + return this.qualifyingTotal; + } + /** * Gets the name. * @@ -446,19 +434,38 @@ public String getSafeName() { } @JsonIgnore - public List getParticipations() { - return this.participations; + @Transient + public String getSortCode() { + String agName = (this.ageGroup != null ? this.ageGroup.getName() : ""); + + String result; + if (agName == null || agName.isEmpty()) { + String catName = "zzzz" + "_" + getGender() + getSortCodeLimitString(); + result = catName; + } else { + result = this.ageGroup.getCode() + "_" + getGender() + getSortCodeLimitString(); + } + // logger.debug("Category {} sort code {}", this, result); + return result; } - /** - * @return the qualifyingTotal - */ - public int getQualifyingTotal() { - return this.qualifyingTotal; + @Transient + @JsonIgnore + public String getSortCodeLimitString() { + if (this.id == null || this.maximumWeight == null + || this.maximumWeight - Math.round(this.maximumWeight) > 0.1) { + String val = "temp_" + this.minimumWeight + "_" + this.maximumWeight; + return val; + } + if (this.maximumWeight > 130) { + return "999"; + } else { + return String.format("%03d", (int) (Math.round(this.maximumWeight))); + } } public String getTranslatedGender() { - if (gender == null) { + if (this.gender == null) { return ""; } switch (getGender()) { @@ -471,20 +478,6 @@ public String getTranslatedGender() { } } - @JsonIgnore - @Transient - public String getNameWithAgeGroup() { - String agName = (this.ageGroup != null ? this.ageGroup.getName() : ""); - String catName = getLimitString(); - String result; - if (agName == null || agName.isEmpty()) { - result = getTranslatedGender() + " " + catName; - } else { - result = agName + " " + catName; - } - return result.trim(); - } - public String getUpperBound() { if (getMaximumWeight() > 998) { return ">" + Math.round(getMinimumWeight()); @@ -553,13 +546,6 @@ public Integer getWrYth() { return this.wrYth; } - /** - * @return a code that changes if the category was edited in a way that requires reassigning athletes - */ - public int reassignmentHashCode() { - return Objects.hash(code, gender, maximumWeight, minimumWeight, qualifyingTotal); - } - @Override public int hashCode() { return Objects.hash(getSafeName()); @@ -588,6 +574,13 @@ public String longDump() { + ", code=" + this.code + "]"; } + /** + * @return a code that changes if the category was edited in a way that requires reassigning athletes + */ + public int reassignmentHashCode() { + return Objects.hash(this.code, this.gender, this.maximumWeight, this.minimumWeight, this.qualifyingTotal); + } + public boolean sameAs(Category prevCat) { return this.compareTo(prevCat) == 0; } @@ -639,6 +632,11 @@ public void setMaximumWeight(Double maximumWeight) { this.maximumWeight = maximumWeight; } + @JsonIgnore + @Transient + public void setMedalingSortCode() { + } + /** * Sets the minimum weight. * @@ -696,13 +694,18 @@ public String toString() { return getDisplayName(); } - public String getName() { - return name; + @JsonIgnore + @Transient + ChampionshipType getChampionshipType() { + ChampionshipType championshipType = this.ageGroup != null ? this.ageGroup.getChampionshipType() : null; + return championshipType; } - public static String codeFromName(String catName) { - Category cat = CategoryRepository.codeFromName(catName); - return cat != null ? cat.getCode() : null; + @JsonIgnore + @Transient + private boolean isAlreadyGendered() { + boolean alreadyGendered = this.ageGroup != null ? this.ageGroup.isAlreadyGendered() : false; + return alreadyGendered; } } diff --git a/owlcms/src/main/java/app/owlcms/data/category/CategoryRankingHolder.java b/owlcms/src/main/java/app/owlcms/data/category/CategoryRankingHolder.java index d06c3c9f75..ec7968c10b 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/CategoryRankingHolder.java +++ b/owlcms/src/main/java/app/owlcms/data/category/CategoryRankingHolder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -20,6 +20,10 @@ public class CategoryRankingHolder implements IRankHolder { protected int totalRank = 0; protected int categoryScoreRank = 0; + public int getCategoryScoreRank() { + return this.categoryScoreRank; + } + public int getCleanJerkRank() { return this.cleanJerkRank; } @@ -40,6 +44,10 @@ public int getTotalRank() { return this.totalRank; } + public void setCategoryScoreRank(int scoreRank) { + this.categoryScoreRank = scoreRank; + } + public void setCleanJerkRank(int cleanJerkRank) { this.cleanJerkRank = cleanJerkRank; } @@ -59,12 +67,4 @@ public void setSnatchRank(int snatchRank) { public void setTotalRank(int totalRank) { this.totalRank = totalRank; } - - public int getCategoryScoreRank() { - return categoryScoreRank; - } - - public void setCategoryScoreRank(int scoreRank) { - this.categoryScoreRank = scoreRank; - } } diff --git a/owlcms/src/main/java/app/owlcms/data/category/CategoryRepository.java b/owlcms/src/main/java/app/owlcms/data/category/CategoryRepository.java index f4f5110719..5f7355d859 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/CategoryRepository.java +++ b/owlcms/src/main/java/app/owlcms/data/category/CategoryRepository.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -41,6 +41,12 @@ public class CategoryRepository { logger.setLevel(Level.INFO); } + public static Category codeFromName(String catName) { + synchronized (allCategories) { + return allCategories.get(catName.trim()); + } + } + /** * Count filtered. * @@ -110,7 +116,7 @@ public static Category doFindByName(String string, EntityManager em) { public static List doFindEligibleCategories(Athlete a, Gender gender, Integer ageFromFields, Double bw, int qualifyingTotal) { - + List allEligible = CategoryRepository.findByGenderAgeBW(gender, ageFromFields, null); if (logger.isEnabledFor(Level.TRACE) && a.getLastName().contentEquals("Molnar")) { logger.trace("allEligible bw={} {} -- {}", bw, allEligible.size(), LoggerUtils.whereFrom()); @@ -127,24 +133,6 @@ public static List doFindEligibleCategories(Athlete a, Gender gender, return allEligible; } - private static List checkMultipleBWClasses(Gender gender, Integer ageFromFields, Double bw, - List allEligible) { - // > 998 is our signal for max weight in category - if ((bw != null && bw > 998) && !allEligible.isEmpty()) { - double bodyWeight = allEligible.get(0).getMinimumWeight() + 1; - List otherEligibles = CategoryRepository.findByGenderAgeBW(gender, ageFromFields, bodyWeight); - HashSet allEligibleSet = new HashSet<>(allEligible); - for (Category otherEligible : otherEligibles) { - if (!otherEligible.sameAsAny(allEligibleSet)) { - allEligible.add(otherEligible); - } - } - allEligible = allEligible.stream() - .collect(Collectors.toList()); - } - return allEligible; - } - public static List doFindFiltered(EntityManager em, String name, Gender gender, Championship ageDivision, AgeGroup ageGroup, Integer age, Double bodyWeight, Boolean active, int offset, int limit) { String qlString = "select c from Category c" @@ -174,8 +162,8 @@ public static List findActive() { List findFiltered = findFiltered((String) null, (Gender) null, (Championship) null, (AgeGroup) null, (Integer) null, (Double) null, true, -1, -1); - - //logger.debug("findActive **** {} {}", findFiltered.size(), LoggerUtils.stackTrace()); + + // logger.debug("findActive **** {} {}", findFiltered.size(), LoggerUtils.stackTrace()); findFiltered.sort(new RegistrationPreferenceComparator()); return findFiltered; } @@ -310,6 +298,17 @@ public static Category getById(Long id, EntityManager em) { return (Category) query.getResultList().stream().findFirst().orElse(null); } + public static void resetCodeMap() { + synchronized (allCategories) { + findActive().stream() + // .peek(c -> logger.debug("============ adding {} ; {} : {}", c.getDisplayName(), c.getNameWithAgeGroup(), c.getCode())) + .forEach(c -> { + allCategories.put(c.getDisplayName(), c); + allCategories.put(c.getNameWithAgeGroup(), c); + }); + } + } + /** * Save. * @@ -325,6 +324,24 @@ public static Category save(Category category) { }); } + private static List checkMultipleBWClasses(Gender gender, Integer ageFromFields, Double bw, + List allEligible) { + // > 998 is our signal for max weight in category + if ((bw != null && bw > 998) && !allEligible.isEmpty()) { + double bodyWeight = allEligible.get(0).getMinimumWeight() + 1; + List otherEligibles = CategoryRepository.findByGenderAgeBW(gender, ageFromFields, bodyWeight); + HashSet allEligibleSet = new HashSet<>(allEligible); + for (Category otherEligible : otherEligibles) { + if (!otherEligible.sameAsAny(allEligibleSet)) { + allEligible.add(otherEligible); + } + } + allEligible = allEligible.stream() + .collect(Collectors.toList()); + } + return allEligible; + } + private static String filteringJoins(AgeGroup ag, Integer age) { List fromList = new LinkedList<>(); // if (ag != null || age != null) { @@ -409,21 +426,4 @@ private static void setFilteringParameters(String name, Gender gender, Champions query.setParameter("gender", gender); } } - - public static void resetCodeMap() { - synchronized (allCategories) { - findActive().stream() - //.peek(c -> logger.debug("============ adding {} ; {} : {}", c.getDisplayName(), c.getNameWithAgeGroup(), c.getCode())) - .forEach(c -> { - allCategories.put(c.getDisplayName(), c); - allCategories.put(c.getNameWithAgeGroup(), c); - }); - } - } - - public static Category codeFromName(String catName) { - synchronized (allCategories) { - return allCategories.get(catName.trim()); - } - } } diff --git a/owlcms/src/main/java/app/owlcms/data/category/IRankHolder.java b/owlcms/src/main/java/app/owlcms/data/category/IRankHolder.java index 66f5b15157..1033ed548e 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/IRankHolder.java +++ b/owlcms/src/main/java/app/owlcms/data/category/IRankHolder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/category/Participation.java b/owlcms/src/main/java/app/owlcms/data/category/Participation.java index 41587ade99..887565efa0 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/Participation.java +++ b/owlcms/src/main/java/app/owlcms/data/category/Participation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -30,8 +30,7 @@ /** * Association class between Athlete and Category. Holds rankings and points of athlete and category. * - * An athlete participates in one or more category (when eligible according to age, gender and qualifying total). A - * category contains zero or more athletes. + * An athlete participates in one or more category (when eligible according to age, gender and qualifying total). A category contains zero or more athletes. * * @author Jean-François Lamy */ @@ -69,8 +68,8 @@ public class Participation implements IRankHolder { @Column(columnDefinition = "integer default 0") private int teamCombinedRank; /** - * Athlete is member of team for the age group. Points will be scored according to ranks. An athlete can be - * qualified for JR and SR, but only on the JR team for example. + * Athlete is member of team for the age group. Points will be scored according to ranks. An athlete can be qualified for JR and SR, but only on the JR team + * for example. */ @Column(columnDefinition = "boolean default true") private boolean teamMember = true; @@ -83,7 +82,6 @@ public class Participation implements IRankHolder { @Column(columnDefinition = "integer default 0") private int teamTotalRank; - public Participation(Athlete athlete, Category category) { this(); // logger.trace("new participation {} {} {}", athlete.getShortName(), category, @@ -135,6 +133,10 @@ public Category getCategory() { return this.category; } + public int getCategoryScoreRank() { + return this.categoryScoreRank; + } + @Transient @JsonIgnore public int getCleanJerkPoints() { @@ -241,6 +243,10 @@ public void setCategory(Category category) { this.category = category; } + public void setCategoryScoreRank(int scoreRank) { + this.categoryScoreRank = scoreRank; + } + public void setCleanJerkRank(int cleanJerkRank) { this.cleanJerkRank = cleanJerkRank; // logger.trace("cleanJerkRank {}", long_dump()); @@ -308,12 +314,4 @@ public String toString() { private boolean isTeamMember() { return this.teamMember; } - - public int getCategoryScoreRank() { - return categoryScoreRank; - } - - public void setCategoryScoreRank(int scoreRank) { - this.categoryScoreRank = scoreRank; - } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/data/category/ParticipationId.java b/owlcms/src/main/java/app/owlcms/data/category/ParticipationId.java index 29892ba268..aa993424b1 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/ParticipationId.java +++ b/owlcms/src/main/java/app/owlcms/data/category/ParticipationId.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/category/RegistrationPreferenceComparator.java b/owlcms/src/main/java/app/owlcms/data/category/RegistrationPreferenceComparator.java index 11bc0e26a8..1579d4b268 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/RegistrationPreferenceComparator.java +++ b/owlcms/src/main/java/app/owlcms/data/category/RegistrationPreferenceComparator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/category/RobiCategories.java b/owlcms/src/main/java/app/owlcms/data/category/RobiCategories.java index 9a611b6953..926fa476c7 100644 --- a/owlcms/src/main/java/app/owlcms/data/category/RobiCategories.java +++ b/owlcms/src/main/java/app/owlcms/data/category/RobiCategories.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -33,8 +33,8 @@ import ch.qos.logback.classic.Logger; /** - * This class is used to compute the Robi score for athletes based on their body weight. It locates what the athlete's - * category if the Athlete was competing in a IWF competition. + * This class is used to compute the Robi score for athletes based on their body weight. It locates what the athlete's category if the Athlete was competing in + * a IWF competition. */ public class RobiCategories { @@ -64,7 +64,7 @@ public int compare(Category c1, Category c2) { return 1; } } catch (Exception e) { - + } return 0; } @@ -76,8 +76,7 @@ public int compare(Category c1, Category c2) { private static ArrayList ythReferenceCategories; /** - * Create category templates that will be copied to instantiate the actual categories. The world records are read - * and included in the template. + * Create category templates that will be copied to instantiate the actual categories. The world records are read and included in the template. * * @param workbook * @return diff --git a/owlcms/src/main/java/app/owlcms/data/competition/Competition.java b/owlcms/src/main/java/app/owlcms/data/competition/Competition.java index 192bc6876a..92abd4947b 100644 --- a/owlcms/src/main/java/app/owlcms/data/competition/Competition.java +++ b/owlcms/src/main/java/app/owlcms/data/competition/Competition.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/competition/CompetitionRepository.java b/owlcms/src/main/java/app/owlcms/data/competition/CompetitionRepository.java index 758effb4ea..e09f3c527f 100644 --- a/owlcms/src/main/java/app/owlcms/data/competition/CompetitionRepository.java +++ b/owlcms/src/main/java/app/owlcms/data/competition/CompetitionRepository.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/competition/DebuggingTextField.java b/owlcms/src/main/java/app/owlcms/data/competition/DebuggingTextField.java index ac889ba777..158bf0be31 100644 --- a/owlcms/src/main/java/app/owlcms/data/competition/DebuggingTextField.java +++ b/owlcms/src/main/java/app/owlcms/data/competition/DebuggingTextField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/config/Config.java b/owlcms/src/main/java/app/owlcms/data/config/Config.java index 257047685b..0fd2b9c396 100644 --- a/owlcms/src/main/java/app/owlcms/data/config/Config.java +++ b/owlcms/src/main/java/app/owlcms/data/config/Config.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -181,7 +181,7 @@ public boolean featureSwitch(String string, boolean trueIfPresent) { return !trueIfPresent; } String[] switches = paramFeatureSwitches.toLowerCase().split("[,; ]"); - //logger.debug("featureSwitches {}",Arrays.asList(switches)); + // logger.debug("featureSwitches {}",Arrays.asList(switches)); boolean present = Arrays.asList(switches).contains(string.toLowerCase()); return trueIfPresent ? present : !present; } diff --git a/owlcms/src/main/java/app/owlcms/data/config/ConfigRepository.java b/owlcms/src/main/java/app/owlcms/data/config/ConfigRepository.java index dcf710f8ad..ebfd501880 100644 --- a/owlcms/src/main/java/app/owlcms/data/config/ConfigRepository.java +++ b/owlcms/src/main/java/app/owlcms/data/config/ConfigRepository.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/export/AthleteSessionDataReader.java b/owlcms/src/main/java/app/owlcms/data/export/AthleteSessionDataReader.java index 845661e3fb..0a18922b6c 100644 --- a/owlcms/src/main/java/app/owlcms/data/export/AthleteSessionDataReader.java +++ b/owlcms/src/main/java/app/owlcms/data/export/AthleteSessionDataReader.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.export; import java.beans.PropertyDescriptor; @@ -26,9 +32,9 @@ /** * Read athlete information from a json export, updating the lifting data for a list of sessions - * + * * Used when the sessions were recorded off line. - * + * * @author jf@jflamy.dev */ public class AthleteSessionDataReader { @@ -41,6 +47,30 @@ public static void importAthletes(InputStream is, List sessions) throws I doImportAthletes(is, sessionIds); } + private static void copyAttributes(Athlete source, Athlete target, String[] attributesToRead) { + boolean validating = Athlete.isSkipValidationsDuringImport(); + try { + logger.info("importing results for {} {} (session {})", target.getFullName(), target.getId(), target.getGroup()); + Athlete.setSkipValidationsDuringImport(true); + for (String attribute : attributesToRead) { + if (attribute.equals("id") || attribute.equals("group")) { + continue; + } + try { + PropertyDescriptor pd = new PropertyDescriptor(attribute, Athlete.class); + Method getter = pd.getReadMethod(); + Method setter = pd.getWriteMethod(); + Object value = getter.invoke(source); + setter.invoke(target, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + } finally { + Athlete.setSkipValidationsDuringImport(validating); + } + } + private static void doImportAthletes(InputStream is, List sessionIds) throws IOException, JsonParseException { JsonFactory factory = JsonFactory.builder() .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION) @@ -51,7 +81,7 @@ private static void doImportAthletes(InputStream is, List sessionIds) thro "id", "lotNumber", "group", - + "bodyWeight", "snatch1AutomaticProgression", @@ -102,23 +132,6 @@ private static void doImportAthletes(InputStream is, List sessionIds) thro updateAthletes(jsonAthletes, attributesToRead); } - private static void updateAthletes(List jsonAthletes, String[] attributesToRead) { - // Find existing athlete with the same id and lot - JPAService.runInTransaction(em -> { - for (Athlete jsonAthlete : jsonAthletes) { - Long id = jsonAthlete.getId(); - Athlete existingAthlete = AthleteRepository.findById(id); - if (existingAthlete != null) { - copyAttributes(jsonAthlete, existingAthlete, attributesToRead); - em.merge(existingAthlete); - } else { - logger.error("did not find athlete {}", id); - } - } - return null; - }); - } - private static List readAthletes(JsonParser parser, List athletes, String[] attributesToRead, List sessionIds) throws IOException { @@ -188,27 +201,20 @@ private static List readAthletes(JsonParser parser, return athletes; } - private static void copyAttributes(Athlete source, Athlete target, String[] attributesToRead) { - boolean validating = Athlete.isSkipValidationsDuringImport(); - try { - logger.info("importing results for {} {} (session {})", target.getFullName(), target.getId(), target.getGroup()); - Athlete.setSkipValidationsDuringImport(true); - for (String attribute : attributesToRead) { - if (attribute.equals("id") || attribute.equals("group")) { - continue; - } - try { - PropertyDescriptor pd = new PropertyDescriptor(attribute, Athlete.class); - Method getter = pd.getReadMethod(); - Method setter = pd.getWriteMethod(); - Object value = getter.invoke(source); - setter.invoke(target, value); - } catch (Exception e) { - e.printStackTrace(); + private static void updateAthletes(List jsonAthletes, String[] attributesToRead) { + // Find existing athlete with the same id and lot + JPAService.runInTransaction(em -> { + for (Athlete jsonAthlete : jsonAthletes) { + Long id = jsonAthlete.getId(); + Athlete existingAthlete = AthleteRepository.findById(id); + if (existingAthlete != null) { + copyAttributes(jsonAthlete, existingAthlete, attributesToRead); + em.merge(existingAthlete); + } else { + logger.error("did not find athlete {}", id); } } - } finally { - Athlete.setSkipValidationsDuringImport(validating); - } + return null; + }); } } diff --git a/owlcms/src/main/java/app/owlcms/data/export/CompetitionData.java b/owlcms/src/main/java/app/owlcms/data/export/CompetitionData.java index 3d5ebf7782..0434e2261d 100644 --- a/owlcms/src/main/java/app/owlcms/data/export/CompetitionData.java +++ b/owlcms/src/main/java/app/owlcms/data/export/CompetitionData.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -86,7 +86,7 @@ public InputStream exportData() { throw new RuntimeException(e); } } - + public InputStream exportData(UI ui, Notification notification) { if (ui != null) { ui.access(() -> notification.open()); @@ -227,8 +227,8 @@ public void restore(InputStream inputStream) { CompetitionData updated = this.importData(inputStream); Config config = updated.getConfig(); byte[] blob = config.getLocalZipBlob(); - - if ( blob != null) { + + if (blob != null) { logger.info("override zip found {} bytes", blob.length); } Config.setCurrent(config); @@ -266,7 +266,7 @@ public void restore(InputStream inputStream) { } if (updated.getRecordConfig() != null) { - em.merge(updated.getRecordConfig()); + em.merge(updated.getRecordConfig()); } em.merge(competition); @@ -298,8 +298,8 @@ public void setAthletes(List athletes) { } /** - * When importing data, set the imported Competition instance as the current instance. This is required because it - * affects how some objects are processed (e.g., birth dates). + * When importing data, set the imported Competition instance as the current instance. This is required because it affects how some objects are processed + * (e.g., birth dates). * * @param competition the competition to set */ @@ -311,8 +311,8 @@ public void setCompetition(Competition competition) { } /** - * When importing data, set the imported Competition instance as the current instance. This is prudent in case the - * configuration might affect further processing. + * When importing data, set the imported Competition instance as the current instance. This is prudent in case the configuration might affect further + * processing. * * @param config the config to set */ diff --git a/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfo.java b/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfo.java index 40972fb36d..b5eda71609 100644 --- a/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfo.java +++ b/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfo.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.group; import java.util.ArrayList; @@ -17,6 +23,22 @@ public class AgeGroupInfo implements Comparable { static Logger logger = (Logger) LoggerFactory.getLogger(AgeGroupInfo.class); + public static Comparator ageComparator = (o1, o2) -> { + if (o1.ageGroup == null || o2.ageGroup == null) { + return ObjectUtils.compare(o1.ageGroup, o2.ageGroup, true); + } + int compare; + compare = ObjectUtils.compare(o1.ageGroup.getMaxAge(), o2.ageGroup.getMaxAge()); + if (compare != 0) { + return compare; + } + compare = ObjectUtils.compare(o1.ageGroup.getMinAge(), o2.ageGroup.getMinAge()); + if (compare != 0) { + return compare; + } + compare = ObjectUtils.compare(o1.ageGroup.getName(), o2.ageGroup.getName()); + return compare; + }; AgeGroup ageGroup; Double smallestWeightClass; Double largestWeightClass; @@ -36,27 +58,9 @@ public void addToList(String key, BWCatInfo info) { this.subCats.put(key, info); } - - public static Comparator ageComparator = (o1, o2) -> { - if (o1.ageGroup == null || o2.ageGroup == null) { - return ObjectUtils.compare(o1.ageGroup, o2.ageGroup, true); - } - int compare; - compare = ObjectUtils.compare(o1.ageGroup.getMaxAge(), o2.ageGroup.getMaxAge()); - if (compare != 0) { - return compare; - } - compare = ObjectUtils.compare(o1.ageGroup.getMinAge(), o2.ageGroup.getMinAge()); - if (compare != 0) { - return compare; - } - compare = ObjectUtils.compare(o1.ageGroup.getName(), o2.ageGroup.getName()); - return compare; - }; - @Override public int compareTo(AgeGroupInfo o) { - return ageComparator.compare(this,o); + return ageComparator.compare(this, o); } public AgeGroup getAgeGroup() { diff --git a/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfoFactory.java b/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfoFactory.java index 38ad405b5c..a49c524d58 100644 --- a/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfoFactory.java +++ b/owlcms/src/main/java/app/owlcms/data/group/AgeGroupInfoFactory.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.group; import java.util.List; @@ -11,6 +17,10 @@ import ch.qos.logback.classic.Logger; public class AgeGroupInfoFactory { + public static List getNbForSessionBlock(int i) { + return null; + } + Logger logger = (Logger) LoggerFactory.getLogger(AgeGroupInfoFactory.class); public List getAgeGroupInfos(Group group) { @@ -43,11 +53,10 @@ public List getAgeGroupInfos(Group group) { BWCatInfo bwi = new BWCatInfo(a.getCategory().getMaximumWeight().intValue(), a.getCategory().getLimitString(), a.getSubCategory()); agi.addToList(bwi.getKey(), bwi); - ageGroupMap.put(ageGroup, agi); - //logger.debug("created ageGroup {} {}", ageGroup, agi.isUnanimous()); + // logger.debug("created ageGroup {} {}", ageGroup, agi.isUnanimous()); } else { - //logger.debug("found ageGroup {} {} {}", ageGroup, agi.getNbAthletes(), agi.isUnanimous()); + // logger.debug("found ageGroup {} {} {}", ageGroup, agi.getNbAthletes(), agi.isUnanimous()); agi.setNbAthletes(agi.getNbAthletes() + 1); if (agi.getSmallestWeightClass() == null || a.getCategory().getMaximumWeight() < agi.getSmallestWeightClass()) { @@ -62,7 +71,7 @@ public List getAgeGroupInfos(Group group) { if (subCategory != null) { if (agi.getBestSubCategory() != null) { int compare = subCategory.compareToIgnoreCase(agi.getBestSubCategory()); - //logger.debug("compare {} {} {} {}", subCategory, agi.getBestSubCategory(), compare, agi.isUnanimous()); + // logger.debug("compare {} {} {} {}", subCategory, agi.getBestSubCategory(), compare, agi.isUnanimous()); if (compare < 0) { // A is better than B agi.setBestSubCategory(subCategory); @@ -71,7 +80,7 @@ public List getAgeGroupInfos(Group group) { } else { // largest was null, if we are "A", still unanimous int compare = "A".compareToIgnoreCase(subCategory); - //logger.debug("current best = {}, athlete = {}", agi.getBestSubCategory(), subCategory); + // logger.debug("current best = {}, athlete = {}", agi.getBestSubCategory(), subCategory); agi.setBestSubCategory(subCategory); agi.setUnanimous(agi.isUnanimous() && (compare == 0)); } @@ -94,21 +103,17 @@ public List getAgeGroupInfos(Group group) { agi.setWeightClassRange(a.getCategory().getLimitString()); } else { String weightClassRange = Translator.translate("Range.LowerUpper", - (int) Math.round(agi.getSmallestWeightClass()),agi.getLargestWeightClassLimitString()); + (int) Math.round(agi.getSmallestWeightClass()), agi.getLargestWeightClassLimitString()); agi.setWeightClassRange(weightClassRange); } } - //logger.debug("athlete {} largest sub {} unanimous {} list {}", a, a.getSubCategory(), agi.isUnanimous(), agi.getList()); + // logger.debug("athlete {} largest sub {} unanimous {} list {}", a, a.getSubCategory(), agi.isUnanimous(), agi.getList()); agi.addAthlete(a); } -// for (AgeGroupInfo agi: ageGroupMap.values()) { -// //logger.debug("***** {} {} {} {} {}", agi.getAgeGroup(), agi.getWeightClassRange(), agi.getBestSubCategory(), agi.isUnanimous(), agi.getList()); -// } + // for (AgeGroupInfo agi: ageGroupMap.values()) { + // //logger.debug("***** {} {} {} {} {}", agi.getAgeGroup(), agi.getWeightClassRange(), agi.getBestSubCategory(), agi.isUnanimous(), agi.getList()); + // } return ageGroupMap.values().stream().toList(); } - - public static List getNbForSessionBlock(int i) { - return null; - } } diff --git a/owlcms/src/main/java/app/owlcms/data/group/BWCatInfo.java b/owlcms/src/main/java/app/owlcms/data/group/BWCatInfo.java index 38d9d30978..ed804e36c8 100644 --- a/owlcms/src/main/java/app/owlcms/data/group/BWCatInfo.java +++ b/owlcms/src/main/java/app/owlcms/data/group/BWCatInfo.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.group; import org.apache.commons.lang3.ObjectUtils; @@ -8,7 +14,6 @@ class BWCatInfo implements Comparable { String subCat; public BWCatInfo(int maxWeight, String limitString, String subCat) { - super(); this.maxWeight = maxWeight; this.limitString = limitString; this.subCat = subCat != null && !subCat.isBlank() ? subCat : "A"; @@ -18,8 +23,9 @@ public BWCatInfo(int maxWeight, String limitString, String subCat) { public int compareTo(BWCatInfo o) { int compare = 0; compare = ObjectUtils.compare(this.maxWeight, o.maxWeight); - if (compare != 0) + if (compare != 0) { return compare; + } String subCat2 = this.subCat; String subCat3 = o.subCat; compare = ObjectUtils.compare(subCat2, subCat3); @@ -27,10 +33,10 @@ public int compareTo(BWCatInfo o) { } public String getFormattedString() { - return limitString+subCat; + return this.limitString + this.subCat; } - + public String getKey() { - return String.format("%03d%s", maxWeight, subCat); + return String.format("%03d%s", this.maxWeight, this.subCat); } } diff --git a/owlcms/src/main/java/app/owlcms/data/group/DisplayGroup.java b/owlcms/src/main/java/app/owlcms/data/group/DisplayGroup.java index 6a99cdb652..79aa3b2125 100644 --- a/owlcms/src/main/java/app/owlcms/data/group/DisplayGroup.java +++ b/owlcms/src/main/java/app/owlcms/data/group/DisplayGroup.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.group; import app.owlcms.data.platform.Platform; diff --git a/owlcms/src/main/java/app/owlcms/data/group/Group.java b/owlcms/src/main/java/app/owlcms/data/group/Group.java index 450c65df36..244ac3cfeb 100644 --- a/owlcms/src/main/java/app/owlcms/data/group/Group.java +++ b/owlcms/src/main/java/app/owlcms/data/group/Group.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -66,129 +66,20 @@ @JsonIgnoreProperties(ignoreUnknown = true, value = { "hibernateLazyInitializer", "logger", "athletes" }) public class Group implements Comparable { - public record Range (Integer min, Integer max) { + public record Range(Integer min, Integer max) { public String getFormattedRange() { - if (min == Integer.MAX_VALUE && max == 0) { + if (this.min == Integer.MAX_VALUE && this.max == 0) { return ""; - } else if (min == max) { - return min.toString(); + } else if (this.min == this.max) { + return this.min.toString(); } else { - return min.toString()+" - "+max.toString(); + return this.min.toString() + " - " + this.max.toString(); } } - }; - - @Transient - @JsonIgnore - public Range getStartingRange() { - int min = Integer.MAX_VALUE; - int max = 0; - for (Athlete a : getAthletes()) { - Integer q = a.getQualifyingTotal(); - if (q == null) { - continue; - } - min = q < min ? q : min; - max = q > max ? q : max; - } - return new Range(min, max); - } - - public void setFormattedRange(String unused) { - } - public String getFormattedRange() { - List athletes = getAthletes(); - Boolean unanimous = true; - Double smallestWeightClass = null; - Double largestWeightClass = null; - String largestWeightClassLimitString = null; - String weightClassRange = null; - String bestSubCategory = null; - TreeMap subCats = new TreeMap<>(); - - for (Athlete a : athletes) { - AgeGroup ageGroup = a.getAgeGroup(); - if (ageGroup == null) { - continue; - } - - String subCategory = a.getSubCategory(); - if (subCategory.isBlank()) { - subCategory = null; - } - - if (weightClassRange == null) { - smallestWeightClass = a.getCategory().getMaximumWeight(); - largestWeightClass = a.getCategory().getMaximumWeight(); - largestWeightClassLimitString = a.getCategory().getLimitString(); - weightClassRange = a.getCategory().getLimitString(); - bestSubCategory = subCategory; - - BWCatInfo bwi = new BWCatInfo(a.getCategory().getMaximumWeight().intValue(), a.getCategory().getLimitString(), a.getSubCategory()); - subCats.put(bwi.getKey(), bwi); - } else { - if (smallestWeightClass == null - || a.getCategory().getMaximumWeight() < smallestWeightClass) { - smallestWeightClass = a.getCategory().getMaximumWeight(); - } - - if (largestWeightClass == null - || a.getCategory().getMaximumWeight() > largestWeightClass) { - largestWeightClass = a.getCategory().getMaximumWeight(); - largestWeightClassLimitString = a.getCategory().getLimitString(); - } - - if (subCategory != null) { - if (bestSubCategory != null) { - int compare = subCategory.compareToIgnoreCase(bestSubCategory); - - if (compare < 0) { - // A is better than B - bestSubCategory = subCategory; - } - - unanimous = unanimous && (compare == 0); - } else { - // largest was null, if we are "A", still unanimous - int compare = "A".compareToIgnoreCase(subCategory); - bestSubCategory = subCategory; - unanimous = unanimous && (compare == 0); - } - } else { - if (bestSubCategory != null) { - // a null subcategory is considered to be the same as "A". - int compare = "A".compareToIgnoreCase(bestSubCategory); - unanimous = unanimous && (compare == 0); - } else { - // all null subCategories so far. - unanimous = true; - } - } - - BWCatInfo bwi = new BWCatInfo(a.getCategory().getMaximumWeight().intValue(), a.getCategory().getLimitString(), a.getSubCategory()); - subCats.put(bwi.getKey(), bwi); - - if (Math.abs(largestWeightClass - smallestWeightClass) < 0.1) { - // same - weightClassRange = a.getCategory().getLimitString(); - } else { - weightClassRange = (int) Math.round(smallestWeightClass) + "-" - + largestWeightClassLimitString; - } - } - } - - if (unanimous) { - if (bestSubCategory == null) { - return weightClassRange; - } else { - return weightClassRange + " " + bestSubCategory; - } - } else { - return subCats.values().stream().map(v -> v.getFormattedString()).collect(Collectors.joining(", ")); - } + private enum USAFlagOrder { + RED, WHITE, BLUE, STARS, STRIPES, GOLD, ROGUE } private final static Logger logger = (Logger) LoggerFactory.getLogger(Group.class); @@ -196,7 +87,6 @@ public String getFormattedRange() { private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm"; private final static DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder().parseLenient() .appendPattern(DATE_FORMAT).toFormatter(); - public static Comparator weighinTimeComparator = (lifter1, lifter2) -> { Group lifter1Group = lifter1.getGroup(); Group lifter2Group = lifter2.getGroup(); @@ -246,11 +136,6 @@ public String getFormattedRange() { return 0; }; - - private enum USAFlagOrder { - RED, WHITE, BLUE, STARS, STRIPES, GOLD, ROGUE - } - public static Comparator groupWeighinTimeComparator = (lifter1Group, lifter2Group) -> { int compare; @@ -418,6 +303,9 @@ public static DisplayGroup getEmptyDisplayGroup() { private String weighIn1; private String weighIn2; private LocalDateTime weighInTime; + @Transient + @JsonIgnore + Pattern pattern = Pattern.compile("(\\d+)\\s+(\\w+)"); /** * Instantiates a new group. @@ -457,43 +345,6 @@ public Group(String groupName, LocalDateTime weighin, LocalDateTime competition) this.setCompetitionTime(competition); } - @Transient - @JsonIgnore - Pattern pattern = Pattern.compile("(\\d+)\\s+(\\w+)"); - - @Transient - @JsonIgnore - public Integer getSessionBlock() { - if (Config.getCurrent().featureSwitch("usawSessionBlocks")) { - Matcher matcher = pattern.matcher(this.getName()); - if (matcher.find()) { - String number = matcher.group(1); - // String word = matcher.group(2); - try { - return Integer.parseInt(number); - } catch (NumberFormatException e) { - return 999; - } - } - return 999; - } - return 1; - } - - @Transient - @JsonIgnore - public List getAgeGroupInfo() { - List ageGroupInfos = new AgeGroupInfoFactory().getAgeGroupInfos(this); - return ageGroupInfos; - } - - @Transient - @JsonIgnore - public List getAgeGroupInfoByAge() { - List ageGroupInfos = new AgeGroupInfoFactory().getAgeGroupInfos(this); - return ageGroupInfos.stream().sorted().toList(); - } - /* * (non-Javadoc) * @@ -554,19 +405,17 @@ public void copy(Group source) throws IllegalAccessException, InvocationTargetEx this.setId(myId); } - // @Override - public void doDone() { boolean previousDone = this.isDone(); boolean groupDone = true; - for (Athlete a: this.getAthletes()) { + for (Athlete a : this.getAthletes()) { boolean weighedIn = a.getBodyWeight() != null && a.getBodyWeight() > 0.1; if (weighedIn && !a.isDone()) { groupDone = false; break; } } - //logger.debug("done? {} before={} after={} {}", getName(), this.done, groupDone, LoggerUtils.whereFrom()); + // logger.debug("done? {} before={} after={} {}", getName(), this.done, groupDone, LoggerUtils.whereFrom()); this.setDone(groupDone); if (this.isDone() != previousDone) { GroupRepository.save(this); @@ -603,6 +452,20 @@ public String fullDump() { + this.reserve + ", id=" + this.id + "]"; } + @Transient + @JsonIgnore + public List getAgeGroupInfo() { + List ageGroupInfos = new AgeGroupInfoFactory().getAgeGroupInfos(this); + return ageGroupInfos; + } + + @Transient + @JsonIgnore + public List getAgeGroupInfoByAge() { + List ageGroupInfos = new AgeGroupInfoFactory().getAgeGroupInfos(this); + return ageGroupInfos.stream().sorted().toList(); + } + @Transient @JsonIgnore public List getAlphaAthletes() { @@ -611,6 +474,8 @@ public List getAlphaAthletes() { return athletes; } + // @Override + /** * Gets the announcer. * @@ -670,6 +535,99 @@ public String getDescription() { return this.description; } + public String getFormattedRange() { + List athletes = getAthletes(); + boolean unanimous = true; + Double smallestWeightClass = null; + Double largestWeightClass = null; + String largestWeightClassLimitString = null; + String weightClassRange = null; + String bestSubCategory = null; + TreeMap subCats = new TreeMap<>(); + + for (Athlete a : athletes) { + AgeGroup ageGroup = a.getAgeGroup(); + if (ageGroup == null) { + continue; + } + + String subCategory = a.getSubCategory(); + if (subCategory.isBlank()) { + subCategory = null; + } + + if (weightClassRange == null) { + smallestWeightClass = a.getCategory().getMaximumWeight(); + largestWeightClass = a.getCategory().getMaximumWeight(); + largestWeightClassLimitString = a.getCategory().getLimitString(); + weightClassRange = a.getCategory().getLimitString(); + bestSubCategory = subCategory; + + BWCatInfo bwi = new BWCatInfo(a.getCategory().getMaximumWeight().intValue(), a.getCategory().getLimitString(), a.getSubCategory()); + subCats.put(bwi.getKey(), bwi); + } else { + if (smallestWeightClass == null + || a.getCategory().getMaximumWeight() < smallestWeightClass) { + smallestWeightClass = a.getCategory().getMaximumWeight(); + } + + if (largestWeightClass == null + || a.getCategory().getMaximumWeight() > largestWeightClass) { + largestWeightClass = a.getCategory().getMaximumWeight(); + largestWeightClassLimitString = a.getCategory().getLimitString(); + } + + if (subCategory != null) { + if (bestSubCategory != null) { + int compare = subCategory.compareToIgnoreCase(bestSubCategory); + + if (compare < 0) { + // A is better than B + bestSubCategory = subCategory; + } + + unanimous = unanimous && (compare == 0); + } else { + // largest was null, if we are "A", still unanimous + int compare = "A".compareToIgnoreCase(subCategory); + bestSubCategory = subCategory; + unanimous = unanimous && (compare == 0); + } + } else { + if (bestSubCategory != null) { + // a null subcategory is considered to be the same as "A". + int compare = "A".compareToIgnoreCase(bestSubCategory); + unanimous = unanimous && (compare == 0); + } else { + // all null subCategories so far. + unanimous = true; + } + } + + BWCatInfo bwi = new BWCatInfo(a.getCategory().getMaximumWeight().intValue(), a.getCategory().getLimitString(), a.getSubCategory()); + subCats.put(bwi.getKey(), bwi); + + if (Math.abs(largestWeightClass - smallestWeightClass) < 0.1) { + // same + weightClassRange = a.getCategory().getLimitString(); + } else { + weightClassRange = (int) Math.round(smallestWeightClass) + "-" + + largestWeightClassLimitString; + } + } + } + + if (unanimous) { + if (bestSubCategory == null) { + return weightClassRange; + } else { + return weightClassRange + " " + bestSubCategory; + } + } else { + return subCats.values().stream().map(v -> v.getFormattedString()).collect(Collectors.joining(", ")); + } + } + /** * Gets the id. * @@ -952,6 +910,41 @@ public String getReserve() { return this.reserve; } + @Transient + @JsonIgnore + public Integer getSessionBlock() { + if (Config.getCurrent().featureSwitch("usawSessionBlocks")) { + Matcher matcher = this.pattern.matcher(this.getName()); + if (matcher.find()) { + String number = matcher.group(1); + // String word = matcher.group(2); + try { + return Integer.parseInt(number); + } catch (NumberFormatException e) { + return 999; + } + } + return 999; + } + return 1; + } + + @Transient + @JsonIgnore + public Range getStartingRange() { + int min = Integer.MAX_VALUE; + int max = 0; + for (Athlete a : getAthletes()) { + Integer q = a.getQualifyingTotal(); + if (q == null) { + continue; + } + min = q < min ? q : min; + max = q > max ? q : max; + } + return new Range(min, max); + } + /** * Gets the technical controller. * @@ -1053,6 +1046,10 @@ public void setDescription(String description) { this.description = description; } + public void setFormattedRange(String unused) { + + } + /** * @param id the id to set */ diff --git a/owlcms/src/main/java/app/owlcms/data/group/GroupRepository.java b/owlcms/src/main/java/app/owlcms/data/group/GroupRepository.java index 104007b366..5a91780bb3 100644 --- a/owlcms/src/main/java/app/owlcms/data/group/GroupRepository.java +++ b/owlcms/src/main/java/app/owlcms/data/group/GroupRepository.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/BenchmarkData.java b/owlcms/src/main/java/app/owlcms/data/jpa/BenchmarkData.java index a49c3e671a..9877a67b46 100644 --- a/owlcms/src/main/java/app/owlcms/data/jpa/BenchmarkData.java +++ b/owlcms/src/main/java/app/owlcms/data/jpa/BenchmarkData.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -227,8 +227,7 @@ private static void drawLots(EntityManager em) { /** * Setup benchmark data. * - * 4 groups A-D, 14 athletes per session, all IWF and IMWA age groups. 81 sessions required to produce 1134 athletes - * (target size of benchmark). + * 4 groups A-D, 14 athletes per session, all IWF and IMWA age groups. 81 sessions required to produce 1134 athletes (target size of benchmark). * * @param sessionsPerDay * diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/DemoData.java b/owlcms/src/main/java/app/owlcms/data/jpa/DemoData.java index b946a87a43..c9d59ac4c9 100644 --- a/owlcms/src/main/java/app/owlcms/data/jpa/DemoData.java +++ b/owlcms/src/main/java/app/owlcms/data/jpa/DemoData.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -53,7 +53,7 @@ public class DemoData { /** * Insert initial data if the database is empty. * - * @param nbAthletes how many athletes + * @param nbAthletes how many athletes * @param forcedInsertion */ public static void insertInitialData(int nbAthletes, EnumSet forcedInsertion) { @@ -137,8 +137,8 @@ protected static Competition createDefaultCompetition(EnumSet competition.setCompetitionName("Spring Equinox Open"); competition.setCompetitionCity("Sometown, Lower Cascadia"); - //competition.setCompetitionDate(LocalDate.of(2019, 03, 23)); - + // competition.setCompetitionDate(LocalDate.of(2019, 03, 23)); + // same reference year will be used for athlete creation int referenceYear = LocalDate.now().getYear(); competition.setCompetitionDate(LocalDate.of(referenceYear, 03, 23)); @@ -203,11 +203,11 @@ protected static void drawLots(EntityManager em) { * * @param em * - * @param competition the competition - * @param liftersToLoad the lifters to load + * @param competition the competition + * @param liftersToLoad the lifters to load * @param forcedInsertion - * @param w the w - * @param c the c + * @param w the w + * @param c the c */ protected static void setupDemoData(EntityManager em, int liftersToLoad, EnumSet forcedInsertion) { diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/HikariDataSourcePoolDetail.java b/owlcms/src/main/java/app/owlcms/data/jpa/HikariDataSourcePoolDetail.java index 83f1da32b4..426ff3aef2 100644 --- a/owlcms/src/main/java/app/owlcms/data/jpa/HikariDataSourcePoolDetail.java +++ b/owlcms/src/main/java/app/owlcms/data/jpa/HikariDataSourcePoolDetail.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.jpa; import java.lang.reflect.Field; @@ -11,35 +17,35 @@ import ch.qos.logback.classic.Logger; public class HikariDataSourcePoolDetail { - private final HikariDataSource dataSource; - private final static Logger logger = (Logger) LoggerFactory.getLogger(HikariDataSourcePoolDetail.class); + private final static Logger logger = (Logger) LoggerFactory.getLogger(HikariDataSourcePoolDetail.class); + private final HikariDataSource dataSource; - public HikariDataSourcePoolDetail(HikariDataSource dataSource) { - this.dataSource = dataSource; - } + public HikariDataSourcePoolDetail(HikariDataSource dataSource) { + this.dataSource = dataSource; + } - public HikariPool getHikariPool() { - Field field; + public int getActive() { try { - field = dataSource.getClass().getDeclaredField("pool"); + return getHikariPool().getActiveConnections(); + } catch (Exception ex) { + return -1; + } + } + + public HikariPool getHikariPool() { + Field field; + try { + field = this.dataSource.getClass().getDeclaredField("pool"); field.setAccessible(true); - HikariPool hikariPool = (HikariPool) field.get(dataSource); + HikariPool hikariPool = (HikariPool) field.get(this.dataSource); return hikariPool; } catch (Exception e) { - LoggerUtils.logError(logger,e); + LoggerUtils.logError(logger, e); } return null; - } - - public int getActive() { - try { - return getHikariPool().getActiveConnections(); - } catch (Exception ex) { - return -1; - } - } - - public int getMax() { - return dataSource.getMaximumPoolSize(); - } + } + + public int getMax() { + return this.dataSource.getMaximumPoolSize(); + } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/JPAService.java b/owlcms/src/main/java/app/owlcms/data/jpa/JPAService.java index 88c44520cd..b1d8315fc9 100644 --- a/owlcms/src/main/java/app/owlcms/data/jpa/JPAService.java +++ b/owlcms/src/main/java/app/owlcms/data/jpa/JPAService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -77,6 +77,7 @@ public class JPAService { static { logger.setLevel(Level.INFO); } + static Map whereFrom = new HashMap<>(); /** * Close. @@ -88,11 +89,17 @@ public static void close() { setFactory(null); } - /** - * @return the factory - */ - static EntityManagerFactory getFactory() { - return factory; + public static int getPoolStatistics() { + SessionFactory sessionFactory = factory.unwrap(SessionFactory.class); + ConnectionProvider connectionProvider = sessionFactory.getSessionFactoryOptions().getServiceRegistry() + .getService(ConnectionProvider.class); + HikariDataSource dataSource = connectionProvider.unwrap(HikariDataSource.class); + HikariDataSourcePoolDetail dsd = new HikariDataSourcePoolDetail(dataSource); + int active = dsd.getActive(); + if (logger.isTraceEnabled()) { + logger.trace("HikariDataSource details: max={} active={}", dsd.getMax(), active); + } + return active; } /** @@ -197,17 +204,6 @@ public static Properties processSettings(boolean inMemory, boolean reset) throws return properties; } - private static void traceLeak() { - if (logger.isTraceEnabled()) { - int active = JPAService.getPoolStatistics(); - if (active > 0) { - logger.trace("active > 0 {}", whereFrom.values()); - } - } - } - - static Map whereFrom = new HashMap<>(); - /** * Run in transaction. * @@ -343,6 +339,13 @@ protected static void setFactory(EntityManagerFactory factory) { JPAService.factory = factory; } + /** + * @return the factory + */ + static EntityManagerFactory getFactory() { + return factory; + } + /** * Gets the factory from code (without a persistance.xml file) * @@ -361,19 +364,6 @@ private static EntityManagerFactory getFactory(boolean memoryMode, boolean reset return factory; } - public static int getPoolStatistics() { - SessionFactory sessionFactory = factory.unwrap(SessionFactory.class); - ConnectionProvider connectionProvider = sessionFactory.getSessionFactoryOptions().getServiceRegistry() - .getService(ConnectionProvider.class); - HikariDataSource dataSource = connectionProvider.unwrap(HikariDataSource.class); - HikariDataSourcePoolDetail dsd = new HikariDataSourcePoolDetail(dataSource); - int active = dsd.getActive(); - if (logger.isTraceEnabled()) { - logger.trace("HikariDataSource details: max={} active={}", dsd.getMax(), active); - } - return active; - } - private static Properties h2FileProperties(String schemaGeneration, String dbUrl, String userName, String password) { setLocalDb(true); @@ -540,11 +530,10 @@ private static Properties pgProperties(String schemaGeneration, String dbUrl, St * H2 can expose its embedded server on demand, as well as a console * *

- * Not enabled by default, protected by a feature switch - * (-DH2ServerPort=9092 or OWLCMS_H2SERVERPORT=9092) + * Not enabled by default, protected by a feature switch (-DH2ServerPort=9092 or OWLCMS_H2SERVERPORT=9092) *

- * When using a tool to connect, such as the H2 console (java -jar h2-1.4.200.jar) or DBVisualizer, the - * the URL given to the tool must include the absolute path to the database for example: + * When using a tool to connect, such as the H2 console (java -jar h2-1.4.200.jar) or DBVisualizer, the the URL given to the tool must include + * the absolute path to the database for example: * *

 	 * jdbc:h2:tcp://localhost:9092/c:/dev/git/owlcms4/owlcms/database/owlcms
@@ -568,4 +557,13 @@ private static void startH2EmbeddedServer() {
 		}
 	}
 
+	private static void traceLeak() {
+		if (logger.isTraceEnabled()) {
+			int active = JPAService.getPoolStatistics();
+			if (active > 0) {
+				logger.trace("active > 0 {}", whereFrom.values());
+			}
+		}
+	}
+
 }
diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateAttributeConverter.java b/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateAttributeConverter.java
index 6ebd1934d1..c6078ebd4e 100644
--- a/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateAttributeConverter.java
+++ b/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateAttributeConverter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateTimeAttributeConverter.java b/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateTimeAttributeConverter.java
index 7f41df1747..8eec8914e4 100644
--- a/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateTimeAttributeConverter.java
+++ b/owlcms/src/main/java/app/owlcms/data/jpa/LocalDateTimeAttributeConverter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/LocaleAttributeConverter.java b/owlcms/src/main/java/app/owlcms/data/jpa/LocaleAttributeConverter.java
index f4c6090f1e..d9a4428dea 100644
--- a/owlcms/src/main/java/app/owlcms/data/jpa/LocaleAttributeConverter.java
+++ b/owlcms/src/main/java/app/owlcms/data/jpa/LocaleAttributeConverter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/PersistenceUnitInfoImpl.java b/owlcms/src/main/java/app/owlcms/data/jpa/PersistenceUnitInfoImpl.java
index b89b86d56c..b2fefd268e 100644
--- a/owlcms/src/main/java/app/owlcms/data/jpa/PersistenceUnitInfoImpl.java
+++ b/owlcms/src/main/java/app/owlcms/data/jpa/PersistenceUnitInfoImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/jpa/ProdData.java b/owlcms/src/main/java/app/owlcms/data/jpa/ProdData.java
index b4d4b8f4f1..fef470e650 100644
--- a/owlcms/src/main/java/app/owlcms/data/jpa/ProdData.java
+++ b/owlcms/src/main/java/app/owlcms/data/jpa/ProdData.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/platform/Platform.java b/owlcms/src/main/java/app/owlcms/data/platform/Platform.java
index 8914c1d6fd..337eca33ff 100644
--- a/owlcms/src/main/java/app/owlcms/data/platform/Platform.java
+++ b/owlcms/src/main/java/app/owlcms/data/platform/Platform.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -154,17 +154,16 @@ public static void setCurrent(Platform p) {
 	 */
 	private Boolean showTimer = false;
 	private String soundMixerName;
-	
+
 	// nonStandardBar needed for backward compatibility (old column is present in imports)
 	@SuppressWarnings("unused")
 	@JsonIgnore
 	private Boolean nonStandardBar = false;
-	
+
 	// unfortunate choice of name in old code base, needed for imports to work.
-	@Column(name="nonStandardBarAvailable")
+	@Column(name = "nonStandardBarAvailable")
 	@JsonProperty("nonStandardBarAvailable")
 	private Boolean useNonStandardBar = false;
-	
 	@Column(columnDefinition = "integer default 40")
 	private Integer collarThreshold = 40;
 
@@ -173,7 +172,7 @@ public static void setCurrent(Platform p) {
 	 */
 	public Platform() {
 		setId(IdUtils.getTimeBasedId());
-		//logger.debug"new Platform 1 {} {}",this.getNbB_5(), LoggerUtils.whereFrom());
+		// logger.debug"new Platform 1 {} {}",this.getNbB_5(), LoggerUtils.whereFrom());
 	}
 
 	/**
@@ -184,8 +183,8 @@ public Platform() {
 	public Platform(String name) {
 		setId(IdUtils.getTimeBasedId());
 		this.setName(name);
-		//logger.debug"new Platform 2",this.getNbB_5());
-		//this.defaultPlates();
+		// logger.debug"new Platform 2",this.getNbB_5());
+		// this.defaultPlates();
 	}
 
 	@Override
@@ -240,6 +239,12 @@ public boolean equals(Object obj) {
 
 	}
 
+	@Transient
+	@JsonIgnore
+	public Integer getCollarThreshold() {
+		return this.collarThreshold;
+	}
+
 	/**
 	 * Gets the id.
 	 *
@@ -437,6 +442,18 @@ public Integer getNbS_5() {
 		return this.nbS_5;
 	}
 
+	// /**
+	// * Gets the official bar.
+	// *
+	// * @return the official bar
+	// */
+	// public Integer getOfficialBar() {
+	// if (this.isNonStandardBar()) {
+	// return 0;
+	// }
+	// return this.officialBar;
+	// }
+
 	/**
 	 * Gets the light bar.
 	 *
@@ -449,18 +466,6 @@ public Integer getNonStandardBarWeight() {
 		return this.nonStandardBarWeight;
 	}
 
-//	/**
-//	 * Gets the official bar.
-//	 *
-//	 * @return the official bar
-//	 */
-//	public Integer getOfficialBar() {
-//		if (this.isNonStandardBar()) {
-//			return 0;
-//		}
-//		return this.officialBar;
-//	}
-
 	/**
 	 * Gets the show decision lights.
 	 *
@@ -491,6 +496,10 @@ public String getSoundMixerName() {
 		return this.soundMixerName;
 	}
 
+	public Boolean getUseNonStandardBar() {
+		return Boolean.TRUE.equals(this.useNonStandardBar);
+	}
+
 	@Override
 	public int hashCode() {
 		// https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
@@ -500,9 +509,9 @@ public int hashCode() {
 	public Boolean isUseNonStandardBar() {
 		return getUseNonStandardBar();
 	}
-	
-	public Boolean getUseNonStandardBar() {
-		return Boolean.TRUE.equals(useNonStandardBar);
+
+	public void setCollarThreshold(Integer collarThreshold) {
+		this.collarThreshold = collarThreshold;
 	}
 
 	/**
@@ -530,12 +539,12 @@ public void setNbB_15(Integer nbB_15) {
 	}
 
 	public void setNbB_20(Integer nbB_20) {
-		//logger.debug("nbB_20 = {} {}",nbB_20, LoggerUtils.whereFrom());
+		// logger.debug("nbB_20 = {} {}",nbB_20, LoggerUtils.whereFrom());
 		this.nbB_20 = nbB_20;
 	}
 
 	public void setNbB_5(Integer nbB_5) {
-		//logger.debug"setting 5kg bumper {}",nbB_5);
+		// logger.debug"setting 5kg bumper {}",nbB_5);
 		this.nbB_5 = nbB_5;
 	}
 
@@ -656,10 +665,14 @@ public void setNbS_5(Integer nbS_5) {
 		this.nbS_5 = nbS_5;
 	}
 
-	public void setUseNonStandardBar(Boolean nonStandardBarAvailable) {
-		logger.debug("nsba {} ({})",true, System.identityHashCode(this));
-		this.useNonStandardBar = nonStandardBarAvailable;
-	}
+	// /**
+	// * Sets the official bar.
+	// *
+	// * @param officialBar the new official bar
+	// */
+	// public void setOfficialBar(Integer officialBar) {
+	// this.officialBar = officialBar;
+	// }
 
 	/**
 	 * Sets the light bar.
@@ -670,15 +683,6 @@ public void setNonStandardBarWeight(Integer lightBar) {
 		this.nonStandardBarWeight = lightBar;
 	}
 
-//	/**
-//	 * Sets the official bar.
-//	 *
-//	 * @param officialBar the new official bar
-//	 */
-//	public void setOfficialBar(Integer officialBar) {
-//		this.officialBar = officialBar;
-//	}
-
 	/**
 	 * Sets the show decision lights.
 	 *
@@ -726,6 +730,11 @@ public void setSoundMixerName(String soundMixerName) {
 		this.mixerChecked = true;
 	}
 
+	public void setUseNonStandardBar(Boolean nonStandardBarAvailable) {
+		logger.debug("nsba {} ({})", true, System.identityHashCode(this));
+		this.useNonStandardBar = nonStandardBarAvailable;
+	}
+
 	@Override
 	public String toString() {
 		return this.name; // $NON-NLS-1$
@@ -737,14 +746,4 @@ private void setMixer(Mixer soundMixer) {
 		this.mixer = soundMixer;
 	}
 
-	@Transient
-	@JsonIgnore
-	public Integer getCollarThreshold() {
-		return collarThreshold;
-	}
-
-	public void setCollarThreshold(Integer collarThreshold) {
-		this.collarThreshold = collarThreshold;
-	}
-
 }
diff --git a/owlcms/src/main/java/app/owlcms/data/platform/PlatformRepository.java b/owlcms/src/main/java/app/owlcms/data/platform/PlatformRepository.java
index 3ada744ed2..da9d45c882 100644
--- a/owlcms/src/main/java/app/owlcms/data/platform/PlatformRepository.java
+++ b/owlcms/src/main/java/app/owlcms/data/platform/PlatformRepository.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/records/FederationStructureReader.java b/owlcms/src/main/java/app/owlcms/data/records/FederationStructureReader.java
index d9480c73ac..0928eb6b56 100644
--- a/owlcms/src/main/java/app/owlcms/data/records/FederationStructureReader.java
+++ b/owlcms/src/main/java/app/owlcms/data/records/FederationStructureReader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -26,8 +26,8 @@
 /**
  * Read federation structure from an Excel file
  *
- * Example: qc < ca < panam < iwf but also ca < commonwealth < iwf and qc < francophonie At a competition, qc can break
- * all these records (if included in the records file). but usa would not.
+ * Example: qc < ca < panam < iwf but also ca < commonwealth < iwf and qc < francophonie At a competition, qc can break all these records (if included in the
+ * records file). but usa would not.
  *
  * @author Jean-François Lamy
  *
diff --git a/owlcms/src/main/java/app/owlcms/data/records/RecordConfig.java b/owlcms/src/main/java/app/owlcms/data/records/RecordConfig.java
index d2f6bb47bc..bd1eb84f7c 100644
--- a/owlcms/src/main/java/app/owlcms/data/records/RecordConfig.java
+++ b/owlcms/src/main/java/app/owlcms/data/records/RecordConfig.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.data.records;
 
 import java.util.ArrayList;
diff --git a/owlcms/src/main/java/app/owlcms/data/records/RecordDefinitionReader.java b/owlcms/src/main/java/app/owlcms/data/records/RecordDefinitionReader.java
index 3950b015ff..8967903390 100644
--- a/owlcms/src/main/java/app/owlcms/data/records/RecordDefinitionReader.java
+++ b/owlcms/src/main/java/app/owlcms/data/records/RecordDefinitionReader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -46,8 +46,7 @@
 /**
  * Read records from an Excel file.
  *
- * Records for snatch, clean&jerk and total are read. All available tabs are scanned. Reading stops at first empty line.
- * Header line is skipped.
+ * Records for snatch, clean&jerk and total are read. All available tabs are scanned. Reading stops at first empty line. Header line is skipped.
  *
  * @author Jean-François Lamy
  *
@@ -57,7 +56,6 @@ public class RecordDefinitionReader {
 	private final static Logger logger = (Logger) LoggerFactory.getLogger(RecordDefinitionReader.class);
 	private final static Logger startupLogger = Main.getStartupLogger();
 
-	
 	public static List createRecords(Workbook workbook, String name, String baseName) {
 		cleanUp(baseName);
 		DateTimeFormatter ymdFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@@ -306,7 +304,7 @@ public static List createRecords(Workbook workbook, String name, String
 								}
 								case 16: { // Q
 									if (cell.getCellType() == CellType.NUMERIC) {
-										//String cellValue = NumberToTextConverter.toText(cell.getNumericCellValue());
+										// String cellValue = NumberToTextConverter.toText(cell.getNumericCellValue());
 										rec.setEvent("");
 										break;
 									}
diff --git a/owlcms/src/main/java/app/owlcms/data/records/RecordEvent.java b/owlcms/src/main/java/app/owlcms/data/records/RecordEvent.java
index b16efe7116..8d2a28a0c7 100644
--- a/owlcms/src/main/java/app/owlcms/data/records/RecordEvent.java
+++ b/owlcms/src/main/java/app/owlcms/data/records/RecordEvent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -43,10 +43,6 @@
 @JsonIgnoreProperties(ignoreUnknown = true, value = { "hibernateLazyInitializer", "logger" })
 @JsonInclude(Include.NON_NULL)
 public class RecordEvent {
-	
-	RecordEvent() {
-		setId(IdUtils.getTimeBasedId());
-	}
 
 	public class MissingAgeGroup extends Exception {
 	}
@@ -93,7 +89,7 @@ public static RecordEvent newRecord(Athlete a, RecordEvent rec, Double value, Gr
 	private Double athleteBW;
 	private Integer athleteAge;
 	@Id
-	//@GeneratedValue(strategy = GenerationType.AUTO)
+	// @GeneratedValue(strategy = GenerationType.AUTO)
 	Long id;
 	Double recordValue;
 	private String ageGrp;
@@ -121,6 +117,10 @@ public static RecordEvent newRecord(Athlete a, RecordEvent rec, Double value, Gr
 	@JsonIgnore
 	private final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
 
+	RecordEvent() {
+		setId(IdUtils.getTimeBasedId());
+	}
+
 	// @Override
 	// public boolean equals(Object obj) {
 	// if (this == obj) {
@@ -149,19 +149,16 @@ public static RecordEvent newRecord(Athlete a, RecordEvent rec, Double value, Gr
 
 	@Override
 	public boolean equals(Object o) {
-		if (this == o)
+		if (this == o) {
 			return true;
+		}
 
-		if (!(o instanceof RecordEvent))
+		if (!(o instanceof RecordEvent)) {
 			return false;
+		}
 
 		RecordEvent other = (RecordEvent) o;
-		return id != null && id.equals(other.getId());
-	}
-
-	@Override
-	public int hashCode() {
-		return getClass().hashCode();
+		return this.id != null && this.id.equals(other.getId());
 	}
 
 	public void fillDefaults() throws MissingAgeGroup, MissingGender, UnknownIWFBodyWeightCategory {
@@ -267,20 +264,6 @@ public String getFileName() {
 	public Gender getGender() {
 		return this.gender;
 	}
-	
-	public String getTranslatedGender() {
-		return Translator.translate("Gender."+this.gender);
-	}
-	
-	public String getTranslatedLift() {
-		return Translator.translate("Record."+this.recordLift);
-	}
-	
-	public void setTranslatedGender(String ignored) {
-	}
-	
-	public void setTranslatedLift(String ignored) {
-	}
 
 	/**
 	 * Group Name. If not empty, record was set in the current competition.Autan
@@ -357,15 +340,18 @@ public String getResRecordLift() {
 		}
 	}
 
-	// @Override
-	// public int hashCode() {
-	// return Objects.hash(this.ageGrp, this.ageGrpLower, this.ageGrpUpper, this.athleteName, this.birthDate,
-	// this.birthYear, this.bwCatLower,
-	// this.bwCatString, this.bwCatUpper, this.categoryString, this.event, this.eventLocation, this.gender,
-	// this.groupNameString, this.id, this.nation,
-	// this.recordDate, this.recordFederation, this.recordLift, this.recordName, this.recordValue,
-	// this.fileName, this.recordYear);
-	// }
+	public String getTranslatedGender() {
+		return Translator.translate("Gender." + this.gender);
+	}
+
+	public String getTranslatedLift() {
+		return Translator.translate("Record." + this.recordLift);
+	}
+
+	@Override
+	public int hashCode() {
+		return getClass().hashCode();
+	}
 
 	/**
 	 * The two records are equivalent (ignores Id in database)
@@ -428,6 +414,16 @@ public boolean sameRecordAs(Object obj) {
 		        && this.recordYear == other.recordYear;
 	}
 
+	// @Override
+	// public int hashCode() {
+	// return Objects.hash(this.ageGrp, this.ageGrpLower, this.ageGrpUpper, this.athleteName, this.birthDate,
+	// this.birthYear, this.bwCatLower,
+	// this.bwCatString, this.bwCatUpper, this.categoryString, this.event, this.eventLocation, this.gender,
+	// this.groupNameString, this.id, this.nation,
+	// this.recordDate, this.recordFederation, this.recordLift, this.recordName, this.recordValue,
+	// this.fileName, this.recordYear);
+	// }
+
 	public void setAgeGrp(String ageGrp) {
 		this.ageGrp = ageGrp;
 	}
@@ -547,6 +543,12 @@ public void setRecordYear(int parseInt) {
 		this.recordYear = parseInt;
 	}
 
+	public void setTranslatedGender(String ignored) {
+	}
+
+	public void setTranslatedLift(String ignored) {
+	}
+
 	@Override
 	public String toString() {
 		return getKey();
diff --git a/owlcms/src/main/java/app/owlcms/data/records/RecordFilter.java b/owlcms/src/main/java/app/owlcms/data/records/RecordFilter.java
index 9f2a1be07e..1989f07ad1 100644
--- a/owlcms/src/main/java/app/owlcms/data/records/RecordFilter.java
+++ b/owlcms/src/main/java/app/owlcms/data/records/RecordFilter.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.data.records;
 
 import java.util.ArrayList;
@@ -64,7 +70,7 @@ public static JsonValue buildRecordJson(List displayedRecords, Set<
 			String order = getRowOrder(re.getRecordName(), re.getFileName());
 
 			rowOrder.put(order, re.getRecordName());
-			
+
 			// synthetic key to arrange records in correct box.
 			// expected order U13 < U15 < JR < U23 < SR < Open
 			// Open is after SR, because is 0-999 -- is less specific than 15-999
@@ -72,7 +78,7 @@ public static JsonValue buildRecordJson(List displayedRecords, Set<
 			try {
 				String key2 = String.format("%d_%03d_%03d_%03d_%s",
 				        re.getGender().ordinal(),
-				        re.getAgeGrpUpper(), 999-re.getAgeGrpLower(), 
+				        re.getAgeGrpUpper(), 999 - re.getAgeGrpLower(),
 				        re.getBwCatUpper(),
 				        // re.getRecordFederation()
 				        recordNameIsCategory ? re.getRecordFederation() : "");
diff --git a/owlcms/src/main/java/app/owlcms/data/scoring/AgeFactors.java b/owlcms/src/main/java/app/owlcms/data/scoring/AgeFactors.java
index 651f761eda..df63be2876 100644
--- a/owlcms/src/main/java/app/owlcms/data/scoring/AgeFactors.java
+++ b/owlcms/src/main/java/app/owlcms/data/scoring/AgeFactors.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -23,8 +23,7 @@
 
 /**
  *
- * Compute Q Points according to https://osf.io/8x3nb/ (formulas in https://osf.io/download/r2gxa/ and
- * https://osf.io/download/bmctw/)
+ * Compute Q Points according to https://osf.io/8x3nb/ (formulas in https://osf.io/download/r2gxa/ and https://osf.io/download/bmctw/)
  *
  * This class keeps the code for applying an age factor like SMF/SMHF even though this has not been discussed.
  */
@@ -32,8 +31,8 @@ public class AgeFactors {
 
 	private static final int STARTING_AGE = 8;
 	private static final int STARTING_BW = 30;
-	private static final int NB_AGE = 20-STARTING_AGE+1;
-	private static final int NB_BW = 115-STARTING_BW+1;
+	private static final int NB_AGE = 20 - STARTING_AGE + 1;
+	private static final int NB_BW = 115 - STARTING_BW + 1;
 	final static float[][][] z = new float[2][NB_BW][NB_AGE];
 	private static boolean loaded = false;
 	static Logger logger = (Logger) LoggerFactory.getLogger(AgeFactors.class);
@@ -45,12 +44,12 @@ public static float doGetScore(Gender gender, Double dBW, Integer age, Integer l
 
 		dBW = Math.max(STARTING_BW, Math.min(190.0D, dBW));
 		float floorScore = zCoefficient(gender, (int) Math.floor(dBW), age) * liftedWeight;
-		float ceilingScore = zCoefficient(gender, (int) Math.ceil(dBW), age)  * liftedWeight;
+		float ceilingScore = zCoefficient(gender, (int) Math.ceil(dBW), age) * liftedWeight;
 		double interpolated = floorScore + ((dBW - Math.floor(dBW)) * (ceilingScore - floorScore));
 
-//		logger.debug("doGetScore gender={} bw={} total={} floor={} ceil={} score={}", gender, dBW, liftedWeight,
-//		        floorScore,
-//		        ceilingScore, interpolated);
+		// logger.debug("doGetScore gender={} bw={} total={} floor={} ceil={} score={}", gender, dBW, liftedWeight,
+		// floorScore,
+		// ceilingScore, interpolated);
 
 		return (float) interpolated;
 	}
@@ -59,7 +58,7 @@ public static float getAgeAdjustedTotal(Athlete a, Integer liftedWeight) {
 		if (liftedWeight == null || a == null || a.getAge() == null || a.getBodyWeight() == null) {
 			return 0.0F;
 		}
-		
+
 		Gender gender = a.getGender();
 		Double dBW = a.getBodyWeight();
 		Integer age = a.getAge();
@@ -73,7 +72,7 @@ public static float getAgeAdjustedTotal(Athlete a, Integer liftedWeight) {
 	}
 
 	public static int kgTarget(Gender gender, double targetScore, double bw, int age) {
-		var coef = zCoefficient(gender, (int)bw, age);
+		var coef = zCoefficient(gender, (int) bw, age);
 		return (int) Math.ceil(targetScore / coef);
 	}
 
diff --git a/owlcms/src/main/java/app/owlcms/data/scoring/GAMX.java b/owlcms/src/main/java/app/owlcms/data/scoring/GAMX.java
index acdf421771..947c70e531 100644
--- a/owlcms/src/main/java/app/owlcms/data/scoring/GAMX.java
+++ b/owlcms/src/main/java/app/owlcms/data/scoring/GAMX.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -24,8 +24,7 @@
 
 /**
  *
- * Compute Q Points according to https://osf.io/8x3nb/ (formulas in https://osf.io/download/r2gxa/ and
- * https://osf.io/download/bmctw/)
+ * Compute Q Points according to https://osf.io/8x3nb/ (formulas in https://osf.io/download/r2gxa/ and https://osf.io/download/bmctw/)
  *
  * This class keeps the code for applying an age factor like SMF/SMHF even though this has not been discussed.
  */
@@ -52,9 +51,9 @@ public static float doGetGamx(Gender gender, Double dBW, Integer liftedWeight) {
 		float ceilingScore = M_CONSTANT + zCoefficient(gender, (int) Math.ceil(dBW), liftedWeight) * SD_CONSTANT;
 		double interpolated = floorScore + ((dBW - Math.floor(dBW)) * (ceilingScore - floorScore));
 
-//		logger.debug("doGetGamx gender={} bw={} total={} floor={} ceil={} score={}", gender, dBW, liftedWeight,
-//		        floorScore,
-//		        ceilingScore, interpolated);
+		// logger.debug("doGetGamx gender={} bw={} total={} floor={} ceil={} score={}", gender, dBW, liftedWeight,
+		// floorScore,
+		// ceilingScore, interpolated);
 
 		return (float) interpolated;
 	}
diff --git a/owlcms/src/main/java/app/owlcms/data/scoring/QPoints.java b/owlcms/src/main/java/app/owlcms/data/scoring/QPoints.java
index 3a25545019..a746b992a8 100644
--- a/owlcms/src/main/java/app/owlcms/data/scoring/QPoints.java
+++ b/owlcms/src/main/java/app/owlcms/data/scoring/QPoints.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -24,8 +24,7 @@
 
 /**
  *
- * Compute Q Points according to https://osf.io/8x3nb/ (formulas in https://osf.io/download/r2gxa/ and
- * https://osf.io/download/bmctw/)
+ * Compute Q Points according to https://osf.io/8x3nb/ (formulas in https://osf.io/download/r2gxa/ and https://osf.io/download/bmctw/)
  *
  * The age coefficients are the 2025 coefficients for QMasters
  */
@@ -193,20 +192,6 @@ private void loadCoefficients() {
 		this.setWomenBeta2(Double.valueOf((String) this.props.get("qpoints.womenBeta2")));
 	}
 
-	/**
-	 * @throws IOException
-	 */
-	private void loadProps() {
-		this.props = new Properties();
-		String name = "/qpoints/qpoints" + this.qpointsYear + ".properties";
-		try {
-			InputStream stream = ResourceWalker.getResourceAsStream(name);
-			this.props.load(stream);
-		} catch (Exception e) {
-			this.logger.error("could not load {} because {}\n{}", name, e, LoggerUtils.stackTrace(e));
-		}
-	}
-
 	/**
 	 * @return
 	 * @throws IOException
@@ -231,6 +216,20 @@ private HashMap loadMap() {
 		return this.men;
 	}
 
+	/**
+	 * @throws IOException
+	 */
+	private void loadProps() {
+		this.props = new Properties();
+		String name = "/qpoints/qpoints" + this.qpointsYear + ".properties";
+		try {
+			InputStream stream = ResourceWalker.getResourceAsStream(name);
+			this.props.load(stream);
+		} catch (Exception e) {
+			this.logger.error("could not load {} because {}\n{}", name, e, LoggerUtils.stackTrace(e));
+		}
+	}
+
 	private void setMenBeta0(Double menBeta0) {
 		this.menBeta0 = menBeta0;
 	}
diff --git a/owlcms/src/main/java/app/owlcms/data/scoring/SinclairCoefficients.java b/owlcms/src/main/java/app/owlcms/data/scoring/SinclairCoefficients.java
index ec0b200314..9daae2dab0 100644
--- a/owlcms/src/main/java/app/owlcms/data/scoring/SinclairCoefficients.java
+++ b/owlcms/src/main/java/app/owlcms/data/scoring/SinclairCoefficients.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -120,11 +120,19 @@ public Double womenMaxWeight() {
 		return this.womenMaxWeight;
 	}
 
+	Properties getProps() {
+		return this.props;
+	}
+
+	void setProps(Properties props) {
+		this.props = props;
+	}
+
 	private void loadCoefficients() {
 		if (this.getProps() == null) {
 			loadProps();
 		}
-		//logger.debug("**** loadCoefficicients {} {}",getProps().get("sinclair.menCoefficient"), LoggerUtils.stackTrace());
+		// logger.debug("**** loadCoefficicients {} {}",getProps().get("sinclair.menCoefficient"), LoggerUtils.stackTrace());
 		this.menCoefficient = Double.valueOf((String) this.getProps().get("sinclair.menCoefficient"));
 		this.menMaxWeight = Double.valueOf((String) this.getProps().get("sinclair.menMaxWeight"));
 		this.womenCoefficient = Double.valueOf((String) this.getProps().get("sinclair.womenCoefficient"));
@@ -139,13 +147,13 @@ private synchronized void loadProps() {
 		try {
 			InputStream stream = ResourceWalker.getResourceAsStream(name);
 			if (this.getProps() != null) {
-				//logger.debug("**** props already loaded {}",this.sinclairYear);
+				// logger.debug("**** props already loaded {}",this.sinclairYear);
 				return;
 			}
-			//logger.debug("**** loading props {}", this.sinclairYear);
+			// logger.debug("**** loading props {}", this.sinclairYear);
 			this.setProps(new Properties());
 			this.getProps().load(stream);
-			//logger.debug("**** props loaded {} {}",this.sinclairYear, getProps().get("sinclair.womenCoefficient"));
+			// logger.debug("**** props loaded {} {}",this.sinclairYear, getProps().get("sinclair.womenCoefficient"));
 		} catch (Throwable e) {
 			this.logger.error("could not load {} because {}\n{}", name, e, LoggerUtils.stackTrace(e));
 		}
@@ -174,12 +182,4 @@ private HashMap loadSMM() {
 		}
 		return this.smf;
 	}
-
-	Properties getProps() {
-		return props;
-	}
-
-	void setProps(Properties props) {
-		this.props = props;
-	}
 }
diff --git a/owlcms/src/main/java/app/owlcms/data/team/ITeam.java b/owlcms/src/main/java/app/owlcms/data/team/ITeam.java
index de258f3d1c..5e7c71f8e6 100644
--- a/owlcms/src/main/java/app/owlcms/data/team/ITeam.java
+++ b/owlcms/src/main/java/app/owlcms/data/team/ITeam.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/team/Team.java b/owlcms/src/main/java/app/owlcms/data/team/Team.java
index 237244115a..3820e8643e 100644
--- a/owlcms/src/main/java/app/owlcms/data/team/Team.java
+++ b/owlcms/src/main/java/app/owlcms/data/team/Team.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -24,16 +24,31 @@
 public class Team {
 
 	public static String[] flagExtensions = {
-		".svg",
-		".png",
-		".jpg",
-		".jpeg",
-		".webp"
+	        ".svg",
+	        ".png",
+	        ".jpg",
+	        ".jpeg",
+	        ".webp"
 	};
 	public static Comparator pointsComparator = ((a,
 	        b) -> -ObjectUtils.compare(a.getPoints(), b.getPoints(), true));
 	public static Comparator scoreComparator = ((a,
 	        b) -> -ObjectUtils.compare(a.getScore(), b.getScore(), true));
+
+	public static String[] getFlagExtensions() {
+		return flagExtensions;
+	}
+
+	public static String getImgTag(String teamName, String style) {
+		String teamFileName = URLUtils.sanitizeFilename(teamName);
+
+		return Arrays.stream(getFlagExtensions())
+		        .map(ext -> URLUtils.getImgTag("flags/", teamFileName, ext, style))
+		        .filter(img -> img != null)
+		        .findFirst()
+		        .orElse(null);
+	}
+
 	private int counted;
 	private Gender gender;
 	private String name;
@@ -47,20 +62,6 @@ public class Team {
 	private double qPoints = 0.0D;
 	private Ranking scoringSystem;
 
-	public static String[] getFlagExtensions() {
-		return flagExtensions;
-	}
-
-	public static String getImgTag(String teamName, String style) {
-		String teamFileName = URLUtils.sanitizeFilename(teamName);
-
-		return Arrays.stream(getFlagExtensions())
-			.map(ext -> URLUtils.getImgTag("flags/", teamFileName, ext, style))
-			.filter(img -> img != null)
-			.findFirst()
-			.orElse(null);
-	}
-
 	public Team(String curTeamName, Gender gender) {
 		this.name = curTeamName;
 		this.gender = gender;
diff --git a/owlcms/src/main/java/app/owlcms/data/team/TeamResultsTreeData.java b/owlcms/src/main/java/app/owlcms/data/team/TeamResultsTreeData.java
index beea538b4b..ab3722dce4 100644
--- a/owlcms/src/main/java/app/owlcms/data/team/TeamResultsTreeData.java
+++ b/owlcms/src/main/java/app/owlcms/data/team/TeamResultsTreeData.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/team/TeamSelectionTreeData.java b/owlcms/src/main/java/app/owlcms/data/team/TeamSelectionTreeData.java
index 7f8f990e99..4c67a750c2 100644
--- a/owlcms/src/main/java/app/owlcms/data/team/TeamSelectionTreeData.java
+++ b/owlcms/src/main/java/app/owlcms/data/team/TeamSelectionTreeData.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/data/team/TeamTreeItem.java b/owlcms/src/main/java/app/owlcms/data/team/TeamTreeItem.java
index 23acc11cb3..22bbfbc0e2 100644
--- a/owlcms/src/main/java/app/owlcms/data/team/TeamTreeItem.java
+++ b/owlcms/src/main/java/app/owlcms/data/team/TeamTreeItem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/athletecard/AthleteCard.java b/owlcms/src/main/java/app/owlcms/displays/athletecard/AthleteCard.java
index 20de3ebbdf..9990b76b87 100644
--- a/owlcms/src/main/java/app/owlcms/displays/athletecard/AthleteCard.java
+++ b/owlcms/src/main/java/app/owlcms/displays/athletecard/AthleteCard.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-Fran�ois Lamy
+ * Copyright © 2009-present Jean-Fran�ois Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/attemptboard/AbstractAttemptBoard.java b/owlcms/src/main/java/app/owlcms/displays/attemptboard/AbstractAttemptBoard.java
index da268fdccd..783cec82f3 100644
--- a/owlcms/src/main/java/app/owlcms/displays/attemptboard/AbstractAttemptBoard.java
+++ b/owlcms/src/main/java/app/owlcms/displays/attemptboard/AbstractAttemptBoard.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -585,14 +585,14 @@ protected void doAthleteUpdate(Athlete a, FieldOfPlay fop) {
 			this.getElement().setProperty("nameSizeOverride",
 			        "font-size: 8vh; line-height: 8vh; text-wrap: balance; text-overflow: hidden");
 		}
-		
+
 		String lFirst = a.getFirstName();
 		// add the out-of-competition marker if defined in the translation file.
 		if (!a.isEligibleForIndividualRanking() && lFirst != null && !lFirst.isBlank()) {
 			lFirst = Translator.translate("Attempt.Extra/Invited", lFirst);
 		}
 		this.getElement().setProperty("firstName", lFirst);
-		
+
 		this.getElement().setProperty("decisionVisible", false);
 		Category category2 = a.getCategory();
 		this.getElement().setProperty("category", category2 != null ? category2.getDisplayName() : "");
@@ -830,7 +830,6 @@ private void doNotification(String text, String recordText, String theme, int du
 
 		OwlcmsSession.withFop(fop -> {
 			n.open();
-			return;
 		});
 	}
 
diff --git a/owlcms/src/main/java/app/owlcms/displays/attemptboard/AttemptBoard.java b/owlcms/src/main/java/app/owlcms/displays/attemptboard/AttemptBoard.java
index ae0b2ebe02..ce03b5b1a0 100644
--- a/owlcms/src/main/java/app/owlcms/displays/attemptboard/AttemptBoard.java
+++ b/owlcms/src/main/java/app/owlcms/displays/attemptboard/AttemptBoard.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/attemptboard/BrandedAttemptBoard.java b/owlcms/src/main/java/app/owlcms/displays/attemptboard/BrandedAttemptBoard.java
index 8db3f59739..4f48702743 100644
--- a/owlcms/src/main/java/app/owlcms/displays/attemptboard/BrandedAttemptBoard.java
+++ b/owlcms/src/main/java/app/owlcms/displays/attemptboard/BrandedAttemptBoard.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/attemptboard/DecisionBoard.java b/owlcms/src/main/java/app/owlcms/displays/attemptboard/DecisionBoard.java
index 3cdaccb8f3..5e7eecb915 100644
--- a/owlcms/src/main/java/app/owlcms/displays/attemptboard/DecisionBoard.java
+++ b/owlcms/src/main/java/app/owlcms/displays/attemptboard/DecisionBoard.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/options/DisplayOptions.java b/owlcms/src/main/java/app/owlcms/displays/options/DisplayOptions.java
index da06d538de..3b4ee56f42 100644
--- a/owlcms/src/main/java/app/owlcms/displays/options/DisplayOptions.java
+++ b/owlcms/src/main/java/app/owlcms/displays/options/DisplayOptions.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/CurrentAthlete.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/CurrentAthlete.java
index 8075b71e5e..4d538b38e6 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/CurrentAthlete.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/CurrentAthlete.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-Fran�ois Lamy
+ * Copyright © 2009-present Jean-Fran�ois Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -348,7 +348,6 @@ protected void doUpdate(Athlete a, UIEvent e) {
 			// change bottom line as soon as possible
 			updateDisplay(computeLiftType(a), fop);
 
-
 		}
 		// logger.debug("leave top alone {} {}", leaveTopAlone, fop.getState());
 		if (leaveTopAlone && fop.getState() == FOPState.CURRENT_ATHLETE_DISPLAYED) {
@@ -533,6 +532,11 @@ protected void setTranslationMap() {
 		this.getElement().setPropertyJson("t", translations);
 	}
 
+	@Override
+	protected void setWideTeamNames(boolean wide) {
+		this.getElement().setProperty("teamWidthClass", (wide ? "wideTeams" : "narrowTeams"));
+	}
+
 	@Override
 	protected void updateDisplay(String liftType, FieldOfPlay fop) {
 		// logger.debug("updateBottom {}",LoggerUtils.stackTrace());
@@ -616,11 +620,6 @@ private void setDone(boolean b) {
 		this.groupDone = b;
 	}
 
-	@Override
-	protected void setWideTeamNames(boolean wide) {
-		this.getElement().setProperty("teamWidthClass", (wide ? "wideTeams" : "narrowTeams"));
-	}
-
 	private void syncWithFOP(UIEvent.SwitchGroup e) {
 		switch (e.getState()) {
 			case INACTIVE:
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/Results.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/Results.java
index a263939f72..da9708c0e4 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/Results.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/Results.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -586,6 +586,58 @@ public void slaveSwitchGroup(UIEvent.SwitchGroup e) {
 		});
 	}
 
+	protected String computedScore(Athlete a) {
+		AgeGroup ageGroup = a.getAgeGroup();
+		Ranking ageGroupScoringSystem = ageGroup != null ? ageGroup.getComputedScoringSystem() : null;
+		// logger.debug("a {} agegroup {} scoring {}", a.getLastName(), a.getAgeGroup(), a.getAgeGroup().getScoringSystem());
+
+		Competition current = Competition.getCurrent();
+		boolean sinclair = current.isSinclair();
+		Competition current2 = Competition.getCurrent();
+		boolean displayGlobal = current2.isDisplayScores();
+		Competition current3 = Competition.getCurrent();
+		Ranking scoringSystem = current3.getScoringSystem();
+
+		if (ageGroupScoringSystem != null && !sinclair && !displayGlobal) {
+			double value = Ranking.getRankingValue(a, Ranking.CATEGORY_SCORE);
+			String score;
+			if (ageGroupScoringSystem == Ranking.TOTAL) {
+				score = value > 0.001 ? String.format("%.0f", value) : "-";
+			} else {
+				score = value > 0.001 ? String.format("%.3f", value) : "-";
+			}
+			return score;
+		} else {
+			double value = Ranking.getRankingValue(a, scoringSystem);
+			String score = value > 0.001 ? String.format("%.3f", value) : "-";
+			return score;
+		}
+	}
+
+	protected String computedScoreRank(Athlete a) {
+		Ranking ageGroupScoringSystem = a.getAgeGroup().getComputedScoringSystem();
+
+		Competition current = Competition.getCurrent();
+		boolean sinclair = current.isSinclair();
+		Competition current2 = Competition.getCurrent();
+		boolean displayGlobal = current2.isDisplayScoreRanks();
+		Competition current3 = Competition.getCurrent();
+		Ranking bestLifterScoringSystem = current3.getScoringSystem();
+
+		if (a.isEligibleForIndividualRanking()) {
+			if (ageGroupScoringSystem != null && !sinclair && !displayGlobal) {
+				Integer value = Ranking.getRanking(a, Ranking.CATEGORY_SCORE);
+				return value != null && value > 0 ? "" + value : "-";
+			} else {
+				Integer value = Ranking.getRanking(a, bestLifterScoringSystem);
+				return value != null && value > 0 ? "" + value : "-";
+			}
+		} else {
+			return Translator.translate("Results.Extra/Invited");
+		}
+
+	}
+
 	protected void computeLeaders(boolean done) {
 		OwlcmsSession.withFop(fop -> {
 			Athlete curAthlete = fop.getCurAthlete();
@@ -992,14 +1044,6 @@ protected BiPredicate getSeparatorPredicate() {
 		return separator;
 	}
 
-	private boolean isAllBWCategory(Athlete cur) {
-		// score-based all-bodyweight categories need to be identified
-		var cat = cur.getCategory();
-		var min = cat.getMinimumWeight();
-		var max = cat.getMaximumWeight();
-		return (min < 10 && max > 900);
-	}
-
 	/**
 	 * @see com.vaadin.flow.component.Component#onAttach(com.vaadin.flow.component.AttachEvent)
 	 */
@@ -1124,58 +1168,6 @@ protected void updateDisplay(String liftType, FieldOfPlay fop) {
 		computeRecords(done);
 	}
 
-	protected String computedScore(Athlete a) {
-		AgeGroup ageGroup = a.getAgeGroup();
-		Ranking ageGroupScoringSystem = ageGroup != null ? ageGroup.getComputedScoringSystem() : null;
-		// logger.debug("a {} agegroup {} scoring {}", a.getLastName(), a.getAgeGroup(), a.getAgeGroup().getScoringSystem());
-
-		Competition current = Competition.getCurrent();
-		boolean sinclair = current.isSinclair();
-		Competition current2 = Competition.getCurrent();
-		boolean displayGlobal = current2.isDisplayScores();
-		Competition current3 = Competition.getCurrent();
-		Ranking scoringSystem = current3.getScoringSystem();
-
-		if (ageGroupScoringSystem != null && !sinclair && !displayGlobal) {
-			double value = Ranking.getRankingValue(a, Ranking.CATEGORY_SCORE);
-			String score;
-			if (ageGroupScoringSystem == Ranking.TOTAL) {
-				score = value > 0.001 ? String.format("%.0f", value) : "-";
-			} else {
-				score = value > 0.001 ? String.format("%.3f", value) : "-";
-			}
-			return score;
-		} else {
-			double value = Ranking.getRankingValue(a, scoringSystem);
-			String score = value > 0.001 ? String.format("%.3f", value) : "-";
-			return score;
-		}
-	}
-
-	protected String computedScoreRank(Athlete a) {
-		Ranking ageGroupScoringSystem = a.getAgeGroup().getComputedScoringSystem();
-
-		Competition current = Competition.getCurrent();
-		boolean sinclair = current.isSinclair();
-		Competition current2 = Competition.getCurrent();
-		boolean displayGlobal = current2.isDisplayScoreRanks();
-		Competition current3 = Competition.getCurrent();
-		Ranking bestLifterScoringSystem = current3.getScoringSystem();
-
-		if (a.isEligibleForIndividualRanking()) {
-			if (ageGroupScoringSystem != null && !sinclair && !displayGlobal) {
-				Integer value = Ranking.getRanking(a, Ranking.CATEGORY_SCORE);
-				return value != null && value > 0 ? "" + value : "-";
-			} else {
-				Integer value = Ranking.getRanking(a, bestLifterScoringSystem);
-				return value != null && value > 0 ? "" + value : "-";
-			}
-		} else {
-			return Translator.translate("Results.Extra/Invited");
-		}
-
-	}
-
 	private String computeLiftType(Athlete a) {
 		if (a == null || a.getAttemptsDone() > 6) {
 			return null;
@@ -1215,6 +1207,14 @@ private String formatKg(String total) {
 		        : (total.startsWith("-") ? "(" + total.substring(1) + ")" : total);
 	}
 
+	private boolean isAllBWCategory(Athlete cur) {
+		// score-based all-bodyweight categories need to be identified
+		var cat = cur.getCategory();
+		var min = cat.getMinimumWeight();
+		var max = cat.getMaximumWeight();
+		return (min < 10 && max > 900);
+	}
+
 	private void setDisplay() {
 		OwlcmsSession.withFop(fop -> {
 			setBoardMode(fop.getState(), fop.getBreakType(), fop.getCeremonyType(), this.getElement());
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsJury.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsJury.java
index 7b4f402027..6bc3e66a91 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsJury.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsJury.java
@@ -1,10 +1,16 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.displays.scoreboard;
 
 import app.owlcms.nui.displays.scoreboards.WarmupNoLeadersPage;
 
 @SuppressWarnings("serial")
 public class ResultsJury extends ResultsNoLeaders {
-	
+
 	public ResultsJury(WarmupNoLeadersPage page) {
 		super(page);
 	}
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsLiftingOrder.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsLiftingOrder.java
index 2ad3049cad..aeeaee0d27 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsLiftingOrder.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsLiftingOrder.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.displays.scoreboard;
 
 import java.util.List;
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMedals.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMedals.java
index e528be5ee6..e7e7f715f0 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMedals.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMedals.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-Fran�ois Lamy
+ * Copyright © 2009-present Jean-Fran�ois Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -96,15 +96,6 @@ public void doBreak(UIEvent event) {
 		OwlcmsSession.withFop(fop -> doBreak(fop));
 	}
 
-	private void doBreak(FieldOfPlay fop) {
-		this.getElement().setProperty("fullName",
-		        inferGroupName() + " – " + inferMessage(fop.getBreakType(), fop.getCeremonyType(), true));
-		this.getElement().setProperty("teamName", "");
-		this.getElement().setProperty("attempt", "");
-		setDisplay();
-		updateDisplay(computeLiftType(fop.getCurAthlete()), fop);
-	}
-
 	@Override
 	public void doCeremony(UIEvent.CeremonyStarted e) {
 		this.setCeremony(true);
@@ -127,11 +118,6 @@ public void doCeremony(UIEvent.CeremonyStarted e) {
 		});
 	}
 
-	@Override
-	public Championship getChampionship() {
-		return this.ageDivision;
-	}
-
 	@Override
 	public AgeGroup getAgeGroup() {
 		return this.ageGroup;
@@ -148,13 +134,17 @@ public Category getCategory() {
 	}
 
 	@Override
-	public boolean isShowInitialDialog() {
-		return false;
+	public Championship getChampionship() {
+		return this.ageDivision;
+	}
+
+	public boolean isCeremony() {
+		return this.ceremony;
 	}
 
 	@Override
-	public void setChampionship(Championship ageDivision) {
-		this.ageDivision = ageDivision;
+	public boolean isShowInitialDialog() {
+		return false;
 	}
 
 	@Override
@@ -172,10 +162,41 @@ public void setCategory(Category category) {
 		this.category = category;
 	}
 
+	public void setCeremony(boolean ceremony) {
+		this.ceremony = ceremony;
+	}
+
+	@Override
+	public void setChampionship(Championship ageDivision) {
+		this.ageDivision = ageDivision;
+	}
+
+	public void setScoreRanks(boolean scoreNeeded) {
+		this.getElement().setProperty("showSinclair", scoreNeeded);
+		this.getElement().setProperty("showSinclairRank", scoreNeeded);
+	}
+
 	@Override
 	public void setSilenced(boolean silent) {
 	}
 
+	public void setTitles(JsonObject jMC, Category cat) {
+		jMC.put("categoryName", cat.getDisplayName());
+		Ranking scoringSystem = cat.getAgeGroup().getScoringSystem();
+		String rankingTitle = Translator.translate("Rank");
+		if (scoringSystem != null && scoringSystem != Ranking.TOTAL) {
+			String scoreScoringTitle = Translator.translate("Score");
+			scoreScoringTitle = Ranking.getScoringTitle(scoringSystem);
+			jMC.put("rankingTitle", "");
+			jMC.put("scoreScoringTitle", scoreScoringTitle);
+			jMC.put("scoreRankingTitle", rankingTitle);
+		} else {
+			jMC.put("rankingTitle", rankingTitle);
+			jMC.put("scoreScoringTitle", "");
+			jMC.put("scoreRankingTitle", "");
+		}
+	}
+
 	@Subscribe
 	public void slaveAllEvents(UIEvent e) {
 		// uiLog(e);
@@ -288,6 +309,29 @@ public void slaveVideoRefresh(UIEvent.VideoRefresh e) {
 		});
 	}
 
+	public void syncWithFOP(FieldOfPlay fop) {
+		// logger.debug("syncWithFOP");
+		switch (fop.getState()) {
+			case INACTIVE:
+				this.setGroup(null);
+				this.setCategory(null);
+				doEmpty();
+				break;
+			// case BREAK:
+			default:
+				setCeremony(fop.getCeremonyType() == CeremonyType.MEDALS);
+				if (!this.isCeremony()) {
+					this.setGroup(fop.getGroup());
+					this.setCategory(null);
+					doRefresh(new UIEvent.SwitchGroup(fop.getGroup(), FOPState.BREAK, fop.getCurAthlete(), this, fop));
+				}
+				break;
+			// default:
+			// setDisplay();
+			// updateDisplay(null, fop);
+		}
+	}
+
 	@Override
 	protected void doEmpty() {
 		// no need to hide, text is self evident.
@@ -449,6 +493,13 @@ protected void setWideTeamNames(boolean wide) {
 		this.getElement().setProperty("teamWidthClass", (wide ? "wideTeams" : "narrowTeams"));
 	}
 
+	@Override
+	protected void uiLog(UIEvent e) {
+		// this.logger./**/warn(">>>>> {} {} {} {}",
+		// this.getClass().getSimpleName(), e.getClass().getSimpleName(), e.getOrigin(),
+		// LoggerUtils.whereFrom());
+	}
+
 	@Override
 	protected void updateDisplay(String liftType, FieldOfPlay fop) {
 		// logger.debug("updateBottom");
@@ -527,28 +578,6 @@ private void computeGroupMedalsJson(TreeMap> medals2) {
 		}
 	}
 
-	public void setScoreRanks(boolean scoreNeeded) {
-		this.getElement().setProperty("showSinclair", scoreNeeded);
-		this.getElement().setProperty("showSinclairRank", scoreNeeded);
-	}
-
-	public void setTitles(JsonObject jMC, Category cat) {
-		jMC.put("categoryName", cat.getDisplayName());
-		Ranking scoringSystem = cat.getAgeGroup().getScoringSystem();
-		String rankingTitle = Translator.translate("Rank");
-		if (scoringSystem != null && scoringSystem != Ranking.TOTAL) {
-			String scoreScoringTitle = Translator.translate("Score");
-			scoreScoringTitle = Ranking.getScoringTitle(scoringSystem);
-			jMC.put("rankingTitle", "");
-			jMC.put("scoreScoringTitle", scoreScoringTitle);
-			jMC.put("scoreRankingTitle", rankingTitle);
-		} else {
-			jMC.put("rankingTitle", rankingTitle);
-			jMC.put("scoreScoringTitle", "");
-			jMC.put("scoreRankingTitle", "");
-		}
-	}
-
 	private String computeLiftType(Athlete a) {
 		if (a == null || a.getAttemptsDone() > 6) {
 			return null;
@@ -566,22 +595,19 @@ private void computeMedalsJson(TreeMap> medals2) {
 		}
 	}
 
-	private void doMedalsDisplay() {
-		medalsInit();
-		checkVideo(this);
-		this.teamFlags = URLUtils.checkFlags();
-		doMedals(this.getFop());
-
-		if (!Competition.getCurrent().isSnatchCJTotalMedals()) {
-			getElement().setProperty("noLiftRanks", "noranks");
-		}
-		this.getElement().setProperty("displayTitle", Translator.translate("CeremonyType.MEDALS"));
+	private void doBreak(FieldOfPlay fop) {
+		this.getElement().setProperty("fullName",
+		        inferGroupName() + " – " + inferMessage(fop.getBreakType(), fop.getCeremonyType(), true));
+		this.getElement().setProperty("teamName", "");
+		this.getElement().setProperty("attempt", "");
+		setDisplay();
+		updateDisplay(computeLiftType(fop.getCurAthlete()), fop);
 	}
 
-	private void doRefresh(UIEvent e) {
-		FieldOfPlay fop2 = e.getFop();
-		doMedals(fop2);
-	}
+	// private void retrieveFromSessionStorage(String key, SerializableConsumer resultHandler) {
+	// getElement().executeJs("return window.sessionStorage.getItem($0);", key)
+	// .then(String.class, resultHandler);
+	// }
 
 	private void doMedals(FieldOfPlay fop2) {
 		if (this.getCategory() == null) {
@@ -605,16 +631,28 @@ private void doMedals(FieldOfPlay fop2) {
 		computeMedalsJson(this.getMedals());
 	}
 
+	private void doMedalsDisplay() {
+		medalsInit();
+		checkVideo(this);
+		this.teamFlags = URLUtils.checkFlags();
+		doMedals(this.getFop());
+
+		if (!Competition.getCurrent().isSnatchCJTotalMedals()) {
+			getElement().setProperty("noLiftRanks", "noranks");
+		}
+		this.getElement().setProperty("displayTitle", Translator.translate("CeremonyType.MEDALS"));
+	}
+
+	private void doRefresh(UIEvent e) {
+		FieldOfPlay fop2 = e.getFop();
+		doMedals(fop2);
+	}
+
 	private String formatKg(String total) {
 		return (total == null || total.trim().isEmpty()) ? "-"
 		        : (total.startsWith("-") ? "(" + total.substring(1) + ")" : total);
 	}
 
-	// private void retrieveFromSessionStorage(String key, SerializableConsumer resultHandler) {
-	// getElement().executeJs("return window.sessionStorage.getItem($0);", key)
-	// .then(String.class, resultHandler);
-	// }
-
 	/**
 	 * Compute Json string ready to be used by web component template
 	 *
@@ -675,6 +713,14 @@ private void getAttemptsJson(Athlete a) {
 		}
 	}
 
+	private TreeMap> getMedals() {
+		return this.medals;
+	}
+
+	private UI getUi() {
+		return this.ui;
+	}
+
 	private boolean isMedalist(Athlete a) {
 		if (a.getGroup() == null) {
 			return false;
@@ -718,6 +764,14 @@ private void setDisplay() {
 		});
 	}
 
+	private void setMedals(TreeMap> medals) {
+		this.medals = medals;
+	}
+
+	private void setUi(UI ui) {
+		this.ui = ui;
+	}
+
 	private void syncWithFOP(UIEvent.SwitchGroup e) {
 		switch (e.getState()) {
 			case INACTIVE:
@@ -745,58 +799,4 @@ private void syncWithFOP(UIEvent.SwitchGroup e) {
 		}
 	}
 
-	public void syncWithFOP(FieldOfPlay fop) {
-		// logger.debug("syncWithFOP");
-		switch (fop.getState()) {
-			case INACTIVE:
-				this.setGroup(null);
-				this.setCategory(null);
-				doEmpty();
-				break;
-			// case BREAK:
-			default:
-				setCeremony(fop.getCeremonyType() == CeremonyType.MEDALS);
-				if (!this.isCeremony()) {
-					this.setGroup(fop.getGroup());
-					this.setCategory(null);
-					doRefresh(new UIEvent.SwitchGroup(fop.getGroup(), FOPState.BREAK, fop.getCurAthlete(), this, fop));
-				}
-				break;
-			// default:
-			// setDisplay();
-			// updateDisplay(null, fop);
-		}
-	}
-
-	@Override
-	protected void uiLog(UIEvent e) {
-		// this.logger./**/warn(">>>>> {} {} {} {}",
-		// this.getClass().getSimpleName(), e.getClass().getSimpleName(), e.getOrigin(),
-		// LoggerUtils.whereFrom());
-	}
-
-	private TreeMap> getMedals() {
-		return medals;
-	}
-
-	private void setMedals(TreeMap> medals) {
-		this.medals = medals;
-	}
-
-	private UI getUi() {
-		return ui;
-	}
-
-	private void setUi(UI ui) {
-		this.ui = ui;
-	}
-
-	public boolean isCeremony() {
-		return ceremony;
-	}
-
-	public void setCeremony(boolean ceremony) {
-		this.ceremony = ceremony;
-	}
-
 }
\ No newline at end of file
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMultiRanks.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMultiRanks.java
index 19582cecc3..f0f1e228af 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMultiRanks.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsMultiRanks.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsNoLeaders.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsNoLeaders.java
index b61f556046..bcac3eab2e 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsNoLeaders.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsNoLeaders.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankingOrder.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankingOrder.java
index 0c8f5677b5..9e4c09f379 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankingOrder.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankingOrder.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.displays.scoreboard;
 
 import java.util.List;
diff --git a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankings.java b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankings.java
index 67b0a120d1..759a60dcd7 100644
--- a/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankings.java
+++ b/owlcms/src/main/java/app/owlcms/displays/scoreboard/ResultsRankings.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.displays.scoreboard;
 
 import java.util.Collections;
@@ -42,7 +48,7 @@ protected JsonValue getAthletesJson(List rankingOrder, final FieldOfPla
 		        : Collections.emptyList();
 
 		athletes.stream()
-				.filter(a -> a.getGroup() != null)
+		        .filter(a -> a.getGroup() != null)
 		        .sorted((a, b) -> {
 			        int aTotalRank = a.getTotalRank();
 			        aTotalRank = aTotalRank == 0 ? 999 : aTotalRank;
diff --git a/owlcms/src/main/java/app/owlcms/displays/top/AbstractTop.java b/owlcms/src/main/java/app/owlcms/displays/top/AbstractTop.java
index 2493ca98a5..1439298d21 100644
--- a/owlcms/src/main/java/app/owlcms/displays/top/AbstractTop.java
+++ b/owlcms/src/main/java/app/owlcms/displays/top/AbstractTop.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.displays.top;
 
 import app.owlcms.apputils.queryparameters.TopParameters;
@@ -14,11 +20,6 @@ public class AbstractTop extends Results implements TopParameters {
 	private String ageGroupPrefix;
 	private Category category;
 
-	@Override
-	final public Championship getChampionship() {
-		return this.ageDivision;
-	}
-
 	@Override
 	final public AgeGroup getAgeGroup() {
 		return this.ageGroup;
@@ -35,8 +36,8 @@ final public Category getCategory() {
 	}
 
 	@Override
-	final public void setChampionship(Championship ageDivision) {
-		this.ageDivision = ageDivision;
+	final public Championship getChampionship() {
+		return this.ageDivision;
 	}
 
 	@Override
@@ -54,4 +55,9 @@ final public void setCategory(Category cat) {
 		this.category = cat;
 	}
 
+	@Override
+	final public void setChampionship(Championship ageDivision) {
+		this.ageDivision = ageDivision;
+	}
+
 }
diff --git a/owlcms/src/main/java/app/owlcms/displays/top/TopSinclair.java b/owlcms/src/main/java/app/owlcms/displays/top/TopSinclair.java
index 275beefc56..92cc88a976 100644
--- a/owlcms/src/main/java/app/owlcms/displays/top/TopSinclair.java
+++ b/owlcms/src/main/java/app/owlcms/displays/top/TopSinclair.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-Fran�ois Lamy
+ * Copyright © 2009-present Jean-Fran�ois Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/top/TopTeams.java b/owlcms/src/main/java/app/owlcms/displays/top/TopTeams.java
index b402eaf62e..34b1562fdd 100644
--- a/owlcms/src/main/java/app/owlcms/displays/top/TopTeams.java
+++ b/owlcms/src/main/java/app/owlcms/displays/top/TopTeams.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-Fran�ois Lamy
+ * Copyright © 2009-present Jean-Fran�ois Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/top/TopTeamsSinclair.java b/owlcms/src/main/java/app/owlcms/displays/top/TopTeamsSinclair.java
index 9ca55f620e..da1c931ff8 100644
--- a/owlcms/src/main/java/app/owlcms/displays/top/TopTeamsSinclair.java
+++ b/owlcms/src/main/java/app/owlcms/displays/top/TopTeamsSinclair.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/video/StreamingEventMonitor.java b/owlcms/src/main/java/app/owlcms/displays/video/StreamingEventMonitor.java
index 3b9d483870..38fc45d218 100644
--- a/owlcms/src/main/java/app/owlcms/displays/video/StreamingEventMonitor.java
+++ b/owlcms/src/main/java/app/owlcms/displays/video/StreamingEventMonitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-Fran�ois Lamy
+ * Copyright © 2009-present Jean-Fran�ois Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/displays/video/StylesDirSelection.java b/owlcms/src/main/java/app/owlcms/displays/video/StylesDirSelection.java
index 2a461c4771..2544915ffe 100644
--- a/owlcms/src/main/java/app/owlcms/displays/video/StylesDirSelection.java
+++ b/owlcms/src/main/java/app/owlcms/displays/video/StylesDirSelection.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.displays.video;
 
 import java.io.FileNotFoundException;
diff --git a/owlcms/src/main/java/app/owlcms/endpoints/CompetitionExport.java b/owlcms/src/main/java/app/owlcms/endpoints/CompetitionExport.java
index 397e443720..b50e64a7d7 100644
--- a/owlcms/src/main/java/app/owlcms/endpoints/CompetitionExport.java
+++ b/owlcms/src/main/java/app/owlcms/endpoints/CompetitionExport.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -40,17 +40,15 @@
 import jakarta.servlet.http.HttpServletResponse;
 
 /**
- * A file servlet supporting resume of downloads and client-side caching and GZIP of text content. This servlet can also
- * be used for images, client-side caching would become more efficient. This servlet can also be used for text files,
- * GZIP would decrease network bandwidth.
+ * A file servlet supporting resume of downloads and client-side caching and GZIP of text content. This servlet can also be used for images, client-side caching
+ * would become more efficient. This servlet can also be used for text files, GZIP would decrease network bandwidth.
  *
  * @author BalusC
  * @link http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html
  */
 @SuppressWarnings("serial")
 /**
- * Modified to fetch files under the ./local directory relative to the startup directory and, failing that, as a
- * resource on the classpath.
+ * Modified to fetch files under the ./local directory relative to the startup directory and, failing that, as a resource on the classpath.
  *
  * @author Jean-François Lamy
  *
diff --git a/owlcms/src/main/java/app/owlcms/endpoints/SimulationServlet.java b/owlcms/src/main/java/app/owlcms/endpoints/SimulationServlet.java
index 29a72dfcdc..d0eddba103 100644
--- a/owlcms/src/main/java/app/owlcms/endpoints/SimulationServlet.java
+++ b/owlcms/src/main/java/app/owlcms/endpoints/SimulationServlet.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -39,17 +39,15 @@
 import jakarta.servlet.http.HttpServletResponse;
 
 /**
- * A file servlet supporting resume of downloads and client-side caching and GZIP of text content. This servlet can also
- * be used for images, client-side caching would become more efficient. This servlet can also be used for text files,
- * GZIP would decrease network bandwidth.
+ * A file servlet supporting resume of downloads and client-side caching and GZIP of text content. This servlet can also be used for images, client-side caching
+ * would become more efficient. This servlet can also be used for text files, GZIP would decrease network bandwidth.
  *
  * @author BalusC
  * @link http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html
  */
 @SuppressWarnings("serial")
 /**
- * Modified to fetch files under the ./local directory relative to the startup directory and, failing that, as a
- * resource on the classpath.
+ * Modified to fetch files under the ./local directory relative to the startup directory and, failing that, as a resource on the classpath.
  *
  * @author Jean-François Lamy
  *
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/CountdownType.java b/owlcms/src/main/java/app/owlcms/fieldofplay/CountdownType.java
index 0598372ab0..ce631f75f4 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/CountdownType.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/CountdownType.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.fieldofplay;
 
 public enum CountdownType {
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/FOPError.java b/owlcms/src/main/java/app/owlcms/fieldofplay/FOPError.java
index 9023055f9c..8396cbc847 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/FOPError.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/FOPError.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/FOPEvent.java b/owlcms/src/main/java/app/owlcms/fieldofplay/FOPEvent.java
index 2f231f5dea..a0260f0eb3 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/FOPEvent.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/FOPEvent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -380,6 +380,10 @@ public boolean equals(Object obj) {
 			return this.isDecision() == other.isDecision() && this.getRefIndex() == other.getRefIndex();
 		}
 
+		public int getRefIndex() {
+			return this.refIndex;
+		}
+
 		@Override
 		public int hashCode() {
 			final int prime = 31;
@@ -388,25 +392,21 @@ public int hashCode() {
 			return result;
 		}
 
-		@Override
-		public String toString() {
-			return "[decision=" + this.isDecision() + ", refIndex=" + this.getRefIndex() + "]";
+		public boolean isDecision() {
+			return this.decision;
 		}
 
-		public int getRefIndex() {
-			return refIndex;
+		public void setDecision(boolean decision) {
+			this.decision = decision;
 		}
 
 		public void setRefIndex(int refIndex) {
 			this.refIndex = refIndex;
 		}
 
-		public boolean isDecision() {
-			return decision;
-		}
-
-		public void setDecision(boolean decision) {
-			this.decision = decision;
+		@Override
+		public String toString() {
+			return "[decision=" + this.isDecision() + ", refIndex=" + this.getRefIndex() + "]";
 		}
 
 	}
@@ -705,10 +705,9 @@ public void setResultChange(boolean resultChange) {
 
 	protected Athlete athlete;
 	/**
-	 * When a FOPEvent (for example stopping the clock) is handled, it is often reflected as a series of UIEvents (for
-	 * example, all the displays running the clock get told to stop it). The user interface that gave the order doesn't
-	 * want to be notified again, so we memorize which user interface element created the original order so it can
-	 * ignore it.
+	 * When a FOPEvent (for example stopping the clock) is handled, it is often reflected as a series of UIEvents (for example, all the displays running the
+	 * clock get told to stop it). The user interface that gave the order doesn't want to be notified again, so we memorize which user interface element created
+	 * the original order so it can ignore it.
 	 */
 	protected Object origin;
 	final Logger logger = (Logger) LoggerFactory.getLogger(FOPEvent.class);
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/FOPState.java b/owlcms/src/main/java/app/owlcms/fieldofplay/FOPState.java
index 12924f25ef..fae35d5364 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/FOPState.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/FOPState.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -24,8 +24,7 @@ public enum FOPState {
 	CURRENT_ATHLETE_DISPLAYED,
 
 	/**
-	 * time is running. Either automatically started on announce (if using the default "start on announce", or manually
-	 * by timekeeper (in traditional mode)
+	 * time is running. Either automatically started on announce (if using the default "start on announce", or manually by timekeeper (in traditional mode)
 	 */
 	TIME_RUNNING,
 
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/FieldOfPlay.java b/owlcms/src/main/java/app/owlcms/fieldofplay/FieldOfPlay.java
index 0e3dfd1668..a363ec9db9 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/FieldOfPlay.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/FieldOfPlay.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -319,6 +319,10 @@ public Athlete getAthleteUnderReview() {
 		return this.athleteUnderReview;
 	}
 
+	public int getBarWeight() {
+		return this.barWeight;
+	}
+
 	public IBreakTimer getBreakTimer() {
 		// if (!(this.breakTimer.getClass().isAssignableFrom(ProxyBreakTimer.class)))
 		// throw new RuntimeException("wrong athleteTimer setup");
@@ -481,6 +485,10 @@ public List getNewRecords() {
 		return this.newRecords;
 	}
 
+	public Athlete getNextAthlete() {
+		return this.nextAthlete;
+	}
+
 	/**
 	 * @return the platform
 	 */
@@ -981,17 +989,6 @@ public synchronized void handleFOPEvent(FOPEvent e) {
 		}
 	}
 
-	private void restartTimer(FOPEvent e) {
-		cancelWakeUpRef();
-		if (decisionDisplayTimer != null) {
-			decisionDisplayTimer.cancel();
-		}
-		resetDecisions();
-		pushOutUIEvent(new UIEvent.DecisionReset(getCurAthlete(), this, this));
-		transitionToLifting(e, group, announcerDecisionImmediate);
-		fopEventPost(new FOPEvent.TimeStarted(this));
-	}
-
 	public void init(List athletes, IProxyTimer timer, IProxyTimer breakTimer, boolean alreadyLoaded) {
 		this.athleteTimer = timer;
 		this.athleteTimer.setFop(this);
@@ -1076,10 +1073,18 @@ public boolean isEmitSoundsOnServer() {
 		return b;
 	}
 
+	public boolean isLightBarInUse() {
+		return this.lightBarInUse;
+	}
+
 	public boolean isRefereeForcedDecision() {
 		return this.refereeForcedDecision;
 	}
 
+	public boolean isSingleReferee() {
+		return this.singleReferee;
+	}
+
 	public boolean isTestingMode() {
 		return this.testingMode;
 	}
@@ -1088,6 +1093,10 @@ public synchronized boolean isTimeoutEmitted() {
 		return this.timeoutEmitted;
 	}
 
+	public boolean isUseCollarsIfAvailable() {
+		return this.useCollarsIfAvailable;
+	}
+
 	/**
 	 * all grids get their athletes from this method.
 	 *
@@ -1144,6 +1153,12 @@ public synchronized void loadGroup(Group group, Object origin, boolean forceLoad
 		}
 	}
 
+	public void pushOutUIEvent(UIEvent event) {
+		// logger.debug("!!!! {}",event);
+		getUiEventBus().post(event);
+		getEventForwardingBus().post(event);
+	}
+
 	public boolean recomputeLiftingOrder(boolean currentDisplayAffected, boolean resultChange) {
 		Competition comp = Competition.getCurrent();
 		// because of recalculation of ranks, if same category is lifting on two FOPs, strange things can happen
@@ -1366,6 +1381,11 @@ public void setRefereeTime(Long[] refereeTime) {
 		this.refereeTime = refereeTime;
 	}
 
+	public void setSingleReferee(boolean solo) {
+		// logger.debug("===== set single referee {}",solo);
+		this.singleReferee = solo;
+	}
+
 	/**
 	 * @param testingMode true if we don't want wait delays during testing.
 	 */
@@ -1434,8 +1454,8 @@ void emitFinalWarning() {
 		if (!isFinalWarningEmitted()) {
 			this.logger.info("{}Final Warning", FieldOfPlay.getLoggingName(this));
 			if (isEmitSoundsOnServer()) {
-				finalWarningSound = new Sound(getSoundMixer(), "finalWarning.wav");
-				finalWarningSound.emit();
+				this.finalWarningSound = new Sound(getSoundMixer(), "finalWarning.wav");
+				this.finalWarningSound.emit();
 			}
 			pushOutUIEvent(new UIEvent.TimeRemaining(this, 30, this));
 			setFinalWarningEmitted(true);
@@ -1446,8 +1466,8 @@ void emitInitialWarning() {
 		if (!isInitialWarningEmitted()) {
 			this.logger.info("{}Initial Warning", FieldOfPlay.getLoggingName(this));
 			if (isEmitSoundsOnServer()) {
-				initialWarningSound = new Sound(getSoundMixer(), "initialWarning.wav");
-				initialWarningSound.emit();
+				this.initialWarningSound = new Sound(getSoundMixer(), "initialWarning.wav");
+				this.initialWarningSound.emit();
 			}
 			pushOutUIEvent(new UIEvent.TimeRemaining(this, 90, this));
 			setInitialWarningEmitted(true);
@@ -1458,8 +1478,8 @@ void emitTimeOver() {
 		if (!isTimeoutEmitted()) {
 			this.logger.info("{}Time Over", FieldOfPlay.getLoggingName(this));
 			if (isEmitSoundsOnServer()) {
-				timeOverSound = new Sound(getSoundMixer(), "timeOver.wav");
-				timeOverSound.emit();
+				this.timeOverSound = new Sound(getSoundMixer(), "timeOver.wav");
+				this.timeOverSound.emit();
 
 			}
 			pushOutUIEvent(new UIEvent.TimeRemaining(this, 0, this));
@@ -1467,12 +1487,6 @@ void emitTimeOver() {
 		}
 	}
 
-	public void pushOutUIEvent(UIEvent event) {
-		// logger.debug("!!!! {}",event);
-		getUiEventBus().post(event);
-		getEventForwardingBus().post(event);
-	}
-
 	/**
 	 * Sets the state.
 	 *
@@ -1515,6 +1529,70 @@ private void cancelWakeUpRef() {
 		this.wakeUpRef = null;
 	}
 
+	private void changePlatformEquipment(Athlete a, Integer newWeight) {
+		// skip during unit tests or results editing
+		if (getPlatform() == null || a == null) {
+			return;
+		}
+		boolean use15Bar = false;
+		if (Config.getCurrent().featureSwitch("childrenEquipment")) {
+			getPlatform().setNbB_5(1);
+			getPlatform().setNbB_10(1);
+			getPlatform().setNbB_15(1);
+			getPlatform().setNbB_20(1);
+			getPlatform().setNbL_2_5(1);
+			getPlatform().setNbL_5(1);
+		}
+		AgeGroup ageGroup = a.getAgeGroup();
+		boolean boysLightBarAllowed = Config.getCurrent().featureSwitch("lightBarU13")
+		        && (ageGroup != null && ageGroup.getMinAge() <= 12 && ageGroup.getMaxAge() <= 20);
+		use15Bar = (a != null && a.getGender() != Gender.M) || boysLightBarAllowed;
+
+		Integer age = this.curAthlete.getAge();
+		if (Config.getCurrent().featureSwitch("usawCollars") && age != null && age > 13) {
+			this.setLightBarInUse(false);
+			Gender gender = this.curAthlete != null ? this.curAthlete.getGender() : null;
+			this.setBarWeight((gender != null && gender == Gender.M) ? 20 : 15);
+			this.setUseCollarsIfAvailable(true);
+		} else if (getPlatform().isUseNonStandardBar()) {
+			this.logger.trace("non standard bar: {}", getPlatform().getNonStandardBarWeight());
+			Integer nonStandardBarWeight = getPlatform().getNonStandardBarWeight();
+			this.setBarWeight(nonStandardBarWeight);
+			this.setLightBarInUse((a.getGender() == Gender.F && nonStandardBarWeight != 15) ||
+			        (a.getGender() == Gender.M && nonStandardBarWeight != 20));
+			this.setUseCollarsIfAvailable(this.curWeight >= getPlatform().getCollarThreshold());
+		} else if (newWeight <= 14 && getPlatform().getNbB_5() > 0) {
+			this.logger.trace("<= 14");
+			this.setLightBarInUse(true);
+			this.setBarWeight(5);
+			this.setUseCollarsIfAvailable(false);
+		} else if (newWeight <= 19 && getPlatform().getNbB_10() > 0) {
+			this.logger.trace("<= 19");
+			this.setLightBarInUse(true);
+			this.setBarWeight(10);
+			this.setUseCollarsIfAvailable(false);
+		} else if ((newWeight < getPlatform().getCollarThreshold() && (getPlatform().getNbB_20() == 0 || use15Bar) && (getPlatform().getNbB_15() > 0))) {
+			this.logger.trace("< 40 15");
+			this.setLightBarInUse(a.getGender() != Gender.F);
+			this.setBarWeight(15);
+			this.setUseCollarsIfAvailable(false);
+		} else {
+			boolean useCollars = newWeight >= getPlatform().getCollarThreshold();
+			if ((useCollars && (getPlatform().getNbB_20() == 0 || use15Bar) && (getPlatform().getNbB_15() > 0))) {
+				this.logger.trace(">=40 15 collars");
+				this.setLightBarInUse(a.getGender() != Gender.F);
+				this.setBarWeight(15);
+				this.setUseCollarsIfAvailable(true);
+			} else {
+				this.logger.trace("standard");
+				this.setLightBarInUse(false);
+				Gender gender = this.curAthlete != null ? this.curAthlete.getGender() : null;
+				this.setBarWeight((gender != null && gender == Gender.M) ? 20 : 15);
+				this.setUseCollarsIfAvailable(useCollars);
+			}
+		}
+	}
+
 	private void checkDeferredWeightChanges() {
 		if (!this.deferredWeightChanges.isEmpty()) {
 			// decision reset did not happen, we have pending weight changes.
@@ -1680,15 +1758,6 @@ private void doPossiblySoloRefereeUpdate(FOPEvent e) {
 		}
 	}
 
-	public boolean isSingleReferee() {
-		return this.singleReferee;
-	}
-
-	public void setSingleReferee(boolean solo) {
-		// logger.debug("===== set single referee {}",solo);
-		this.singleReferee = solo;
-	}
-
 	private void doSetState(FOPState state) {
 		if (state == CURRENT_ATHLETE_DISPLAYED) {
 			Athlete a = getCurAthlete();
@@ -1891,10 +1960,6 @@ private List getLastNewRecords() {
 		return this.lastNewRecords;
 	}
 
-	public Athlete getNextAthlete() {
-		return this.nextAthlete;
-	}
-
 	private int getPrevWeight() {
 		return this.prevWeight;
 	}
@@ -2243,7 +2308,7 @@ private void recomputeOrderAndRanks(boolean recomputeCategoryRanks) {
 		long endLeaders = 0;
 
 		var initialList = getLiftingOrder();
-		logger.debug("{}recompute ranks recomputeCategoryRanks={} [{}]", FieldOfPlay.getLoggingName(this),
+		this.logger.debug("{}recompute ranks recomputeCategoryRanks={} [{}]", FieldOfPlay.getLoggingName(this),
 		        recomputeCategoryRanks, LoggerUtils.whereFrom());
 		if (recomputeCategoryRanks) {
 			// we update the ranks all athletes in our category, as well as the current scoring system
@@ -2325,29 +2390,6 @@ private void recomputeOrderAndRanks(boolean recomputeCategoryRanks) {
 
 	}
 
-	private List updateScoringSystemRanking(EntityManager em, List l) {
-		if (Competition.getCurrent().isDisplayScoreRanks()) {
-			// long beforeRanks = System.currentTimeMillis();
-			try {
-				// this only computes the current scoring system
-				Competition.getCurrent().scoringSystemRankings(em);
-			} catch (Exception e) {
-				this.logger.error("{} scoringSystemRankings exception {}\n ", FieldOfPlay.getLoggingName(this),
-				        e,
-				        LoggerUtils.stackTrace(e));
-			}
-			// long afterRanks = System.currentTimeMillis();
-			// logger.debug("-------------------- scoringSystemRankings {}ms", afterRanks - beforeRanks);
-		}
-
-		List nl = new LinkedList<>();
-		for (Athlete a : l) {
-			nl.add(em.merge(a));
-		}
-		em.flush();
-		return nl;
-	}
-
 	private void recomputeRecordsMap(List athletes) {
 		// logger.debug("recompute record map");
 		this.groupRecords.clear();
@@ -2384,6 +2426,17 @@ private void resetEmittedFlags() {
 		setClockStoppedDecisionsAllowed(false);
 	}
 
+	private void restartTimer(FOPEvent e) {
+		cancelWakeUpRef();
+		if (this.decisionDisplayTimer != null) {
+			this.decisionDisplayTimer.cancel();
+		}
+		resetDecisions();
+		pushOutUIEvent(new UIEvent.DecisionReset(getCurAthlete(), this, this));
+		transitionToLifting(e, this.group, this.announcerDecisionImmediate);
+		fopEventPost(new FOPEvent.TimeStarted(this));
+	}
+
 	private boolean resumeLifting(FOPEvent e) {
 		// time will be restarted anyway
 		setWeightAtLastStart(0);
@@ -2422,6 +2475,10 @@ private void setAthleteUnderReview(Athlete curAthlete2) {
 		this.athleteUnderReview = curAthlete2;
 	}
 
+	private void setBarWeight(int i) {
+		this.barWeight = i;
+	}
+
 	private void setBreakParams(FOPEvent.BreakStarted e, IBreakTimer breakTimer2, BreakType breakType2,
 	        CountdownType countdownType2) {
 		this.setBreakType(breakType2);
@@ -2519,6 +2576,10 @@ private void setLiftingOrder(List liftingOrder) {
 		this.liftingOrder = liftingOrder;
 	}
 
+	private void setLightBarInUse(boolean b) {
+		this.lightBarInUse = b;
+	}
+
 	private void setPreviousAthlete(Athlete athlete) {
 		this.previousAthlete = athlete;
 	}
@@ -2574,6 +2635,10 @@ private synchronized void setTimeoutEmitted(boolean timeoutEmitted) {
 		this.timeoutEmitted = timeoutEmitted;
 	}
 
+	private void setUseCollarsIfAvailable(boolean b) {
+		this.useCollarsIfAvailable = b;
+	}
+
 	private void setWeightAtLastStart() {
 		setWeightAtLastStart(getCurAthlete().getNextAttemptRequestedWeight());
 	}
@@ -2583,7 +2648,7 @@ private synchronized void showDecisionAfterDelay(Object origin2, int reversalDel
 		// reversalDelay);
 		assert !isDecisionDisplayScheduled(); // caller checks.
 		setDecisionDisplayScheduled(true); // so there are never two scheduled...
-		decisionDisplayTimer = new DelayTimer(isTestingMode()).schedule(() -> showDecisionNow(origin2), reversalDelay);
+		this.decisionDisplayTimer = new DelayTimer(isTestingMode()).schedule(() -> showDecisionNow(origin2), reversalDelay);
 	}
 
 	/**
@@ -2933,84 +2998,6 @@ private void uiDisplayCurrentAthleteAndTime(boolean currentDisplayAffected, FOPE
 		}
 	}
 
-	private void changePlatformEquipment(Athlete a, Integer newWeight) {
-		// skip during unit tests or results editing
-		if (getPlatform() == null || a == null) {
-			return;
-		}
-		boolean use15Bar = false;
-		if (Config.getCurrent().featureSwitch("childrenEquipment")) {
-			getPlatform().setNbB_5(1);
-			getPlatform().setNbB_10(1);
-			getPlatform().setNbB_15(1);
-			getPlatform().setNbB_20(1);
-			getPlatform().setNbL_2_5(1);
-			getPlatform().setNbL_5(1);
-		}
-		AgeGroup ageGroup = a.getAgeGroup();
-		boolean boysLightBarAllowed = Config.getCurrent().featureSwitch("lightBarU13")
-		        && (ageGroup != null && ageGroup.getMinAge() <= 12 && ageGroup.getMaxAge() <= 20);
-		use15Bar = (a != null && a.getGender() != Gender.M) || boysLightBarAllowed;
-
-		Integer age = curAthlete.getAge();
-		if (Config.getCurrent().featureSwitch("usawCollars") && age != null && age > 13 ) {
-			this.setLightBarInUse(false);
-			Gender gender = curAthlete != null ? curAthlete.getGender() : null;
-			this.setBarWeight((gender != null && gender == Gender.M) ? 20 : 15);
-			this.setUseCollarsIfAvailable(true);
-		} 
-		else if (getPlatform().isUseNonStandardBar()) {
-			logger.trace("non standard bar: {}", getPlatform().getNonStandardBarWeight());
-			Integer nonStandardBarWeight = getPlatform().getNonStandardBarWeight();
-			this.setBarWeight(nonStandardBarWeight);
-			this.setLightBarInUse((a.getGender() == Gender.F && nonStandardBarWeight != 15) ||
-			        (a.getGender() == Gender.M && nonStandardBarWeight != 20));
-			this.setUseCollarsIfAvailable(this.curWeight >= getPlatform().getCollarThreshold());
-		} else if (newWeight <= 14 && getPlatform().getNbB_5() > 0) {
-			logger.trace("<= 14");
-			this.setLightBarInUse(true);
-			this.setBarWeight(5);
-			this.setUseCollarsIfAvailable(false);
-		} else if (newWeight <= 19 && getPlatform().getNbB_10() > 0) {
-			logger.trace("<= 19");
-			this.setLightBarInUse(true);
-			this.setBarWeight(10);
-			this.setUseCollarsIfAvailable(false);
-		} else if ((newWeight < getPlatform().getCollarThreshold() && (getPlatform().getNbB_20() == 0 || use15Bar) && (getPlatform().getNbB_15() > 0))) {
-			logger.trace("< 40 15");
-			this.setLightBarInUse(a.getGender() != Gender.F);
-			this.setBarWeight(15);
-			this.setUseCollarsIfAvailable(false);
-		} else {
-			boolean useCollars = newWeight >= getPlatform().getCollarThreshold();
-			if ((useCollars && (getPlatform().getNbB_20() == 0 || use15Bar) && (getPlatform().getNbB_15() > 0))) {
-				logger.trace(">=40 15 collars");
-				this.setLightBarInUse(a.getGender() != Gender.F);
-				this.setBarWeight(15);
-				this.setUseCollarsIfAvailable(true);
-			} else {
-				logger.trace("standard");
-				this.setLightBarInUse(false);
-				Gender gender = curAthlete != null ? curAthlete.getGender() : null;
-				this.setBarWeight((gender != null && gender == Gender.M) ? 20 : 15);
-				this.setUseCollarsIfAvailable(useCollars);
-			}
-		}
-		return;
-	}
-
-	private void setUseCollarsIfAvailable(boolean b) {
-		this.useCollarsIfAvailable = b;
-	}
-
-	private void setBarWeight(int i) {
-		this.barWeight = i;
-	}
-
-	private void setLightBarInUse(boolean b) {
-		this.lightBarInUse = b;
-	}
-
 	private synchronized void uiShowDownSignalOnSlaveDisplays(Object origin2) {
 		boolean announcerImmediate = origin2 instanceof AnnouncerContent && isAnnouncerDecisionImmediate();
 		boolean emitSoundsOnServer2 = isEmitSoundsOnServer();
@@ -3034,7 +3021,7 @@ private synchronized void uiShowDownSignalOnSlaveDisplays(Object origin2) {
 
 	private void uiShowPlates(BarbellOrPlatesChanged e) {
 		if (e.getOrigin() != this) {
-			changePlatformEquipment(curAthlete, curWeight);
+			changePlatformEquipment(this.curAthlete, this.curWeight);
 		}
 		pushOutUIEvent(new UIEvent.BarbellOrPlatesChanged(e.getOrigin(), this));
 	}
@@ -3163,7 +3150,7 @@ private void updateRefereeDecisions(FOPEvent.DecisionFullUpdate e) {
 		} else {
 			// this should never happen, but the order of JavaScript callbacks
 			// from the browser to the server is not guaranteed.
-			logger.error("ignoring out of order DecisionFullUpdate event {}", e);
+			this.logger.error("ignoring out of order DecisionFullUpdate event {}", e);
 		}
 	}
 
@@ -3173,6 +3160,29 @@ private void updateRefereeDecisions(FOPEvent.DecisionUpdate e) {
 		processRefereeDecisions(e);
 	}
 
+	private List updateScoringSystemRanking(EntityManager em, List l) {
+		if (Competition.getCurrent().isDisplayScoreRanks()) {
+			// long beforeRanks = System.currentTimeMillis();
+			try {
+				// this only computes the current scoring system
+				Competition.getCurrent().scoringSystemRankings(em);
+			} catch (Exception e) {
+				this.logger.error("{} scoringSystemRankings exception {}\n ", FieldOfPlay.getLoggingName(this),
+				        e,
+				        LoggerUtils.stackTrace(e));
+			}
+			// long afterRanks = System.currentTimeMillis();
+			// logger.debug("-------------------- scoringSystemRankings {}ms", afterRanks - beforeRanks);
+		}
+
+		List nl = new LinkedList<>();
+		for (Athlete a : l) {
+			nl.add(em.merge(a));
+		}
+		em.flush();
+		return nl;
+	}
+
 	private void warnMissingKg() {
 		int missingKg = this.getCurAthlete().startingTotalDelta();
 		if (missingKg > 0) {
@@ -3199,16 +3209,4 @@ private void weightChangeDoNotDisturb(WeightChange e) {
 		uiDisplayCurrentAthleteAndTime(false, e, false);
 	}
 
-	public boolean isUseCollarsIfAvailable() {
-		return useCollarsIfAvailable;
-	}
-
-	public int getBarWeight() {
-		return barWeight;
-	}
-
-	public boolean isLightBarInUse() {
-		return lightBarInUse;
-	}
-
 }
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/IBreakTimer.java b/owlcms/src/main/java/app/owlcms/fieldofplay/IBreakTimer.java
index d43531a0ca..9ce4086d8b 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/IBreakTimer.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/IBreakTimer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/IProxyTimer.java b/owlcms/src/main/java/app/owlcms/fieldofplay/IProxyTimer.java
index 4d791e06c2..e9dc1d2b92 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/IProxyTimer.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/IProxyTimer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderInfo.java b/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderInfo.java
index 55e2ede9f4..e931a99daf 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderInfo.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -32,7 +32,7 @@ public int compareTo(LiftOrderInfo actualLiftInfo) {
 		}
 
 		// same kind of lift.
-		
+
 		compare = Integer.compare(this.getWeight(), actualLiftInfo.getWeight());
 		if (compare != 0) {
 			// same attempt, bigger weight goes later
@@ -50,7 +50,7 @@ public int compareTo(LiftOrderInfo actualLiftInfo) {
 			// same weight, same attempt, bigger progression first
 			return -compare;
 		}
-		
+
 		// when same progression between 2 and 3 must also look at progression between 1 and 2
 		compare = Integer.compare(this.getCumulativeProgression(), actualLiftInfo.getCumulativeProgression());
 		if (compare != 0) {
@@ -81,9 +81,10 @@ public boolean equals(Object obj) {
 			return false;
 		}
 		LiftOrderInfo other = (LiftOrderInfo) obj;
-		return getAttemptNo()==(other.getAttemptNo())
-		        && getLotNumber()==(other.getLotNumber()) && getProgression()==(other.getProgression()) && getCumulativeProgression()==(other.getCumulativeProgression())
-		        && getStartNumber()==(other.getStartNumber()) && getWeight()==(other.getWeight());
+		return getAttemptNo() == (other.getAttemptNo())
+		        && getLotNumber() == (other.getLotNumber()) && getProgression() == (other.getProgression())
+		        && getCumulativeProgression() == (other.getCumulativeProgression())
+		        && getStartNumber() == (other.getStartNumber()) && getWeight() == (other.getWeight());
 	}
 
 	public Athlete getAthlete() {
@@ -94,6 +95,10 @@ public int getAttemptNo() {
 		return this.attemptNo;
 	}
 
+	public int getCumulativeProgression() {
+		return this.cumulativeProgression;
+	}
+
 	public int getLotNumber() {
 		return this.lotNumber;
 	}
@@ -128,6 +133,10 @@ public void setAttemptNo(int attemptNo) {
 		this.attemptNo = attemptNo;
 	}
 
+	public void setCumulativeProgression(int cumulativeProgression) {
+		this.cumulativeProgression = cumulativeProgression;
+	}
+
 	public void setLotNumber(int lotNumber) {
 		this.lotNumber = lotNumber;
 	}
@@ -153,12 +162,4 @@ public String toString() {
 		        + "]";
 	}
 
-	public void setCumulativeProgression(int cumulativeProgression) {
-		this.cumulativeProgression = cumulativeProgression;
-	}
-
-	public int getCumulativeProgression() {
-		return cumulativeProgression;
-	}
-
 }
\ No newline at end of file
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderReconstruction.java b/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderReconstruction.java
index 666771aa54..06872da0f1 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderReconstruction.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/LiftOrderReconstruction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyAthleteTimer.java b/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyAthleteTimer.java
index 3328cd2daf..0e22f3bd55 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyAthleteTimer.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyAthleteTimer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -19,8 +19,8 @@
 import ch.qos.logback.classic.Logger;
 
 /**
- * Class ProxyBreakTimer. Relay serverTimer instructions from {@link FieldOfPlay} to the actual timers associated with each
- * screen. Memorize the elapsed time and serverTimer state.
+ * Class ProxyBreakTimer. Relay serverTimer instructions from {@link FieldOfPlay} to the actual timers associated with each screen. Memorize the elapsed time
+ * and serverTimer state.
  *
  * @author Jean-François Lamy
  */
@@ -169,7 +169,48 @@ public void start() {
 
 		if (!Config.getCurrent().featureSwitch("oldTimers")) {
 			this.serverTimer = new Timer();
-			serverTimer.schedule(computeTask(timeRemaining), timeRemaining % 30000);
+			this.serverTimer.schedule(computeTask(this.timeRemaining), this.timeRemaining % 30000);
+		}
+	}
+
+	/**
+	 * @see app.owlcms.fieldofplay.IProxyTimer#stop()
+	 */
+	@Override
+	public void stop() {
+		if (this.running) {
+			computeTimeRemaining();
+		}
+		if (this.logger.isDebugEnabled()) {
+			this.logger.debug("{}stopping Time -- timeRemaining = {} ({})", FieldOfPlay.getLoggingName(getFop()),
+			        this.timeRemaining,
+			        LoggerUtils.whereFrom());
+		}
+		this.timeRemainingAtLastStop = this.timeRemaining;
+		if (this.serverTimer != null) {
+			this.logger.info("{}+++++ stopping serverTimer", FieldOfPlay.getLoggingName(this.fop));
+			this.serverTimer.cancel();
+		}
+		getFop().pushOutUIEvent(new UIEvent.StopTime(this.timeRemaining, null, getFop()));
+		this.running = false;
+	}
+
+	@Override
+	public void timeOver(Object origin) {
+		// avoid sending multiple events to FOP
+		boolean needToSendEvent = !getFop().isTimeoutEmitted();
+		if (needToSendEvent) {
+			getFop().emitTimeOver();
+			getFop().fopEventPost(new FOPEvent.TimeOver(origin));
+		}
+		// leave enough time for buzzer event to propagate allowing for some clock drift
+		if (this.running) {
+			try {
+				// timers that are more than 1 sec. late will now stop silently.
+				Thread.sleep(1000);
+				this.stop();
+			} catch (InterruptedException e) {
+			}
 		}
 	}
 
@@ -178,58 +219,58 @@ private TimerTask computeTask(int timeRemaining2) {
 		int nbStops = (timeRemaining) / 30000;
 		switch (nbStops) {
 			case 0 -> {
-				logger.debug("{}+++++ scheduling serverTimer timeOver {}", FieldOfPlay.getLoggingName(fop), timeRemaining);
+				this.logger.debug("{}+++++ scheduling serverTimer timeOver {}", FieldOfPlay.getLoggingName(this.fop), timeRemaining);
 				return new TimerTask() {
 					@Override
 					public void run() {
-						logger.info("{}+++++ running time over", FieldOfPlay.getLoggingName(fop));
+						ProxyAthleteTimer.this.logger.info("{}+++++ running time over", FieldOfPlay.getLoggingName(ProxyAthleteTimer.this.fop));
 						timeOver(this);
 					}
 				};
 			}
 			case 1 -> {
-				logger.debug("{}+++++ scheduling serverTimer finalWarning {}", FieldOfPlay.getLoggingName(fop), timeRemaining);
+				this.logger.debug("{}+++++ scheduling serverTimer finalWarning {}", FieldOfPlay.getLoggingName(this.fop), timeRemaining);
 				return new TimerTask() {
 					@Override
 					public void run() {
-						logger.info("{}+++++ running final warning", FieldOfPlay.getLoggingName(fop));
+						ProxyAthleteTimer.this.logger.info("{}+++++ running final warning", FieldOfPlay.getLoggingName(ProxyAthleteTimer.this.fop));
 						finalWarning(this);
 						// next task is time over, in 30sec.
-						serverTimer.schedule(computeTask(0), 30000);
+						ProxyAthleteTimer.this.serverTimer.schedule(computeTask(0), 30000);
 					}
 				};
 			}
 			case 2 -> {
-				logger.debug("{}+++++ scheduling serverTimer 1:00 {}", FieldOfPlay.getLoggingName(fop), timeRemaining);
+				this.logger.debug("{}+++++ scheduling serverTimer 1:00 {}", FieldOfPlay.getLoggingName(this.fop), timeRemaining);
 				return new TimerTask() {
 					@Override
 					public void run() {
-						logger.info("{}running 1:00", FieldOfPlay.getLoggingName(fop));
+						ProxyAthleteTimer.this.logger.info("{}running 1:00", FieldOfPlay.getLoggingName(ProxyAthleteTimer.this.fop));
 						// nothing to do, next task is final warning, in 30s.
-						serverTimer.schedule(computeTask(30000), 30000);
+						ProxyAthleteTimer.this.serverTimer.schedule(computeTask(30000), 30000);
 					}
 				};
 			}
 			case 3 -> {
-				logger.debug("{}+++++ scheduling server serverTimer initialWarning {}", FieldOfPlay.getLoggingName(fop), timeRemaining);
+				this.logger.debug("{}+++++ scheduling server serverTimer initialWarning {}", FieldOfPlay.getLoggingName(this.fop), timeRemaining);
 				return new TimerTask() {
 					@Override
 					public void run() {
-						logger.info("{}+++++ running initial warning", FieldOfPlay.getLoggingName(fop));
+						ProxyAthleteTimer.this.logger.info("{}+++++ running initial warning", FieldOfPlay.getLoggingName(ProxyAthleteTimer.this.fop));
 						initialWarning(this);
 						// next task is final warning, in 60 seconds.
-						serverTimer.schedule(computeTask(30000), 60000);
+						ProxyAthleteTimer.this.serverTimer.schedule(computeTask(30000), 60000);
 					}
 				};
 			}
 			case 4 -> {
-				logger.debug("{}+++++ scheduling server serverTimer 2:00 {}", FieldOfPlay.getLoggingName(fop), timeRemaining);
+				this.logger.debug("{}+++++ scheduling server serverTimer 2:00 {}", FieldOfPlay.getLoggingName(this.fop), timeRemaining);
 				return new TimerTask() {
 					@Override
 					public void run() {
-						logger.info("{}+++++ running 2:00", FieldOfPlay.getLoggingName(fop));
+						ProxyAthleteTimer.this.logger.info("{}+++++ running 2:00", FieldOfPlay.getLoggingName(ProxyAthleteTimer.this.fop));
 						// next task is initial warning, in 30s.
-						serverTimer.schedule(computeTask(90000), 30000);
+						ProxyAthleteTimer.this.serverTimer.schedule(computeTask(90000), 30000);
 					}
 				};
 			}
@@ -239,47 +280,6 @@ public void run() {
 		}
 	}
 
-	/**
-	 * @see app.owlcms.fieldofplay.IProxyTimer#stop()
-	 */
-	@Override
-	public void stop() {
-		if (this.running) {
-			computeTimeRemaining();
-		}
-		if (this.logger.isDebugEnabled()) {
-			this.logger.debug("{}stopping Time -- timeRemaining = {} ({})", FieldOfPlay.getLoggingName(getFop()),
-			        this.timeRemaining,
-			        LoggerUtils.whereFrom());
-		}
-		this.timeRemainingAtLastStop = this.timeRemaining;
-		if (this.serverTimer != null) {
-			logger.info("{}+++++ stopping serverTimer", FieldOfPlay.getLoggingName(fop));
-			this.serverTimer.cancel();
-		}
-		getFop().pushOutUIEvent(new UIEvent.StopTime(this.timeRemaining, null, getFop()));
-		this.running = false;
-	}
-
-	@Override
-	public void timeOver(Object origin) {
-		// avoid sending multiple events to FOP
-		boolean needToSendEvent = !getFop().isTimeoutEmitted();
-		if (needToSendEvent) {
-			getFop().emitTimeOver();
-			getFop().fopEventPost(new FOPEvent.TimeOver(origin));
-		}
-		// leave enough time for buzzer event to propagate allowing for some clock drift
-		if (this.running) {
-			try {
-				// timers that are more than 1 sec. late will now stop silently.
-				Thread.sleep(1000);
-				this.stop();
-			} catch (InterruptedException e) {
-			}
-		}
-	}
-
 	/**
 	 * Compute time elapsed since start and adjust time remaining accordingly.
 	 */
diff --git a/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyBreakTimer.java b/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyBreakTimer.java
index ce6d43779a..bc72b825ae 100644
--- a/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyBreakTimer.java
+++ b/owlcms/src/main/java/app/owlcms/fieldofplay/ProxyBreakTimer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -220,7 +220,7 @@ public void setTimeRemaining(int timeRemaining2, boolean indefinite) {
 	@Override
 	public void start() {
 		BreakType breakType = getFop().getBreakType();
-		//logger.debug("{}****** starting break with breakType = {} from={}", FieldOfPlay.getLoggingName(fop), breakType, LoggerUtils.whereFrom());
+		// logger.debug("{}****** starting break with breakType = {} from={}", FieldOfPlay.getLoggingName(fop), breakType, LoggerUtils.whereFrom());
 		if (breakType == null) {
 			this.logger.error("null breaktype {}", LoggerUtils.stackTrace());
 		}
@@ -236,33 +236,22 @@ millisRemaining, getOrigin(), false,
 		// logger.debug("posting {}", event);
 		getFop().pushOutUIEvent(event);
 		setRunning(true);
-		
+
 		if (Config.getCurrent().featureSwitch("oldTimers")) {
 			return;
 		}
-		
+
 		// if a break is running, need to stop it before starting another.
 		if (this.serverTimer != null) {
-			//logger.debug("Cancelling running timer");
-			serverTimer.cancel();
+			// logger.debug("Cancelling running timer");
+			this.serverTimer.cancel();
 		}
 		this.serverTimer = new Timer();
-		TimerTask timerTask = computeTask(timeRemaining);
-		serverTimer.schedule(timerTask, timeRemaining);
+		TimerTask timerTask = computeTask(this.timeRemaining);
+		this.serverTimer.schedule(timerTask, this.timeRemaining);
 
 	}
 
-	private TimerTask computeTask(int timeRemaining2) {
-		logger.info("{}+++++ scheduling serverTimer break over {}", FieldOfPlay.getLoggingName(fop), timeRemaining);
-		return new TimerTask() {
-			@Override
-			public void run() {
-				logger.info("{}+++++ running break over", FieldOfPlay.getLoggingName(fop));
-				timeOver(this);
-			}
-		};
-	}
-
 	/**
 	 * @see app.owlcms.fieldofplay.IProxyTimer#stop()
 	 */
@@ -318,6 +307,17 @@ FieldOfPlay getFop() {
 		return this.fop;
 	}
 
+	private TimerTask computeTask(int timeRemaining2) {
+		this.logger.info("{}+++++ scheduling serverTimer break over {}", FieldOfPlay.getLoggingName(this.fop), this.timeRemaining);
+		return new TimerTask() {
+			@Override
+			public void run() {
+				ProxyBreakTimer.this.logger.info("{}+++++ running break over", FieldOfPlay.getLoggingName(ProxyBreakTimer.this.fop));
+				timeOver(this);
+			}
+		};
+	}
+
 	/**
 	 * Compute time elapsed since start and adjust time remaining accordingly.
 	 */
@@ -337,12 +337,12 @@ private int getMillis() {
 		        : getTimeRemaining());
 	}
 
-	private void setRunning(boolean running) {
-		this.running = running;
-	}
-
 	private void setIndefinite(boolean indefinite) {
 		// logger.debug("breakTimer setIndefinite {} {}",indefinite, LoggerUtils.whereFrom());
 		this.indefinite = indefinite;
 	}
+
+	private void setRunning(boolean running) {
+		this.running = running;
+	}
 }
diff --git a/owlcms/src/main/java/app/owlcms/init/InitialData.java b/owlcms/src/main/java/app/owlcms/init/InitialData.java
index d1bb7963fd..3e4dcea180 100644
--- a/owlcms/src/main/java/app/owlcms/init/InitialData.java
+++ b/owlcms/src/main/java/app/owlcms/init/InitialData.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/init/MoquetteAuthenticator.java b/owlcms/src/main/java/app/owlcms/init/MoquetteAuthenticator.java
index 5c696d028a..e7c99d5e43 100644
--- a/owlcms/src/main/java/app/owlcms/init/MoquetteAuthenticator.java
+++ b/owlcms/src/main/java/app/owlcms/init/MoquetteAuthenticator.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.init;
 
 import java.nio.charset.StandardCharsets;
diff --git a/owlcms/src/main/java/app/owlcms/init/OwlcmsFactory.java b/owlcms/src/main/java/app/owlcms/init/OwlcmsFactory.java
index 68cf83a799..0a0c5012ca 100644
--- a/owlcms/src/main/java/app/owlcms/init/OwlcmsFactory.java
+++ b/owlcms/src/main/java/app/owlcms/init/OwlcmsFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -33,9 +33,8 @@
 /**
  * Singleton, one per running JVM (i.e. one instance of owlcms, or one unit test)
  *
- * This class allows a web session to locate the event bus on which information will be broacast. All web pages talk to
- * one another via the event bus. The {@link OwlcmsSession} class is used to remember the current field of play for the
- * user.
+ * This class allows a web session to locate the event bus on which information will be broacast. All web pages talk to one another via the event bus. The
+ * {@link OwlcmsSession} class is used to remember the current field of play for the user.
  *
  * @author owlcms
  */
@@ -51,6 +50,16 @@ public class OwlcmsFactory {
 		logger.setLevel(Level.INFO);
 	}
 
+	public static void awaitLatch() throws InterruptedException {
+		// logger.debug("***** awaitLatch {} {}",latch.getCount(), LoggerUtils.whereFrom());
+		latch.await();
+	}
+
+	public static void countDownLatch() throws InterruptedException {
+		// logger.debug("***** countDownLatch {} {}",latch.getCount(), LoggerUtils.whereFrom());
+		latch.countDown();
+	}
+
 	public static EventBus getAppUIBus() {
 		if (appEventBus == null) {
 			appEventBus = new EventBus();
@@ -101,22 +110,6 @@ public static Collection getFOPs() {
 		return values;
 	}
 
-	private static CountDownLatch getInitializationLatch() {
-		//logger.debug("***** getInitializationLatch {} {}",latch.getCount(), LoggerUtils.whereFrom());
-		return latch;
-	}
-	
-	public static void awaitLatch() throws InterruptedException {
-		//logger.debug("***** awaitLatch {} {}",latch.getCount(), LoggerUtils.whereFrom());
-		latch.await();
-	}
-	
-	
-	public static void countDownLatch() throws InterruptedException {
-		//logger.debug("***** countDownLatch {} {}",latch.getCount(), LoggerUtils.whereFrom());
-		latch.countDown();
-	}
-
 	public static String getVersion() {
 		return StartupUtils.getVersion();
 	}
@@ -202,7 +195,7 @@ public static FieldOfPlay unregisterFOP(Platform platform) {
 	public static void waitDBInitialized() {
 		try {
 			CountDownLatch initializationLatch = OwlcmsFactory.getInitializationLatch();
-			logger.debug("******** latch.getCount() {}",latch.getCount());
+			logger.debug("******** latch.getCount() {}", latch.getCount());
 			initializationLatch.await();
 		} catch (InterruptedException e) {
 		}
@@ -212,6 +205,11 @@ static void setFopByName(Map fopByName) {
 		OwlcmsFactory.fopByName = fopByName;
 	}
 
+	private static CountDownLatch getInitializationLatch() {
+		// logger.debug("***** getInitializationLatch {} {}",latch.getCount(), LoggerUtils.whereFrom());
+		return latch;
+	}
+
 	/**
 	 * @param defaultFOP the defaultFOP to set
 	 */
diff --git a/owlcms/src/main/java/app/owlcms/init/OwlcmsSession.java b/owlcms/src/main/java/app/owlcms/init/OwlcmsSession.java
index b4a4107f4f..c9227a03a5 100644
--- a/owlcms/src/main/java/app/owlcms/init/OwlcmsSession.java
+++ b/owlcms/src/main/java/app/owlcms/init/OwlcmsSession.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -44,6 +44,64 @@ public class OwlcmsSession {
 		logger.setLevel(Level.INFO);
 	}
 
+	public static Locale computeLocale() {
+		Locale locale = (Locale) getAttribute(LOCALE);
+		if (locale != null) {
+			return locale;
+		}
+		locale = Translator.getForcedLocale();
+		if (locale != null) {
+			// logger.debug("forced locale {}",locale);
+		}
+
+		UI currentUi = UI.getCurrent();
+		if (locale == null && currentUi != null) {
+			locale = currentUi.getLocale();
+
+			final var loc = locale;
+			// is Browser language supported
+			List locales = Translator.getAvailableLocales();
+			boolean supported = locales.stream().anyMatch(l -> l.getLanguage().equals(loc.getLanguage()));
+			if (!supported) {
+				locale = null;
+				logger.debug("browser locale = {}", locale);
+			} else {
+				logger.debug("using browser locale = {}", locale);
+			}
+		}
+
+		// get first defined locale from translation file, else default
+		if (locale == null) {
+			List locales = Translator.getAvailableLocales();
+			if (locales != null && !locales.isEmpty()) {
+				locale = locales.get(0);
+			} else {
+				// defensive, can't happen
+				locale = Locale.ENGLISH;
+			}
+		}
+
+		if (locale.getCountry() == "") {
+			// add the country from Locale.getDefault -- probably the country we're running
+			// in.
+			// this may result in strange things for cloud -- such as es_US but the locale
+			// logic will not
+			// find es_US and will fall back to using es
+			// this will however work for en_US and en_UK and en_CA when running on a
+			// laptop, for date formats.
+			String country = Locale.getDefault().getCountry();
+			String variant = locale.getVariant();
+			String language = locale.getLanguage();
+			locale = new Locale(language, country, variant);
+		}
+		if (currentUi != null) {
+			currentUi.setLocale(locale);
+			setAttribute(LOCALE, locale);
+		}
+
+		return locale;
+	}
+
 	/**
 	 * Gets the attribute.
 	 *
@@ -59,7 +117,7 @@ public static OwlcmsSession getCurrent() {
 		if (currentVaadinSession != null) {
 			OwlcmsSession owlcmsSession = (OwlcmsSession) currentVaadinSession.getAttribute("owlcmsSession");
 			if (owlcmsSession == null) {
-				//logger.trace("creating new OwlcmsSession {}", LoggerUtils.whereFrom());
+				// logger.trace("creating new OwlcmsSession {}", LoggerUtils.whereFrom());
 				owlcmsSession = new OwlcmsSession();
 				currentVaadinSession.setAttribute("owlcmsSession", owlcmsSession);
 			}
@@ -75,10 +133,10 @@ public static OwlcmsSession getCurrent() {
 
 	public static FieldOfPlay getFop() {
 		FieldOfPlay fop = (FieldOfPlay) getAttribute(FOP);
-//		if (fop == null) {
-//			//fop = OwlcmsFactory.getDefaultFOP();
-//			throw new RuntimeException("no fop set");
-//		}
+		// if (fop == null) {
+		// //fop = OwlcmsFactory.getDefaultFOP();
+		// throw new RuntimeException("no fop set");
+		// }
 		return fop;
 	}
 
@@ -116,6 +174,11 @@ public static String getRequestedUrl() {
 		return (String) getAttribute(REQUESTED_URL);
 	}
 
+	public static void invalidate() {
+		VaadinSession currentVaadinSession = VaadinSession.getCurrent();
+		currentVaadinSession.getSession().invalidate();
+	}
+
 	public static boolean isAuthenticated() {
 		return Boolean.TRUE.equals(getAttribute(AUTHENTICATED));
 	}
@@ -147,7 +210,7 @@ public static void setDisplayAuthenticated(boolean b) {
 	}
 
 	public static void setFop(FieldOfPlay fop) {
-		//logger.debug("setFop {} from {}", (fop != null ? fop.getName() : null), LoggerUtils.whereFrom());
+		// logger.debug("setFop {} from {}", (fop != null ? fop.getName() : null), LoggerUtils.whereFrom());
 		setAttribute(FOP, fop);
 	}
 
@@ -169,64 +232,6 @@ public static void withFop(Consumer command) {
 		}
 	}
 
-	public static Locale computeLocale() {
-		Locale locale = (Locale) getAttribute(LOCALE);
-		if (locale != null) {
-			return locale;
-		}
-		locale = Translator.getForcedLocale();
-		if (locale != null) {
-			//logger.debug("forced locale {}",locale);
-		}
-		
-		UI currentUi = UI.getCurrent();
-		if (locale == null && currentUi != null) {
-			locale = currentUi.getLocale();
-
-			final var loc = locale;
-			// is Browser language supported
-			List locales = Translator.getAvailableLocales();
-			boolean supported = locales.stream().anyMatch(l -> l.getLanguage().equals(loc.getLanguage()));
-			if (!supported) {
-				locale = null;
-				logger.debug("browser locale = {}", locale);
-			} else {
-				logger.debug("using browser locale = {}", locale);
-			}
-		}
-
-		// get first defined locale from translation file, else default
-		if (locale == null) {
-			List locales = Translator.getAvailableLocales();
-			if (locales != null && !locales.isEmpty()) {
-				locale = locales.get(0);
-			} else {
-				// defensive, can't happen
-				locale = Locale.ENGLISH;
-			}
-		}
-
-		if (locale.getCountry() == "") {
-			// add the country from Locale.getDefault -- probably the country we're running
-			// in.
-			// this may result in strange things for cloud -- such as es_US but the locale
-			// logic will not
-			// find es_US and will fall back to using es
-			// this will however work for en_US and en_UK and en_CA when running on a
-			// laptop, for date formats.
-			String country = Locale.getDefault().getCountry();
-			String variant = locale.getVariant();
-			String language = locale.getLanguage();
-			locale = new Locale(language, country, variant);
-		}
-		if (currentUi != null) {
-			currentUi.setLocale(locale);
-			setAttribute(LOCALE,locale);
-		}
-
-		return locale;
-	}
-
 	private Properties attributes = new Properties();
 
 	public OwlcmsSession() {
@@ -244,9 +249,4 @@ public void setLocale(Locale locale) {
 		}
 	}
 
-	public static void invalidate() {
-		VaadinSession currentVaadinSession = VaadinSession.getCurrent();
-		currentVaadinSession.getSession().invalidate();
-	}
-
 }
diff --git a/owlcms/src/main/java/app/owlcms/jetty/EmbeddedJetty.java b/owlcms/src/main/java/app/owlcms/jetty/EmbeddedJetty.java
index b420bca914..3ccf1b189a 100644
--- a/owlcms/src/main/java/app/owlcms/jetty/EmbeddedJetty.java
+++ b/owlcms/src/main/java/app/owlcms/jetty/EmbeddedJetty.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.jetty;
 
 import java.util.concurrent.CountDownLatch;
@@ -15,10 +21,29 @@ public class EmbeddedJetty extends com.github.mvysny.vaadinboot.VaadinBoot {
 
 	private static Logger startLogger = (Logger) LoggerFactory.getLogger(EmbeddedJetty.class);
 	private static EmbeddedJetty server;
+
+	public static void restart() {
+		if (server != null) {
+			server.stop("stopping for restart");
+		}
+		try {
+			LogbackConfigReloader.reloadLogbackConfiguration();
+			startLogger.info("restarting.");
+			server.run();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	public static void stop(boolean restart) {
+		if (server != null) {
+			server.stop(restart ? "stopping prior to restart." : "intentional stop.");
+		}
+	}
+
 	private Runnable initConfig;
 	private Runnable initData;
 	private CountDownLatch latch;
-	
 	Logger logger = (Logger) LoggerFactory.getLogger(EmbeddedJetty.class);
 
 	public EmbeddedJetty(CountDownLatch countDownLatch, String appName) {
@@ -27,14 +52,42 @@ public EmbeddedJetty(CountDownLatch countDownLatch, String appName) {
 	}
 
 	public CountDownLatch getLatch() {
-		return latch;
+		return this.latch;
+	}
+
+	@Override
+	public void onStarted(WebAppContext c) {
+		startLogger.info("started on port {}", this.getPort());
+	}
+
+	@Override
+	public void run() throws Exception {
+		server = this;
+		start();
+
+		// this gets called both when CTRL+C is pressed, and when main() terminates.
+		Runtime.getRuntime().addShutdownHook(new Thread(() -> stop("Shutdown hook called, shutting down")));
+		startLogger.info("Press CTRL+C to shutdown");
+
+		// Open.open(getServerURL());
+
+		new Thread(() -> {
+			this.logger.info("Starting browser");
+			Options openOptions = new Options();
+			openOptions.setNewInstance(true);
+			openOptions.setBackground(true);
+			openOptions.setWait(false);
+			Open.open(getServerURL(), openOptions);
+			this.logger.info("Browser started");
+		}).start();
+
 	}
 
 	public void run(Integer serverPort, String string) throws Exception {
 		this.setPort(serverPort);
 		this.run();
-		initConfig.run();
-		initData.run();
+		this.initConfig.run();
+		this.initData.run();
 	}
 
 	public EmbeddedJetty setInitConfig(Runnable initConfig) {
@@ -56,51 +109,4 @@ public EmbeddedJetty setStartLogger(Logger startLogger) {
 		return this;
 	}
 
-	@Override
-	public void onStarted(WebAppContext c) {
-		startLogger.info("started on port {}", this.getPort());
-	}
-
-    @Override
-	public void run() throws Exception {
-    	server = this;
-        start();        
-
-        // this gets called both when CTRL+C is pressed, and when main() terminates.
-        Runtime.getRuntime().addShutdownHook(new Thread(() -> stop("Shutdown hook called, shutting down")));
-        startLogger.info("Press CTRL+C to shutdown");
-
-        //Open.open(getServerURL());
-        
-		new Thread(() -> {
-			logger.info("Starting browser");
-			Options openOptions = new Options();
-			openOptions.setNewInstance(true);
-			openOptions.setBackground(true);
-			openOptions.setWait(false);
-			Open.open(getServerURL(), openOptions);
-			logger.info("Browser started");
-		}).start();
-
-    }
-    
-    public static void stop(boolean restart) {
-    	if (server != null) {
-    		server.stop(restart ? "stopping prior to restart." : "intentional stop.");
-    	}
-    }
-    
-    public static void restart() {
-    	if (server != null) {
-    		server.stop("stopping for restart");
-    	}
-    	try {
-    		LogbackConfigReloader.reloadLogbackConfiguration();
-    		startLogger.info("restarting.");
-    		server.run();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-    }
-
 }
diff --git a/owlcms/src/main/java/app/owlcms/monitors/EventForwarder.java b/owlcms/src/main/java/app/owlcms/monitors/EventForwarder.java
index 87d777d1dd..2ba77540c7 100644
--- a/owlcms/src/main/java/app/owlcms/monitors/EventForwarder.java
+++ b/owlcms/src/main/java/app/owlcms/monitors/EventForwarder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -88,6 +88,24 @@ public class EventForwarder implements BreakDisplay, HasBoardMode, IUnregister {
 	final private static Logger logger = (Logger) LoggerFactory.getLogger(EventForwarder.class);
 	final private static Logger uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + logger.getName());
 	public static final Object singleThreadLock = new Object();
+	private static Map eventForwarderByName = new HashMap<>();
+
+	synchronized public static EventForwarder initEventForwarderByName(String name, FieldOfPlay fieldOfPlay) {
+		EventForwarder eventForwarder = eventForwarderByName.get(name);
+		if (eventForwarder == null) {
+			logger.info("{}creating event forwarder", FieldOfPlay.getLoggingName(fieldOfPlay));
+			EventForwarder newForwarder = new EventForwarder(name, fieldOfPlay);
+			eventForwarderByName.put(name, newForwarder);
+			return newForwarder;
+		} else {
+			// reusing the found forwarder, forcing the values
+			logger.info("{}reusing event forwarder", FieldOfPlay.getLoggingName(fieldOfPlay));
+			eventForwarder.getFop().setEventForwarder(eventForwarder);
+			eventForwarder.setFop(fieldOfPlay);
+			return eventForwarder;
+		}
+	}
+
 	private boolean NO_KEEPALIVE = false;
 	private String attempt;
 	private Integer attemptNumber;
@@ -143,23 +161,8 @@ public class EventForwarder implements BreakDisplay, HasBoardMode, IUnregister {
 	private String forwardedFopName;
 	private String liftType;
 	private String liftTypeKey;
-	private static Map eventForwarderByName = new HashMap<>();
-
-	synchronized public static EventForwarder initEventForwarderByName(String name, FieldOfPlay fieldOfPlay) {
-		EventForwarder eventForwarder = eventForwarderByName.get(name);
-		if (eventForwarder == null) {
-			logger.info("{}creating event forwarder", FieldOfPlay.getLoggingName(fieldOfPlay));
-			EventForwarder newForwarder = new EventForwarder(name, fieldOfPlay);
-			eventForwarderByName.put(name, newForwarder);
-			return newForwarder;
-		} else {
-			// reusing the found forwarder, forcing the values
-			logger.info("{}reusing event forwarder", FieldOfPlay.getLoggingName(fieldOfPlay));
-			eventForwarder.getFop().setEventForwarder(eventForwarder);
-			eventForwarder.setFop(fieldOfPlay);
-			return eventForwarder;
-		}
-	}
+	Map debouncingHash = new HashMap<>();
+	Map debouncingMillis = new HashMap<>();
 
 	private EventForwarder(String name, FieldOfPlay emittingFop) {
 		this.setForwardedFopName(name);
@@ -249,33 +252,13 @@ public void doCeremony(UIEvent.CeremonyStarted e) {
 		setAttempt("");
 		setHidden(false);
 		setCeremonyEventType("ceremonyStarted");
-		setCeremonyType(ceremonyType);
+		setCeremonyType(this.ceremonyType);
 		setCeremonySession(e.getCeremonySession() != null ? e.getCeremonySession() : null);
 		setCeremonyCategory(e.getCeremonyCategory() != null ? e.getCeremonyCategory() : null);
 		setCeremonyAgeGroup(e.getAgeGroup() != null ? e.getAgeGroup() : null);
 		setCeremonyChampionship(e.getChampionship() != null ? e.getChampionship() : null);
 	}
 
-	private void setCeremonyEventType(String ceremonyEventType) {
-		this.ceremonyEventType = ceremonyEventType;
-	}
-
-	private void setCeremonyChampionship(Championship ceremonyChampionship) {
-		this.ceremonyChampionship = ceremonyChampionship;
-	}
-
-	private void setCeremonyAgeGroup(AgeGroup ceremonyAgeGroup) {
-		this.ceremonyAgeGroup = ceremonyAgeGroup;
-	}
-
-	private void setCeremonyCategory(Category ceremonyCategory) {
-		this.ceremonyCategory = ceremonyCategory;
-	}
-
-	private void setCeremonySession(Group ceremonySession) {
-		this.ceremonySession = ceremonySession;
-	}
-
 	public String getBoardMode() {
 		return this.boardMode;
 	}
@@ -535,15 +518,6 @@ public void slaveCeremonyDone(UIEvent.CeremonyDone e) {
 		pushUpdate(e);
 	}
 
-	private void doCeremony(CeremonyDone e) {
-		setCeremonyEventType("ceremonyDone");
-		setCeremonyType(null);
-		setCeremonySession(null);
-		setCeremonyCategory(null);
-		setCeremonyAgeGroup(null);
-		setCeremonyChampionship(null);
-	}
-
 	@Subscribe
 	public void slaveCeremonyStarted(UIEvent.CeremonyStarted e) {
 		uiLog(e);
@@ -1070,14 +1044,14 @@ private synchronized Map createUpdate(UIEvent event) {
 
 		CeremonyType ceremonyType = getFop().getCeremonyType();
 		String cts = ceremonyType != null ? ceremonyType.name() : null;
-		mapPut(sb, "ceremonyEventType", ceremonyEventType);
+		mapPut(sb, "ceremonyEventType", this.ceremonyEventType);
 		mapPut(sb, "ceremonyType", cts);
-		mapPut(sb, "ceremonySession", ceremonySession != null ? ceremonySession.getName() : null);
-		mapPut(sb, "ceremonyCategory", ceremonyCategory != null ? ceremonyCategory.getDisplayName() : null);
+		mapPut(sb, "ceremonySession", this.ceremonySession != null ? this.ceremonySession.getName() : null);
+		mapPut(sb, "ceremonyCategory", this.ceremonyCategory != null ? this.ceremonyCategory.getDisplayName() : null);
 		mapPut(sb, "ceremonyType", ceremonyType != null ? ceremonyType.name() : null);
-		mapPut(sb, "ceremonyCategory", ceremonyCategory != null ? ceremonyCategory.getDisplayName() : null);
-		mapPut(sb, "ceremonyAgeGroup", ceremonyAgeGroup != null ? ceremonyAgeGroup.getName() : null);
-		mapPut(sb, "ceremonyChampionship", ceremonyChampionship != null ? ceremonyChampionship.getName() : null);
+		mapPut(sb, "ceremonyCategory", this.ceremonyCategory != null ? this.ceremonyCategory.getDisplayName() : null);
+		mapPut(sb, "ceremonyAgeGroup", this.ceremonyAgeGroup != null ? this.ceremonyAgeGroup.getName() : null);
+		mapPut(sb, "ceremonyChampionship", this.ceremonyChampionship != null ? this.ceremonyChampionship.getName() : null);
 
 		// current athlete & attempt
 		mapPut(sb, "startNumber", this.startNumber != null ? this.startNumber.toString() : null);
@@ -1128,9 +1102,6 @@ private synchronized Map createUpdate(UIEvent event) {
 		return sb;
 	}
 
-	private void recomputeRemainingTimes(Map sb) {
-	}
-
 	private void doBreak(UIEvent e, Group g) {
 		OwlcmsSession.withFop(fop -> {
 			createUpdate(e);
@@ -1148,6 +1119,15 @@ private void doBreak(UIEvent e, Group g) {
 
 	}
 
+	private void doCeremony(CeremonyDone e) {
+		setCeremonyEventType("ceremonyDone");
+		setCeremonyType(null);
+		setCeremonySession(null);
+		setCeremonyCategory(null);
+		setCeremonyAgeGroup(null);
+		setCeremonyChampionship(null);
+	}
+
 	private void doDone(UIEvent e, Group g) {
 		logger.debug("forwarding doDone {}", g == null ? null : g.getName());
 		computeCurrentGroup(g);
@@ -1464,6 +1444,11 @@ private FieldOfPlay getFop() {
 		return this.fop;
 	}
 
+	@SuppressWarnings("unused")
+	private String getForwardedFopName() {
+		return this.forwardedFopName;
+	}
+
 	private Map getLastDecisionMap() {
 		return this.lastDecisionMap;
 	}
@@ -1570,6 +1555,9 @@ private void pushUpdateDoIt(UIEvent e2) {
 		sendPost(updateUrl, current.getParamUpdateKey(), this.lastUpdate);
 	}
 
+	private void recomputeRemainingTimes(Map sb) {
+	}
+
 	private void sendConfig(String url, String updateKey) {
 		if (url == null || updateKey == null) {
 			logger.error("cannot send config info, url or updateKey is null");
@@ -1629,16 +1617,13 @@ private void sendConfig(String url, String updateKey) {
 		}
 	}
 
-	Map debouncingHash = new HashMap<>();
-	Map debouncingMillis = new HashMap<>();
-
 	private void sendPost(String url, String updateKey, Map parameters) {
 		if (url == null) {
 			return;
 		}
-		Integer previousDebounceHash = debouncingHash.get(url);
-		Long previousDebounceMillis = debouncingMillis.get(url);
-		Long deltaMillis = System.currentTimeMillis() - (previousDebounceMillis != null ? previousDebounceMillis : 0);
+		Integer previousDebounceHash = this.debouncingHash.get(url);
+		Long previousDebounceMillis = this.debouncingMillis.get(url);
+		long deltaMillis = System.currentTimeMillis() - (previousDebounceMillis != null ? previousDebounceMillis : 0);
 		Integer hashCode = parameters.hashCode();
 
 		// debounce, sometimes several identical updates in a rapid succession
@@ -1660,6 +1645,26 @@ private void setCategoryName(String name) {
 		this.categoryName = name;
 	}
 
+	private void setCeremonyAgeGroup(AgeGroup ceremonyAgeGroup) {
+		this.ceremonyAgeGroup = ceremonyAgeGroup;
+	}
+
+	private void setCeremonyCategory(Category ceremonyCategory) {
+		this.ceremonyCategory = ceremonyCategory;
+	}
+
+	private void setCeremonyChampionship(Championship ceremonyChampionship) {
+		this.ceremonyChampionship = ceremonyChampionship;
+	}
+
+	private void setCeremonyEventType(String ceremonyEventType) {
+		this.ceremonyEventType = ceremonyEventType;
+	}
+
+	private void setCeremonySession(Group ceremonySession) {
+		this.ceremonySession = ceremonySession;
+	}
+
 	private void setCeremonyType(CeremonyType ceremonyType) {
 		this.ceremonyType = ceremonyType;
 	}
@@ -1675,6 +1680,10 @@ private void setFopState(FOPState state) {
 		this.fopState = state;
 	}
 
+	private void setForwardedFopName(String name) {
+		this.forwardedFopName = name;
+	}
+
 	private void setGroupAthletes(JsonValue athletesJson) {
 		this.groupAthletes = athletesJson;
 	}
@@ -1773,13 +1782,4 @@ private synchronized void updateState() {
 		setCeremonyType(ceremonyType);
 	}
 
-	@SuppressWarnings("unused")
-	private String getForwardedFopName() {
-		return forwardedFopName;
-	}
-
-	private void setForwardedFopName(String name) {
-		this.forwardedFopName = name;
-	}
-
 }
diff --git a/owlcms/src/main/java/app/owlcms/monitors/IUnregister.java b/owlcms/src/main/java/app/owlcms/monitors/IUnregister.java
index 25e542cb32..600875ae8a 100644
--- a/owlcms/src/main/java/app/owlcms/monitors/IUnregister.java
+++ b/owlcms/src/main/java/app/owlcms/monitors/IUnregister.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.monitors;
 
 public interface IUnregister {
diff --git a/owlcms/src/main/java/app/owlcms/monitors/MQTTMonitor.java b/owlcms/src/main/java/app/owlcms/monitors/MQTTMonitor.java
index 3c793b2ef1..735e1eb167 100644
--- a/owlcms/src/main/java/app/owlcms/monitors/MQTTMonitor.java
+++ b/owlcms/src/main/java/app/owlcms/monitors/MQTTMonitor.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.monitors;
 
 import java.io.UnsupportedEncodingException;
@@ -57,50 +63,6 @@
  */
 public class MQTTMonitor extends Thread implements IUnregister {
 
-	private static Map mqttMonitorByName = new HashMap<>();
-
-	synchronized public static MQTTMonitor initMQTTMonitorByName(String monitorName, FieldOfPlay fieldOfPlay) {
-		MQTTMonitor existingMonitor = mqttMonitorByName.get(monitorName);
-		if (existingMonitor == null) {
-			logger.info("{}creating MQTT monitor", FieldOfPlay.getLoggingName(fieldOfPlay));
-			MQTTMonitor newForwarder = new MQTTMonitor(monitorName, fieldOfPlay);
-			// fieldOfPlay.setMqttMonitor(newForwarder);
-			mqttMonitorByName.put(monitorName, newForwarder);
-			return newForwarder;
-		} else {
-			logger.info("{}reusing MQTT monitor", FieldOfPlay.getLoggingName(fieldOfPlay));
-			// existingMonitor.getFop().setMqttMonitor(existingMonitor);
-			existingMonitor.setFop(fieldOfPlay);
-			return existingMonitor;
-		}
-	}
-
-	public static MQTTMonitor getMqttMonitorByName(String name) {
-		return mqttMonitorByName.get(name);
-	}
-	
-	public static void reset() {
-		for (Entry e : mqttMonitorByName.entrySet()) {
-			MQTTMonitor monitor = e.getValue();
-			logger.info("unregistering MQTT monitor for platform {}", monitor.getMonitoredFopName());
-			monitor.setFop(null);
-			FieldOfPlay fop2 = OwlcmsFactory.getFOPByName(monitor.getMonitoredFopName());
-			if (fop2 != null) {
-				fop2.setEventForwarder(null);
-			}
-			try {
-				monitor.client.disconnect();
-			} catch (MqttException ex) {
-				try {
-					monitor.client.disconnectForcibly();
-				} catch (MqttException e1) {
-					LoggerUtils.logError(logger, e1);
-				}
-			}
-		}
-		mqttMonitorByName.clear();
-	}
-
 	/**
 	 * This inner class contains the routines executed when an MQTT message is received.
 	 */
@@ -300,7 +262,9 @@ private void postFopTimeEvents(String topic, String messageStr) {
 		}
 	}
 
+	private static Map mqttMonitorByName = new HashMap<>();
 	private static Logger logger = (Logger) LoggerFactory.getLogger(MQTTMonitor.class);
+
 	static {
 		logger.setLevel(Level.DEBUG);
 	}
@@ -320,6 +284,48 @@ public static MqttAsyncClient createMQTTClient(FieldOfPlay fop) throws MqttExcep
 		return client;
 	}
 
+	public static MQTTMonitor getMqttMonitorByName(String name) {
+		return mqttMonitorByName.get(name);
+	}
+
+	synchronized public static MQTTMonitor initMQTTMonitorByName(String monitorName, FieldOfPlay fieldOfPlay) {
+		MQTTMonitor existingMonitor = mqttMonitorByName.get(monitorName);
+		if (existingMonitor == null) {
+			logger.info("{}creating MQTT monitor", FieldOfPlay.getLoggingName(fieldOfPlay));
+			MQTTMonitor newForwarder = new MQTTMonitor(monitorName, fieldOfPlay);
+			// fieldOfPlay.setMqttMonitor(newForwarder);
+			mqttMonitorByName.put(monitorName, newForwarder);
+			return newForwarder;
+		} else {
+			logger.info("{}reusing MQTT monitor", FieldOfPlay.getLoggingName(fieldOfPlay));
+			// existingMonitor.getFop().setMqttMonitor(existingMonitor);
+			existingMonitor.setFop(fieldOfPlay);
+			return existingMonitor;
+		}
+	}
+
+	public static void reset() {
+		for (Entry e : mqttMonitorByName.entrySet()) {
+			MQTTMonitor monitor = e.getValue();
+			logger.info("unregistering MQTT monitor for platform {}", monitor.getMonitoredFopName());
+			monitor.setFop(null);
+			FieldOfPlay fop2 = OwlcmsFactory.getFOPByName(monitor.getMonitoredFopName());
+			if (fop2 != null) {
+				fop2.setEventForwarder(null);
+			}
+			try {
+				monitor.client.disconnect();
+			} catch (MqttException ex) {
+				try {
+					monitor.client.disconnectForcibly();
+				} catch (MqttException e1) {
+					LoggerUtils.logError(logger, e1);
+				}
+			}
+		}
+		mqttMonitorByName.clear();
+	}
+
 	private MqttAsyncClient client;
 	private FieldOfPlay fop;
 	private String password;
@@ -345,6 +351,13 @@ public void publishMqttConfig() {
 		publishMqttConfig("owlcms/fop/config");
 	}
 
+	public void publishRefDecision(int i, boolean goodLift) throws MqttPersistenceException, MqttException {
+		// 0 is the announcer decision, bump by 1.
+		String message = Integer.toString(i + 1) + " " + (goodLift ? "good" : "bad");
+		this.client.publish("owlcms/refbox/decision/" + this.getFop().getName(),
+		        new MqttMessage(message.getBytes(StandardCharsets.UTF_8)));
+	}
+
 	public void publishStartAthleteTimer() throws MqttPersistenceException, MqttException {
 		this.client.publish("owlcms/clock/" + this.getFop().getName(),
 		        new MqttMessage("start".getBytes(StandardCharsets.UTF_8)));
@@ -355,13 +368,6 @@ public void publishStopAthleteTimer() throws MqttPersistenceException, MqttExcep
 		        new MqttMessage("stop".getBytes(StandardCharsets.UTF_8)));
 	}
 
-	public void publishRefDecision(int i, boolean goodLift) throws MqttPersistenceException, MqttException {
-		// 0 is the announcer decision, bump by 1.
-		String message = Integer.toString(i + 1) + " " + (goodLift ? "good" : "bad");
-		this.client.publish("owlcms/refbox/decision/" + this.getFop().getName(),
-		        new MqttMessage(message.getBytes(StandardCharsets.UTF_8)));
-	}
-
 	public void setFop(FieldOfPlay fop) {
 		this.fop = fop;
 		// logger.debug("MQTTMonitor setFop {} {} {}\n{}", fop.getName(), System.identityHashCode(fop), System.identityHashCode(this),
@@ -591,7 +597,7 @@ private void doConnect() throws MqttSecurityException, MqttException {
 
 		publishMqttLedOnOff();
 		logger.info("{}connected to {} MQTT broker {}",
-		        FieldOfPlay.getLoggingName(fop),
+		        FieldOfPlay.getLoggingName(this.fop),
 		        (external ? "external" : "embedded"),
 		        this.client.getCurrentServerURI());
 
@@ -634,6 +640,11 @@ private void doPublishMQTTSummon(int ref) throws MqttException, MqttPersistenceE
 		this.client.publish(deprecatedTopic, new MqttMessage(("on").getBytes(StandardCharsets.UTF_8)));
 	}
 
+	@SuppressWarnings("unused")
+	private String getMonitoredFopName() {
+		return this.monitoredFopName;
+	}
+
 	private void publishMqttBreak(BreakStarted e) throws MqttPersistenceException, MqttException {
 		try {
 			this.client.publish("owlcms/fop/break/" + this.getFop().getName(),
@@ -864,6 +875,10 @@ private void publishMqttWakeUpRef(int ref, boolean on) {
 		}
 	}
 
+	private void setMonitoredFopName(String monitorName) {
+		this.monitoredFopName = monitorName;
+	}
+
 	private MqttConnectOptions setUpConnectionOptions(String username, String password) {
 		MqttConnectOptions connOpts = new MqttConnectOptions();
 		connOpts.setCleanSession(true);
@@ -893,13 +908,4 @@ private void sleep(int ms) {
 		}
 	}
 
-	@SuppressWarnings("unused")
-	private String getMonitoredFopName() {
-		return monitoredFopName;
-	}
-
-	private void setMonitoredFopName(String monitorName) {
-		this.monitoredFopName = monitorName;
-	}
-
 }
diff --git a/owlcms/src/main/java/app/owlcms/monitors/OBSMonitor.java b/owlcms/src/main/java/app/owlcms/monitors/OBSMonitor.java
index 630027fdba..c7e054a21a 100644
--- a/owlcms/src/main/java/app/owlcms/monitors/OBSMonitor.java
+++ b/owlcms/src/main/java/app/owlcms/monitors/OBSMonitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-Fran�ois Lamy
+ * Copyright © 2009-present Jean-Fran�ois Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsComboBoxProvider.java b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsComboBoxProvider.java
index de0dda10a2..c25d4fde74 100644
--- a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsComboBoxProvider.java
+++ b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsComboBoxProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudFormFactory.java
index 985573ac2c..4493da47fb 100644
--- a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudFormFactory.java
+++ b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudFormFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -94,9 +94,8 @@ public OwlcmsCrudFormFactory(Class domainType, ResponsiveStep... responsiveSt
 	}
 
 	/**
-	 * @see org.vaadin.crudui.form.impl.form.factory.DefaultCrudFormFactory#buildNewForm(org.vaadin.crudui.crud.CrudOperation,
-	 *      java.lang.Object, boolean, com.vaadin.flow.component.ComponentEventListener,
-	 *      com.vaadin.flow.component.ComponentEventListener)
+	 * @see org.vaadin.crudui.form.impl.form.factory.DefaultCrudFormFactory#buildNewForm(org.vaadin.crudui.crud.CrudOperation, java.lang.Object, boolean,
+	 *      com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.ComponentEventListener)
 	 */
 	@Override
 	public Component buildNewForm(CrudOperation operation, T domainObject, boolean readOnly,
@@ -153,8 +152,8 @@ public Component buildNewForm(CrudOperation operation, T domainObject, boolean r
 	/**
 	 * Special button that uses an auxilliary field focus trigger to perform the operation.
 	 *
-	 * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildOperationButton(org.vaadin.crudui.crud.CrudOperation,
-	 *      java.lang.Object, com.vaadin.flow.component.ComponentEventListener)
+	 * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildOperationButton(org.vaadin.crudui.crud.CrudOperation, java.lang.Object,
+	 *      com.vaadin.flow.component.ComponentEventListener)
 	 */
 	@Override
 	public Button buildOperationButton(CrudOperation operation, T domainObject,
@@ -258,8 +257,7 @@ public boolean setErrorLabel(BinderValidationStatus validationStatus, boolean
 	}
 
 	/**
-	 * Utility method to avoid unreadable cast (Class>) when using WrappedTextField
-	 * subclasses
+	 * Utility method to avoid unreadable cast (Class>) when using WrappedTextField subclasses
 	 *
 	 * @see org.vaadin.crudui.form.AbstractCrudFormFactory#setFieldType(java.lang.String, java.lang.Class)
 	 */
@@ -340,8 +338,8 @@ protected Dialog buildConfirmDialog(CrudOperation operation, T domainObject,
 	/**
 	 * Added support for a delete button
 	 *
-	 * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildOperationButton(org.vaadin.crudui.crud.CrudOperation,
-	 *      java.lang.Object, com.vaadin.flow.component.ComponentEventListener)
+	 * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildOperationButton(org.vaadin.crudui.crud.CrudOperation, java.lang.Object,
+	 *      com.vaadin.flow.component.ComponentEventListener)
 	 */
 	protected Button buildDeleteButton(CrudOperation operation, T domainObject,
 	        ComponentEventListener> gridCallBackAction) {
@@ -354,9 +352,8 @@ protected Button buildDeleteButton(CrudOperation operation, T domainObject,
 	}
 
 	/**
-	 * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildFooter(org.vaadin.crudui.crud.CrudOperation,
-	 *      java.lang.Object, com.vaadin.flow.component.ComponentEventListener,
-	 *      com.vaadin.flow.component.ComponentEventListener)
+	 * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildFooter(org.vaadin.crudui.crud.CrudOperation, java.lang.Object,
+	 *      com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.ComponentEventListener)
 	 */
 	@Override
 	protected Component buildFooter(CrudOperation operation, T domainObject,
diff --git a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudGrid.java b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudGrid.java
index bf9006dc17..5ee387ca54 100644
--- a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudGrid.java
+++ b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsCrudGrid.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -109,7 +109,7 @@ protected void deleteButtonClicked() {
 			throw e2;
 		}
 	}
-	
+
 	protected void deleteButtonClicked(T domainObject) {
 		try {
 			this.deleteOperation.perform(domainObject);
@@ -126,7 +126,7 @@ protected void deleteCallBack() {
 		this.getOwlcmsGridLayout().hideForm();
 		this.deleteButtonClicked();
 	}
-	
+
 	protected void deleteCallBack(T domainObject) {
 		this.getOwlcmsGridLayout().hideForm();
 		this.deleteButtonClicked(domainObject);
@@ -139,8 +139,7 @@ protected void findAllButtonClicked() {
 	}
 
 	/**
-	 * Do nothing. Initialization must wait for crudGrid to be constructed, constuctor calls {@link #initLayoutGrid()}
-	 * instead.
+	 * Do nothing. Initialization must wait for crudGrid to be constructed, constuctor calls {@link #initLayoutGrid()} instead.
 	 *
 	 * @see org.vaadin.crudui.crud.impl.GridCrud#initLayout()
 	 */
@@ -149,8 +148,7 @@ protected void initLayout() {
 	}
 
 	/**
-	 * Replacement initialization We do not create the crudGrid automatically, but instead receive the crudGrid
-	 * pre-populated.
+	 * Replacement initialization We do not create the crudGrid automatically, but instead receive the crudGrid pre-populated.
 	 */
 	protected void initLayoutGrid() {
 		initToolbar();
@@ -206,12 +204,12 @@ protected void initToolbar() {
 		this.deleteButton.getElement().setAttribute("title", Translator.translate("Delete"));
 		// crudLayout.addToolbarComponent(deleteButton);
 
-		//updateButtons();
+		// updateButtons();
 	}
 
 	protected void saveCallBack(OwlcmsCrudGrid owlcmsCrudGrid, String successMessage, CrudOperation operation, T domainObject) {
 		try {
-			//logger.debug("postOperation {}", domainObject);
+			// logger.debug("postOperation {}", domainObject);
 			owlcmsCrudGrid.getOwlcmsGridLayout().hideForm();
 			refreshGrid();
 			Notification.show(successMessage);
@@ -224,8 +222,8 @@ protected void saveCallBack(OwlcmsCrudGrid owlcmsCrudGrid, String successMess
 	/**
 	 * Show form with a delete button.
 	 *
-	 * @see org.vaadin.crudui.crud.impl.GridCrud#showForm(org.vaadin.crudui.crud.CrudOperation, java.lang.Object,
-	 *      boolean, java.lang.String, com.vaadin.flow.component.ComponentEventListener)
+	 * @see org.vaadin.crudui.crud.impl.GridCrud#showForm(org.vaadin.crudui.crud.CrudOperation, java.lang.Object, boolean, java.lang.String,
+	 *      com.vaadin.flow.component.ComponentEventListener)
 	 */
 	@Override
 	protected void showForm(CrudOperation operation, T domainObject, boolean readOnly, String successMessage,
diff --git a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsGridLayout.java b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsGridLayout.java
index 8a8a0b85cd..df61241866 100644
--- a/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsGridLayout.java
+++ b/owlcms/src/main/java/app/owlcms/nui/crudui/OwlcmsGridLayout.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/AbstractDisplayPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/AbstractDisplayPage.java
index 29bdce5712..a621d53bb4 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/AbstractDisplayPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/AbstractDisplayPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays;
 
 import java.util.List;
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/DisplayNavigationContent.java b/owlcms/src/main/java/app/owlcms/nui/displays/DisplayNavigationContent.java
index f4de6fe9cc..771731d7a5 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/DisplayNavigationContent.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/DisplayNavigationContent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
-L * Copyright (c) 2009-2023 Jean-François Lamy
+L * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
@@ -108,13 +108,13 @@ public DisplayNavigationContent() {
 			        Translator.translate("Scoreboard.LiftingOrder"));
 			VerticalLayout intro1 = new VerticalLayout();
 			addP(intro1, Translator.translate("WarmupScoreboards.explanation"));
-			Button juryScoreboard = openInNewTab(JuryScoreboardPage.class,Translator.translate("Jury"));
+			Button juryScoreboard = openInNewTab(JuryScoreboardPage.class, Translator.translate("Jury"));
 			scoreboardWLeaders.getElement().setAttribute("title", Translator.translate("ScoreboardWLeadersMouseOver"));
 			FlexibleGridLayout grid1 = HomeNavigationContent.navigationGrid(
 			        scoreboard,
 			        scoreboardWLeaders,
 			        liftingOrder,
-			        scoreboardMultiRanks, 
+			        scoreboardMultiRanks,
 			        juryScoreboard);
 			doGroup(Translator.translate("WarmupScoreboards"), intro1, grid1, this);
 
@@ -159,7 +159,7 @@ public DisplayNavigationContent() {
 
 			DebugUtils.gc();
 		} catch (Throwable x) {
-			LoggerUtils.logError(logger,x);
+			LoggerUtils.logError(logger, x);
 		}
 	}
 
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/SoundEntries.java b/owlcms/src/main/java/app/owlcms/nui/displays/SoundEntries.java
index 7fabfe8f97..5842c92e8b 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/SoundEntries.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/SoundEntries.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays;
 
 import com.vaadin.flow.component.Component;
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/VideoNavigationContent.java b/owlcms/src/main/java/app/owlcms/nui/displays/VideoNavigationContent.java
index 9cdd38a554..df48f50138 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/VideoNavigationContent.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/VideoNavigationContent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009-2023 Jean-François Lamy
+ * Copyright © 2009-present Jean-François Lamy
  *
  * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
  * License text at https://opensource.org/licenses/NPOSL-3.0
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AbstractAttemptBoardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AbstractAttemptBoardPage.java
index 814b261296..65882ae6e8 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AbstractAttemptBoardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AbstractAttemptBoardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.attemptboards;
 
 import org.slf4j.LoggerFactory;
@@ -13,8 +19,7 @@
 import ch.qos.logback.classic.Logger;
 
 /**
- * Wrapper class to wrap a board as navigable page, to store the board display options, and to present an option editing
- * dialog.
+ * Wrapper class to wrap a board as navigable page, to store the board display options, and to present an option editing dialog.
  *
  * @author jflamy
  *
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingAttemptBoardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingAttemptBoardPage.java
index 0ca6fd5ab6..e82bc3e97a 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingAttemptBoardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingAttemptBoardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.attemptboards;
 
 import java.util.Map;
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingDecisionBoardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingDecisionBoardPage.java
index 77c8edd161..4d82dd25fb 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingDecisionBoardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/AthleteFacingDecisionBoardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.attemptboards;
 
 import java.util.Map;
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingAttemptBoardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingAttemptBoardPage.java
index 22fc3ccbd0..d97d4d39ef 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingAttemptBoardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingAttemptBoardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.attemptboards;
 
 import java.util.Map;
@@ -60,7 +66,7 @@ protected void init() {
 		fullMap.putAll(initialMap);
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
-		
+
 		AbstractAttemptBoard board = (AbstractAttemptBoard) getBoard();
 		board.setPublicFacing(true);
 		this.addComponent(board);
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingDecisionBoardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingDecisionBoardPage.java
index c134b357e8..b12b568716 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingDecisionBoardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/attemptboards/PublicFacingDecisionBoardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.attemptboards;
 
 import java.util.Map;
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/AbstractResultsDisplayPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/AbstractResultsDisplayPage.java
index db6dd4196e..bf90e30298 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/AbstractResultsDisplayPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/AbstractResultsDisplayPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import org.slf4j.LoggerFactory;
@@ -17,8 +23,7 @@
 import ch.qos.logback.classic.Logger;
 
 /**
- * Wrapper class to wrap a board as navigable page, to store the board display options, and to present an option editing
- * dialog.
+ * Wrapper class to wrap a board as navigable page, to store the board display options, and to present an option editing dialog.
  *
  * @author jflamy
  *
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/CurrentAthletePage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/CurrentAthletePage.java
index 5a57a937dd..89128b8aea 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/CurrentAthletePage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/CurrentAthletePage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.HashMap;
@@ -50,8 +56,8 @@ public boolean isShowInitialDialog() {
 
 	@Override
 	protected void init() {
-		logger = (Logger) LoggerFactory.getLogger(CurrentAthletePage.class);
-		uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
+		this.logger = (Logger) LoggerFactory.getLogger(CurrentAthletePage.class);
+		this.uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
 		var board = new CurrentAthlete(this);
 		this.setBoard(board);
 
@@ -77,7 +83,7 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/JuryScoreboardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/JuryScoreboardPage.java
index b38ba26d51..d0eaaabe2f 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/JuryScoreboardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/JuryScoreboardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.HashMap;
@@ -67,7 +73,7 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/MedalsPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/MedalsPage.java
index 79bc22d20c..9b47e86543 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/MedalsPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/MedalsPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicMultiRanksPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicMultiRanksPage.java
index 9abda5f579..448e49d7fa 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicMultiRanksPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicMultiRanksPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
@@ -104,16 +110,16 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
 		board.setFop(getFop());
 		getMedalsBoard().setFop(getFop());
-		
+
 		this.setResultsBoard((ResultsMultiRanks) board);
 		this.setMedalsBoard(getMedalsBoard());
-		
+
 		this.addComponent((Component) board);
 		getMedalsBoard().setVisible(false);
 		this.addComponent(getMedalsBoard());
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicNoLeadersPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicNoLeadersPage.java
index 7ae726ef4f..52ebdbafed 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicNoLeadersPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicNoLeadersPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
@@ -30,7 +36,6 @@ public String getPageTitle() {
 		return Translator.translate("Scoreboard") + OwlcmsSession.getFopNameIfMultiple();
 	}
 
-
 	@Override
 	protected void setDefaultParameters() {
 		// when navigating to the page, Vaadin will call setParameter+readParameters
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicRankingOrderPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicRankingOrderPage.java
index 0ea84f8243..cad6401d15 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicRankingOrderPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicRankingOrderPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.HashMap;
@@ -103,29 +109,29 @@ protected void createComponents() {
 		getMedalsBoard().getStyle().set("display", "none");
 		this.ui = UI.getCurrent();
 	}
-	
+
+	@Override
+	protected void init() {
+		this.logger = (Logger) LoggerFactory.getLogger(this.getClass());
+		this.uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
+		createComponents();
+		setDefaultParameters();
+	}
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
 		board.setFop(getFop());
 		getMedalsBoard().setFop(getFop());
-		
+
 		this.setResultsBoard((Results) board);
 		this.setMedalsBoard(getMedalsBoard());
-		
+
 		this.addComponent((Component) board);
 		getMedalsBoard().setVisible(false);
 		this.addComponent(getMedalsBoard());
 	}
 
-	@Override
-	protected void init() {
-		this.logger = (Logger) LoggerFactory.getLogger(this.getClass());
-		this.uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
-		createComponents();
-		setDefaultParameters();
-	}
-
 	protected void setDefaultParameters() {
 		// when navigating to the page, Vaadin will call setParameter+readParameters
 		// these parameters will be applied.
@@ -150,10 +156,6 @@ protected void setDefaultParameters() {
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
 
-	private void setMedalsBoard(ResultsMedals medalsBoard) {
-		this.medalsBoard = medalsBoard;
-	}
-
 	protected void setResultsBoard(Results board) {
 		this.resultsBoard = board;
 	}
@@ -161,4 +163,8 @@ protected void setResultsBoard(Results board) {
 	private final ResultsMedals getMedalsBoard() {
 		return this.medalsBoard;
 	}
+
+	private void setMedalsBoard(ResultsMedals medalsBoard) {
+		this.medalsBoard = medalsBoard;
+	}
 }
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicScoreboardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicScoreboardPage.java
index b383e12bfc..43b17ba031 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicScoreboardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/PublicScoreboardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.HashMap;
@@ -83,11 +89,11 @@ public void slaveCeremonyStarted(UIEvent.CeremonyStarted e) {
 			getResultsBoard().getStyle().set("display", "none");
 		});
 	}
-	
+
 	@Subscribe
 	public void slaveVideoRefresh(UIEvent.VideoRefresh e) {
 		// this should never have isVideo() in actual practice.
-		
+
 		// logger.debug("videorefresh {}",e.getFop());
 		if (!isVideo()) {
 			return;
@@ -110,50 +116,31 @@ public void slaveVideoRefresh(UIEvent.VideoRefresh e) {
 		});
 	}
 
-	private void createComponents() {
-		var board = new Results();
-		setMedalsBoard(new ResultsMedals());
-		this.setBoard(board);
-
-		getMedalsBoard().setDownSilenced(true);
-		getMedalsBoard().setDarkMode(board.isDarkMode());
-		getMedalsBoard().setVideo(board.isVideo());
-		getMedalsBoard().setPublicDisplay(board.isPublicDisplay());
-		getMedalsBoard().setSingleReferee(board.isSingleReferee());
-		getMedalsBoard().setAbbreviatedName(board.isAbbreviatedName());
-		getMedalsBoard().setTeamWidth(board.getTeamWidth());
-		getMedalsBoard().setEmFontSize(board.getEmFontSize());
-		checkVideo(getMedalsBoard());
-
-		getMedalsBoard().getStyle().set("display", "none");
-		this.ui = UI.getCurrent();
+	@Override
+	protected void init() {
+		this.logger = (Logger) LoggerFactory.getLogger(this.getClass());
+		this.uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
+		createComponents();
+		setDefaultParameters();
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		uiEventBusRegister(this, getFop());
 		DisplayParameters board = (DisplayParameters) this.getBoard();
 		board.setFop(getFop());
 		getMedalsBoard().setFop(getFop());
-		
+
 		this.setResultsBoard((Results) board);
 		this.setMedalsBoard(getMedalsBoard());
-		
+
 		this.addComponent((Component) board);
 		this.addComponent(getMedalsBoard());
-		
+
 		((Component) board).setVisible(true);
 		getMedalsBoard().setVisible(false);
 	}
 
-	@Override
-	protected void init() {
-		this.logger = (Logger) LoggerFactory.getLogger(this.getClass());
-		this.uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
-		createComponents();
-		setDefaultParameters();
-	}
-
 	protected void setDefaultParameters() {
 		// when navigating to the page, Vaadin will call setParameter+readParameters
 		// these parameters will be applied.
@@ -178,16 +165,35 @@ protected void setDefaultParameters() {
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
 
-	private void setMedalsBoard(ResultsMedals medalsBoard) {
-		this.medalsBoard = medalsBoard;
-	}
-
 	protected void setResultsBoard(Results board) {
 		this.resultsBoard = board;
 	}
 
+	private void createComponents() {
+		var board = new Results();
+		setMedalsBoard(new ResultsMedals());
+		this.setBoard(board);
+
+		getMedalsBoard().setDownSilenced(true);
+		getMedalsBoard().setDarkMode(board.isDarkMode());
+		getMedalsBoard().setVideo(board.isVideo());
+		getMedalsBoard().setPublicDisplay(board.isPublicDisplay());
+		getMedalsBoard().setSingleReferee(board.isSingleReferee());
+		getMedalsBoard().setAbbreviatedName(board.isAbbreviatedName());
+		getMedalsBoard().setTeamWidth(board.getTeamWidth());
+		getMedalsBoard().setEmFontSize(board.getEmFontSize());
+		checkVideo(getMedalsBoard());
+
+		getMedalsBoard().getStyle().set("display", "none");
+		this.ui = UI.getCurrent();
+	}
+
 	private ResultsMedals getMedalsBoard() {
-		return medalsBoard;
+		return this.medalsBoard;
+	}
+
+	private void setMedalsBoard(ResultsMedals medalsBoard) {
+		this.medalsBoard = medalsBoard;
 	}
 
 }
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/RankingsPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/RankingsPage.java
index ec58a65f9e..6b6e0dd7a7 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/RankingsPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/RankingsPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupLiftingOrderPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupLiftingOrderPage.java
index 883e4a7b0a..a485845f7c 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupLiftingOrderPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupLiftingOrderPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
@@ -61,7 +67,7 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupMultiRanksPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupMultiRanksPage.java
index b75e6305ef..d9dd8c53bf 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupMultiRanksPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupMultiRanksPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
@@ -57,7 +63,7 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupNoLeadersPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupNoLeadersPage.java
index c13d66cc2d..4aad5450bf 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupNoLeadersPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupNoLeadersPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
@@ -36,7 +42,7 @@ public String getPageTitle() {
 
 	@Override
 	protected void init() {
-		logger = (Logger) LoggerFactory.getLogger(WarmupNoLeadersPage.class);
+		this.logger = (Logger) LoggerFactory.getLogger(WarmupNoLeadersPage.class);
 		var board = new Results();
 		this.setBoard(board);
 
@@ -62,7 +68,7 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupRankingOrderPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupRankingOrderPage.java
index bbe2e69c12..3c10c2083d 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupRankingOrderPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupRankingOrderPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.Map;
@@ -61,7 +67,7 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupScoreboardPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupScoreboardPage.java
index 49cf5ad52a..ead482ac9a 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupScoreboardPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/scoreboards/WarmupScoreboardPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.scoreboards;
 
 import java.util.HashMap;
@@ -30,7 +36,7 @@ public class WarmupScoreboardPage extends AbstractResultsDisplayPage {
 	Map> urlParameterMap = new HashMap<>();
 
 	public WarmupScoreboardPage() {
-		// intentionally empty.  init() will be called as required.
+		// intentionally empty. init() will be called as required.
 	}
 
 	@Override
@@ -40,9 +46,9 @@ public String getPageTitle() {
 
 	@Override
 	protected void init() {
-		logger = (Logger) LoggerFactory.getLogger(WarmupScoreboardPage.class);
-		uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
-		
+		this.logger = (Logger) LoggerFactory.getLogger(WarmupScoreboardPage.class);
+		this.uiEventLogger = (Logger) LoggerFactory.getLogger("UI" + this.logger.getName());
+
 		// each subclass must define this routine.
 		// otherwise we end up with multiple instances of the Results board.
 		var board = new Results();
@@ -72,7 +78,7 @@ protected void init() {
 		fullMap.putAll(additionalMap);
 		setDefaultParameters(QueryParameters.simple(fullMap));
 	}
-	
+
 	@Override
 	protected void onAttach(AttachEvent attachEvent) {
 		DisplayParameters board = (DisplayParameters) this.getBoard();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/top/TopSinclairPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/top/TopSinclairPage.java
index 7ca3a9a775..455f331f47 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/top/TopSinclairPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/top/TopSinclairPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.top;
 
 import java.util.HashMap;
@@ -53,11 +59,6 @@ public void addDialogContent(Component target, VerticalLayout vl) {
 		DisplayOptions.addLightingEntries(vl, target, this);
 	}
 
-	@Override
-	public Championship getChampionship() {
-		return this.ageDivision;
-	}
-
 	@Override
 	public final AgeGroup getAgeGroup() {
 		return this.ageGroup;
@@ -74,14 +75,14 @@ public final Category getCategory() {
 	}
 
 	@Override
-	public String getPageTitle() {
-		return Translator.translate("Scoreboard.TopScore",
-		        Ranking.getScoringTitle(Competition.getCurrent().getScoringSystem()));
+	public Championship getChampionship() {
+		return this.ageDivision;
 	}
 
 	@Override
-	public void setChampionship(Championship ageDivision) {
-		this.ageDivision = ageDivision;
+	public String getPageTitle() {
+		return Translator.translate("Scoreboard.TopScore",
+		        Ranking.getScoringTitle(Competition.getCurrent().getScoringSystem()));
 	}
 
 	@Override
@@ -99,6 +100,11 @@ public final void setCategory(Category cat) {
 		this.category = cat;
 	}
 
+	@Override
+	public void setChampionship(Championship ageDivision) {
+		this.ageDivision = ageDivision;
+	}
+
 	@Override
 	protected void init() {
 		var board = new TopSinclair();
diff --git a/owlcms/src/main/java/app/owlcms/nui/displays/top/TopTeamsPage.java b/owlcms/src/main/java/app/owlcms/nui/displays/top/TopTeamsPage.java
index 7ffdf65496..a193b8e840 100644
--- a/owlcms/src/main/java/app/owlcms/nui/displays/top/TopTeamsPage.java
+++ b/owlcms/src/main/java/app/owlcms/nui/displays/top/TopTeamsPage.java
@@ -1,3 +1,9 @@
+/*******************************************************************************
+ * Copyright © 2009-present Jean-François Lamy
+ *
+ * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
+ * License text at https://opensource.org/licenses/NPOSL-3.0
+ *******************************************************************************/
 package app.owlcms.nui.displays.top;
 
 import java.util.HashMap;
@@ -88,11 +94,6 @@ public void addDialogContent(Component target, VerticalLayout vl) {
 		        new HorizontalLayout(championshipComboBox, ageGroupPrefixComboBox));
 	}
 
-	@Override
-	public final Championship getChampionship() {
-		return this.ageDivision;
-	}
-
 	@Override
 	public final AgeGroup getAgeGroup() {
 		return this.ageGroup;
@@ -108,6 +109,11 @@ public final Category getCategory() {
 		return this.category;
 	}
 
+	@Override
+	public final Championship getChampionship() {
+		return this.ageDivision;
+	}
+
 	/**
 	 * @see com.vaadin.flow.router.HasDynamicTitle#getPageTitle()
 	 */
@@ -117,8 +123,7 @@ public String getPageTitle() {
 	}
 
 	/**
-	 * @see app.owlcms.apputils.queryparameters.DisplayParametersReader#readParams(com.vaadin.flow.router.Location,
-	 *      java.util.Map)
+	 * @see app.owlcms.apputils.queryparameters.DisplayParametersReader#readParams(com.vaadin.flow.router.Location, java.util.Map)
 	 */
 	@Override
 	public HashMap> readParams(Location location, Map> parametersMap) {
@@ -171,13 +176,6 @@ public HashMap> readParams(Location location, Map> readParams(Location location, Map> parametersMap) {
@@ -177,13 +182,6 @@ public HashMap> readParams(Location location, Map
- * 
  • If the IP environment variable is present, it is expected to be a commma-separated address list of IPv4 - * addresses. Browser must come from one of these addresses The IP address(es) will normally be those for the local - * router or routers used at the competition site. + *
  • If the IP environment variable is present, it is expected to be a commma-separated address list of IPv4 addresses. Browser must come from one of these + * addresses The IP address(es) will normally be those for the local router or routers used at the competition site. *
  • if a PIN environment variable is present, the PIN will be required (even if no IP whitelist) - *
  • if PIN enviroment variable is not present, all accesses from the whitelisted routers will be allowed. This can be - * sufficient if the router password is well-protected (which is not likely). Users can type any NIP, including an empty - * value. + *
  • if PIN enviroment variable is not present, all accesses from the whitelisted routers will be allowed. This can be sufficient if the router password is + * well-protected (which is not likely). Users can type any NIP, including an empty value. *
  • if neither IP nor PIN is present, no check is done ({@link RequireLogin} does not display this view). * */ diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/AnnouncerContent.java b/owlcms/src/main/java/app/owlcms/nui/lifting/AnnouncerContent.java index 18d81a0552..b2c8fa7c54 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/AnnouncerContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/AnnouncerContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -116,15 +116,6 @@ public AnnouncerContent() { } - @Override - protected void onAttach(AttachEvent attachEvent) { - super.onAttach(attachEvent); - createTopBarGroupSelect(); - // setLiveLights(!Config.getCurrent().featureSwitch("noLiveLights")); - // setCenterNotifications(Config.getCurrent().featureSwitch("centerAnnouncerNotifications")); - defineFilters(this.getCrudGrid()); - } - /** * Not used in this class. We use createInitialBar and createTopBar as required. * @@ -175,6 +166,16 @@ public String getPageTitle() { return Translator.translate("Announcer") + OwlcmsSession.getFopNameIfMultiple(); } + @Override + public boolean isCenterNotifications() { + return this.centerNotifications; + } + + @Override + public boolean isDeclarations() { + return this.declarations; + } + /** * The URL contains the group, contrary to other screens. * @@ -188,11 +189,28 @@ public boolean isIgnoreGroupFromURL() { return false; } + @Override + public boolean isLiveLights() { + // logger.debug("is live lights {} -- {}",this.liveLights, LoggerUtils.whereFrom()); + return this.liveLights; + } + @Override public boolean isSingleReferee() { return this.singleReferee; } + @Override + public void setCenterNotifications(boolean centerNotifications) { + // logger.debug"setCenterNotifications {} {}",centerNotifications,LoggerUtils.whereFrom()); + this.centerNotifications = centerNotifications; + } + + @Override + public void setDeclarations(boolean showDeclarations) { + this.declarations = showDeclarations; + } + @Override public void setHeaderContent() { getRouterLayout().setMenuTitle(getMenuTitle()); @@ -202,6 +220,11 @@ public void setHeaderContent() { getRouterLayout().updateHeader(false); } + @Override + public void setLiveLights(boolean showLiveLights) { + this.liveLights = showLiveLights; + } + @Override public void setSingleReferee(boolean b) { this.singleReferee = b; @@ -351,12 +374,6 @@ public void slaveRefereeDecision(UIEvent.Decision e) { }); } - @Override - @Subscribe - public void slaveUpdateGrid(Decision e) { - // do nothing, prevents premature update of lifting order grid - } - @Subscribe public void slaveStartTime(UIEvent.StartTime e) { UIEventProcessor.uiAccess(this, this.uiEventBus, e, () -> { @@ -365,6 +382,12 @@ public void slaveStartTime(UIEvent.StartTime e) { }); } + @Override + @Subscribe + public void slaveUpdateGrid(Decision e) { + // do nothing, prevents premature update of lifting order grid + } + /** * @see app.owlcms.nui.shared.AthleteGridContent#announcerButtons(com.vaadin.flow.component.orderedlayout.FlexLayout) */ @@ -712,38 +735,6 @@ protected void createTopBarSettingsMenu() { } - @Override - public void setLiveLights(boolean showLiveLights) { - this.liveLights = showLiveLights; - } - - @Override - public boolean isLiveLights() { - // logger.debug("is live lights {} -- {}",this.liveLights, LoggerUtils.whereFrom()); - return this.liveLights; - } - - @Override - public void setCenterNotifications(boolean centerNotifications) { - // logger.debug"setCenterNotifications {} {}",centerNotifications,LoggerUtils.whereFrom()); - this.centerNotifications = centerNotifications; - } - - @Override - public boolean isCenterNotifications() { - return this.centerNotifications; - } - - @Override - public void setDeclarations(boolean showDeclarations) { - this.declarations = showDeclarations; - } - - @Override - public boolean isDeclarations() { - return this.declarations; - } - /** * @see app.owlcms.nui.shared.AthleteGridContent#decisionButtons(com.vaadin.flow.component.orderedlayout.HorizontalLayout) */ @@ -761,6 +752,15 @@ protected HorizontalLayout decisionButtons(FlexLayout announcerBar) { return decisions; } + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + createTopBarGroupSelect(); + // setLiveLights(!Config.getCurrent().featureSwitch("noLiveLights")); + // setCenterNotifications(Config.getCurrent().featureSwitch("centerAnnouncerNotifications")); + defineFilters(this.getCrudGrid()); + } + private void badLift() { var fop = getFop(); long now = System.currentTimeMillis(); diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/AthleteCardFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/lifting/AthleteCardFormFactory.java index d899ba527c..c2ca8efc76 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/AthleteCardFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/AthleteCardFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -145,8 +145,7 @@ public Athlete add(Athlete athlete) { /** * Add bean-level validations * - * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildBinder(org.vaadin.crudui.crud.CrudOperation, - * java.lang.Object) + * @see org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory#buildBinder(org.vaadin.crudui.crud.CrudOperation, java.lang.Object) */ @Override public Binder buildBinder(CrudOperation operation, Athlete doNotUse) { @@ -163,8 +162,7 @@ public Binder buildBinder(CrudOperation operation, Athlete doNotUse) { } /** - * @see app.owlcms.nui.shared.CustomFormFactory#buildCaption(org.vaadin.crudui.crud.CrudOperation, - * app.owlcms.data.athlete.Athlete) + * @see app.owlcms.nui.shared.CustomFormFactory#buildCaption(org.vaadin.crudui.crud.CrudOperation, app.owlcms.data.athlete.Athlete) */ @Override public String buildCaption(CrudOperation operation, final Athlete aFromDb) { @@ -180,9 +178,9 @@ public String buildCaption(CrudOperation operation, final Athlete aFromDb) { } /** - * @see app.owlcms.nui.crudui.OwlcmsCrudFormFactory#buildFooter(org.vaadin.crudui.crud.CrudOperation, - * java.lang.Object, com.vaadin.flow.component.ComponentEventListener, - * com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.ComponentEventListener) + * @see app.owlcms.nui.crudui.OwlcmsCrudFormFactory#buildFooter(org.vaadin.crudui.crud.CrudOperation, java.lang.Object, + * com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.ComponentEventListener, + * com.vaadin.flow.component.ComponentEventListener) */ @Override public Component buildFooter(CrudOperation operation, Athlete unused, @@ -248,10 +246,9 @@ public Component buildFooter(CrudOperation operation, Athlete unused, } /** - * @see app.owlcms.nui.shared.CustomFormFactory#buildNewForm(org.vaadin.crudui.crud.CrudOperation, - * app.owlcms.data.athlete.Athlete, boolean, com.vaadin.flow.component.ComponentEventListener, + * @see app.owlcms.nui.shared.CustomFormFactory#buildNewForm(org.vaadin.crudui.crud.CrudOperation, app.owlcms.data.athlete.Athlete, boolean, * com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.ComponentEventListener, - * com.vaadin.flow.component.button.Button) + * com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.button.Button) */ @Override public Component buildNewForm(CrudOperation operation, Athlete aFromList, boolean readOnly, @@ -336,8 +333,8 @@ public Component buildNewForm(CrudOperation operation, Athlete aFromList, boolea /** * Special version because we use setBean instead of readBean * - * @see app.owlcms.nui.crudui.OwlcmsCrudFormFactory#buildOperationButton(org.vaadin.crudui.crud.CrudOperation, - * java.lang.Object, com.vaadin.flow.component.ComponentEventListener) + * @see app.owlcms.nui.crudui.OwlcmsCrudFormFactory#buildOperationButton(org.vaadin.crudui.crud.CrudOperation, java.lang.Object, + * com.vaadin.flow.component.ComponentEventListener) */ @Override public Button buildOperationButton(CrudOperation operation, Athlete domainObject, @@ -349,8 +346,8 @@ public Button buildOperationButton(CrudOperation operation, Athlete domainObject button.addClickListener((f) -> { performOperationAndCallback(operation, domainObject, callBack, isIgnoreErrors()); // the field value change listener will set the following to true if the user edits using the interface - // already initialized correctly in the form, should not be reset here. see # - //domainObject.setCheckTiming(false); + // already initialized correctly in the form, should not be reset here. see # + // domainObject.setCheckTiming(false); }); return button; } @@ -1162,8 +1159,8 @@ private void setActualLiftClass(BindingValidationStatus status) throws Number } /** - * set the automatic progressions. This is invoked as a validator because we don't want to be called if the entered - * value is invalid. Only the side-effects are interesting, so we return true. + * set the automatic progressions. This is invoked as a validator because we don't want to be called if the entered value is invalid. Only the side-effects + * are interesting, so we return true. * * @param athlete * @return true always diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/JuryContent.java b/owlcms/src/main/java/app/owlcms/nui/lifting/JuryContent.java index 95e657e445..df009c8d34 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/JuryContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/JuryContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -99,7 +99,7 @@ public JuryContent() { // all this does is call init() -- which we override. // when navigating to the page, Vaadin will call setParameter+readParameters // these parameters will be applied - + setDefaultParameters(QueryParameters.simple(Map.of( SoundParameters.SILENT, "true", SoundParameters.DOWNSILENT, "true", diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/JuryDialog.java b/owlcms/src/main/java/app/owlcms/nui/lifting/JuryDialog.java index 7e20874185..bb7c159544 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/JuryDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/JuryDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -109,13 +109,13 @@ public JuryDialog(JuryContent origin, Athlete athleteUnderReview, JuryDeliberati public void doClose(boolean noAction) { UI.getCurrent().access(() -> { if (Competition.getCurrent().isAnnouncerControlledJuryDecision() - && (deliberation == JuryDeliberationEventType.START_DELIBERATION - || deliberation == JuryDeliberationEventType.CHALLENGE)) { + && (this.deliberation == JuryDeliberationEventType.START_DELIBERATION + || this.deliberation == JuryDeliberationEventType.CHALLENGE)) { if (noAction) { resumeLifting(noAction); } else { // announcer has been notified to announce, remind the jury - ((JuryContent) origin).slaveNotification( + ((JuryContent) this.origin).slaveNotification( new UIEvent.Notification(null, this, UIEvent.Notification.Level.WARNING, "Jury.AnnouncerWillAnnounce", @@ -131,25 +131,6 @@ public void doClose(boolean noAction) { }); } - private void resumeLifting(boolean noAction) { - OwlcmsSession.withFop(fop -> { - fop.fopEventPost(new FOPEvent.StartLifting(this)); - }); - if (noAction) { - ((JuryContent) this.origin).doSync(); - } - this.close(); - - String message = this.deliberation == JuryDeliberationEventType.START_DELIBERATION - ? "{}end of jury deliberation" - : (this.deliberation == JuryDeliberationEventType.CHALLENGE - ? "{}end of challenge" - : "{}end jury break"); - this.logger.info( - message, - FieldOfPlay.getLoggingName(OwlcmsSession.getFop())); - } - private void addCallController() { FormLayout layout3 = new FormLayout(); FormItem callController; @@ -419,6 +400,25 @@ private Athlete getReviewedAthlete() { return this.reviewedAthlete; } + private void resumeLifting(boolean noAction) { + OwlcmsSession.withFop(fop -> { + fop.fopEventPost(new FOPEvent.StartLifting(this)); + }); + if (noAction) { + ((JuryContent) this.origin).doSync(); + } + this.close(); + + String message = this.deliberation == JuryDeliberationEventType.START_DELIBERATION + ? "{}end of jury deliberation" + : (this.deliberation == JuryDeliberationEventType.CHALLENGE + ? "{}end of challenge" + : "{}end jury break"); + this.logger.info( + message, + FieldOfPlay.getLoggingName(OwlcmsSession.getFop())); + } + private void setReviewedAthlete(Athlete reviewedAthlete) { this.reviewedAthlete = reviewedAthlete; } diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/LiftingNavigationContent.java b/owlcms/src/main/java/app/owlcms/nui/lifting/LiftingNavigationContent.java index 9c25ee9c31..4a460ee1c3 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/LiftingNavigationContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/LiftingNavigationContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -56,43 +56,6 @@ public class LiftingNavigationContent extends BaseNavigationContent implements N public LiftingNavigationContent() { DebugUtils.gc(); } - - @Override - protected void onAttach(AttachEvent attachEvent) { - - super.onAttach(attachEvent); - - logger.trace("LiftingNavigationContent onAttach start"); - - Button weighIn = openInNewTabNoParam(WeighinContent.class, Translator.translate("WeighIn_Title")); - weighIn.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS); - weighIn.setIcon(new Icon(VaadinIcon.SCALE)); - // weighIn.addThemeVariants(ButtonVariant.LUMO_PRIMARY); - FlexibleGridLayout grid3 = HomeNavigationContent.navigationGrid(weighIn); - doGroup(Translator.translate("WeighIn_Title"), grid3, this); - - Button announcer = openInNewTab(AnnouncerContent.class, Translator.translate("Announcer")); - announcer.setIcon(new Icon(VaadinIcon.MICROPHONE)); - announcer.setTabIndex(2); - announcer.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS); - announcer.setThemeName(FOP, isAttached()); - Button marshall = openInNewTab(MarshallContent.class, Translator.translate("Marshall")); - Button timekeeper = openInNewTab(TimekeeperContent.class, Translator.translate("Timekeeper")); - Button technical = openInNewTab(TCContent.class, Translator.translate("PlatesCollarBarbell")); - - VerticalLayout intro = new VerticalLayout(); - addP(intro, Translator.translate("AnnouncerSelectsGroup") + Translator.translate("ChangesGroupEverywhere") - + Translator.translate("AnnouncerEtc")); - intro.getStyle().set("margin-bottom", "0"); - - FlexibleGridLayout grid1 = HomeNavigationContent.navigationGrid(announcer, marshall, timekeeper, technical); - doGroup(Translator.translate("Scoreboard.LiftingOrder"), intro, grid1, this); - - Button referee = openInNewTab(RefContent.class, Translator.translate("Referee_Mobile_Device")); - Button jury = openInNewTab(JuryContent.class, Translator.translate("Jury_Console")); - FlexibleGridLayout grid2 = HomeNavigationContent.navigationGrid(referee, jury); - doGroup(Translator.translate("Referees_Jury"), grid2, this); - } @Override public String getMenuTitle() { @@ -128,4 +91,41 @@ protected HorizontalLayout createMenuBarFopField(String label, String placeHolde fopField.setAlignItems(Alignment.CENTER); return fopField; } + + @Override + protected void onAttach(AttachEvent attachEvent) { + + super.onAttach(attachEvent); + + logger.trace("LiftingNavigationContent onAttach start"); + + Button weighIn = openInNewTabNoParam(WeighinContent.class, Translator.translate("WeighIn_Title")); + weighIn.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS); + weighIn.setIcon(new Icon(VaadinIcon.SCALE)); + // weighIn.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + FlexibleGridLayout grid3 = HomeNavigationContent.navigationGrid(weighIn); + doGroup(Translator.translate("WeighIn_Title"), grid3, this); + + Button announcer = openInNewTab(AnnouncerContent.class, Translator.translate("Announcer")); + announcer.setIcon(new Icon(VaadinIcon.MICROPHONE)); + announcer.setTabIndex(2); + announcer.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS); + announcer.setThemeName(FOP, isAttached()); + Button marshall = openInNewTab(MarshallContent.class, Translator.translate("Marshall")); + Button timekeeper = openInNewTab(TimekeeperContent.class, Translator.translate("Timekeeper")); + Button technical = openInNewTab(TCContent.class, Translator.translate("PlatesCollarBarbell")); + + VerticalLayout intro = new VerticalLayout(); + addP(intro, Translator.translate("AnnouncerSelectsGroup") + Translator.translate("ChangesGroupEverywhere") + + Translator.translate("AnnouncerEtc")); + intro.getStyle().set("margin-bottom", "0"); + + FlexibleGridLayout grid1 = HomeNavigationContent.navigationGrid(announcer, marshall, timekeeper, technical); + doGroup(Translator.translate("Scoreboard.LiftingOrder"), intro, grid1, this); + + Button referee = openInNewTab(RefContent.class, Translator.translate("Referee_Mobile_Device")); + Button jury = openInNewTab(JuryContent.class, Translator.translate("Jury_Console")); + FlexibleGridLayout grid2 = HomeNavigationContent.navigationGrid(referee, jury); + doGroup(Translator.translate("Referees_Jury"), grid2, this); + } } diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/MarshallContent.java b/owlcms/src/main/java/app/owlcms/nui/lifting/MarshallContent.java index 505ca0ba55..ba5177761f 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/MarshallContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/MarshallContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -114,6 +114,27 @@ public String getPageTitle() { return Translator.translate("Marshall") + OwlcmsSession.getFopNameIfMultiple(); } + @Override + public boolean isLiveLights() { + // logger.debug("is live lights {} -- {}",this.liveLights, LoggerUtils.whereFrom()); + return this.liveLights; + } + + @Override + public boolean isStartOrder() { + return this.startOrder; + } + + @Override + public void setLiveLights(boolean showLiveLights) { + this.liveLights = showLiveLights; + } + + @Override + public void setStartOrder(boolean useStartOrder) { + this.startOrder = useStartOrder; + } + @Subscribe public void slaveRefereeDecision(UIEvent.Decision e) { UIEventProcessor.uiAccess(this, this.uiEventBus, e, () -> { @@ -157,15 +178,6 @@ protected HorizontalLayout announcerButtons(FlexLayout announcerBar) { return buttons; } - /** - * @see app.owlcms.nui.shared.AthleteGridContent#decisionButtons(com.vaadin.flow.component.orderedlayout.HorizontalLayout) - */ - @Override - protected HorizontalLayout decisionButtons(FlexLayout announcerBar) { - HorizontalLayout decisions = new HorizontalLayout(); - return decisions; - } - @Override protected void createTopBarSettingsMenu() { this.topBarSettings = new MenuBar(); @@ -205,25 +217,13 @@ protected void createTopBarSettingsMenu() { startOrder.setCheckable(true); startOrder.setChecked(this.isStartOrder()); } - - @Override - public boolean isLiveLights() { - // logger.debug("is live lights {} -- {}",this.liveLights, LoggerUtils.whereFrom()); - return this.liveLights; - } - - @Override - public void setLiveLights(boolean showLiveLights) { - this.liveLights = showLiveLights; - } + /** + * @see app.owlcms.nui.shared.AthleteGridContent#decisionButtons(com.vaadin.flow.component.orderedlayout.HorizontalLayout) + */ @Override - public void setStartOrder(boolean useStartOrder) { - this.startOrder = useStartOrder; - } - - @Override - public boolean isStartOrder() { - return this.startOrder; + protected HorizontalLayout decisionButtons(FlexLayout announcerBar) { + HorizontalLayout decisions = new HorizontalLayout(); + return decisions; } } diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/NextAthleteAble.java b/owlcms/src/main/java/app/owlcms/nui/lifting/NextAthleteAble.java index 670bc2173d..732771bc62 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/NextAthleteAble.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/NextAthleteAble.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.lifting; import java.util.List; @@ -5,11 +11,11 @@ import app.owlcms.data.athlete.Athlete; public interface NextAthleteAble { - + List getAthletes(); - + Athlete getNextAthlete(Athlete current); - + Athlete getPreviousAthlete(Athlete current); } diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/TCContent.java b/owlcms/src/main/java/app/owlcms/nui/lifting/TCContent.java index 723c5766f4..63751ba9b3 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/TCContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/TCContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -123,12 +123,17 @@ public void setCrudFormFactory(OwlcmsCrudFormFactory crudFormFactory) { this.crudFormFactory = crudFormFactory; } - @Override @Subscribe - public void slaveUpdateGrid(UIEvent.LiftingOrderUpdated e) { - OwlcmsSession.withFop((fop) -> UIEventProcessor.uiAccess(this.plates, this.uiEventBus, () -> { - this.plates.computeImageArea(fop, true); - })); + public void slaveBarbellChanged(UIEvent.BarbellOrPlatesChanged e) { + FieldOfPlay fop2 = OwlcmsSession.getFop(); + if (e.getOrigin() == this) { + return; + } + if (fop2 != null) { + this.platform = fop2.getPlatform(); + // logger.debug("slaveBarbellChanged"); + this.plates.computeImageArea(fop2, true); + } } @Override @@ -139,17 +144,12 @@ public void slaveUpdateGrid(UIEvent.Decision e) { })); } + @Override @Subscribe - public void slaveBarbellChanged(UIEvent.BarbellOrPlatesChanged e) { - FieldOfPlay fop2 = OwlcmsSession.getFop(); - if (e.getOrigin() == this) { - return; - } - if (fop2 != null) { - this.platform = fop2.getPlatform(); - // logger.debug("slaveBarbellChanged"); - plates.computeImageArea(fop2, true); - } + public void slaveUpdateGrid(UIEvent.LiftingOrderUpdated e) { + OwlcmsSession.withFop((fop) -> UIEventProcessor.uiAccess(this.plates, this.uiEventBus, () -> { + this.plates.computeImageArea(fop, true); + })); } @Override diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/TimekeeperContent.java b/owlcms/src/main/java/app/owlcms/nui/lifting/TimekeeperContent.java index 08a266f0a4..5297909e5e 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/TimekeeperContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/TimekeeperContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/UIEventProcessor.java b/owlcms/src/main/java/app/owlcms/nui/lifting/UIEventProcessor.java index 047d2314b6..82b0dff4d8 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/UIEventProcessor.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/UIEventProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -21,14 +21,13 @@ public interface UIEventProcessor { /** * Access the ui safely * - * Do nothing if the event originates from ourselves -- if we stop the clock on the timekeeper device, there is no - * need to obey the command to stop the clock on all the other devices, since we are the cause of that event. + * Do nothing if the event originates from ourselves -- if we stop the clock on the timekeeper device, there is no need to obey the command to stop the + * clock on all the other devices, since we are the cause of that event. * * @param attachedComponent the component we are updating (any of them if several) * @param uiEventBus the bus on which we are listening * @param e the event we received - * @param selfOrigin our reference element -- for composite objects, we will likely use the parent of the - * hierarchy + * @param selfOrigin our reference element -- for composite objects, we will likely use the parent of the hierarchy * @param command */ public static void uiAccessIgnoreIfSelfOrigin(Component attachedComponent, EventBus uiEventBus, UIEvent e, diff --git a/owlcms/src/main/java/app/owlcms/nui/lifting/WeighinContent.java b/owlcms/src/main/java/app/owlcms/nui/lifting/WeighinContent.java index 5473598ee5..8dae163f0c 100644 --- a/owlcms/src/main/java/app/owlcms/nui/lifting/WeighinContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/lifting/WeighinContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -379,15 +379,15 @@ public Athlete getNextAthlete(Athlete current) { // Make sure we have updated data for the current athlete if (current != null) { - for (int i = 0; i < all.size(); i++) { - if (all.get(i).getId().equals(current.getId())) { - current = all.get(i); + for (Athlete element : all) { + if (element.getId().equals(current.getId())) { + current = element; break; } } - if (current == null) { - current = all.get(0); - } +// if (current == null) { +// current = all.get(0); +// } } else if (all.size() > 0) { current = all.get(0); } @@ -401,8 +401,7 @@ public Athlete getNextAthlete(Athlete current) { // quick workaround: a "no show" is indicated by removing the session. Double curWeight = current.getBodyWeight(); if (curWeight != null || current.getGroup() == null) { - for (int i = 0; i < all.size(); i++) { - Athlete next = all.get(i); + for (Athlete next : all) { if (next.getBodyWeight() == null) { return next; } @@ -414,8 +413,7 @@ public Athlete getNextAthlete(Athlete current) { } } // start from the top again instead of exiting - for (int i = 0; i < all.size(); i++) { - Athlete next = all.get(i); + for (Athlete next : all) { if (next.getBodyWeight() == null) { return next; } @@ -556,11 +554,9 @@ public void setNextMode(boolean b) { * Note: because we have the @Route, the parameters are parsed *before* our parent layout is created. * * @param event Vaadin navigation event - * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query - * parameters instead. + * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query parameters instead. * - * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, - * java.lang.String) + * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, java.lang.String) */ @Override public void setParameter(BeforeEvent event, @OptionalParameter String parameter) { @@ -655,10 +651,10 @@ protected List athletesFindAll() { * @return the form factory that will create the actual form on demand */ protected OwlcmsCrudFormFactory createFormFactory() { - athleteEditingFormFactory = new NAthleteRegistrationFormFactory(Athlete.class, + this.athleteEditingFormFactory = new NAthleteRegistrationFormFactory(Athlete.class, this.getCurrentGroup(), this); - createFormLayout(athleteEditingFormFactory); - return athleteEditingFormFactory; + createFormLayout(this.athleteEditingFormFactory); + return this.athleteEditingFormFactory; } /** @@ -689,13 +685,13 @@ protected OwlcmsCrudGrid createGrid(OwlcmsCrudFormFactory crud grid.addColumn("entryTotal").setHeader(Translator.translate("EntryTotal")).setAutoWidth(true); grid.addColumn("federationCodes").setHeader(Translator.translate("Registration.FederationCodesShort")) .setAutoWidth(true); - + List> sortOrder = new ArrayList<>(); // groupWeighinTimeComparator implements traditional platform name comparisons e.g. USAW. - groupCol.setComparator((a,b) -> Group.groupWeighinTimeComparator.compare(a.getGroup(), b.getGroup())); - sortOrder.add(new GridSortOrder(groupCol, SortDirection.ASCENDING)); + groupCol.setComparator((a, b) -> Group.groupWeighinTimeComparator.compare(a.getGroup(), b.getGroup())); + sortOrder.add(new GridSortOrder<>(groupCol, SortDirection.ASCENDING)); grid.sort(sortOrder); - + NextCrudGrid crudGrid = new NextCrudGrid(Athlete.class, new OwlcmsGridLayout(Athlete.class) { @Override public void hideForm() { @@ -858,67 +854,7 @@ protected List participationFindAll() { // enable quick batch mode only when doing a session boolean sessionSelected = this.getGroup() != null && !this.getGroup().getName().equals("*"); - ((NextCrudGrid) crudGrid).batchButton.setEnabled(sessionSelected); - return found; - } - - private List filterAthletes(List athletes) { - Category catFilterValue = getCategoryValue(); - Group group2 = getGroup() == null - ? null - : (getGroup().getName() == "*" ? null : getGroup()); - Stream stream = athletes.stream() - .filter(a -> { - Platform platformFilterValue = getPlatform(); - if (platformFilterValue == null) { - return true; - } - Platform athletePlaform = a.getGroup() != null - ? (a.getGroup().getPlatform() != null ? a.getGroup().getPlatform() : null) - : null; - return platformFilterValue.equals(athletePlaform); - }) - .filter(a -> { - return group2 != null ? group2.equals(a.getGroup()) - : true; - }) - .filter(a -> { - String fLastName = getLastName(); - if (fLastName == null) { - return true; - } - String aLastName = a.getLastName(); - if (aLastName == null || aLastName.isBlank()) { - return false; - } - aLastName = aLastName.toLowerCase(); - fLastName = fLastName.toLowerCase(); - return aLastName.startsWith(fLastName); - }) - .filter(a -> getWeighedIn() == null - || (getWeighedIn() ? (a.getBodyWeight() != null && a.getBodyWeight() > 0) - : (a.getBodyWeight() == null || a.getBodyWeight() < 0.1))) - .filter(a -> catFilterValue != null ? a.getCategory() != null : true) - .filter(a -> { - Gender genderFilterValue = getGender(); - Gender athleteGender = a.getGender(); - boolean catOk = (catFilterValue == null - || catFilterValue.toString().equals(a.getCategory().toString())) - && (genderFilterValue == null || genderFilterValue == athleteGender); - return catOk; - }) - .filter(a -> getTeam() != null ? getTeam().contentEquals(a.getTeam()) - : true) - .map(a -> { - if (a.getTeam() == null) { - a.setTeam(""); - } - return a; - }); - - List found = stream.sorted( - groupCategoryComparator()) - .collect(Collectors.toList()); + ((NextCrudGrid) this.crudGrid).batchButton.setEnabled(sessionSelected); return found; } @@ -978,7 +914,7 @@ private Button createJuryButton() { JXLSDownloader juryButton = new JXLSDownloader( () -> { - generateStartNumbers(); + generateStartNumbers(); JXLSJurySheet rs = new JXLSJurySheet(); // group may have been edited since the page was loaded Group curGroup = getGroupFilter().getValue(); @@ -999,8 +935,8 @@ private Button createStartingWeightsButton() { JXLSDownloader startingWeightsButton = new JXLSDownloader( () -> { - generateStartNumbers(); - JXLSResultSheet rs = new JXLSResultSheet(false); + generateStartNumbers(); + JXLSResultSheet rs = new JXLSResultSheet(false); // group may have been edited since the page was loaded Group curGroup = getGroupFilter().getValue(); rs.setGroup(curGroup != null ? GroupRepository.getById(curGroup.getId()) : null); @@ -1037,15 +973,75 @@ private Button createWeighInButton() { private void doSwitchGroup(Group newCurrentGroup) { if (newCurrentGroup != null && newCurrentGroup.getName() == "*") { setCurrentGroup(null); - athleteEditingFormFactory.setCurrentGroup(null); + this.athleteEditingFormFactory.setCurrentGroup(null); } else { setCurrentGroup(newCurrentGroup); - athleteEditingFormFactory.setCurrentGroup(newCurrentGroup); + this.athleteEditingFormFactory.setCurrentGroup(newCurrentGroup); } // getRouterLayout().updateHeader(true); getGroupFilter().setValue(newCurrentGroup); } + private List filterAthletes(List athletes) { + Category catFilterValue = getCategoryValue(); + Group group2 = getGroup() == null + ? null + : (getGroup().getName() == "*" ? null : getGroup()); + Stream stream = athletes.stream() + .filter(a -> { + Platform platformFilterValue = getPlatform(); + if (platformFilterValue == null) { + return true; + } + Platform athletePlaform = a.getGroup() != null + ? (a.getGroup().getPlatform() != null ? a.getGroup().getPlatform() : null) + : null; + return platformFilterValue.equals(athletePlaform); + }) + .filter(a -> { + return group2 != null ? group2.equals(a.getGroup()) + : true; + }) + .filter(a -> { + String fLastName = getLastName(); + if (fLastName == null) { + return true; + } + String aLastName = a.getLastName(); + if (aLastName == null || aLastName.isBlank()) { + return false; + } + aLastName = aLastName.toLowerCase(); + fLastName = fLastName.toLowerCase(); + return aLastName.startsWith(fLastName); + }) + .filter(a -> getWeighedIn() == null + || (getWeighedIn() ? (a.getBodyWeight() != null && a.getBodyWeight() > 0) + : (a.getBodyWeight() == null || a.getBodyWeight() < 0.1))) + .filter(a -> catFilterValue != null ? a.getCategory() != null : true) + .filter(a -> { + Gender genderFilterValue = getGender(); + Gender athleteGender = a.getGender(); + boolean catOk = (catFilterValue == null + || catFilterValue.toString().equals(a.getCategory().toString())) + && (genderFilterValue == null || genderFilterValue == athleteGender); + return catOk; + }) + .filter(a -> getTeam() != null ? getTeam().contentEquals(a.getTeam()) + : true) + .map(a -> { + if (a.getTeam() == null) { + a.setTeam(""); + } + return a; + }); + + List found = stream.sorted( + groupCategoryComparator()) + .collect(Collectors.toList()); + return found; + } + private void generateStartNumbers() { Group group = getCurrentGroup(); if (group == null) { diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupContent.java index 1d6c0fcc0f..8b12e47766 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -239,6 +239,10 @@ public Collection findAll() { return all; } + public GridCrud getCrud() { + return this.crud; + } + @Override public String getMenuTitle() { return Translator.translate("EditAgeGroups"); @@ -261,6 +265,10 @@ public void highlightResetButton() { this.resetCats.setThemeName("primary error"); } + public void setCrud(GridCrud crud) { + this.crud = crud; + } + @Override public void setHeaderContent() { getRouterLayout().setMenuTitle(getMenuTitle()); @@ -322,7 +330,7 @@ protected GridCrud createGrid(OwlcmsCrudFormFactory crudForm grid.addColumn(new TextRenderer<>( item -> { Ranking ss = item.getScoringSystem(); - String tr = (ss != null ? Translator.translate("Ranking."+ss) : ""); + String tr = (ss != null ? Translator.translate("Ranking." + ss) : ""); return tr; })) .setHeader(Translator.translate("CeremonyType.MEDALS")); @@ -446,12 +454,4 @@ private void unHighlightResetButton() { this.resetCats.setThemeName(""); } - public GridCrud getCrud() { - return crud; - } - - public void setCrud(GridCrud crud) { - this.crud = crud; - } - } diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupEditingFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupEditingFormFactory.java index 8cab0af13c..b89048bafd 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupEditingFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupEditingFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -131,7 +131,7 @@ public Component buildNewForm(CrudOperation operation, AgeGroup aFromDb, boolean ComboBox championshipField = new ComboBox<>(); List list = Championship.getMap().values().stream().sorted().toList(); - championshipField.setItems(new ListDataProvider(list)); + championshipField.setItems(new ListDataProvider<>(list)); championshipField.setItemLabelGenerator((ad) -> ad.getName()); championshipField.setRequired(true); championshipField.setRequiredIndicatorVisible(false); @@ -142,7 +142,7 @@ public Component buildNewForm(CrudOperation operation, AgeGroup aFromDb, boolean medalScoreSystemField.setClearButtonVisible(true); List rankings = Arrays.asList(Ranking.values()); List medalScoreRankings = rankings.stream().filter(r -> r.isMedalScore()).toList(); - medalScoreSystemField.setItems(new ListDataProvider(medalScoreRankings)); + medalScoreSystemField.setItems(new ListDataProvider<>(medalScoreRankings)); medalScoreSystemField.setItemLabelGenerator((ad) -> Translator.translate("Ranking." + ad.name())); // logger.debug("***** scoring system {}", aFromDb.getMedalScoringSystem()); this.binder.forField(medalScoreSystemField).bind(AgeGroup::getMedalScoringSystem, AgeGroup::setScoringSystem); @@ -205,20 +205,19 @@ public Component buildNewForm(CrudOperation operation, AgeGroup aFromDb, boolean this.binder.forField(this.catField).bind(AgeGroup::getCategories, AgeGroup::setCategories); formLayout.addFormItem(this.catField, createLabel(Translator.translate("BodyWeightCategories"))); + // if (minAgeField.getValue().isEmpty()) { + // minAgeField.setValue("0"); + // } + // if (maxAgeField.getValue().isEmpty()) { + // maxAgeField.setValue("999"); + // } + // if (genderField.getValue() == null) { + // genderField.setValue(Gender.F); + // } + // if (championshipField.getValue() == null) { + // championshipField.setValue(Championship.ofType(ChampionshipType.U)); + // } -// if (minAgeField.getValue().isEmpty()) { -// minAgeField.setValue("0"); -// } -// if (maxAgeField.getValue().isEmpty()) { -// maxAgeField.setValue("999"); -// } -// if (genderField.getValue() == null) { -// genderField.setValue(Gender.F); -// } -// if (championshipField.getValue() == null) { -// championshipField.setValue(Championship.ofType(ChampionshipType.U)); -// } - this.binder.readBean(aFromDb); Component footerLayout = this.buildFooter(operation, aFromDb, cancelButtonClickListener, @@ -231,28 +230,23 @@ public Component buildNewForm(CrudOperation operation, AgeGroup aFromDb, boolean return mainLayout; } - private Component createLabel(String translate) { - Div label = new Div(translate); - return label; - } - @Override public Button buildOperationButton(CrudOperation operation, AgeGroup domainObject, ComponentEventListener> gridCallBackAction) { return super.buildOperationButton(operation, domainObject, gridCallBackAction); } + @Override + public void delete(AgeGroup ageGroup) { + AgeGroupRepository.delete(ageGroup); + } + // @Override // public TextField defineOperationTrigger(CrudOperation operation, AgeGroup domainObject, // ComponentEventListener> action) { // return super.defineOperationTrigger(operation, domainObject, action); // } - @Override - public void delete(AgeGroup ageGroup) { - AgeGroupRepository.delete(ageGroup); - } - @Override public Collection findAll() { // will not be called, handled by the grid. @@ -304,4 +298,9 @@ protected void bindField(HasValue field, String property, Class propertyType, super.bindField(field, property, propertyType, c); } + private Component createLabel(String translate) { + Div label = new Div(translate); + return label; + } + } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupsFileUploadDialog.java b/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupsFileUploadDialog.java index a0dc535bf7..4ec869df83 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupsFileUploadDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/AgeGroupsFileUploadDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionContent.java index 5b5c7a7dca..5649328408 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionEditingFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionEditingFormFactory.java index b7595d784e..2e1f773fc0 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionEditingFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/CompetitionEditingFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -365,15 +365,15 @@ private FormLayout pointScoresForm() { layout.addFormItem(scoringCombo, Translator.translate("Competition.scoringSystemTitle")); this.binder.forField(scoringCombo).bind(Competition::getScoringSystem, Competition::setScoringSystem); -// Checkbox showScoressOnScoreboard = new Checkbox(); -// layout.addFormItem(showScoressOnScoreboard, Translator.translate("Competition.showScoresOnScoreboard")); -// this.binder.forField(showScoressOnScoreboard) -// .bind(Competition::isDisplayScores, Competition::setDisplayScores); -// -// Checkbox showScoreRanksOnScoreboard = new Checkbox(); -// layout.addFormItem(showScoreRanksOnScoreboard, Translator.translate("Competition.showScoreRanksOnScoreboard")); -// this.binder.forField(showScoreRanksOnScoreboard) -// .bind(Competition::isDisplayScoreRanks, Competition::setDisplayScoreRanks); + // Checkbox showScoressOnScoreboard = new Checkbox(); + // layout.addFormItem(showScoressOnScoreboard, Translator.translate("Competition.showScoresOnScoreboard")); + // this.binder.forField(showScoressOnScoreboard) + // .bind(Competition::isDisplayScores, Competition::setDisplayScores); + // + // Checkbox showScoreRanksOnScoreboard = new Checkbox(); + // layout.addFormItem(showScoreRanksOnScoreboard, Translator.translate("Competition.showScoreRanksOnScoreboard")); + // this.binder.forField(showScoreRanksOnScoreboard) + // .bind(Competition::isDisplayScoreRanks, Competition::setDisplayScoreRanks); RadioButtonGroup sinclairYear = new RadioButtonGroup<>(); layout.addFormItem(sinclairYear, Translator.translate("sinclair")); @@ -381,11 +381,11 @@ private FormLayout pointScoresForm() { this.binder.forField(sinclairYear) .bind(Competition::getSinclairYear, Competition::setSinclairYear); -// Checkbox sinclairMeetField = new Checkbox(); -// layout.addFormItem(sinclairMeetField, -// labelWithHelp("Competition.SinclairMeet", "Competition.SinclairMeetExplanation")); -// this.binder.forField(sinclairMeetField) -// .bind(Competition::isSinclair, Competition::setSinclair); + // Checkbox sinclairMeetField = new Checkbox(); + // layout.addFormItem(sinclairMeetField, + // labelWithHelp("Competition.SinclairMeet", "Competition.SinclairMeetExplanation")); + // this.binder.forField(sinclairMeetField) + // .bind(Competition::isSinclair, Competition::setSinclair); Checkbox customScoreField = new Checkbox(); layout.addFormItem(customScoreField, diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigContent.java index d68996a9c3..6e75d33c33 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigEditingFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigEditingFormFactory.java index 6ebec0a940..1f9f0dbd11 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigEditingFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/ConfigEditingFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -147,7 +147,7 @@ public Component buildNewForm(CrudOperation operation, Config config, boolean re tzLayout, separator(), translationLayout)); ts.add(Translator.translate("Config.ConnexionsTab"), new VerticalLayout( - new Div(), + new Div(), publicResultsLayout, separator(), videoDataLayout, separator(), mqttLayout, separator())); @@ -444,29 +444,6 @@ private FormLayout publicResultsForm() { return layout; } - private FormLayout videoDataForm() { - FormLayout layout = createLayout(); - Component title = createTitle("Config.VideoDataTitle"); - layout.add(title); - layout.setColspan(title, 2); - - TextField videoDataField = new TextField(); - videoDataField.setWidthFull(); - layout.addFormItem(videoDataField, Translator.translate("Config.videoDataURL")); - this.binder.forField(videoDataField) - .withNullRepresentation("") - .bind(Config::getVideoDataURL, Config::setVideoDataURL); - - PasswordField updateKey = new PasswordField(); - updateKey.setWidthFull(); - layout.addFormItem(updateKey, Translator.translate("Config.UpdateKey")); - this.binder.forField(updateKey) - .withNullRepresentation("") - .bind(Config::getVideoDataKey, Config::setVideoDataKey); - - return layout; - } - private Hr separator() { Hr hr = new Hr(); hr.getStyle().set("margin-top", "0.5em"); @@ -581,4 +558,27 @@ private FormLayout tzForm() { return layout; } + private FormLayout videoDataForm() { + FormLayout layout = createLayout(); + Component title = createTitle("Config.VideoDataTitle"); + layout.add(title); + layout.setColspan(title, 2); + + TextField videoDataField = new TextField(); + videoDataField.setWidthFull(); + layout.addFormItem(videoDataField, Translator.translate("Config.videoDataURL")); + this.binder.forField(videoDataField) + .withNullRepresentation("") + .bind(Config::getVideoDataURL, Config::setVideoDataURL); + + PasswordField updateKey = new PasswordField(); + updateKey.setWidthFull(); + layout.addFormItem(updateKey, Translator.translate("Config.UpdateKey")); + this.binder.forField(updateKey) + .withNullRepresentation("") + .bind(Config::getVideoDataKey, Config::setVideoDataKey); + + return layout; + } + } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/DocsContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/DocsContent.java index 50e8e7f7a3..346d0c6f56 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/DocsContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/DocsContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -84,8 +84,7 @@ public class DocsContent extends RegistrationContent implements HasDynamicTitle, private ComboBox platformFilter; /** - * Instantiates a new announcer content. Does nothing. Content is created in - * {@link #setParameter(BeforeEvent, String)} after URL parameters are parsed. + * Instantiates a new announcer content. Does nothing. Content is created in {@link #setParameter(BeforeEvent, String)} after URL parameters are parsed. */ public DocsContent() { } @@ -171,8 +170,7 @@ public ComboBox getCategoryFilter() { } /** - * @see app.owlcms.apputils.queryparameters.DisplayParameters#readParams(com.vaadin.flow.router.Location, - * java.util.Map) + * @see app.owlcms.apputils.queryparameters.DisplayParameters#readParams(com.vaadin.flow.router.Location, java.util.Map) */ @Override @@ -224,7 +222,7 @@ public String getPageTitle() { } public ComboBox getPlatformFilter() { - return platformFilter; + return this.platformFilter; } @Override @@ -296,11 +294,9 @@ public void setHeaderContent() { * Note: because we have the @Route, the parameters are parsed *before* our parent layout is created. * * @param event Vaadin navigation event - * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query - * parameters instead. + * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query parameters instead. * - * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, - * java.lang.String) + * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, java.lang.String) */ @Override public void setParameter(BeforeEvent event, @OptionalParameter String unused) { @@ -441,7 +437,7 @@ protected Button createSessionsButton() { // get current version of athletes. List athletesFindAll = athletesFindAll(true); startingXlsWriter.setSortedAthletes(athletesFindAll); - startingXlsWriter.setPostProcessor(null); + startingXlsWriter.setPostProcessor(null); return startingXlsWriter; }, diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsContent.java index 9c32f02ea5..aef4099ecb 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -863,7 +863,7 @@ private KitElement doElementSchedule(BiConsumer errorProcesso JXLSStartingListDocs xlsWriter = new JXLSStartingListDocs(); xlsWriter.setPostProcessor((w) -> { if (xlsWriter.getFirstMergeLine() != null) { - logger.debug("merging {} {}", xlsWriter.getFirstMergeLine(), xlsWriter.getMergeColumnList()); + logger.debug("merging {} {}", xlsWriter.getFirstMergeLine(), xlsWriter.getMergeColumnList()); // merged columns fixMerges(w, xlsWriter.getFirstMergeLine(), xlsWriter.getMergeColumnList()); fixLastLine(w); @@ -878,27 +878,6 @@ private KitElement doElementSchedule(BiConsumer errorProcesso }); } - private void fixLastLine(Workbook w) { - Sheet sheet = w.getSheetAt(0); - // Define the border style properties - Map properties = new HashMap<>(); - properties.put(CellUtil.BORDER_BOTTOM, BorderStyle.THIN); - properties.put(CellUtil.BOTTOM_BORDER_COLOR, IndexedColors.BLACK.getIndex()); - - // Retrieve the last row - int lastRowNum = sheet.getLastRowNum(); - Row lastRow = sheet.getRow(lastRowNum); - - // Apply the border style to the cells in the last row - for (int i = 0; i < lastRow.getLastCellNum(); i++) { - Cell cell = lastRow.getCell(i); - if (cell == null) { - cell = lastRow.createCell(i); - } - CellUtil.setCellStyleProperties(cell, properties); - } - } - private KitElement doElementStartList(PreCompetitionTemplates templateDefinition, BiConsumer errorProcessor) { return checkKit("startList", templateDefinition, @@ -1066,6 +1045,27 @@ private List filterAthletes(List athletes) { return found; } + private void fixLastLine(Workbook w) { + Sheet sheet = w.getSheetAt(0); + // Define the border style properties + Map properties = new HashMap<>(); + properties.put(CellUtil.BORDER_BOTTOM, BorderStyle.THIN); + properties.put(CellUtil.BOTTOM_BORDER_COLOR, IndexedColors.BLACK.getIndex()); + + // Retrieve the last row + int lastRowNum = sheet.getLastRowNum(); + Row lastRow = sheet.getRow(lastRowNum); + + // Apply the border style to the cells in the last row + for (int i = 0; i < lastRow.getLastCellNum(); i++) { + Cell cell = lastRow.getCell(i); + if (cell == null) { + cell = lastRow.createCell(i); + } + CellUtil.setCellStyleProperties(cell, properties); + } + } + private void fixMerges(Workbook workbook, Integer startRowNum, List columns) { try { Sheet sheet = workbook.getSheetAt(0); diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsGrid.java b/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsGrid.java index 39edc2d404..2b686c1a3d 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsGrid.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/DocumentsGrid.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.preparation; import java.util.Set; @@ -16,14 +22,20 @@ final class DocumentsGrid extends OwlcmsCrudGrid { super(domainType, crudLayout, owlcmsCrudFormFactory, grid); } + public Set getSelectedItems() { + return this.grid.getSelectedItems(); + } + @Override - protected void updateButtons() { + protected void cancelCallback() { + this.getOwlcmsGridLayout().hideForm(); } - public Set getSelectedItems() { - return grid.getSelectedItems(); + @Override + protected void findAllButtonClicked() { + refreshGrid(); } - + @Override protected void initLayoutGrid() { initToolbar(); @@ -42,12 +54,6 @@ protected void initLayoutGrid() { } @Override - protected void findAllButtonClicked() { - refreshGrid(); - } - - @Override - protected void cancelCallback() { - this.getOwlcmsGridLayout().hideForm(); + protected void updateButtons() { } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/EditChampionshipsDialog.java b/owlcms/src/main/java/app/owlcms/nui/preparation/EditChampionshipsDialog.java index 9d866dc138..0897dedcc5 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/EditChampionshipsDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/EditChampionshipsDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -30,19 +30,18 @@ public EditChampionshipsDialog(AgeGroupContent ageGroupContent) { dialog.setHeaderTitle(Translator.translate("EditChampionships.Title")); VerticalLayout content = new VerticalLayout(); -// Paragraph paragraph = new Paragraph(); -// paragraph.getElement().setProperty("innerHTML", Translator.translate("EditChampionships.Intro")); -// paragraph.setWidth("550px"); + // Paragraph paragraph = new Paragraph(); + // paragraph.getElement().setProperty("innerHTML", Translator.translate("EditChampionships.Intro")); + // paragraph.setWidth("550px"); - - updateChampionshipsTable(championshipsTable); - content.add(/* paragraph, */championshipsTable); + updateChampionshipsTable(this.championshipsTable); + content.add(this./* paragraph, */championshipsTable); HorizontalLayout buttons = new HorizontalLayout(); Button closeButton = new Button(Translator.translate("Close"), event -> { dialog.close(); ageGroupContent.getCrud().refreshGrid(); - + }); closeButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY); @@ -69,7 +68,7 @@ public void updateChampionshipsTable(VerticalLayout championshipsTable) { updateChampionshipsTable(championshipsTable); }); delete.addThemeVariants(ButtonVariant.LUMO_ERROR); - HorizontalLayout ctRow = new HorizontalLayout(nameField,update,delete); + HorizontalLayout ctRow = new HorizontalLayout(nameField, update, delete); championshipsTable.add(ctRow); }); HorizontalLayout addRow = new HorizontalLayout(); @@ -78,8 +77,8 @@ public void updateChampionshipsTable(VerticalLayout championshipsTable) { Championship.addChampionship(nameField.getValue(), ChampionshipType.U); updateChampionshipsTable(championshipsTable); }); - addRow.add(nameField,addButton); + addRow.add(nameField, addButton); championshipsTable.add(addRow); - + } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/JsonUploadDialog.java b/owlcms/src/main/java/app/owlcms/nui/preparation/JsonUploadDialog.java index b348bfe7ea..f6f42e9e36 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/JsonUploadDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/JsonUploadDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/LocalOverrideUploadDialog.java b/owlcms/src/main/java/app/owlcms/nui/preparation/LocalOverrideUploadDialog.java index caf1e9154b..02028c5266 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/LocalOverrideUploadDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/LocalOverrideUploadDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/NRegistrationFileUploadDialog.java b/owlcms/src/main/java/app/owlcms/nui/preparation/NRegistrationFileUploadDialog.java index 244d1c14e9..52adf18bcf 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/NRegistrationFileUploadDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/NRegistrationFileUploadDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -56,10 +56,10 @@ public NRegistrationFileUploadDialog(boolean sbdeFormat) { ta.setVisible(false); upload.addSucceededListener(event -> { - processor = this.sbdeFormat // (buffer.getInputStream()) + this.processor = this.sbdeFormat // (buffer.getInputStream()) ? new ORegistrationFileProcessor() : new NRegistrationFileProcessor(); - fileName = event.getFileName(); + this.fileName = event.getFileName(); // try { // buffer.getInputStream().reset(); processInput(buffer.getInputStream(), ta); @@ -102,7 +102,10 @@ public void processInput(InputStream inputStream, TextArea ta) { // process athletes now that groups have been adjusted processAthletes(inputStream, ta, false); this.processor.adjustParticipations(); - return; + } + + private boolean eraseAthletes() { + return this.fileName != null && !this.fileName.contains("_add"); } private int processAthletes(InputStream inputStream, TextArea ta, boolean dryRun) { @@ -112,10 +115,6 @@ private int processAthletes(InputStream inputStream, TextArea ta, boolean dryRun return this.processor.doProcessAthletes(inputStream, dryRun, errorConsumer, displayUpdater, eraseAthletes()); } - private boolean eraseAthletes() { - return fileName != null && !fileName.contains("_add"); - } - private int processGroups(InputStream inputStream, TextArea ta, boolean dryRun) { StringBuffer sb = new StringBuffer(); Consumer errorConsumer = str -> sb.append(str); diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformContent.java index 19b2cc4bb2..6a64d5a2c5 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformEditingFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformEditingFormFactory.java index d00fab5a22..9f22149c46 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformEditingFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/PlatformEditingFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/PreCompetitionTemplates.java b/owlcms/src/main/java/app/owlcms/nui/preparation/PreCompetitionTemplates.java index f8ec571e20..4ecf08b018 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/PreCompetitionTemplates.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/PreCompetitionTemplates.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.preparation; import java.util.function.Consumer; @@ -6,49 +12,48 @@ import app.owlcms.data.competition.Competition; public enum PreCompetitionTemplates { - BY_CATEGORY("/templates/categories", ".xlsx", - () -> Competition.getCurrent().getCategoriesListTemplateFileName(), + BY_CATEGORY("/templates/categories", ".xlsx", + () -> Competition.getCurrent().getCategoriesListTemplateFileName(), (v) -> Competition.getCurrent().setCategoriesListTemplateFileName(v)), - BY_BODYWEIGHT("/templates/bwStart", ".xlsx", - () -> Competition.getCurrent().getBodyWeightListTemplateFileName(), + BY_BODYWEIGHT("/templates/bwStart", ".xlsx", + () -> Competition.getCurrent().getBodyWeightListTemplateFileName(), (v) -> Competition.getCurrent().setBodyWeightListTemplateFileName(v)), - BY_TEAM("/templates/teams", ".xlsx", - () -> Competition.getCurrent().getTeamsListTemplateFileName(), + BY_TEAM("/templates/teams", ".xlsx", + () -> Competition.getCurrent().getTeamsListTemplateFileName(), (v) -> Competition.getCurrent().setTeamsListTemplateFileName(v)), - - START_LIST("/templates/start", ".xlsx", - () -> Competition.getCurrent().getStartListTemplateFileName(), + + START_LIST("/templates/start", ".xlsx", + () -> Competition.getCurrent().getStartListTemplateFileName(), (v) -> Competition.getCurrent().setStartListTemplateFileName(v)), - SCHEDULE("/templates/schedule", ".xlsx", - () -> Competition.getCurrent().getScheduleTemplateFileName(), + SCHEDULE("/templates/schedule", ".xlsx", + () -> Competition.getCurrent().getScheduleTemplateFileName(), (v) -> Competition.getCurrent().setScheduleTemplateFileName(v)), - OFFICIALS("/templates/officials", ".xlsx", - () -> Competition.getCurrent().getOfficialsListTemplateFileName(), + OFFICIALS("/templates/officials", ".xlsx", + () -> Competition.getCurrent().getOfficialsListTemplateFileName(), (v) -> Competition.getCurrent().setOfficialsListTemplateFileName(v)), - CHECKIN("/templates/checkin", ".xlsx", - () -> Competition.getCurrent().getCheckInTemplateFileName(), + CHECKIN("/templates/checkin", ".xlsx", + () -> Competition.getCurrent().getCheckInTemplateFileName(), (v) -> Competition.getCurrent().setCheckInTemplateFileName(v)), - CARDS("/templates/cards", ".xlsx", - () -> Competition.getCurrent().getCardsTemplateFileName(), + CARDS("/templates/cards", ".xlsx", + () -> Competition.getCurrent().getCardsTemplateFileName(), (v) -> Competition.getCurrent().setCardsTemplateFileName(v)), - WEIGHIN("/templates/weighin", ".xlsx", - () -> Competition.getCurrent().getWeighInFormTemplateFileName(), + WEIGHIN("/templates/weighin", ".xlsx", + () -> Competition.getCurrent().getWeighInFormTemplateFileName(), (v) -> Competition.getCurrent().setWeighInFormTemplateFileName(v)), - INTRODUCTION("/templates/introduction", ".xlsx", - () -> Competition.getCurrent().getIntroductionTemplateFileName(), + INTRODUCTION("/templates/introduction", ".xlsx", + () -> Competition.getCurrent().getIntroductionTemplateFileName(), (v) -> Competition.getCurrent().setIntroductionTemplateFileName(v)), EMPTY_PROTOCOL("/templates/emptyProtocol", ".xlsx", - () -> Competition.getCurrent().getEmptyProtocolTemplateFileName(), + () -> Competition.getCurrent().getEmptyProtocolTemplateFileName(), (v) -> Competition.getCurrent().setEmptyProtocolTemplateFileName(v)), - JURY("/templates/jury", ".xlsx", - () -> Competition.getCurrent().getJuryTemplateFileName(), + JURY("/templates/jury", ".xlsx", + () -> Competition.getCurrent().getJuryTemplateFileName(), (v) -> Competition.getCurrent().setJuryTemplateFileName(v)), PRE_WEIGHIN("", ".zip", null, null), - POST_WEIGHIN("", ".zip", null, null), + POST_WEIGHIN("", ".zip", null, null), ; - String folder; String extension; diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/PreparationNavigationContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/PreparationNavigationContent.java index 8a95e51902..95facfb1e5 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/PreparationNavigationContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/PreparationNavigationContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -82,10 +82,11 @@ public PreparationNavigationContent() { Notification notification = new Notification(Translator.translate("Processing")); notification.setPosition(Position.TOP_END); notification.addThemeVariants(NotificationVariant.LUMO_WARNING); - emptyRegistrationWriter.setDoneCallback((s) -> this.getUI().get().access(() -> { + emptyRegistrationWriter.setDoneCallback((s) -> this.getUI().get().access(() -> { notification.close(); })); - Div downloadDiv = DownloadButtonFactory.createDynamicJXLSDownloadButton("Registration", Translator.translate("DownloadRegistrationTemplate"), emptyRegistrationWriter, + Div downloadDiv = DownloadButtonFactory.createDynamicJXLSDownloadButton("Registration", Translator.translate("DownloadRegistrationTemplate"), + emptyRegistrationWriter, notification); downloadDiv.setWidthFull(); @@ -98,10 +99,10 @@ public PreparationNavigationContent() { Notification notification1 = new Notification(Translator.translate("LongProcessing")); notification1.setPosition(Position.TOP_END); notification1.addThemeVariants(NotificationVariant.LUMO_WARNING); - registrationWriter.setDoneCallback((s) -> this.getUI().get().access(() -> { + registrationWriter.setDoneCallback((s) -> this.getUI().get().access(() -> { notification1.close(); })); - + Div sbdeDiv = DownloadButtonFactory.createDynamicJXLSDownloadButton("SBDE", Translator.translate("AdvancedPreparation.Export"), registrationWriter, notification1); sbdeDiv.setWidthFull(); @@ -117,10 +118,10 @@ public PreparationNavigationContent() { Button uploadJson = new Button(Translator.translate("ExportDatabase.UploadJson"), new Icon(VaadinIcon.UPLOAD_ALT), buttonClickEvent -> new JsonUploadDialog(UI.getCurrent()).open()); - + Notification notification2 = new Notification(Translator.translate("LongProcessing")); notification2.setPosition(Position.TOP_END); - //notification2.addThemeVariants(NotificationVariant.LUMO_WARNING); + // notification2.addThemeVariants(NotificationVariant.LUMO_WARNING); Div exportJsonDiv = DownloadButtonFactory.createDynamicJsonDownloadButton("owlcmsDatabase", Translator.translate("ExportDatabase.DownloadJson"), notification2); Optional exportJsonButton = exportJsonDiv.getChildren().findFirst(); diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/RecordConfigEditingFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/RecordConfigEditingFormFactory.java index 1666f282fa..8684724c64 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/RecordConfigEditingFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/RecordConfigEditingFormFactory.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.preparation; import java.io.IOException; @@ -187,7 +193,7 @@ private FormLayout exportAllForm() { Div allRecords = new Div(); allRecords.add(dd.createImmediateDownloadButton()); allRecords.setWidthFull(); - + var recordsWriter1 = new JXLSExportRecords(UI.getCurrent(), true, true); JXLSDownloader dd1 = new JXLSDownloader( () -> { diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/RecordsContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/RecordsContent.java index ebb1501558..88fce06019 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/RecordsContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/RecordsContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/RegistrationContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/RegistrationContent.java index b3684bf7e2..7158cd9a97 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/RegistrationContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/RegistrationContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -166,9 +166,9 @@ public void clearFilters() { public FlexLayout createMenuArea() { createTopBarGroupSelect(); -// Button bwButton = createBWButton(); -// Button categoriesListButton = createCategoriesListButton(); -// Button teamsListButton = createTeamsListButton(); + // Button bwButton = createBWButton(); + // Button categoriesListButton = createCategoriesListButton(); + // Button teamsListButton = createTeamsListButton(); Button drawLots = new Button(Translator.translate("DrawLotNumbers"), (e) -> { drawLots(); @@ -208,13 +208,13 @@ public FlexLayout createMenuArea() { hr.getStyle().set("margin", "0"); hr.getStyle().set("padding", "0"); FlexLayout buttons = new FlexLayout( -// new NativeLabel(Translator.translate("Preparation")), + // new NativeLabel(Translator.translate("Preparation")), drawLots, deleteAthletes, clearLifts, resetCats -// , hr, -// new NativeLabel(Translator.translate("Entries")), -// bwButton, categoriesListButton, teamsListButton - ); + // , hr, + // new NativeLabel(Translator.translate("Entries")), + // bwButton, categoriesListButton, teamsListButton + ); buttons.getStyle().set("flex-wrap", "wrap"); buttons.getStyle().set("gap", "1ex"); buttons.getStyle().set("margin-left", "3em"); @@ -428,11 +428,9 @@ public void setHeaderContent() { * Note: because we have the @Route, the parameters are parsed *before* our parent layout is created. * * @param event Vaadin navigation event - * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query - * parameters instead. + * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query parameters instead. * - * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, - * java.lang.String) + * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, java.lang.String) */ @Override public void setParameter(BeforeEvent event, @OptionalParameter String parameter) { @@ -576,7 +574,7 @@ protected OwlcmsCrudGrid createCrudGrid(OwlcmsCrudFormFactory grid.addColumn("category").setHeader(Translator.translate("Category")).setAutoWidth(true) .setTextAlign(ColumnTextAlign.CENTER) .setRenderer( - new TextRenderer(a -> a.getCategory() != null ? a.getCategory().toString() : "-")); + new TextRenderer<>(a -> a.getCategory() != null ? a.getCategory().toString() : "-")); grid.addColumn(new NumberRenderer<>(Athlete::getBodyWeight, "%.2f", this.getLocale())) .setSortProperty("bodyWeight") .setHeader(Translator.translate("BodyWeight")).setAutoWidth(true).setTextAlign(ColumnTextAlign.CENTER); @@ -593,8 +591,8 @@ protected OwlcmsCrudGrid createCrudGrid(OwlcmsCrudFormFactory List> sortOrder = new ArrayList<>(); // groupWeighinTimeComparator implements traditional platform name comparisons e.g. USAW. - groupCol.setComparator((a,b) -> Group.groupWeighinTimeComparator.compare(a.getGroup(), b.getGroup())); - sortOrder.add(new GridSortOrder(groupCol, SortDirection.ASCENDING)); + groupCol.setComparator((a, b) -> Group.groupWeighinTimeComparator.compare(a.getGroup(), b.getGroup())); + sortOrder.add(new GridSortOrder<>(groupCol, SortDirection.ASCENDING)); grid.sort(sortOrder); OwlcmsCrudGrid crudGrid = new OwlcmsCrudGrid<>(Athlete.class, new OwlcmsGridLayout(Athlete.class) { @@ -620,10 +618,10 @@ public void hideForm() { * @return the form factory that will create the actual form on demand */ protected OwlcmsCrudFormFactory createFormFactory() { - athleteEditingFormFactory = new NAthleteRegistrationFormFactory(Athlete.class, + this.athleteEditingFormFactory = new NAthleteRegistrationFormFactory(Athlete.class, getGroup(), null); // createFormLayout(athleteEditingFormFactory); - return athleteEditingFormFactory; + return this.athleteEditingFormFactory; } protected Button createTeamsListButton() { @@ -816,74 +814,6 @@ protected List participationFindAll() { return found; } - private List filterAthletes(List athletes) { - Category catFilterValue = getCategoryValue(); - Group group2 = getGroup() == null - ? null - : (getGroup().getName() == "*" ? null : getGroup()); - Stream stream = athletes.stream() - .filter(a -> { - Platform platformFilterValue = getPlatform(); - if (platformFilterValue == null) { - return true; - } - Platform athletePlaform = a.getGroup() != null - ? (a.getGroup().getPlatform() != null ? a.getGroup().getPlatform() : null) - : null; - return platformFilterValue.equals(athletePlaform); - }) - .filter(a -> { - return group2 != null ? group2.equals(a.getGroup()) - : true; - }) - .filter(a -> { - String fLastName = getLastName(); - if (fLastName == null) { - return true; - } - String aLastName = a.getLastName(); - if (aLastName == null || aLastName.isBlank()) - return false; - aLastName = aLastName.toLowerCase(); - fLastName = fLastName.toLowerCase(); - return aLastName.startsWith(fLastName); - }) - .filter(a -> { - if (getWeighedIn() == null) { - return true; - } - - if (getWeighedIn()) { - return a.getBodyWeight() != null && a.getBodyWeight() > 0; - } - - return a.getBodyWeight() == null || a.getBodyWeight() == 0; - }) - // .filter(a -> a.getCategory() != null) - .filter(a -> { - Gender genderFilterValue = getGender(); - Gender athleteGender = a.getGender(); - boolean catOk = (catFilterValue == null - || (a.getCategory() != null - && catFilterValue.toString().equals(a.getCategory().toString()))) - && (genderFilterValue == null || genderFilterValue == athleteGender); - return catOk; - }) - .filter(a -> getTeam() != null ? getTeam().contentEquals(a.getTeam()) - : true) - .map(a -> { - if (a.getTeam() == null) { - a.setTeam(""); - } - return a; - }); - - List found = stream.sorted( - groupCategoryComparator()) - .collect(Collectors.toList()); - return found; - } - protected void setAgeGroup(AgeGroup value) { this.ageGroup = value; @@ -953,6 +883,13 @@ protected void updateURLLocations() { gender); } + @SuppressWarnings("unused") + private String athleteLog(Athlete a1) { + Participation mainRankings1 = a1.getMainRankings() != null ? a1.getMainRankings() : null; + Category category1 = mainRankings1 != null ? mainRankings1.getCategory() : null; + return "[" + a1.getShortName() + " " + a1.getGroup() + " " + category1 + " " + a1.getEntryTotal() + "]"; + } + private void clearLifts() { JPAService.runInTransaction(em -> { List athletes = athletesFindAll(false); @@ -992,10 +929,10 @@ private void doSwitchGroup(Group newCurrentGroup) { logger.debug("newCurrentGroup.getName() {}", newCurrentGroup.getName()); if (newCurrentGroup != null && newCurrentGroup.getName() == "*") { setGroup(null); - athleteEditingFormFactory.setCurrentGroup(null); + this.athleteEditingFormFactory.setCurrentGroup(null); } else { setGroup(newCurrentGroup); - athleteEditingFormFactory.setCurrentGroup(newCurrentGroup); + this.athleteEditingFormFactory.setCurrentGroup(newCurrentGroup); } // getRouterLayout().updateHeader(true); getGroupFilter().setValue(newCurrentGroup); @@ -1014,6 +951,75 @@ private void drawLots() { refreshCrudGrid(); } + private List filterAthletes(List athletes) { + Category catFilterValue = getCategoryValue(); + Group group2 = getGroup() == null + ? null + : (getGroup().getName() == "*" ? null : getGroup()); + Stream stream = athletes.stream() + .filter(a -> { + Platform platformFilterValue = getPlatform(); + if (platformFilterValue == null) { + return true; + } + Platform athletePlaform = a.getGroup() != null + ? (a.getGroup().getPlatform() != null ? a.getGroup().getPlatform() : null) + : null; + return platformFilterValue.equals(athletePlaform); + }) + .filter(a -> { + return group2 != null ? group2.equals(a.getGroup()) + : true; + }) + .filter(a -> { + String fLastName = getLastName(); + if (fLastName == null) { + return true; + } + String aLastName = a.getLastName(); + if (aLastName == null || aLastName.isBlank()) { + return false; + } + aLastName = aLastName.toLowerCase(); + fLastName = fLastName.toLowerCase(); + return aLastName.startsWith(fLastName); + }) + .filter(a -> { + if (getWeighedIn() == null) { + return true; + } + + if (getWeighedIn()) { + return a.getBodyWeight() != null && a.getBodyWeight() > 0; + } + + return a.getBodyWeight() == null || a.getBodyWeight() == 0; + }) + // .filter(a -> a.getCategory() != null) + .filter(a -> { + Gender genderFilterValue = getGender(); + Gender athleteGender = a.getGender(); + boolean catOk = (catFilterValue == null + || (a.getCategory() != null + && catFilterValue.toString().equals(a.getCategory().toString()))) + && (genderFilterValue == null || genderFilterValue == athleteGender); + return catOk; + }) + .filter(a -> getTeam() != null ? getTeam().contentEquals(a.getTeam()) + : true) + .map(a -> { + if (a.getTeam() == null) { + a.setTeam(""); + } + return a; + }); + + List found = stream.sorted( + groupCategoryComparator()) + .collect(Collectors.toList()); + return found; + } + private Comparator groupCategoryComparator() { Comparator groupCategoryComparator = (a1, a2) -> { int compare; @@ -1051,13 +1057,6 @@ private void logComparison(int compare, Athlete a1, Athlete a2, String string) { } } - @SuppressWarnings("unused") - private String athleteLog(Athlete a1) { - Participation mainRankings1 = a1.getMainRankings() != null ? a1.getMainRankings() : null; - Category category1 = mainRankings1 != null ? mainRankings1.getCategory() : null; - return "[" + a1.getShortName() + " " + a1.getGroup() + " " + category1 + " " + a1.getEntryTotal() + "]"; - } - private void resetCategories() { AthleteRepository.resetParticipations(); this.setChampionshipItems(Championship.findAllUsed(true)); diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/SessionContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/SessionContent.java index a6afb80e7a..a318b8209a 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/SessionContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/SessionContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -278,7 +278,7 @@ private GridCrud createGrid(OwlcmsCrudFormFactory crudFormFactory) }; Button editDetails = new Button(Translator.translate("Sessions.EditDetails"), clickListener); editDetails.addThemeVariants(ButtonVariant.LUMO_SMALL); - + Button technical = openInNewTab(RegistrationContent.class, translation, p != null ? p.getName() : "?"); // prevent grid row selection from triggering technical.getElement().addEventListener("click", ignore -> { diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/SessionEditingFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/SessionEditingFormFactory.java index 5c996e3e18..ab6f26c94c 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/SessionEditingFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/SessionEditingFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/SessionGrid.java b/owlcms/src/main/java/app/owlcms/nui/preparation/SessionGrid.java index 6c812be2e5..001c366e31 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/SessionGrid.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/SessionGrid.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.preparation; import java.util.Set; @@ -20,14 +26,20 @@ final class SessionGrid extends OwlcmsCrudGrid { super(domainType, crudLayout, owlcmsCrudFormFactory, grid); } + public Set getSelectedItems() { + return this.grid.getSelectedItems(); + } + @Override - protected void updateButtons() { + protected void cancelCallback() { + this.getOwlcmsGridLayout().hideForm(); } - public Set getSelectedItems() { - return grid.getSelectedItems(); + @Override + protected void findAllButtonClicked() { + refreshGrid(); } - + @Override protected void initLayoutGrid() { initToolbar(); @@ -39,10 +51,7 @@ protected void initLayoutGrid() { // grid.addSelectionListener(e -> gridSelectionChanged()); this.grid.addItemClickListener((e) -> { Column c = e.getColumn(); - if (c == null) { - return; - } - if (!this.isClickable()) { + if ((c == null) || !this.isClickable()) { return; } long delta = System.currentTimeMillis() - this.clicked; @@ -58,26 +67,19 @@ protected void initLayoutGrid() { this.crudLayout.setMainComponent(this.grid); } - private void gridSelectionChanged(Group item) { - updateButtons(); - Group domainObject = item; - - if (domainObject != null) { - updateButtonClicked(item); - } else { - crudLayout.hideForm(); - } + @Override + protected void updateButtons() { } void updateButtonClicked(Group domainObject) { - showForm(CrudOperation.UPDATE, domainObject, false, savedMessage, event -> { + showForm(CrudOperation.UPDATE, domainObject, false, this.savedMessage, event -> { try { - Group updatedObject = updateOperation.perform(domainObject); - grid.asSingleSelect().clear(); + Group updatedObject = this.updateOperation.perform(domainObject); + this.grid.asSingleSelect().clear(); refreshGrid(); - grid.asSingleSelect().setValue(updatedObject); - grid.deselect(updatedObject); - showNotification(savedMessage); + this.grid.asSingleSelect().setValue(updatedObject); + this.grid.deselect(updatedObject); + showNotification(this.savedMessage); } catch (IllegalArgumentException ignore) { } catch (CrudOperationException e1) { refreshGrid(); @@ -90,13 +92,14 @@ void updateButtonClicked(Group domainObject) { }); } - @Override - protected void findAllButtonClicked() { - refreshGrid(); - } + private void gridSelectionChanged(Group item) { + updateButtons(); + Group domainObject = item; - @Override - protected void cancelCallback() { - this.getOwlcmsGridLayout().hideForm(); + if (domainObject != null) { + updateButtonClicked(item); + } else { + this.crudLayout.hideForm(); + } } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/TeamItemSelectionFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/TeamItemSelectionFormFactory.java index 662addb73a..39600382ad 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/TeamItemSelectionFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/TeamItemSelectionFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/TeamSelectionContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/TeamSelectionContent.java index 20059e0b83..5690339130 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/TeamSelectionContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/TeamSelectionContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -119,8 +119,7 @@ public class TeamSelectionContent extends BaseContent private JXLSCompetitionBook xlsWriter; /** - * Instantiates a new announcer content. Does nothing. Content is created in - * {@link #setParameter(BeforeEvent, String)} after URL parameters are parsed. + * Instantiates a new announcer content. Does nothing. Content is created in {@link #setParameter(BeforeEvent, String)} after URL parameters are parsed. */ public TeamSelectionContent() { OwlcmsFactory.waitDBInitialized(); @@ -156,15 +155,15 @@ public FlexLayout createMenuArea() { this.topBar.getStyle().set("flex", "100 1"); this.topBar.removeAll(); - //this.topBar.add(this.topBarAgeDivisionSelect, this.topBarAgeGroupPrefixSelect); + // this.topBar.add(this.topBarAgeDivisionSelect, this.topBarAgeGroupPrefixSelect); this.topBar.setJustifyContentMode(FlexComponent.JustifyContentMode.START); this.topBar.setAlignItems(FlexComponent.Alignment.CENTER); return this.topBar; } /** - * Get the content of the crudGrid. Invoked by refreshGrid. Not currently used because we are using instead a - * TreeGrid and a LazyCrudListener() + * Get the content of the crudGrid. Invoked by refreshGrid. Not currently used because we are using instead a TreeGrid and a + * LazyCrudListener() * * @see TreeDataProvider * @see org.vaadin.crudui.crud.CrudListener#findAll() @@ -246,11 +245,9 @@ public void setAgeGroupPrefix(String ageGroupPrefix) { * Note: because we have the @Route, the parameters are parsed *before* our parent layout is created. * * @param event Vaadin navigation event - * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query - * parameters instead. + * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query parameters instead. * - * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, - * java.lang.String) + * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, java.lang.String) */ @Override public void setParameter(BeforeEvent event, @OptionalParameter String parameter) { @@ -334,7 +331,6 @@ protected OwlcmsCrudGrid createCrudGrid(OwlcmsCrudFormFactory warningRenderer = new ComponentRenderer<>(p -> { if (p.isWarning()) { NativeLabel label = new NativeLabel("\u26a0"); diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/TemplateSelectionFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/preparation/TemplateSelectionFormFactory.java index 90c6305df7..aa89325324 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/TemplateSelectionFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/TemplateSelectionFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -45,50 +45,17 @@ public class TemplateSelectionFormFactory extends VerticalLayout { TemplateSelectionFormFactory() { } - private FormLayout createLayout() { - FormLayout layout = new FormLayout(); - // layout.setWidth("1024px"); - layout.setResponsiveSteps(new ResponsiveStep("0", 1, LabelsPosition.TOP), - new ResponsiveStep("800px", 2, LabelsPosition.TOP)); - return layout; - } - - private Component createTitle(String string) { - H4 title = new H4(Translator.translate(string)); - title.getStyle().set("margin-top", "0"); - title.getStyle().set("margin-bottom", "0"); - return title; - } - - public FormLayout preWeighInTemplateSelectionForm(Dialog dialog) { - FormLayout layout = createSetLayoutHeader(PreCompetitionTemplates.PRE_WEIGHIN); - addTemplateSelection(layout, PreCompetitionTemplates.CARDS); - addTemplateSelection(layout, PreCompetitionTemplates.WEIGHIN); - return layout; - } - - private FormLayout createLayoutHeader(PreCompetitionTemplates templateDefinition) { - FormLayout layout = createLayout(); - Component title = createTitle(templateDefinition.name()); - layout.add(title); - layout.setColspan(title, 2); - return layout; - } - - private FormLayout createSetLayoutHeader(PreCompetitionTemplates templateDefinition) { + public FormLayout competitionTemplateSelectionForm() { FormLayout layout = createLayout(); - Component title = createTitle(templateDefinition.name()); + Component title = createTitle(DOCUMENTS_TEMPLATE_SELECTION); layout.add(title); layout.setColspan(title, 2); - Div div = new Div(Translator.translate(DOCUMENTS_IGNORE_NO_TEMPLATE)); - layout.add(div); - layout.setColspan(div, 2); - return layout; - } - - public FormLayout singleTemplateSelection(PreCompetitionTemplates templateDefinition) { - FormLayout layout = createLayoutHeader(templateDefinition); - addTemplateSelection(layout, templateDefinition); + + addTemplateSelection(layout, PreCompetitionTemplates.START_LIST); + addTemplateSelection(layout, PreCompetitionTemplates.SCHEDULE); + addTemplateSelection(layout, PreCompetitionTemplates.OFFICIALS); + addTemplateSelection(layout, PreCompetitionTemplates.CHECKIN); + return layout; } @@ -100,20 +67,13 @@ public FormLayout postWeighInTemplateSelectionForm(Dialog dialog) { return layout; } - public FormLayout competitionTemplateSelectionForm() { - FormLayout layout = createLayout(); - Component title = createTitle(DOCUMENTS_TEMPLATE_SELECTION); - layout.add(title); - layout.setColspan(title, 2); - - addTemplateSelection(layout, PreCompetitionTemplates.START_LIST); - addTemplateSelection(layout, PreCompetitionTemplates.SCHEDULE); - addTemplateSelection(layout, PreCompetitionTemplates.OFFICIALS); - addTemplateSelection(layout, PreCompetitionTemplates.CHECKIN); - + public FormLayout preWeighInTemplateSelectionForm(Dialog dialog) { + FormLayout layout = createSetLayoutHeader(PreCompetitionTemplates.PRE_WEIGHIN); + addTemplateSelection(layout, PreCompetitionTemplates.CARDS); + addTemplateSelection(layout, PreCompetitionTemplates.WEIGHIN); return layout; } - + public FormLayout registrationTemplateSelectionForm() { FormLayout layout = createLayout(); Component title = createTitle(DOCUMENTS_TEMPLATE_SELECTION); @@ -127,6 +87,12 @@ public FormLayout registrationTemplateSelectionForm() { return layout; } + public FormLayout singleTemplateSelection(PreCompetitionTemplates templateDefinition) { + FormLayout layout = createLayoutHeader(templateDefinition); + addTemplateSelection(layout, templateDefinition); + return layout; + } + private void addTemplateSelection(FormLayout layout, PreCompetitionTemplates template) { List prioritizedList = computeResourceList(template.folder, (f) -> f.endsWith(template.extension)); ComboBox templateSelect = createTemplateSelect(layout, template.name(), prioritizedList, template.templateFileNameSupplier.get()); @@ -148,7 +114,7 @@ private void addTemplateSelection(FormLayout layout, PreCompetitionTemplates tem CompetitionRepository.save(current); current = Competition.getCurrent(); } catch (Throwable e1) { - LoggerUtils.logError(logger, e1); + LoggerUtils.logError(this.logger, e1); } }); } @@ -164,6 +130,33 @@ private List computeResourceList(String resourceDirectoryLocation, Pre return prioritizedList; } + private FormLayout createLayout() { + FormLayout layout = new FormLayout(); + // layout.setWidth("1024px"); + layout.setResponsiveSteps(new ResponsiveStep("0", 1, LabelsPosition.TOP), + new ResponsiveStep("800px", 2, LabelsPosition.TOP)); + return layout; + } + + private FormLayout createLayoutHeader(PreCompetitionTemplates templateDefinition) { + FormLayout layout = createLayout(); + Component title = createTitle(templateDefinition.name()); + layout.add(title); + layout.setColspan(title, 2); + return layout; + } + + private FormLayout createSetLayoutHeader(PreCompetitionTemplates templateDefinition) { + FormLayout layout = createLayout(); + Component title = createTitle(templateDefinition.name()); + layout.add(title); + layout.setColspan(title, 2); + Div div = new Div(Translator.translate(DOCUMENTS_IGNORE_NO_TEMPLATE)); + layout.add(div); + layout.setColspan(div, 2); + return layout; + } + private ComboBox createTemplateSelect(FormLayout layout, String labelKey, List prioritizedList, String string) { ComboBox templateSelect = new ComboBox<>(); templateSelect.setPlaceholder(Translator.translate("AvailableTemplates")); @@ -179,6 +172,13 @@ private ComboBox createTemplateSelect(FormLayout layout, String labelK return templateSelect; } + private Component createTitle(String string) { + H4 title = new H4(Translator.translate(string)); + title.getStyle().set("margin-top", "0"); + title.getStyle().set("margin-bottom", "0"); + return title; + } + private Resource searchMatch(List resourceList, String curTemplateName) { Resource found = null; for (Resource curResource : resourceList) { diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/ZipFileField.java b/owlcms/src/main/java/app/owlcms/nui/preparation/ZipFileField.java index 34c4d69508..c6661c948d 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/ZipFileField.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/ZipFileField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/referee/RefContent.java b/owlcms/src/main/java/app/owlcms/nui/referee/RefContent.java index 8824dc2d18..5521aa77a2 100644 --- a/owlcms/src/main/java/app/owlcms/nui/referee/RefContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/referee/RefContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -138,11 +138,9 @@ public String getPageTitle() { * Note: because we have the @Route, the parameters are parsed *before* our parent layout is created. * * @param event Vaadin navigation event - * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query - * parameters instead. + * @param parameter null in this case -- we don't want a vaadin "/" parameter. This allows us to add query parameters instead. * - * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, - * java.lang.String) + * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, java.lang.String) */ @Override public void setParameter(BeforeEvent event, @OptionalParameter String parameter) { @@ -180,8 +178,8 @@ public void slaveDecision(UIEvent.Decision e) { } /** - * This must come from a timer on FieldOfPlay, because if we are using mobile devices there will not be a master - * decision reset coming from the keypad-hosting device + * This must come from a timer on FieldOfPlay, because if we are using mobile devices there will not be a master decision reset coming from the + * keypad-hosting device * * @param e */ diff --git a/owlcms/src/main/java/app/owlcms/nui/results/IFilterCascade.java b/owlcms/src/main/java/app/owlcms/nui/results/IFilterCascade.java index 3178965184..efc666ae69 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/IFilterCascade.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/IFilterCascade.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.results; import java.util.ArrayList; @@ -26,6 +32,14 @@ public interface IFilterCascade { final static Logger logger = (Logger) LoggerFactory.getLogger(IFilterCascade.class); + + default public void clearFilters() { + this.getAgeGroupFilter().clear(); + this.getChampionshipFilter().clear(); + this.getCategoryFilter().clear(); + this.getGenderFilter().clear(); + } + default public void defineFilterCascade(GridCrud crud) { if (this.getChampionshipFilter() == null) { @@ -43,7 +57,7 @@ default public void defineFilterCascade(GridCrud crud) { this.setAgeGroupFilter(new ComboBox<>()); } this.getAgeGroupFilter().setPlaceholder(Translator.translate("AgeGroup")); - //this.getAgeGroupFilter().setEnabled(false); + // this.getAgeGroupFilter().setEnabled(false); this.getAgeGroupFilter().setVisible(false); this.getAgeGroupFilter().setClearButtonVisible(true); this.getAgeGroupFilter().setValue(null); @@ -87,13 +101,6 @@ default public void defineFilterCascade(GridCrud crud) { } } - default public void clearFilters() { - this.getAgeGroupFilter().clear(); - this.getChampionshipFilter().clear(); - this.getCategoryFilter().clear(); - this.getGenderFilter().clear(); - } - default public void defineSelectionListeners() { Championship urlAD = getChampionship(); String urlAG = getAgeGroupPrefix(); @@ -205,9 +212,9 @@ default public void setChampionshipSelectionListener() { this.setChampionshipAgeGroupPrefixes(AgeGroupRepository.findActiveAndUsedAgeGroupNames(championshipValue)); List championshipAgeGroupPrefixes = this.getChampionshipAgeGroupPrefixes(); this.getAgeGroupFilter().setItems(championshipAgeGroupPrefixes); - + boolean notEmpty = championshipAgeGroupPrefixes.size() > 0; - //this.getAgeGroupFilter().setEnabled(notEmpty); + // this.getAgeGroupFilter().setEnabled(notEmpty); this.getAgeGroupFilter().setVisible(championshipAgeGroupPrefixes.size() > 1); String first = (notEmpty && championshipValue.getType() == ChampionshipType.IWF) || (championshipAgeGroupPrefixes.size() == 1) diff --git a/owlcms/src/main/java/app/owlcms/nui/results/PackageContent.java b/owlcms/src/main/java/app/owlcms/nui/results/PackageContent.java index aad936cc80..5f4d506375 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/PackageContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/PackageContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -486,8 +486,8 @@ protected Component createReset() { @Override protected void defineFilters(GridCrud crud) { - //logger.debug("defineFilters"); - + // logger.debug("defineFilters"); + defineFilterCascade(crud); this.includeUnfinishedCategories = new Checkbox(Translator.translate("Video.includeNotCompleted")); getCrudLayout(crud).addFilterComponent(this.includeUnfinishedCategories); diff --git a/owlcms/src/main/java/app/owlcms/nui/results/ResultsNavigationContent.java b/owlcms/src/main/java/app/owlcms/nui/results/ResultsNavigationContent.java index ace6e6d95a..8635bdf7e4 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/ResultsNavigationContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/ResultsNavigationContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -90,9 +90,9 @@ public ResultsNavigationContent() { // template name used only to generate the results file name. Localized template determined by // JXLSTimingStats Competition::getComputedMedalScheduleTemplateFileName, - Competition::setMedalScheduleTemplateFileName, + Competition::setMedalScheduleTemplateFileName, Translator.translate("Results.MedalSchedule"), - Translator.translate("Download")); + Translator.translate("Download")); Div medalScheduleDiv = new Div(); medalScheduleDiv.add(dd2.createDownloadButton()); Optional medalScheduleButton = medalScheduleDiv.getChildren().findFirst(); @@ -120,11 +120,11 @@ public ResultsNavigationContent() { doGroup(Translator.translate("ForEachCompetitionGroup"), grid1, this); doGroup(Translator.translate("TeamResults.Title"), grid2, this); doGroup(Translator.translate("Results.EndOfCompetition"), grid3, this); - + Button importSessions = openInNewTabNoParam(SessionImportContent.class, Translator.translate("ImportSessions.PageTitle")); doHiddenGroup(Translator.translate("ImportSessions.PageTitle"), - new Div(Translator.translate("ImportSessions.Explanation")), - HomeNavigationContent.navigationGrid(importSessions), this); + new Div(Translator.translate("ImportSessions.Explanation")), + HomeNavigationContent.navigationGrid(importSessions), this); DebugUtils.gc(); } diff --git a/owlcms/src/main/java/app/owlcms/nui/results/SessionImportContent.java b/owlcms/src/main/java/app/owlcms/nui/results/SessionImportContent.java index 23e2352ddc..d6f75dcc06 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/SessionImportContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/SessionImportContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -85,21 +85,21 @@ public FlexLayout createMenuArea() { this.topBar.getStyle().set("flex", "100 1"); this.topBar.setJustifyContentMode(FlexComponent.JustifyContentMode.START); this.topBar.setAlignItems(FlexComponent.Alignment.CENTER); - + Button uploadCustom = new Button(Translator.translate("ImportSessions.UploadDatabaseExport"), new Icon(VaadinIcon.UPLOAD_ALT), buttonClickEvent -> { - SessionResultsUploadDialog sessionUploadDialog = new SessionResultsUploadDialog(); - sessionUploadDialog.setCallback((mb) -> { - try { - AthleteSessionDataReader.importAthletes(mb.getInputStream(),getSortedSelection()); - } catch (IOException e) { - LoggerUtils.logError(logger, e); - } - }); - sessionUploadDialog.open(); + SessionResultsUploadDialog sessionUploadDialog = new SessionResultsUploadDialog(); + sessionUploadDialog.setCallback((mb) -> { + try { + AthleteSessionDataReader.importAthletes(mb.getInputStream(), getSortedSelection()); + } catch (IOException e) { + LoggerUtils.logError(logger, e); + } + }); + sessionUploadDialog.open(); }); - topBar.add(uploadCustom); + this.topBar.add(uploadCustom); return this.topBar; } @@ -108,7 +108,6 @@ public FlexLayout createMenuArea() { public void delete(Group domainObjectToDelete) { } - @Override public Collection findAll() { return GroupRepository.findAll().stream().sorted(Group::compareToWeighIn).collect(Collectors.toList()); @@ -174,7 +173,7 @@ private GridCrud createGrid(OwlcmsCrudFormFactory crudFormFactory) grid.addColumn(LocalDateTimeField.getRenderer(Group::getCompetitionTime, this.getLocale())) .setHeader(Translator.translate("StartTime")); grid.addColumn(Group::getPlatform).setHeader(Translator.translate("Platform")).setTextAlign(ColumnTextAlign.CENTER); - + for (Column c : grid.getColumns()) { c.setResizable(true); } diff --git a/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsContent.java b/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsContent.java index 277741b66a..cdacfcfe0c 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -464,7 +464,7 @@ protected void createTopBarGroupSelect() { groups.sort(Group.groupSelectionComparator.reversed()); OwlcmsSession.withFop(fop -> { - //logger.debug("top bar setting group to {} {}", this.getCurrentGroup(), LoggerUtils.whereFrom()); + // logger.debug("top bar setting group to {} {}", this.getCurrentGroup(), LoggerUtils.whereFrom()); getGroupFilter().setValue(this.getCurrentGroup()); // switching to group "*" is understood to mean all groups this.topBarMenu = new GroupSelectionMenu(groups, this.getCurrentGroup(), @@ -483,13 +483,13 @@ protected void createTopBarGroupSelect() { */ @Override protected void defineFilters(GridCrud crud) { - //logger.debug("defineFilters {} - {}\n{}", getGroup(), currentGroup,LoggerUtils.stackTrace()); + // logger.debug("defineFilters {} - {}\n{}", getGroup(), currentGroup,LoggerUtils.stackTrace()); getGroupFilter().setPlaceholder(Translator.translate("Group")); List groups = GroupRepository.findAll(); groups.sort(new NaturalOrderComparator<>()); getGroupFilter().setItems(groups); - getGroupFilter().setValue(currentGroup); + getGroupFilter().setValue(this.currentGroup); createTopBarGroupSelect(); getGroupFilter().setItemLabelGenerator(Group::getName); // hide because the top bar has it @@ -661,6 +661,10 @@ private CrudLayout getCrudLayout(GridCrud crud) { return crud.getCrudLayout(); } + private Group getCurrentGroup() { + return this.currentGroup; + } + private ComboBox getRankingSelector() { return this.rankingSelector; } @@ -681,17 +685,13 @@ private void resetGrid() { init(); } - private void setScoringSystem(Ranking value) { - this.scoringSystem = value; - } - - private Group getCurrentGroup() { - return currentGroup; - } - private void setCurrentGroup(Group currentGroup) { - //logger.debug("setCurrentGroup {} {}",currentGroup, LoggerUtils.whereFrom()); + // logger.debug("setCurrentGroup {} {}",currentGroup, LoggerUtils.whereFrom()); this.currentGroup = currentGroup; } + private void setScoringSystem(Ranking value) { + this.scoringSystem = value; + } + } diff --git a/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsUploadDialog.java b/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsUploadDialog.java index 75d602ea87..6a308fa602 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsUploadDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/SessionResultsUploadDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/results/SessionSelectionGrid.java b/owlcms/src/main/java/app/owlcms/nui/results/SessionSelectionGrid.java index 7c066a0033..3916883b53 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/SessionSelectionGrid.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/SessionSelectionGrid.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.results; import java.util.Set; @@ -16,14 +22,20 @@ final class SessionSelectionGrid extends OwlcmsCrudGrid { super(domainType, crudLayout, owlcmsCrudFormFactory, grid); } + public Set getSelectedItems() { + return this.grid.getSelectedItems(); + } + @Override - protected void updateButtons() { + protected void cancelCallback() { + this.getOwlcmsGridLayout().hideForm(); } - public Set getSelectedItems() { - return grid.getSelectedItems(); + @Override + protected void findAllButtonClicked() { + refreshGrid(); } - + @Override protected void initLayoutGrid() { initToolbar(); @@ -41,14 +53,7 @@ protected void initLayoutGrid() { this.crudLayout.setMainComponent(this.grid); } - - @Override - protected void findAllButtonClicked() { - refreshGrid(); - } - @Override - protected void cancelCallback() { - this.getOwlcmsGridLayout().hideForm(); + protected void updateButtons() { } } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/nui/results/TeamItemResultsFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/results/TeamItemResultsFormFactory.java index 62df6dac37..e7446f176a 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/TeamItemResultsFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/TeamItemResultsFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/results/TeamResultsContent.java b/owlcms/src/main/java/app/owlcms/nui/results/TeamResultsContent.java index 2b5f33e385..58e8170c08 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/TeamResultsContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/TeamResultsContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/results/TeamTreeItemCrudGrid.java b/owlcms/src/main/java/app/owlcms/nui/results/TeamTreeItemCrudGrid.java index ec6c1d787f..11d5069d7f 100644 --- a/owlcms/src/main/java/app/owlcms/nui/results/TeamTreeItemCrudGrid.java +++ b/owlcms/src/main/java/app/owlcms/nui/results/TeamTreeItemCrudGrid.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/AthleteCrudGrid.java b/owlcms/src/main/java/app/owlcms/nui/shared/AthleteCrudGrid.java index f1a8c1578d..5aeafcd8b7 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/AthleteCrudGrid.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/AthleteCrudGrid.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/AthleteGridContent.java b/owlcms/src/main/java/app/owlcms/nui/shared/AthleteGridContent.java index e8901a7dec..09e4cb0c1d 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/AthleteGridContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/AthleteGridContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -308,29 +308,29 @@ public void busyBreakButton() { this.breakButton.getStyle().set("color", "white"); this.breakButton.getStyle().set("background-color", "var(--lumo-error-color)"); // breakButton.setText(Translator.translate("BreakButton.Paused")); - fop = this.getFop(); - //OwlcmsSession.withFop(fop -> { - IBreakTimer breakTimer = fop.getBreakTimer(); - if (!breakTimer.isIndefinite()) { - BreakTimerElement bte = (BreakTimerElement) getBreakTimerElement(); - bte.syncWithFopTimer(fop); - bte.setParent(this.getClass().getSimpleName() + "_" + this.id); - this.breakButton.setIcon(bte); - this.breakButton.setIconAfterText(true); - } + this.fop = this.getFop(); + // OwlcmsSession.withFop(fop -> { + IBreakTimer breakTimer = this.fop.getBreakTimer(); + if (!breakTimer.isIndefinite()) { + BreakTimerElement bte = (BreakTimerElement) getBreakTimerElement(); + bte.syncWithFopTimer(this.fop); + bte.setParent(this.getClass().getSimpleName() + "_" + this.id); + this.breakButton.setIcon(bte); + this.breakButton.setIconAfterText(true); + } - if (fop.getCeremonyType() != null) { - this.breakButton.setText(Translator.translate("CeremonyType." + fop.getCeremonyType())); + if (this.fop.getCeremonyType() != null) { + this.breakButton.setText(Translator.translate("CeremonyType." + this.fop.getCeremonyType())); + } else { + BreakType breakType = this.fop.getBreakType(); + if (breakType != null) { + this.breakButton.setText(Translator.translate("BreakType." + breakType) + "\u00a0\u00a0"); } else { - BreakType breakType = fop.getBreakType(); - if (breakType != null) { - this.breakButton.setText(Translator.translate("BreakType." + breakType) + "\u00a0\u00a0"); - } else { - // break done. the button will be hidden in a subsequent step. - this.breakButton.setText(Translator.translate("BreakButton.Paused") + "\u00a0\u00a0"); - } + // break done. the button will be hidden in a subsequent step. + this.breakButton.setText(Translator.translate("BreakButton.Paused") + "\u00a0\u00a0"); } - //}); + } + // }); } @@ -667,6 +667,15 @@ public void slaveCeremonyStarted(UIEvent.CeremonyStarted e) { }); } + @Subscribe + public void slaveDecision(UIEvent.Decision e) { + Athlete athlete = e.getAthlete(); + // logger.debug("athletegrid slaveDecision"); + UIEventProcessor.uiAccess(this.topBar, this.uiEventBus, e, () -> { + warnOthersIfCurrent(e, athlete, e.getFop()); + }); + } + @Subscribe public void slaveGroupDone(UIEvent.GroupDone e) { uiEventLogger.debug("### {} {} {} {}", this.getClass().getSimpleName(), e.getClass().getSimpleName(), @@ -837,21 +846,7 @@ public void slaveUpdateAnnouncerBar(UIEvent.LiftingOrderUpdated e) { } @Subscribe - public void slaveDecision(UIEvent.Decision e) { - Athlete athlete = e.getAthlete(); - // logger.debug("athletegrid slaveDecision"); - UIEventProcessor.uiAccess(this.topBar, this.uiEventBus, e, () -> { - warnOthersIfCurrent(e, athlete, e.getFop()); - }); - } - - /* - * (non-Javadoc) - * - * @see app.owlcms.nui.group.UIEventProcessor#updateGrid(app.owlcms.fieldofplay. UIEvent.LiftingOrderUpdated) - */ - @Subscribe - public void slaveUpdateGrid(UIEvent.LiftingOrderUpdated e) { + public void slaveUpdateGrid(UIEvent.Decision e) { if (this.getCrudGrid() == null) { return; } @@ -861,8 +856,13 @@ public void slaveUpdateGrid(UIEvent.LiftingOrderUpdated e) { }); } + /* + * (non-Javadoc) + * + * @see app.owlcms.nui.group.UIEventProcessor#updateGrid(app.owlcms.fieldofplay. UIEvent.LiftingOrderUpdated) + */ @Subscribe - public void slaveUpdateGrid(UIEvent.Decision e) { + public void slaveUpdateGrid(UIEvent.LiftingOrderUpdated e) { if (this.getCrudGrid() == null) { return; } @@ -1271,9 +1271,9 @@ protected void do2Minutes() { /** * Notifications for FOP events. Good/bad lifts are done in AnnouncerContent. - * + * * Notification theme styling is done in META-INF/resources/frontend/styles/shared-styles.html - * + * * @param text * @param theme */ @@ -1414,6 +1414,18 @@ protected void fillTopBarLeft() { getTopBarLeft().setId("topBarLeft"); } + protected OwlcmsCrudGrid getCrudGrid() { + return this.crudGrid; + } + + protected HorizontalLayout getDecisionLights() { + return this.decisionLights; + } + + protected ComboBox getGenderFilter() { + return this.genderFilter; + } + protected Object getOrigin() { return this; } @@ -1472,6 +1484,24 @@ protected void onAttach(AttachEvent attachEvent) { this.uiEventBus = uiEventBusRegister(this, getFop()); } + // protected void syncWithFOP(boolean refreshGrid) { + // OwlcmsSession.withFop((fop) -> { + // syncWithFop(refreshGrid, fop); + // }); + // } + + protected void setCrudGrid(OwlcmsCrudGrid crudGrid) { + this.crudGrid = crudGrid; + } + + protected void setDecisionLights(HorizontalLayout decisionLights) { + this.decisionLights = decisionLights; + } + + protected void setGenderFilter(ComboBox genderFilter) { + this.genderFilter = genderFilter; + } + protected void setGroupFilter(ComboBox groupFilter) { this.groupFilter = groupFilter; } @@ -1487,12 +1517,6 @@ protected void setTopBarTitle(String title) { this.topBarTitle = title; } - // protected void syncWithFOP(boolean refreshGrid) { - // OwlcmsSession.withFop((fop) -> { - // syncWithFop(refreshGrid, fop); - // }); - // } - protected void syncWithFop(boolean refreshGrid, FieldOfPlay fop) { createTopBarGroupSelect(); @@ -1503,9 +1527,9 @@ protected void syncWithFop(boolean refreshGrid, FieldOfPlay fop) { // sort by start number by default. // underlying source is lift order, so clearing the sort arrow gives back lift order. List> sortOrder = new ArrayList<>(); - Grid grid = crudGrid.getGrid(); + Grid grid = this.crudGrid.getGrid(); Column col = grid.getColumnByKey("startNumber"); - sortOrder.add(new GridSortOrder(col, SortDirection.ASCENDING)); + sortOrder.add(new GridSortOrder<>(col, SortDirection.ASCENDING)); grid.sort(sortOrder); } else { // underlying order (lift order) @@ -1728,28 +1752,4 @@ private void warnOthersIfCurrent(UIEvent e, Athlete athlete, FieldOfPlay fop) { } - protected OwlcmsCrudGrid getCrudGrid() { - return crudGrid; - } - - protected void setCrudGrid(OwlcmsCrudGrid crudGrid) { - this.crudGrid = crudGrid; - } - - protected ComboBox getGenderFilter() { - return genderFilter; - } - - protected void setGenderFilter(ComboBox genderFilter) { - this.genderFilter = genderFilter; - } - - protected HorizontalLayout getDecisionLights() { - return decisionLights; - } - - protected void setDecisionLights(HorizontalLayout decisionLights) { - this.decisionLights = decisionLights; - } - } diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/BaseNavigationContent.java b/owlcms/src/main/java/app/owlcms/nui/shared/BaseNavigationContent.java index 2292f1c922..d73ef72f58 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/BaseNavigationContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/BaseNavigationContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -63,8 +63,7 @@ public abstract class BaseNavigationContent extends BaseContent private String pageTitle; /** - * Instantiates a new announcer content. Content is created in {@link #setParameter(BeforeEvent, String)} after URL - * parameters are parsed. + * Instantiates a new announcer content. Content is created in {@link #setParameter(BeforeEvent, String)} after URL parameters are parsed. */ public BaseNavigationContent() { OwlcmsFactory.waitDBInitialized(); @@ -82,10 +81,9 @@ public ComboBox createGroupSelect(String placeHolder) { } /** - * The top bar is logically is the master part of a master-detail In the current implementation, the most convenient - * place to put it is in the top bar which is managed by the layout, but this could change. So we change the - * surrounding layout from this class. In this way, only one class (the content) listens for events. Doing it the - * other way around would require multiple layouts, which breaks the idea of a single page app. + * The top bar is logically is the master part of a master-detail In the current implementation, the most convenient place to put it is in the top bar which + * is managed by the layout, but this could change. So we change the surrounding layout from this class. In this way, only one class (the content) listens + * for events. Doing it the other way around would require multiple layouts, which breaks the idea of a single page app. * * @return */ @@ -140,8 +138,7 @@ public void setHeaderContent() { /** * Process URL parameters, including query parameters * - * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, - * java.lang.String) + * @see app.owlcms.apputils.queryparameters.FOPParameters#setParameter(com.vaadin.flow.router.BeforeEvent, java.lang.String) */ @Override public void setParameter(BeforeEvent event, @OptionalParameter String parameter) { @@ -173,8 +170,8 @@ public void updateURLLocation(UI ui, Location location, Group newGroup) { params.remove("group"); } Location location2 = new Location(location.getPath(), new QueryParameters(URLUtils.cleanParams(params))); - //ui.getPage().getHistory().replaceState(null, location2); - logger.debug("new location {}",location2.getPathWithQueryParameters()); + // ui.getPage().getHistory().replaceState(null, location2); + logger.debug("new location {}", location2.getPathWithQueryParameters()); ui.getPage().setLocation(location2.getPathWithQueryParameters()); } @@ -223,12 +220,12 @@ protected Object getOrigin() { * * @see com.vaadin.flow.component.Component#onAttach(com.vaadin.flow.component. AttachEvent) */ -// @Override -// protected void onAttach(AttachEvent attachEvent) { -// OwlcmsSession.withFop(fop -> { -// // we listen on uiEventBus. -// this.uiEventBus = uiEventBusRegister(this, fop); -// }); -// } + // @Override + // protected void onAttach(AttachEvent attachEvent) { + // OwlcmsSession.withFop(fop -> { + // // we listen on uiEventBus. + // this.uiEventBus = uiEventBusRegister(this, fop); + // }); + // } } diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/BreakDialog.java b/owlcms/src/main/java/app/owlcms/nui/shared/BreakDialog.java index 16a609f51d..cfaac0e86f 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/BreakDialog.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/BreakDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/BreakManagement.java b/owlcms/src/main/java/app/owlcms/nui/shared/BreakManagement.java index e3835fc188..fd0e41f2be 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/BreakManagement.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/BreakManagement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -70,6 +70,17 @@ @SuppressWarnings("serial") public class BreakManagement extends BaseContent implements SafeEventBusRegistration { + public class LazyComponent extends Div { + public LazyComponent( + SerializableSupplier supplier) { + addAttachListener(e -> { + if (getElement().getChildCount() == 0) { + add(supplier.get()); + } + }); + } + } + private static final Duration DEFAULT_DURATION = Duration.ofMinutes(10L); final private Logger logger = (Logger) LoggerFactory.getLogger(BreakManagement.class); private Button endIntroButton; @@ -128,7 +139,7 @@ public class BreakManagement extends BaseContent implements SafeEventBusRegistra */ BreakManagement(FieldOfPlay fop, BreakType requestedBreak, CountdownType requestedCountdownType, Integer countdownSecondsRemaining, Dialog parentDialog, Object origin) { - logger.setLevel(Level.DEBUG); + this.logger.setLevel(Level.DEBUG); if (this.logger.isDebugEnabled()) { this.logger.debug("BreakManagement request {} {} {} {}", requestedBreak, requestedCountdownType, fop.getState(), @@ -173,16 +184,12 @@ public class BreakManagement extends BaseContent implements SafeEventBusRegistra * @param origin the origin */ BreakManagement(FieldOfPlay fop, Dialog parentDialog, Object origin) { - logger.setLevel(Level.DEBUG); + this.logger.setLevel(Level.DEBUG); this.requestedBreak = null; this.requestedCountdownType = null; initFromFOP(parentDialog); } - private Category getMedalCategory() { - return this.medalCategory; - } - /** * Everything has been created and has meaningful values, add value change listeners now to avoid spuriuous triggering during interface build-up. * @@ -234,38 +241,24 @@ private void addListeners() { }); this.durationField.addValueChangeListener(e -> { if (!e.isFromClient()) { - return; } // computeTimerRemainingFromFields(CountdownType.DURATION); // doResetTimer(this.timeRemaining.intValue()); }); this.timePicker.addValueChangeListener(e -> { if (!e.isFromClient()) { - return; } // computeTimerRemainingFromFields(CountdownType.TARGET); // doResetTimer(this.timeRemaining.intValue()); }); this.datePicker.addValueChangeListener(e -> { if (!e.isFromClient()) { - return; } // computeTimerRemainingFromFields(CountdownType.TARGET); // doResetTimer(this.timeRemaining.intValue()); }); } - public class LazyComponent extends Div { - public LazyComponent( - SerializableSupplier supplier) { - addAttachListener(e -> { - if (getElement().getChildCount() == 0) { - add(supplier.get()); - } - }); - } - } - private void assembleDialog(VerticalLayout dialogLayout) { if (this.logger.isDebugEnabled()) { this.logger.debug("assembleDialog {} {}", this.requestedBreak, LoggerUtils.whereFrom()); @@ -276,24 +269,23 @@ private void assembleDialog(VerticalLayout dialogLayout) { VerticalLayout ci = createInterruptionColumn(); VerticalLayout cb = createCountdownColumn(); - TabSheet ts = new TabSheet(); Tab iTab = ts.add(Translator.translate("BreakManagement.InterruptionsAndJury"), ci); - Tab bTab = ts.add(Translator.translate("BreakManagement.BreaksAndCeremonies"), - new LazyComponent( - () -> { - // createCeremoniesColumn is expensive due to medals - VerticalLayout cc = createCeremoniesColumn(); - HorizontalLayout bc = new HorizontalLayout(cb, cc); - bc.setSizeFull(); - bc.setJustifyContentMode(JustifyContentMode.EVENLY); - if (!this.lazyCreated) { - selected(); - this.lazyCreated = true; - } - return bc; - })); - + Tab bTab = ts.add(Translator.translate("BreakManagement.BreaksAndCeremonies"), + new LazyComponent( + () -> { + // createCeremoniesColumn is expensive due to medals + VerticalLayout cc = createCeremoniesColumn(); + HorizontalLayout bc = new HorizontalLayout(cb, cc); + bc.setSizeFull(); + bc.setJustifyContentMode(JustifyContentMode.EVENLY); + if (!this.lazyCreated) { + selected(); + this.lazyCreated = true; + } + return bc; + })); + ts.addSelectedChangeListener((e) -> { // don't run until after the lazy tab has been created. if (this.lazyCreated) { @@ -317,29 +309,15 @@ private void assembleDialog(VerticalLayout dialogLayout) { dialogLayout.add(ts); } - private void selected() { - if (this.requestedBreak != null) { - setBreakValue(this.requestedBreak); - computeDefaultTimeValues(); - // if we entered as an interruption, the switch to a break would be for a duration - // (e.g. broken platform, fixed, give athletes a warm-up duration before resuming). - setCountdownTypeValue( - this.requestedBreak.isInterruption() ? CountdownType.DURATION : this.requestedCountdownType); - setEnablement(); - } else { - syncWithFop(); - } - } - private void computeDefaultTimeValues() { - //logger.debug("setting default duration as default {}", LoggerUtils.whereFrom()); + // logger.debug("setting default duration as default {}", LoggerUtils.whereFrom()); setDurationField(DEFAULT_DURATION); - if (fop.getGroup() != null - && fop.getGroup().getCompetitionTime() != null - && fop.getGroup().getCompetitionTime().isAfter(LocalDateTime.now())) { - this.datePicker.setValue(fop.getGroup().getCompetitionTime().toLocalDate()); - this.timePicker.setValue(fop.getGroup().getCompetitionTime().toLocalTime()); + if (this.fop.getGroup() != null + && this.fop.getGroup().getCompetitionTime() != null + && this.fop.getGroup().getCompetitionTime().isAfter(LocalDateTime.now())) { + this.datePicker.setValue(this.fop.getGroup().getCompetitionTime().toLocalDate()); + this.timePicker.setValue(this.fop.getGroup().getCompetitionTime().toLocalTime()); return; } @@ -492,16 +470,16 @@ private VerticalLayout createCeremoniesColumn() { (g1, c1, fop1) -> selectCeremonyCategory(g1, c1), // no group (g1, c1, fop1) -> selectCeremonyCategory(null, c1)); -// Checkbox includeNotCompleted = new Checkbox(); -// includeNotCompleted.addValueChangeListener(e -> { -// groupCategorySelectionMenu.setIncludeNotCompleted(e.getValue()); -// groupCategorySelectionMenu.recompute(); -// }); -// includeNotCompleted.setLabel(Translator.translate("Video.includeNotCompleted")); + // Checkbox includeNotCompleted = new Checkbox(); + // includeNotCompleted.addValueChangeListener(e -> { + // groupCategorySelectionMenu.setIncludeNotCompleted(e.getValue()); + // groupCategorySelectionMenu.recompute(); + // }); + // includeNotCompleted.setLabel(Translator.translate("Video.includeNotCompleted")); HorizontalLayout hl = new HorizontalLayout(); hl.add(groupCategorySelectionMenu -// , includeNotCompleted - ); + // , includeNotCompleted + ); this.startMedalCeremony = new Button( Translator.translate("BreakMgmt.startMedals"), (e) -> { @@ -737,17 +715,6 @@ private void createUI(Dialog parentDialog) { assembleDialog(this); } - // private void doResetTimer(Integer tr) { - // OwlcmsSession.withFop(fop -> { - // IBreakTimer breakTimer = fop.getBreakTimer(); - // if (breakTimer.isRunning()) { - // breakTimer.stop(); - // fop.fopEventPost(new FOPEvent.BreakPaused(tr, this.getOrigin())); - // } - // }); - // setEnablement(); - // } - private void enableStartCountdown(boolean b) { // logger.debug("enabled {} {}",b,LoggerUtils.whereFrom()); this.startCountdown.setEnabled(b); @@ -767,6 +734,17 @@ private ComponentEventListener> endBreak(Dialog dialog) { }; } + // private void doResetTimer(Integer tr) { + // OwlcmsSession.withFop(fop -> { + // IBreakTimer breakTimer = fop.getBreakTimer(); + // if (breakTimer.isRunning()) { + // breakTimer.stop(); + // fop.fopEventPost(new FOPEvent.BreakPaused(tr, this.getOrigin())); + // } + // }); + // setEnablement(); + // } + private BreakType getBreakType() { return this.breakType; } @@ -776,6 +754,10 @@ private CountdownType getCountdownType() { return this.countdownType; } + private Category getMedalCategory() { + return this.medalCategory; + } + private Group getMedalGroup() { return this.medalGroup; } @@ -794,19 +776,29 @@ private LocalDateTime getTarget() { if (date == null) { date = LocalDate.now(); } - if (time == null) { + if (time == null) { time = LocalTime.now(); } target = LocalDateTime.of(date, time); return target; } + private void inferCountdownFromStage() { + switch (this.fop.getCurrentStage()) { + case CLEANJERK -> this.countdownRadios.setValue(BreakType.FIRST_CJ); + case SNATCH -> this.countdownRadios.setValue(BreakType.FIRST_SNATCH); + default -> throw new IllegalArgumentException("Unexpected value: " + this.fop.getCurrentStage()); + } + this.durationField.setValue(DEFAULT_DURATION); + this.setCountdownType(CountdownType.DURATION); + } + private void initFromFOP(Dialog parentDialog) { if (this.logger.isDebugEnabled()) { this.logger.debug("BreakManagement FOP"); } this.fop = OwlcmsSession.getFop(); - this.setFop(fop); + this.setFop(this.fop); CountdownType countdownType2 = this.fop.getCountdownType(); BreakType breakType2 = this.fop.getBreakType(); @@ -873,7 +865,7 @@ private void masterStartBreak(FieldOfPlay fop, boolean interruption) { } if (interruption) { fop.fopEventPost(new FOPEvent.BreakStarted( - interruptionRadios.getValue(), + this.interruptionRadios.getValue(), CountdownType.INDEFINITE, null, null, @@ -901,11 +893,25 @@ private void masterStartCeremony(FieldOfPlay fop, CeremonyType ceremonyType) { private void selectCeremonyCategory(Group g, Category c) { this.endMedalCeremony.removeThemeVariants(ButtonVariant.LUMO_PRIMARY); this.startMedalCeremony.addThemeVariants(ButtonVariant.LUMO_PRIMARY); - //logger.debug("selectCeremonyCategory {} {}",g,c); + // logger.debug("selectCeremonyCategory {} {}",g,c); setMedalGroup(g); setMedalCategory(c); } + private void selected() { + if (this.requestedBreak != null) { + setBreakValue(this.requestedBreak); + computeDefaultTimeValues(); + // if we entered as an interruption, the switch to a break would be for a duration + // (e.g. broken platform, fixed, give athletes a warm-up duration before resuming). + setCountdownTypeValue( + this.requestedBreak.isInterruption() ? CountdownType.DURATION : this.requestedCountdownType); + setEnablement(); + } else { + syncWithFop(); + } + } + private void setBreakTimerFromFields(boolean interruption) { if (this.logger.isDebugEnabled()) { this.logger.debug("setBreakTimerFromFields from={}", LoggerUtils.whereFrom()); @@ -928,7 +934,7 @@ private void setBreakTimerFromFields(boolean interruption) { } final CountdownType curCType = cType; - logger.debug("--- interruption {} {} {}", interruption, curCType, bType); + this.logger.debug("--- interruption {} {} {}", interruption, curCType, bType); OwlcmsSession.withFop(fop -> { if (!interruption && curCType == CountdownType.TARGET) { LocalDateTime target = getTarget(); @@ -966,22 +972,22 @@ private void setBreakValue(BreakType breakType) { } // figure out what the best countdown match would be - if (fop.getState() == FOPState.INACTIVE) { + if (this.fop.getState() == FOPState.INACTIVE) { if (this.countdownRadios.getValue() == null) { // default value this.countdownRadios.setValue(BreakType.BEFORE_INTRODUCTION); } - } else if (fop.getState() != FOPState.BREAK) { + } else if (this.fop.getState() != FOPState.BREAK) { // we are lifting. if (this.countdownRadios.getValue() == null) { // default value inferCountdownFromStage(); } - } else if (fop.getBreakType() != null) { + } else if (this.fop.getBreakType() != null) { // not lifting. if (this.countdownRadios.getValue() == null) { // default value - switch (fop.getBreakType()) { + switch (this.fop.getBreakType()) { case BEFORE_INTRODUCTION -> this.countdownRadios.setValue(BreakType.BEFORE_INTRODUCTION); case FIRST_CJ -> this.countdownRadios.setValue(BreakType.FIRST_CJ); case FIRST_SNATCH -> this.countdownRadios.setValue(BreakType.FIRST_SNATCH); @@ -992,7 +998,7 @@ private void setBreakValue(BreakType breakType) { } } - logger.debug("countdownRadios inferred as {}", this.countdownRadios.getValue()); + this.logger.debug("countdownRadios inferred as {}", this.countdownRadios.getValue()); // this.countdownRadios.setValue(this.countdowns.contains(breakType) ? breakType : null); // setInterruptionRadios(this.interruptions.contains(breakType) ? breakType : null); @@ -1031,16 +1037,6 @@ private void setBreakValue(BreakType breakType) { } - private void inferCountdownFromStage() { - switch (fop.getCurrentStage()) { - case CLEANJERK -> this.countdownRadios.setValue(BreakType.FIRST_CJ); - case SNATCH -> this.countdownRadios.setValue(BreakType.FIRST_SNATCH); - default -> throw new IllegalArgumentException("Unexpected value: " + fop.getCurrentStage()); - } - this.durationField.setValue(DEFAULT_DURATION); - this.setCountdownType(CountdownType.DURATION); - } - private void setCeremonyButtonHighlight(BreakType breakType2) { if (breakType2 == BreakType.FIRST_SNATCH) { if (this.fop.getCeremonyType() == CeremonyType.INTRODUCTION) { @@ -1078,7 +1074,7 @@ private void setCountdownType(CountdownType countdownType) { } private void setCountdownTypeValue(CountdownType ct2) { - logger.debug("setting countdownTypeRadios {} from {}", ct2, LoggerUtils.whereFrom()); + this.logger.debug("setting countdownTypeRadios {} from {}", ct2, LoggerUtils.whereFrom()); setCountdownType(ct2); this.countdownTypeRadios.setValue(ct2); setCountdownFieldVisibility(ct2); @@ -1282,9 +1278,10 @@ private void switchToTarget() { */ private void syncWithFop() { final boolean[] running = new boolean[1]; // wrapper to allow value to be set from lambda - { fop = getFop(); - FOPState fopState = fop.getState(); - IBreakTimer fopBreakTimer = fop.getBreakTimer(); + { + this.fop = getFop(); + FOPState fopState = this.fop.getState(); + IBreakTimer fopBreakTimer = this.fop.getBreakTimer(); int fopLiveTimeRemaining = fopBreakTimer.liveTimeRemaining(); Integer fopBreakDuration = fopBreakTimer.getBreakDuration(); @@ -1296,7 +1293,7 @@ private void syncWithFop() { switch (fopState) { case BREAK: case INACTIVE: - BreakType breakType2 = fop.getBreakType(); + BreakType breakType2 = this.fop.getBreakType(); if (breakType2 == BreakType.GROUP_DONE || fopState == FOPState.INACTIVE) { if (this.logger.isDebugEnabled()) { this.logger.debug("syncWithFOP: explicit BEFORE_INTRODUCTION"); @@ -1310,7 +1307,7 @@ private void syncWithFop() { } setBreakValue(breakType2); - CountdownType ct = fop.getCountdownType(); + CountdownType ct = this.fop.getCountdownType(); setCountdownType(ct); if (ct == CountdownType.INDEFINITE) { fopLiveTimeRemaining = (int) DEFAULT_DURATION.toMillis(); diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/ContentWrapping.java b/owlcms/src/main/java/app/owlcms/nui/shared/ContentWrapping.java index 3175a5e79a..64bbe8d538 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/ContentWrapping.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/ContentWrapping.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/CustomFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/shared/CustomFormFactory.java index de71659b14..96ebdf7473 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/CustomFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/CustomFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -31,8 +31,7 @@ public interface CustomFormFactory { Binder buildBinder(CrudOperation operation, T doNotUse); /** - * @see org.vaadin.crudui.form.impl.form.factory.DefaultCrudFormFactory#buildCaption(org.vaadin.crudui.crud.CrudOperation, - * java.lang.Object) + * @see org.vaadin.crudui.form.impl.form.factory.DefaultCrudFormFactory#buildCaption(org.vaadin.crudui.crud.CrudOperation, java.lang.Object) */ String buildCaption(CrudOperation operation, T aFromDb); @@ -44,9 +43,9 @@ Component buildFooter(CrudOperation operation, T unused, /** * We create a copy of the edited object so that we can validate live * - * @see app.owlcms.nui.crudui.OwlcmsCrudFormFactory#buildNewForm(org.vaadin.crudui.crud.CrudOperation, - * java.lang.Object, boolean, com.vaadin.flow.component.ComponentEventListener, - * com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.ComponentEventListener) + * @see app.owlcms.nui.crudui.OwlcmsCrudFormFactory#buildNewForm(org.vaadin.crudui.crud.CrudOperation, java.lang.Object, boolean, + * com.vaadin.flow.component.ComponentEventListener, com.vaadin.flow.component.ComponentEventListener, + * com.vaadin.flow.component.ComponentEventListener) */ Component buildNewForm(CrudOperation operation, T aFromDb, boolean readOnly, ComponentEventListener> cancelButtonClickListener, diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/DownloadButtonFactory.java b/owlcms/src/main/java/app/owlcms/nui/shared/DownloadButtonFactory.java index dee57e6ba9..7cea832aac 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/DownloadButtonFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/DownloadButtonFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -34,8 +34,7 @@ public class DownloadButtonFactory { @SuppressWarnings("unused") final private static Logger logger = (Logger) LoggerFactory.getLogger(DownloadButtonFactory.class); - public static Div createDynamicJsonDownloadButton(String prefix, String label, Notification notification) { - UI ui = UI.getCurrent(); + public static Div createDynamicDownloadButton(String prefix, String label, InputStreamFactory supplier, Supplier extensionSupplier) { final LazyDownloadButton downloadButton = new LazyDownloadButton( label, new Icon(VaadinIcon.DOWNLOAD_ALT), @@ -43,40 +42,47 @@ public static Div createDynamicJsonDownloadButton(String prefix, String label, N LocalDateTime now = LocalDateTime.now().withNano(0); return prefix + "_" + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH'h'mm")) - + ".json"; + + extensionSupplier.get(); }, + supplier); + return new Div(downloadButton); + } + + public static Div createDynamicDownloadButton(Supplier prefixSupplier, String label, InputStreamFactory supplier, + Supplier extensionSupplier) { + final LazyDownloadButton downloadButton = new LazyDownloadButton( + label, + new Icon(VaadinIcon.DOWNLOAD_ALT), () -> { - return new CompetitionData().exportData(ui, notification); - }); - downloadButton.setNotification(notification); + LocalDateTime now = LocalDateTime.now().withNano(0); + return prefixSupplier.get() + + "_" + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH'h'mm")) + + extensionSupplier.get(); + }, + supplier); return new Div(downloadButton); } - /** - * Creates a new DownloadButton object for a dynamically created file. - * - * @param prefix the prefix - * @param label the label - * @param xlsSource the xls source - * @return the div - */ - public static Div createDynamicXLSXDownloadButton(String prefix, String label, XLSXWorkbookStreamSource xlsSource) { + public static Div createDynamicJsonDownloadButton(String prefix, String label, Notification notification) { + UI ui = UI.getCurrent(); final LazyDownloadButton downloadButton = new LazyDownloadButton( label, new Icon(VaadinIcon.DOWNLOAD_ALT), () -> { LocalDateTime now = LocalDateTime.now().withNano(0); - String value = ".xlsx"; return prefix - + "_" + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH'h'mm';'ss")) - + value; + + "_" + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH'h'mm")) + + ".json"; }, - xlsSource); - + () -> { + return new CompetitionData().exportData(ui, notification); + }); + downloadButton.setNotification(notification); return new Div(downloadButton); } - - public static Div createDynamicJXLSDownloadButton(String fileNamePrefix, String buttonLabel, JXLSWorkbookStreamSource xlsSource, Notification notification) { + + public static Div createDynamicJXLSDownloadButton(String fileNamePrefix, String buttonLabel, JXLSWorkbookStreamSource xlsSource, + Notification notification) { final LazyDownloadButton downloadButton = new LazyDownloadButton( buttonLabel, new Icon(VaadinIcon.DOWNLOAD_ALT), @@ -93,31 +99,27 @@ public static Div createDynamicJXLSDownloadButton(String fileNamePrefix, String return new Div(downloadButton); } - public static Div createDynamicDownloadButton(String prefix, String label, InputStreamFactory supplier, Supplier extensionSupplier) { + /** + * Creates a new DownloadButton object for a dynamically created file. + * + * @param prefix the prefix + * @param label the label + * @param xlsSource the xls source + * @return the div + */ + public static Div createDynamicXLSXDownloadButton(String prefix, String label, XLSXWorkbookStreamSource xlsSource) { final LazyDownloadButton downloadButton = new LazyDownloadButton( label, new Icon(VaadinIcon.DOWNLOAD_ALT), () -> { LocalDateTime now = LocalDateTime.now().withNano(0); + String value = ".xlsx"; return prefix - + "_" + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH'h'mm")) - + extensionSupplier.get(); + + "_" + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH'h'mm';'ss")) + + value; }, - supplier); - return new Div(downloadButton); - } + xlsSource); - public static Div createDynamicDownloadButton(Supplier prefixSupplier, String label, InputStreamFactory supplier, Supplier extensionSupplier) { - final LazyDownloadButton downloadButton = new LazyDownloadButton( - label, - new Icon(VaadinIcon.DOWNLOAD_ALT), - () -> { - LocalDateTime now = LocalDateTime.now().withNano(0); - return prefixSupplier.get() - + "_" + now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH'h'mm")) - + extensionSupplier.get(); - }, - supplier); return new Div(downloadButton); } @@ -137,7 +139,7 @@ public static Div createDynamicZipDownloadButton(String prefix, String label, by return new Div(downloadButton); } - + public static Div createDynamicZipDownloadButton(String prefix, String label, byte[] content, Icon icon) { final LazyDownloadButton downloadButton = new LazyDownloadButton( label, @@ -169,7 +171,7 @@ public static Div createDynamicZipDownloadButton(String prefix, String label, In return new Div(downloadButton); } - + public static Div createDynamicZipDownloadButton(String prefix, String label, InputStreamFactory supplier, Icon icon) { final LazyDownloadButton downloadButton = new LazyDownloadButton( label, @@ -185,5 +187,4 @@ public static Div createDynamicZipDownloadButton(String prefix, String label, In return new Div(downloadButton); } - } diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/HasBoardMode.java b/owlcms/src/main/java/app/owlcms/nui/shared/HasBoardMode.java index 4a998b959c..776a8f4f70 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/HasBoardMode.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/HasBoardMode.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.shared; import org.slf4j.LoggerFactory; @@ -54,7 +60,7 @@ public default BoardMode computeBoardMode(FOPState fopState, BreakType breakType } else if (fopState == FOPState.INACTIVE) { bm = BoardMode.WAIT; } - //logger.debug("computeBoardMode {} {} {} = {} -- {}", fopState, breakType, ceremonyType, bm, LoggerUtils.stackTrace()); + // logger.debug("computeBoardMode {} {} {} = {} -- {}", fopState, breakType, ceremonyType, bm, LoggerUtils.stackTrace()); return bm; } diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/IAthleteEditing.java b/owlcms/src/main/java/app/owlcms/nui/shared/IAthleteEditing.java index 3491d01528..d0f7b9997d 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/IAthleteEditing.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/IAthleteEditing.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/NAthleteRegistrationFormFactory.java b/owlcms/src/main/java/app/owlcms/nui/shared/NAthleteRegistrationFormFactory.java index 2e3297ce7d..24236f83c0 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/NAthleteRegistrationFormFactory.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/NAthleteRegistrationFormFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -227,8 +227,8 @@ public Component buildFooter(CrudOperation operation, footerLayout.add(cancelButton); } - if (previousNext instanceof WeighinContent) { - boolean nextMode = ((WeighinContent) previousNext).isNextMode(); + if (this.previousNext instanceof WeighinContent) { + boolean nextMode = ((WeighinContent) this.previousNext).isNextMode(); if (nextMode) { operationButton.setText(Translator.translate("WeighIn.UpdateAndNext")); } @@ -307,6 +307,10 @@ public Collection findAll() { // } // } + public void setCurrentGroup(Group currentGroup) { + this.currentGroup = currentGroup; + } + @Override public void setValidationStatusHandler(boolean showErrorsOnFields) { this.binder.setValidationStatusHandler((s) -> { @@ -481,7 +485,7 @@ protected void validateCategory(Binder.BindingBuilder binding if (eligibles == null || eligibles.isEmpty()) { return category == null; } - Set selectedEligibles = eligibleField.getValue(); + Set selectedEligibles = this.eligibleField.getValue(); return !selectedEligibles.isEmpty(); } catch (Exception e) { LoggerUtils.logError(logger, e); @@ -599,6 +603,11 @@ private boolean categoryIsEligible(Category category, List eligibles) return eligibles.stream().anyMatch(c -> c.sameAs(category)); } + @SuppressWarnings("unused") + private List championshipsForCategories(Set value) { + return value.stream().map(c -> c.getAgeGroup().getChampionship()).distinct().toList(); + } + private void checkOther20kgFields(LocalizedIntegerField fieldA, LocalizedIntegerField fieldB) { logger.trace("entering checkOther20kgFields {} {}", isCheckOther20kgFields(), @@ -639,24 +648,6 @@ private void configure20kgWeightField(LocalizedIntegerField field) { }); } - private FormLayout createDrawForm() { - FormLayout layout = createLayout(); - Component title = createTitle("Athlete.DrawTitle"); - layout.add(title); - layout.setColspan(title, NB_COLUMNS); - - this.lotNumberField = new LocalizedIntegerField(); - bindField(this.binder.forField(this.lotNumberField), this.lotNumberField, Athlete::getLotNumber, - Athlete::setLotNumber); - layoutAddFormItem(layout, this.lotNumberField, Translator.translate("Lot")); - - this.startNumberField = new LocalizedIntegerField(); - bindField(this.binder.forField(this.startNumberField), this.startNumberField, Athlete::getStartNumber, - Athlete::setStartNumber); - layoutAddFormItem(layout, this.startNumberField, Translator.translate("StartNumber")); - return layout; - } - private FormLayout createCategoryAndSessionForm() { FormLayout layout = createLayout(); Component title = createTitle("Athlete.GroupCatTitle"); @@ -717,6 +708,24 @@ private FormLayout createCategoryAndSessionForm() { return layout; } + private FormLayout createDrawForm() { + FormLayout layout = createLayout(); + Component title = createTitle("Athlete.DrawTitle"); + layout.add(title); + layout.setColspan(title, NB_COLUMNS); + + this.lotNumberField = new LocalizedIntegerField(); + bindField(this.binder.forField(this.lotNumberField), this.lotNumberField, Athlete::getLotNumber, + Athlete::setLotNumber); + layoutAddFormItem(layout, this.lotNumberField, Translator.translate("Lot")); + + this.startNumberField = new LocalizedIntegerField(); + bindField(this.binder.forField(this.startNumberField), this.startNumberField, Athlete::getStartNumber, + Athlete::setStartNumber); + layoutAddFormItem(layout, this.startNumberField, Translator.translate("StartNumber")); + return layout; + } + private FormLayout createIdForm() { FormLayout layout = createLayout(); Component title = createTitle("Athlete.IdentificationTitle"); @@ -1028,12 +1037,9 @@ private void filterCategories(Category category, boolean initCategories) { this.wrappedBWTextField.setValueChangeMode(ValueChangeMode.ON_CHANGE); this.wrappedBWTextField.setAutoselect(true); this.wrappedBWTextField.addValueChangeListener((vc) -> { - if (!vc.isFromClient()) { - return; - } // logger.debug("wrappedBWTextField listenersEnabled={} invalid={}", // isChangeListenersEnabled(), bodyWeightField.isInvalid()); - if (!isChangeListenersEnabled() || this.bodyWeightField.isInvalid()) { + if (!vc.isFromClient() || !isChangeListenersEnabled() || this.bodyWeightField.isInvalid()) { return; } recomputeCategories(this.genderField, this.bodyWeightField, this.categoryField, this.eligibleField, @@ -1077,7 +1083,7 @@ private void filterCategories(Category category, boolean initCategories) { this.categoryField, this.qualifyingTotalField); - logger.debug("**** allEligibles: {} selectedCategories {}", allEligible, selectedCategories); + logger.debug("**** allEligibles: {} selectedCategories {}", this.allEligible, selectedCategories); Stream filter = this.allEligible.stream().filter(c -> c.sameAsAny(selectedCategories)); Category category2 = filter.findFirst().orElse(null); setCategoryFieldValue(category2); @@ -1097,10 +1103,6 @@ private void filterCategories(Category category, boolean initCategories) { setChangeListenersEnabled(true); } - private void setCategoryFieldValue(Category category2) { - this.categoryField.setValue(category2); - } - private List findEligibleCategories(ComboBox genderField, Integer ageFromFields, LocalizedDecimalField bodyWeightField, ComboBox categoryField, LocalizedIntegerField qualifyingTotalField2) { @@ -1215,7 +1217,7 @@ private void recomputeCategories( // logger.debug("recompute, cat={} allEligible = {}", cat, this.allEligible); // category is null or not within eligibles, recompute - List filteredEligibles = allEligible.stream() + List filteredEligibles = this.allEligible.stream() .filter(e -> previousChampionships.isEmpty() || previousChampionships.contains(e.getAgeGroup().getChampionship())).toList(); // logger.debug("eligibilty filtered on championship {}",filteredEligibles); @@ -1243,7 +1245,7 @@ private void recomputeCategories( ageFromFields, bw, qualifyingTotal); // logger.debug("cat-based allEligible {} {}", cat, this.allEligible); // Category bestMatchCategory = bestMatch(this.allEligible); - List filteredEligibles = allEligible.stream() + List filteredEligibles = this.allEligible.stream() .filter(e -> previousChampionships.isEmpty() || previousChampionships.contains(e.getAgeGroup().getChampionship())).toList(); // logger.debug("eligibilty2 filtered on championship {}",filteredEligibles); updateCategoryFields(cat, categoryField, eligibleField, qualifyingTotalField2, @@ -1280,11 +1282,6 @@ private void recomputeCategories( } - @SuppressWarnings("unused") - private List championshipsForCategories(Set value) { - return value.stream().map(c -> c.getAgeGroup().getChampionship()).distinct().toList(); - } - private void safeCategorySetItems(List categories) { Category curCat = this.categoryField.getValue(); logger.debug("safeCategorySetItems curCat={}", curCat); @@ -1298,11 +1295,6 @@ private void safeCategorySetItems(List categories) { setCategoryFieldValue(curCat); } - private void setCategoryFieldItems(List categories) { - // logger.debug("setting categoryFieldItems {}",categories); - this.categoryField.setItems(categories); - } - private Hr separator() { Hr hr = new Hr(); hr.getStyle().set("margin-top", "0.4em"); @@ -1312,6 +1304,15 @@ private Hr separator() { return hr; } + private void setCategoryFieldItems(List categories) { + // logger.debug("setting categoryFieldItems {}",categories); + this.categoryField.setItems(categories); + } + + private void setCategoryFieldValue(Category category2) { + this.categoryField.setValue(category2); + } + private void setChangeListenersEnabled(boolean changeListenersEnabled) { this.changeListenersEnabled = changeListenersEnabled; } @@ -1321,10 +1322,6 @@ private void setCheckOther20kgFields(boolean checkOther20kgFields) { this.checkOther20kgFields = checkOther20kgFields; } - public void setCurrentGroup(Group currentGroup) { - this.currentGroup = currentGroup; - } - private void setEditedAthlete(Athlete editedAthlete) { this.editedAthlete = editedAthlete; } @@ -1365,10 +1362,10 @@ private void setupAthlete(CrudOperation operation, Athlete aFromList) { private void updateCategoryFields(Category bestMatch, ComboBox categoryField, CheckboxGroup eligibleField, LocalizedIntegerField qualifyingTotalField2, List filteredEligibles, - List allEligibles, + List allEligibles, boolean recomputeEligibles) { - //logger.debug("updating category fields {}",LoggerUtils.stackTrace()); + // logger.debug("updating category fields {}",LoggerUtils.stackTrace()); LinkedHashSet newEligibles = new LinkedHashSet<>(); Set prevEligibles; if (recomputeEligibles) { @@ -1377,7 +1374,8 @@ private void updateCategoryFields(Category bestMatch, ComboBox categor } else { prevEligibles = eligibleField.getValue(); } - //logger.debug("updateCategoryFields {} {} - {} {} {}", categoryField.getValue(), bestMatch, prevEligibles, filteredEligibles, LoggerUtils.whereFrom()); + // logger.debug("updateCategoryFields {} {} - {} {} {}", categoryField.getValue(), bestMatch, prevEligibles, filteredEligibles, + // LoggerUtils.whereFrom()); if (prevEligibles != null) { // update the list of eligible categories. Must use the matching items in @@ -1392,7 +1390,7 @@ private void updateCategoryFields(Category bestMatch, ComboBox categor } } } - //logger.debug("updateCategoryFields filteredEligibles {}", filteredEligibles.stream().map(v -> v.shortDump()).collect(Collectors.toList())); + // logger.debug("updateCategoryFields filteredEligibles {}", filteredEligibles.stream().map(v -> v.shortDump()).collect(Collectors.toList())); // List pertinentCategories = CategoryRepository.findByGenderAgeBW(getGenderFieldValue(), // getAgeFromFields(), null); @@ -1400,7 +1398,7 @@ private void updateCategoryFields(Category bestMatch, ComboBox categor boolean listenerStatus = isChangeListenersEnabled(); try { setChangeListenersEnabled(false); - logger.debug("setting items {}",allEligibles); + logger.debug("setting items {}", allEligibles); eligibleField.setItems(allEligibles); } finally { setChangeListenersEnabled(listenerStatus); diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/NavigationPage.java b/owlcms/src/main/java/app/owlcms/nui/shared/NavigationPage.java index 9ece1268b3..b753b7250c 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/NavigationPage.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/NavigationPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsContent.java b/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsContent.java index 2420fd48f0..a4777e1307 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsContent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayout.java b/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayout.java index 1cffcc5fb4..f7ee17464d 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayout.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayout.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.nui.shared; import java.util.ArrayList; diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayoutAware.java b/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayoutAware.java index 1266be8bb9..1fe5f59c9b 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayoutAware.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/OwlcmsLayoutAware.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -22,9 +22,8 @@ public default OwlcmsLayout getAppLayout() { /** * A Vaadin RouterLayout contains an instance of an AppLayout. * - * A RouterLayout is referenced as a layout by some Content, meaning that the content will be inserted inside and - * laid out (i.e. displayed). OwlcmsLayout delegates to an AppLayout which actually does the layouting. AppLayout is - * a Java API to the Google app-layout web component. + * A RouterLayout is referenced as a layout by some Content, meaning that the content will be inserted inside and laid out (i.e. displayed). OwlcmsLayout + * delegates to an AppLayout which actually does the layouting. AppLayout is a Java API to the Google app-layout web component. * * @return the RouterLayout which is the target of the Vaadin Flow Route */ diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/RequireDisplayLogin.java b/owlcms/src/main/java/app/owlcms/nui/shared/RequireDisplayLogin.java index 73d49a30f4..2121353301 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/RequireDisplayLogin.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/RequireDisplayLogin.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/RequireLogin.java b/owlcms/src/main/java/app/owlcms/nui/shared/RequireLogin.java index 4ff5fe220e..21a2158167 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/RequireLogin.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/RequireLogin.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/nui/shared/SafeEventBusRegistration.java b/owlcms/src/main/java/app/owlcms/nui/shared/SafeEventBusRegistration.java index 9fc195e569..4914dfec21 100644 --- a/owlcms/src/main/java/app/owlcms/nui/shared/SafeEventBusRegistration.java +++ b/owlcms/src/main/java/app/owlcms/nui/shared/SafeEventBusRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/simulation/CompetitionSimulator.java b/owlcms/src/main/java/app/owlcms/simulation/CompetitionSimulator.java index 252900ceb6..b4a10d3bb3 100644 --- a/owlcms/src/main/java/app/owlcms/simulation/CompetitionSimulator.java +++ b/owlcms/src/main/java/app/owlcms/simulation/CompetitionSimulator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -44,6 +44,15 @@ public class CompetitionSimulator { final private static Logger logger = (Logger) LoggerFactory.getLogger(CompetitionSimulator.class); private static List registeredSimulators = new ArrayList<>(); private static boolean running; + + public static boolean isRunning() { + return running; + } + + public static void setRunning(boolean b) { + running = true; + } + private Random r = new Random(0); public CompetitionSimulator() { @@ -70,9 +79,9 @@ public String runSimulation() throws InterruptedException { List as = AthleteRepository.findAllByGroupAndWeighIn(g, true); - //if (as.size() == 0) { - as = weighIn(g); - //} + // if (as.size() == 0) { + as = weighIn(g); + // } as = AthleteRepository.findAllByGroupAndWeighIn(g, true); if (as.size() == 0) { logger.info("skipping group {} size {}", g.getName(), as.size()); @@ -117,10 +126,6 @@ public String runSimulation() throws InterruptedException { return "simulation done."; } - public static void setRunning(boolean b) { - running = true; - } - private void clearLifts() { JPAService.runInTransaction(em -> { List athletes = AthleteRepository.doFindAll(em); @@ -146,13 +151,13 @@ private List weighIn(Group g) { Double catUpper = c.getMaximumWeight(); Double catLower = c.getMinimumWeight(); if (catUpper > 998 && catLower <= 1.01) { - //logger.trace("open {} {} {} {}", a.getLastName(), a.getCategoryCode(), catLower, catUpper); + // logger.trace("open {} {} {} {}", a.getLastName(), a.getCategoryCode(), catLower, catUpper); // open category double nextGaussian = r.nextGaussian(85, 15); a.setBodyWeight(nextGaussian); - catUpper = (double) Math.round(2.0+nextGaussian+2.0); + catUpper = (double) Math.round(2.0 + nextGaussian + 2.0); } else { - //logger.trace("!!! not open {} {} {} {}", a.getLastName(), a.getCategoryCode(), catLower, catUpper); + // logger.trace("!!! not open {} {} {} {}", a.getLastName(), a.getCategoryCode(), catLower, catUpper); if (catUpper > 998) { catUpper = catLower * 1.1; } @@ -179,8 +184,4 @@ private List weighIn(Group g) { return as; } - public static boolean isRunning() { - return running; - } - } diff --git a/owlcms/src/main/java/app/owlcms/simulation/FOPSimulator.java b/owlcms/src/main/java/app/owlcms/simulation/FOPSimulator.java index 01570d09eb..b876293482 100644 --- a/owlcms/src/main/java/app/owlcms/simulation/FOPSimulator.java +++ b/owlcms/src/main/java/app/owlcms/simulation/FOPSimulator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -28,9 +28,9 @@ * * Simulate the flow of a competition on a field of play. * - * The actions of technical officials are simulated: the the events that the user interface would send (FOPEvents) are - * posted The state automaton in the FieldOfPlay triggers the user interface updates as required. It is therefore - * possible to create as many real browser windows as required to observe the updates taking place. + * The actions of technical officials are simulated: the the events that the user interface would send (FOPEvents) are posted The state automaton in the + * FieldOfPlay triggers the user interface updates as required. It is therefore possible to create as many real browser windows as required to observe the + * updates taking place. * * @author Jean-François Lamy * @@ -191,7 +191,7 @@ protected void doLift(Athlete a) { Thread.sleep(1000); } catch (InterruptedException e) { } - + // stop time and get decisions if (USE_MQTT_TIMER && mm != null) { try { diff --git a/owlcms/src/main/java/app/owlcms/sound/Sound.java b/owlcms/src/main/java/app/owlcms/sound/Sound.java index 8ea3fdb5ed..afe22d8e35 100644 --- a/owlcms/src/main/java/app/owlcms/sound/Sound.java +++ b/owlcms/src/main/java/app/owlcms/sound/Sound.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/sound/Speakers.java b/owlcms/src/main/java/app/owlcms/sound/Speakers.java index bba4c46dec..d9844663f6 100644 --- a/owlcms/src/main/java/app/owlcms/sound/Speakers.java +++ b/owlcms/src/main/java/app/owlcms/sound/Speakers.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/sound/SunFileReader.java b/owlcms/src/main/java/app/owlcms/sound/SunFileReader.java index 53ff712a94..44443c93a6 100644 --- a/owlcms/src/main/java/app/owlcms/sound/SunFileReader.java +++ b/owlcms/src/main/java/app/owlcms/sound/SunFileReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -37,8 +37,8 @@ abstract class SunFileReader extends AudioFileReader { protected static final int bisBufferSize = 4096; /** - * Calculates the frame size for PCM frames. Note that this method is appropriate for non-packed samples. For - * instance, 12 bit, 2 channels will return 4 bytes, not 3. + * Calculates the frame size for PCM frames. Note that this method is appropriate for non-packed samples. For instance, 12 bit, 2 channels will return 4 + * bytes, not 3. * * @param sampleSizeInBits the size of a single sample in bits * @param channels the number of channels @@ -61,24 +61,21 @@ static final int calculatePCMFrameSize(int sampleSizeInBits, int channels) { * * @param file the File from which file format information should be extracted * @return an AudioFileFormat object describing the audio file format - * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs */ @Override abstract public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException; /** - * Obtains the audio file format of the input stream provided. The stream must point to valid audio file data. In - * general, audio file providers may need to read some data from the stream before determining whether they support - * it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, - * and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, - * this method may fail with an IOException. + * Obtains the audio file format of the input stream provided. The stream must point to valid audio file data. In general, audio file providers may need to + * read some data from the stream before determining whether they support it. These parsers must be able to mark the stream, read enough data to determine + * whether they support the stream, and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, this + * method may fail with an IOException. * * @param stream the input stream from which file format information should be extracted * @return an AudioFileFormat object describing the audio file format - * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs * @see InputStream#markSupported * @see InputStream#mark @@ -103,24 +100,21 @@ abstract public AudioFileFormat getAudioFileFormat(InputStream stream) * * @param file the File for which the AudioInputStream should be constructed * @return an AudioInputStream object based on the audio file data pointed to by the File - * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs */ @Override abstract public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException; /** - * Obtains an audio stream from the input stream provided. The stream must point to valid audio file data. In - * general, audio file providers may need to read some data from the stream before determining whether they support - * it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, - * and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, - * this method may fail with an IOException. + * Obtains an audio stream from the input stream provided. The stream must point to valid audio file data. In general, audio file providers may need to read + * some data from the stream before determining whether they support it. These parsers must be able to mark the stream, read enough data to determine + * whether they support the stream, and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, this + * method may fail with an IOException. * * @param stream the input stream from which the AudioInputStream should be constructed * @return an AudioInputStream object based on the audio file data contained in the input stream. - * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs * @see InputStream#markSupported * @see InputStream#mark diff --git a/owlcms/src/main/java/app/owlcms/sound/Tone.java b/owlcms/src/main/java/app/owlcms/sound/Tone.java index 5032a4de8b..024c7c4133 100644 --- a/owlcms/src/main/java/app/owlcms/sound/Tone.java +++ b/owlcms/src/main/java/app/owlcms/sound/Tone.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/sound/WaveFileFormat.java b/owlcms/src/main/java/app/owlcms/sound/WaveFileFormat.java index b70e9d8ec8..cdaa68d425 100644 --- a/owlcms/src/main/java/app/owlcms/sound/WaveFileFormat.java +++ b/owlcms/src/main/java/app/owlcms/sound/WaveFileFormat.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/sound/WaveFileReader.java b/owlcms/src/main/java/app/owlcms/sound/WaveFileReader.java index 07f8f4f650..84634ea388 100644 --- a/owlcms/src/main/java/app/owlcms/sound/WaveFileReader.java +++ b/owlcms/src/main/java/app/owlcms/sound/WaveFileReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -46,8 +46,7 @@ public final class WaveFileReader extends SunFileReader { * * @param file the File from which file format information should be extracted * @return an AudioFileFormat object describing the audio file format - * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs */ @Override @@ -65,16 +64,14 @@ public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFile } /** - * Obtains the audio file format of the input stream provided. The stream must point to valid audio file data. In - * general, audio file providers may need to read some data from the stream before determining whether they support - * it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, - * and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, - * this method may fail with an IOException. + * Obtains the audio file format of the input stream provided. The stream must point to valid audio file data. In general, audio file providers may need to + * read some data from the stream before determining whether they support it. These parsers must be able to mark the stream, read enough data to determine + * whether they support the stream, and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, this + * method may fail with an IOException. * * @param stream the input stream from which file format information should be extracted * @return an AudioFileFormat object describing the audio file format - * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs * @see InputStream#markSupported * @see InputStream#mark @@ -116,8 +113,7 @@ public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileEx * * @param file the File for which the AudioInputStream should be constructed * @return an AudioInputStream object based on the audio file data pointed to by the File - * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the File does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs */ @Override @@ -136,16 +132,14 @@ public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFi } /** - * Obtains an audio stream from the input stream provided. The stream must point to valid audio file data. In - * general, audio file providers may need to read some data from the stream before determining whether they support - * it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, - * and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, - * this method may fail with an IOException. + * Obtains an audio stream from the input stream provided. The stream must point to valid audio file data. In general, audio file providers may need to read + * some data from the stream before determining whether they support it. These parsers must be able to mark the stream, read enough data to determine + * whether they support the stream, and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, this + * method may fail with an IOException. * * @param stream the input stream from which the AudioInputStream should be constructed * @return an AudioInputStream object based on the audio file data contained in the input stream. - * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the - * system + * @throws UnsupportedAudioFileException if the stream does not point to valid audio file data recognized by the system * @throws IOException if an I/O exception occurs * @see InputStream#markSupported * @see InputStream#mark diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/IRegistrationFileProcessor.java b/owlcms/src/main/java/app/owlcms/spreadsheet/IRegistrationFileProcessor.java index 7273939caf..e210d89e34 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/IRegistrationFileProcessor.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/IRegistrationFileProcessor.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.spreadsheet; import java.io.InputStream; diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsDocs.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsDocs.java index a1d65eec64..f4f3531a65 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsDocs.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsDocs.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -23,11 +23,15 @@ public class JXLSCardsDocs extends JXLSWorkbookStreamSource { public JXLSCardsDocs() { } + @Override + public int getSizeLimit() { + return 200; + } + /* * (non-Javadoc) * - * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# - * postProcess(org.apache.poi.ss.usermodel.Workbook) + * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# postProcess(org.apache.poi.ss.usermodel.Workbook) */ @Override protected void postProcess(Workbook workbook) { @@ -35,7 +39,7 @@ protected void postProcess(Workbook workbook) { setPageBreaks(workbook, 1, this.getPageLength()); return; } - + if (Competition.getCurrent().getComputedCardsTemplateFileName().contains("IWF-")) { setPageBreaks(workbook, 1, 17); } else if (Competition.getCurrent().getComputedCardsTemplateFileName().contains("SmallCards")) { @@ -44,11 +48,6 @@ protected void postProcess(Workbook workbook) { setPageBreaks(workbook, 1, 7); } } - - @Override - public int getSizeLimit() { - return 200; - } protected void setPageBreaks(Workbook workbook, int cardsPerPage, int linesPerCard) { Sheet sheet = workbook.getSheetAt(0); diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsWeighIn.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsWeighIn.java index ec55c38d15..91e11c9263 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsWeighIn.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCardsWeighIn.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -42,7 +42,6 @@ public List getSortedAthletes() { protected void postProcess(Workbook workbook) { if (this.getPageLength() != null) { setPageBreaks(workbook, 1, this.getPageLength()); - return; } } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCategoriesListDocs.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCategoriesListDocs.java index b9991e62ce..0d6b055132 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCategoriesListDocs.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCategoriesListDocs.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCompetitionBook.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCompetitionBook.java index 15ae1d94ac..6339f50a48 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCompetitionBook.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSCompetitionBook.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -33,8 +33,8 @@ * */ public class JXLSCompetitionBook extends JXLSWorkbookStreamSource { - - private static final long serialVersionUID = 1L; + + private static final long serialVersionUID = 1L; private Championship ageDivision; private String ageGroupPrefix; @SuppressWarnings("unused") @@ -47,6 +47,11 @@ public JXLSCompetitionBook(boolean excludeNotWeighed, UI ui) { public JXLSCompetitionBook(UI ui) { } + @Override + public String getAgeGroupPrefix() { + return this.ageGroupPrefix; + } + /** * @return the ageDivision */ @@ -55,17 +60,21 @@ public Championship getChampionship() { return this.ageDivision; } - @Override - public String getAgeGroupPrefix() { - return this.ageGroupPrefix; - } - @Override public List getSortedAthletes() { // not used (setReportingInfo does all the work) return null; } + public boolean isIncludeUnfinished() { + return this.isIncludeUnfinished; + } + + @Override + public void setAgeGroupPrefix(String ageGroupPrefix) { + this.ageGroupPrefix = ageGroupPrefix; + } + /** * @param ageDivision the ageDivision to set */ @@ -75,9 +84,8 @@ public void setChampionship(Championship ageDivision) { this.ageDivision = ageDivision; } - @Override - public void setAgeGroupPrefix(String ageGroupPrefix) { - this.ageGroupPrefix = ageGroupPrefix; + public void setIncludeUnfinished(boolean isIncludeUnifinished) { + this.isIncludeUnfinished = isIncludeUnifinished; } @Override @@ -98,8 +106,7 @@ protected void configureTransformer(XLSTransformer transformer) { /* * team result sheets need columns hidden, print area fixed * - * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# - * postProcess(org.apache.poi.ss.usermodel.Workbook) + * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# postProcess(org.apache.poi.ss.usermodel.Workbook) */ @Override protected void postProcess(Workbook workbook) { @@ -121,10 +128,10 @@ protected void setReportingInfo() { // remove athletes from incomplete categories if (!isIncludeUnfinished()) { for (String k : reportingBeans.keySet()) { - logger.debug("bean {}",k); + this.logger.debug("bean {}", k); Object bean = reportingBeans.get(k); if (bean instanceof List && ((List) bean).size() > 0 && ((List) bean).get(0) instanceof Athlete) { - logger.debug("cleaning up {}", k); + this.logger.debug("cleaning up {}", k); List bean2 = (List) bean; Set unfinishedCategories = AthleteRepository.unfinishedCategories(bean2); bean2 = bean2.stream().filter(a -> !unfinishedCategories.contains(a.getCategoryCode())).toList(); @@ -138,9 +145,9 @@ protected void setReportingInfo() { Ranking overallScoringSystem = this.getBestLifterScoringSystem(); overallScoringSystem = overallScoringSystem != null ? overallScoringSystem : Competition.getCurrent().getScoringSystem(); // make available to the Athlete class in this Thread (and subThreads). - JXLSWorkbookStreamSource.setBestLifterRankingThreadLocal(overallScoringSystem); - reportingBeans.put("bestRankingTitle",Ranking.getScoringTitle(overallScoringSystem)); - + JXLSWorkbookStreamSource.setBestLifterRankingThreadLocal(overallScoringSystem); + reportingBeans.put("bestRankingTitle", Ranking.getScoringTitle(overallScoringSystem)); + reportingBeans.put("mBest", reportingBeans.get(overallScoringSystem.getMReportingName())); reportingBeans.put("wBest", reportingBeans.get(overallScoringSystem.getWReportingName())); setReportingBeans(reportingBeans); @@ -152,7 +159,7 @@ protected void setReportingInfo() { * @param workbook */ private void translateSheets(Workbook workbook) { - logger.debug("translating sheets {}", OwlcmsSession.getLocale()); + this.logger.debug("translating sheets {}", OwlcmsSession.getLocale()); int nbSheets = workbook.getNumberOfSheets(); for (int sheetIndex = 0; sheetIndex < nbSheets; sheetIndex++) { Sheet curSheet = workbook.getSheetAt(sheetIndex); @@ -162,7 +169,7 @@ private void translateSheets(Workbook workbook) { try { workbook.setSheetName(sheetIndex, translatedSheetName != null ? translatedSheetName : sheetName); } catch (Exception e) { - workbook.setSheetName(sheetIndex, (translatedSheetName != null ? translatedSheetName : sheetName)+"."); + workbook.setSheetName(sheetIndex, (translatedSheetName != null ? translatedSheetName : sheetName) + "."); } String leftHeader = Translator.translateOrElseNull("CompetitionBook." + sheetName + "_LeftHeader", @@ -172,7 +179,7 @@ private void translateSheets(Workbook workbook) { } else { curSheet.getHeader().setLeft(leftHeader != null ? leftHeader : ""); } - + String centerHeader = Translator.translateOrElseNull("CompetitionBook." + sheetName + "_CenterHeader", OwlcmsSession.getLocale()); if (centerHeader == null) { @@ -187,8 +194,8 @@ private void translateSheets(Workbook workbook) { OwlcmsSession.getLocale()); if (rightHeader == null && translatedSheetName != null) { curSheet.getHeader().setRight(translatedSheetName); - } else { - curSheet.getHeader().setRight(rightHeader != null ? rightHeader: ""); + } else { + curSheet.getHeader().setRight(rightHeader != null ? rightHeader : ""); } createStandardFooter(workbook); @@ -210,12 +217,4 @@ private void translateSheets(Workbook workbook) { } } - public boolean isIncludeUnfinished() { - return isIncludeUnfinished; - } - - public void setIncludeUnfinished(boolean isIncludeUnifinished) { - this.isIncludeUnfinished = isIncludeUnifinished; - } - } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSExportRecords.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSExportRecords.java index c935fd599a..75277625ef 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSExportRecords.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSExportRecords.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -108,13 +108,13 @@ public List getSortedAthletes() { this.records = RecordRepository.findFiltered(null, null, null, groupName, !this.isAllRecords()); if (this.currentOnly) { var recordMap = this.keepNewest(); - this.records = new ArrayList(recordMap.values().stream().toList()); + this.records = new ArrayList<>(recordMap.values().stream().toList()); this.records.sort(sortRecords()); } else { this.records.sort(sortRecords()); } Map> grouped = groupByAgeGroup(this.records); - List>> list = new ArrayList>>(); + List>> list = new ArrayList<>(); for (Entry> v : grouped.entrySet()) { list.add(v); } @@ -122,16 +122,47 @@ public List getSortedAthletes() { reportingBeans.put("records", this.records); return athletes; } - - private Map> groupByAgeGroup(List events) { - Map> groupedEvents = new LinkedHashMap<>(); - for (RecordEvent record : events) { - String ageGroup = record.getAgeGrp(); - boolean masters = record.getAgeGrpLower() >= 30 && (record.getAgeGrp().startsWith("W") || record.getAgeGrp().startsWith("M")); - groupedEvents.computeIfAbsent(masters ? ageGroup : ageGroup+" "+record.getTranslatedGender(), k -> new ArrayList<>()).add(record); - } - return groupedEvents; - } + + @Override + public InputStream getTemplate(Locale locale) throws IOException { + if (this.inputStream != null) { + this.logger.debug("explicitly set template {}", this.inputStream); + return new BufferedInputStream(this.inputStream); + } + this.logger.debug("getTemplate {}", LoggerUtils.whereFrom()); + return getLocalizedTemplate("/templates/records/exportRecords", ".xls", locale); + } + + public Map keepNewest() { + return this.records.stream() + .collect(Collectors.groupingBy( + RecordEvent::getKey, + Collectors.collectingAndThen( + Collectors.maxBy((r1, r2) -> r1.getRecordLift().compareTo(r2.getRecordLift())), + record -> record.orElseThrow(() -> new IllegalStateException("No record found"))))); + } + + @Override + public void setGroup(Group group) { + this.group = group; + } + + public Comparator sortRecords() { + return Comparator + .comparing(RecordEvent::getRecordFederation) // all records for a federation go together (masters are + // separate) + .thenComparing(RecordEvent::getRecordName) // sometimes several record names for same federation + // (example: event-specific) + .thenComparing(RecordEvent::getGender) // all women, then all men + .thenComparing(RecordEvent::getAgeGrpUpper) // U13 U15 U17 U20 U23 SR + // open has biggest age gap, goes after masters M85 and W85 + .thenComparing((a, b) -> ObjectUtils.compare((a.getAgeGrpUpper() - a.getAgeGrpLower()), (b.getAgeGrpUpper() - b.getAgeGrpLower()))) + .thenComparing(RecordEvent::getAgeGrpLower) // increasing age groups for masters (35, 40, 45...) + .thenComparing(RecordEvent::getBwCatUpper) // increasing body weights + .thenComparing((r) -> r.getRecordLift().ordinal()) // SNATCH, CJ, TOTAL + .thenComparing(RecordEvent::getRecordValue) // increasing records + ; + } @Override protected void setReportingInfo() { @@ -149,11 +180,11 @@ protected void setReportingInfo() { // reuse existing logic for processing records JXLSExportRecords jxlsExportRecords = this; // jxlsExportRecords.setGroup(getGroup()); - logger.debug("fetching records for session {} category {}", getGroup(), getCategory()); + this.logger.debug("fetching records for session {} category {}", getGroup(), getCategory()); try { // Must be called as soon as possible after getSortedAthletes() List records = jxlsExportRecords.getRecords(getCategory()); - logger.debug("{} records found", records.size()); + this.logger.debug("{} records found", records.size()); for (RecordEvent e : records) { if (e.getBwCatUpper() > 250) { e.setBwCatString(">" + e.getBwCatLower()); @@ -161,7 +192,6 @@ protected void setReportingInfo() { e.setBwCatString(Integer.toString(e.getBwCatUpper())); } } - ; getReportingBeans().put("records", records); } catch (Exception e) { // no records @@ -179,53 +209,22 @@ protected void setReportingInfo() { getReportingBeans().put("sessions", sessions); } - @Override - public InputStream getTemplate(Locale locale) throws IOException { - if (this.inputStream != null) { - logger.debug("explicitly set template {}", this.inputStream); - return new BufferedInputStream(this.inputStream); + private Map> groupByAgeGroup(List events) { + Map> groupedEvents = new LinkedHashMap<>(); + for (RecordEvent record : events) { + String ageGroup = record.getAgeGrp(); + boolean masters = record.getAgeGrpLower() >= 30 && (record.getAgeGrp().startsWith("W") || record.getAgeGrp().startsWith("M")); + groupedEvents.computeIfAbsent(masters ? ageGroup : ageGroup + " " + record.getTranslatedGender(), k -> new ArrayList<>()).add(record); } - logger.debug("getTemplate {}", LoggerUtils.whereFrom()); - return getLocalizedTemplate("/templates/records/exportRecords", ".xls", locale); - } - - @Override - public void setGroup(Group group) { - this.group = group; - } - - public Comparator sortRecords() { - return Comparator - .comparing(RecordEvent::getRecordFederation) // all records for a federation go together (masters are - // separate) - .thenComparing(RecordEvent::getRecordName) // sometimes several record names for same federation - // (example: event-specific) - .thenComparing(RecordEvent::getGender) // all women, then all men - .thenComparing(RecordEvent::getAgeGrpUpper) // U13 U15 U17 U20 U23 SR - // open has biggest age gap, goes after masters M85 and W85 - .thenComparing((a,b) -> ObjectUtils.compare((a.getAgeGrpUpper() - a.getAgeGrpLower()), (b.getAgeGrpUpper() - b.getAgeGrpLower()))) - .thenComparing(RecordEvent::getAgeGrpLower) // increasing age groups for masters (35, 40, 45...) - .thenComparing(RecordEvent::getBwCatUpper) // increasing body weights - .thenComparing((r) -> r.getRecordLift().ordinal()) // SNATCH, CJ, TOTAL - .thenComparing(RecordEvent::getRecordValue) // increasing records - ; - } - - public Map keepNewest() { - return records.stream() - .collect(Collectors.groupingBy( - RecordEvent::getKey, - Collectors.collectingAndThen( - Collectors.maxBy((r1, r2) -> r1.getRecordLift().compareTo(r2.getRecordLift())), - record -> record.orElseThrow(() -> new IllegalStateException("No record found"))))); + return groupedEvents; } private boolean isAllRecords() { - return allRecords; + return this.allRecords; } private void setAllRecords(boolean allRecords) { - //logger.debug("***** allRecords = {} {}", allRecords, LoggerUtils.whereFrom()); + // logger.debug("***** allRecords = {} {}", allRecords, LoggerUtils.whereFrom()); this.allRecords = allRecords; } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSJurySheet.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSJurySheet.java index d0a90cd525..511296e9bc 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSJurySheet.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSJurySheet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -26,7 +26,7 @@ public class JXLSJurySheet extends JXLSWorkbookStreamSource { Logger logger = LoggerFactory.getLogger(JXLSJurySheet.class); -// private int nbAthletes; + // private int nbAthletes; public JXLSJurySheet() { } @@ -35,42 +35,40 @@ public JXLSJurySheet() { public List getSortedAthletes() { List athletes = AthleteSorter .displayOrderCopy(AthleteRepository.findAllByGroupAndWeighIn(getGroup(), isExcludeNotWeighed())); -// this.nbAthletes = athletes.size(); + // this.nbAthletes = athletes.size(); return athletes; } /* * (non-Javadoc) * - * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# - * configureTransformer(net.sf.jxls.transformer.XLSTransformer ) + * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# configureTransformer(net.sf.jxls.transformer.XLSTransformer ) */ -// @Override -// protected void configureTransformer(XLSTransformer transformer) { -// String fileName = Competition.getCurrent().getComputedJuryTemplateFileName(); -// if (!fileName.startsWith("Jury.")) { -// transformer.markAsFixedSizeCollection("athletes"); -// } else { -// this.logger./**/warn/**/("not setting fixed size"); -// } -// } + // @Override + // protected void configureTransformer(XLSTransformer transformer) { + // String fileName = Competition.getCurrent().getComputedJuryTemplateFileName(); + // if (!fileName.startsWith("Jury.")) { + // transformer.markAsFixedSizeCollection("athletes"); + // } else { + // this.logger./**/warn/**/("not setting fixed size"); + // } + // } /* * (non-Javadoc) * - * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# - * postProcess(org.apache.poi.ss.usermodel.Workbook) + * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# postProcess(org.apache.poi.ss.usermodel.Workbook) */ -// @Override -// protected void postProcess(Workbook workbook) { -// String tfn = Competition.getCurrent().getComputedJuryTemplateFileName(); -// if (tfn.startsWith("Jury.") || tfn.startsWith("Jury-")) { -// // 11 is the number of lines if 0 athletes were present. -// setPageBreaks(workbook, 11 + nbAthletes); -// } else { -// setPageBreaks(workbook, 13 + nbAthletes); -// } -// } + // @Override + // protected void postProcess(Workbook workbook) { + // String tfn = Competition.getCurrent().getComputedJuryTemplateFileName(); + // if (tfn.startsWith("Jury.") || tfn.startsWith("Jury-")) { + // // 11 is the number of lines if 0 athletes were present. + // setPageBreaks(workbook, 11 + nbAthletes); + // } else { + // setPageBreaks(workbook, 13 + nbAthletes); + // } + // } protected void setPageBreaks(Workbook workbook, int line) { Sheet sheet = workbook.getSheetAt(0); diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalSchedule.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalSchedule.java index 0910283132..a103fd0ff8 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalSchedule.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalSchedule.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -69,48 +69,48 @@ public class SessionStats { this.session = session; } - List computeSessionCategories() { - TreeSet sessionCategories = new TreeSet<>(); - for (Athlete a : session.getAthletes()) { - if (this.gender != null && a.getGender() != this.gender) { - continue; - } - sessionCategories.addAll(a.getEligibleCategories()); - } - ArrayList returned = new ArrayList(); - returned.addAll(sessionCategories); - return returned; + public TreeSet getCategories() { + return this.categories; } public String getCategoriesAsString() { return getCategories().stream().map(c -> c.toString()).distinct().collect(Collectors.joining(", ")); } - public void setCategoriesAsString(String unused) { + public Gender getGender() { + return this.gender; } - public TreeSet getCategories() { - return categories; + public Group getSession() { + return this.session; } public void setCategories(List newCategories) { - this.categories = new TreeSet(newCategories); + this.categories = new TreeSet<>(newCategories); } - public Group getSession() { - return session; + public void setCategoriesAsString(String unused) { } - public void setSession(Group session) { - this.session = session; + public void setGender(Gender gender) { + this.gender = gender; } - public Gender getGender() { - return gender; + public void setSession(Group session) { + this.session = session; } - public void setGender(Gender gender) { - this.gender = gender; + List computeSessionCategories() { + TreeSet sessionCategories = new TreeSet<>(); + for (Athlete a : this.session.getAthletes()) { + if (this.gender != null && a.getGender() != this.gender) { + continue; + } + sessionCategories.addAll(a.getEligibleCategories()); + } + ArrayList returned = new ArrayList<>(); + returned.addAll(sessionCategories); + return returned; } } @@ -150,7 +150,7 @@ protected void setReportingInfo() { SessionStats sessionStats = new SessionStats(session); List newCategories = sessionStats.computeSessionCategories(); - //List ncCodes = newCategories.stream().map(c -> c.getCode()).toList(); + // List ncCodes = newCategories.stream().map(c -> c.getCode()).toList(); newCategories = newCategories.stream().filter(c -> !alreadyMedaledCodes.contains(c.getCode())).toList(); sessionStats.setCategories(newCategories); @@ -163,15 +163,15 @@ protected void setReportingInfo() { medalingPerSession.put(session, sessionStats); } - ArrayList all = new ArrayList(); + ArrayList all = new ArrayList<>(); all.addAll(medalingPerSession.values()); getReportingBeans().put("medalStatsPerSession", all); - ArrayList categories = new ArrayList(); + ArrayList categories = new ArrayList<>(); categorySessions.forEach((Category category, Group session) -> { categories.add(new CategoryStat(category, session)); }); - categories.sort((a, b) -> a.getCategory().compareTo(b.getCategory())) ; + categories.sort((a, b) -> a.getCategory().compareTo(b.getCategory())); getReportingBeans().put("medalStatsPerCategory", categories); } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalsSheet.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalsSheet.java index fff3b9678a..568c83e8b5 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalsSheet.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSMedalsSheet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -54,7 +54,7 @@ public List getSortedAthletes() { this.sortedAthletes = new ArrayList<>(); for (Entry> medalCat : medals.entrySet()) { List medalists = medalCat.getValue(); - //logger.debug("medalCat {} {}", medalCat.getKey(), medalCat.getValue().stream().map(a -> a.getAbbreviatedName()).toList()); + // logger.debug("medalCat {} {}", medalCat.getKey(), medalCat.getValue().stream().map(a -> a.getAbbreviatedName()).toList()); if (medalists != null && !medalists.isEmpty()) { for (Athlete p : medalists) { // logger.trace("Competition.getCurrent().isSnatchCJTotalMedals() @@ -72,11 +72,11 @@ public List getSortedAthletes() { } if (p.getComputedScoringSystem() == Ranking.TOTAL && p.getTotalRank() <= 3) { - //logger.debug("+++ adding total {}", p); + // logger.debug("+++ adding total {}", p); this.sortedAthletes .add(new MAthlete((PAthlete) p, Ranking.TOTAL, p.getTotalRank(), (double) p.getTotal())); } else if (p.getCategoryScoreRank() <= 3) { - //logger.debug("+++ adding score {}", p); + // logger.debug("+++ adding score {}", p); this.sortedAthletes .add(new MAthlete((PAthlete) p, Ranking.CATEGORY_SCORE, p.getCategoryScoreRank(), (p.getCategoryScore()))); } @@ -87,7 +87,7 @@ public List getSortedAthletes() { MAthlete[] array = this.sortedAthletes.toArray(new MAthlete[0]); Arrays.sort(array, new MAthlete.MedalComparator()); this.sortedAthletes = Arrays.asList(array).stream() - //.peek(m -> logger.debug("{} {} {} {}", m.getCategory(), m.getAbbreviatedName(), m.getRankingText(), m.getLiftRank())) + // .peek(m -> logger.debug("{} {} {} {}", m.getCategory(), m.getAbbreviatedName(), m.getRankingText(), m.getLiftRank())) .filter(m -> m.getLiftRank() >= 1 && m.getLiftRank() <= 3) .collect(Collectors.toList()); return this.sortedAthletes; diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistration.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistration.java index 83dcf16df9..c1e4b7b702 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistration.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistrationEmptyExport.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistrationEmptyExport.java index f274d24045..cb4eebeaca 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistrationEmptyExport.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSRegistrationEmptyExport.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSResultSheet.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSResultSheet.java index 3191739557..9f323f64a7 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSResultSheet.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSResultSheet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -124,8 +124,7 @@ public List getSortedAthletes() { /* * (non-Javadoc) * - * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# - * postProcess(org.apache.poi.ss.usermodel.Workbook) + * @see org.concordiainternational.competition.spreadsheet.JXLSWorkbookStreamSource# postProcess(org.apache.poi.ss.usermodel.Workbook) */ @Override protected void postProcess(Workbook workbook) { diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSSBDEExport.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSSBDEExport.java index 8a6296683c..da203ab1f3 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSSBDEExport.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSSBDEExport.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSStartingListDocs.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSStartingListDocs.java index 473a36e728..80b1e9d03f 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSStartingListDocs.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSStartingListDocs.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -208,14 +208,14 @@ public void createTeamColumns(int listColumn, int catColumn) { }); } + public Consumer getPostProcessor() { + return this.postProcessor; + } + @Override public boolean isEmptyOk() { return true; } - - public Consumer getPostProcessor() { - return this.postProcessor; - } // @Override // protected List getSortedAthletes() { diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSTimingStats.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSTimingStats.java index ea6e7f2a82..6a0f289bcc 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSTimingStats.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSTimingStats.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -195,14 +195,14 @@ public List getSortedAthletes() { List athletes = AthleteRepository.findAllByGroupAndWeighIn(null, isExcludeNotWeighed()); athletes = AthleteSorter.registrationExportCopy(athletes); - + if (athletes.isEmpty()) { // prevent outputting silliness. throw new RuntimeException(""); } else { this.logger.debug("{} athletes", athletes.size()); } - + List groups = GroupRepository.findAll(); groups.sort(Group.groupWeighinTimeComparator); @@ -218,15 +218,15 @@ public List getSortedAthletes() { if (curGroup == null) { continue; // we simply skip over athletes with no groups } - + // update stats, min, max. curStat.setNbAthletes(curStat.getNbAthletes() + 1); LocalDateTime minTime = curAthlete.getFirstAttemptedLiftTime(); curStat.updateMinTime(minTime); - + LocalDateTime maxTime = curAthlete.getLastAttemptedLiftTime(); curStat.updateMaxTime(maxTime); - + int nbAttemptedLifts = curAthlete.getActuallyAttemptedLifts(); curStat.setNbAttemptedLifts(curStat.getNbAttemptedLifts() + nbAttemptedLifts); this.logger.debug(curStat.toString()); diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWeighInSheet.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWeighInSheet.java index c9ebc25b4b..0947b73a65 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWeighInSheet.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWeighInSheet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -40,16 +40,16 @@ public JXLSWeighInSheet() { @Override public List getSortedAthletes() { final Group currentGroup = getGroup(); - List collect = AthleteSorter - .registrationOrderCopy(AthleteRepository.findAllByGroupAndWeighIn(currentGroup, null)).stream() - .map(a -> { - if (a.getTeam() == null) { - a.setTeam(""); - } - return a; - }).collect(Collectors.toList()); - // logger.debug("sorted by category {}", collect); - return collect; + List collect = AthleteSorter + .registrationOrderCopy(AthleteRepository.findAllByGroupAndWeighIn(currentGroup, null)).stream() + .map(a -> { + if (a.getTeam() == null) { + a.setTeam(""); + } + return a; + }).collect(Collectors.toList()); + // logger.debug("sorted by category {}", collect); + return collect; } } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWinningSheet.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWinningSheet.java index fb92bedf6e..bb8c62e94c 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWinningSheet.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWinningSheet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -56,34 +56,35 @@ public JXLSWinningSheet(boolean b) { @Override public List getSortedAthletes() { -// Championship championship = getChampionship(); + // Championship championship = getChampionship(); if (this.sortedAthletes != null) { -// logger.debug("%%% sorterdAthletes.size()={}",sortedAthletes.size()); + // logger.debug("%%% sorterdAthletes.size()={}",sortedAthletes.size()); // we are provided with an externally computed list. if (this.resultsByCategory) { Ranking rankingOrder = Ranking.CATEGORY_SCORE; -// if (championship != null && sortedAthletes.size() > 0) { -// Athlete athlete = sortedAthletes.get(0); -// rankingOrder = athlete.getAgeGroup().getComputedScoringSystem(); -// logger.debug("--- athlete {} scoring {}", athlete, rankingOrder); -// if (rankingOrder == null) { -// rankingOrder = Ranking.TOTAL; -// } -// } - + // if (championship != null && sortedAthletes.size() > 0) { + // Athlete athlete = sortedAthletes.get(0); + // rankingOrder = athlete.getAgeGroup().getComputedScoringSystem(); + // logger.debug("--- athlete {} scoring {}", athlete, rankingOrder); + // if (rankingOrder == null) { + // rankingOrder = Ranking.TOTAL; + // } + // } + AthleteSorter.resultsOrder(this.sortedAthletes, rankingOrder, ORDER_BY_CATEGORIES); return this.sortedAthletes; } else { // logger.debug("YYYYYYYYYYYY unique athletes"); // we need to expand all the participations before we filter down. - List allParticipations = Competition.getCurrent().mapToParticipations(this.sortedAthletes, resultsByCategory); + List allParticipations = Competition.getCurrent().mapToParticipations(this.sortedAthletes, this.resultsByCategory); // keep the the most specific category from the championship List uniqueAthletes = allParticipations.stream() .sorted((a, b) -> { int compare = ObjectUtils.compare(a.getLotNumber(), b.getLotNumber(), true); - if (compare != 0) + if (compare != 0) { return compare; + } return Category.specificityComparator.compare(a.getCategory(), b.getCategory()); }) .filter(p -> { @@ -118,7 +119,7 @@ public List getSortedAthletes() { // get all the PAthletes for the current group - athletes show as many times as // they have participations. - List pAthletes = Competition.getCurrent().mapToParticipations(rankedAthletes, resultsByCategory); + List pAthletes = Competition.getCurrent().mapToParticipations(rankedAthletes, this.resultsByCategory); // unfinished categories need to be computed using all relevant athletes, including not weighed-in yet @SuppressWarnings("unchecked") @@ -177,10 +178,6 @@ public List getSortedAthletes() { // @formatter:on } - private Ranking rankingOrder() { - return Ranking.CUSTOM; - } - /* * (non-Javadoc) * @@ -206,6 +203,8 @@ protected void postProcess(Workbook workbook) { createStandardFooter(workbook); } - + private Ranking rankingOrder() { + return Ranking.CUSTOM; + } } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWorkbookStreamSource.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWorkbookStreamSource.java index 763aad8c0c..9c861fc39f 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWorkbookStreamSource.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSWorkbookStreamSource.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -544,7 +544,7 @@ protected void setReportingInfo() { List athletes = getSortedAthletes(); if (athletes != null) { getReportingBeans().put("athletes", athletes); - //logger.debug("*** Athletes : {}",athletes.stream().map(a-> a.getCategory()).toList()); + // logger.debug("*** Athletes : {}",athletes.stream().map(a-> a.getCategory()).toList()); getReportingBeans().put("lifters", athletes); // legacy } Competition competition = Competition.getCurrent(); @@ -570,13 +570,13 @@ protected void setReportingInfo() { List sessions = GroupRepository.findAll().stream().sorted(Group.groupWeighinTimeComparator) .collect(Collectors.toList()); - + Ranking overallScoringSystem = this.getBestLifterScoringSystem(); overallScoringSystem = overallScoringSystem != null ? overallScoringSystem : Competition.getCurrent().getScoringSystem(); - + // make available to the Athlete class in this Thread (and subThreads). - JXLSWorkbookStreamSource.setBestLifterRankingThreadLocal(overallScoringSystem); - reportingBeans.put("bestRankingTitle",Ranking.getScoringTitle(overallScoringSystem)); + JXLSWorkbookStreamSource.setBestLifterRankingThreadLocal(overallScoringSystem); + this.reportingBeans.put("bestRankingTitle", Ranking.getScoringTitle(overallScoringSystem)); getReportingBeans().put("groups", sessions); getReportingBeans().put("sessions", sessions); diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/MAthlete.java b/owlcms/src/main/java/app/owlcms/spreadsheet/MAthlete.java index a34d33bd01..397336fa94 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/MAthlete.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/MAthlete.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.spreadsheet; import java.util.Comparator; @@ -57,10 +63,26 @@ public int getLiftRank() { return this.liftRank; } + public String getLiftResult() { + switch (this.ranking) { + case CLEANJERK: + case SNATCH: + case TOTAL: + int roundedValue = (int) Math.round(this.liftValue); + return String.valueOf(roundedValue); + default: + return String.format("%.3f", this.liftValue); + } + } + public double getLiftValue() { return this.liftValue; } + public String getMedalingSortCode() { + return getCategory().getMedalingSortCode(); + } + public Ranking getRanking() { return this.ranking; } @@ -78,10 +100,17 @@ public String getRankingText() { } } + public void setLiftResult() { + // unused + } + public void setLiftResult(double d) { this.liftValue = d; } + public void setMedalingSortCode(String unused) { + } + public void setRanking(Ranking ranking) { this.ranking = ranking; } @@ -92,28 +121,5 @@ public void setRankingText() { private void setLiftRank(int catMedalRank) { this.liftRank = catMedalRank; } - - public String getLiftResult() { - switch (this.ranking) { - case CLEANJERK: - case SNATCH: - case TOTAL: - int roundedValue = (int) Math.round(this.liftValue); - return String.valueOf(roundedValue); - default: - return String.format("%.3f", this.liftValue); - } - } - - public void setLiftResult() { - // unused - } - - public String getMedalingSortCode() { - return getCategory().getMedalingSortCode(); - } - - public void setMedalingSortCode(String unused) { - } } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/NRegistrationFileProcessor.java b/owlcms/src/main/java/app/owlcms/spreadsheet/NRegistrationFileProcessor.java index f448d7d2dc..04b4d51881 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/NRegistrationFileProcessor.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/NRegistrationFileProcessor.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.spreadsheet; import java.io.IOException; @@ -392,9 +398,22 @@ private String cellToString(Cell cell) { } } + private boolean checkTranslation(String valueRead, String string) { + String translate = Translator.translate(string); + String translate2 = Translator.translateExplicitLocale(string, Locale.ENGLISH); + return valueRead.contentEquals(translate) + || valueRead.contentEquals(translate2); + } + + private boolean checkTranslation(String valueRead, String string, String string2) { + return valueRead.contentEquals(Translator.translate(string) + " " + Translator.translate(string2)) + || valueRead.contentEquals(Translator.translateExplicitLocale(string, Locale.ENGLISH) + " " + + Translator.translateExplicitLocale(string2, Locale.ENGLISH)); + } + private void processException(RAthlete a, String s, Cell c, Exception e, Consumer errorConsumer) { errorConsumer.accept(c.getAddress() + " " + e.getLocalizedMessage() + System.lineSeparator()); - logger.error("{} {} {}", c.getAddress(), s, e.getMessage()); + this.logger.error("{} {} {}", c.getAddress(), s, e.getMessage()); // LoggerUtils.logError(this.logger, e, true); } @@ -453,7 +472,7 @@ private AthleteInput readAthletes(Workbook workbook, RCompetition rComp, Consume } a.setGender(s); } catch (Exception e) { - processException(a, s, c, new Exception(Translator.translate("Registration.IllegalGender",s)), errorConsumer); + processException(a, s, c, new Exception(Translator.translate("Registration.IllegalGender", s)), errorConsumer); } }); } else if (checkTranslation(trimmedCellValue, "Card.category")) { @@ -630,17 +649,4 @@ private AthleteInput readAthletes(Workbook workbook, RCompetition rComp, Consume return new AthleteInput(athletes); } - private boolean checkTranslation(String valueRead, String string, String string2) { - return valueRead.contentEquals(Translator.translate(string) + " " + Translator.translate(string2)) - || valueRead.contentEquals(Translator.translateExplicitLocale(string, Locale.ENGLISH) + " " - + Translator.translateExplicitLocale(string2, Locale.ENGLISH)); - } - - private boolean checkTranslation(String valueRead, String string) { - String translate = Translator.translate(string); - String translate2 = Translator.translateExplicitLocale(string, Locale.ENGLISH); - return valueRead.contentEquals(translate) - || valueRead.contentEquals(translate2); - } - } \ No newline at end of file diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/ORegistrationFileProcessor.java b/owlcms/src/main/java/app/owlcms/spreadsheet/ORegistrationFileProcessor.java index a216518a49..fece8e978d 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/ORegistrationFileProcessor.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/ORegistrationFileProcessor.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.spreadsheet; import java.io.IOException; diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/PAthlete.java b/owlcms/src/main/java/app/owlcms/spreadsheet/PAthlete.java index 2c69794bef..04fe102421 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/PAthlete.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/PAthlete.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -32,8 +32,8 @@ /** * Fake athlete that belongs to a single category. * - * Used to produce results and team rankings for a given eligibility category. Use athlete as a basis, and a copy of the - * participation to the eligible category to recover ranks and points. + * Used to produce results and team rankings for a given eligibility category. Use athlete as a basis, and a copy of the participation to the eligible category + * to recover ranks and points. * * @author Jean-François Lamy * @@ -49,36 +49,18 @@ public class PAthlete extends Athlete implements IRankHolder { private Participation originalParticipation; private Participation p; - public PAthlete(Participation p) { - this.a = p.getAthlete(); - this.c = p.getCategory(); - this.p = new Participation(p, this.a, this.c); - this.originalParticipation = p; - } - public PAthlete(Athlete a2) { this.a = a2; this.c = a2.getCategory(); this.p = a2.getMainRankings(); - this.originalParticipation = p; + this.originalParticipation = this.p; } - @Override - public Boolean getCategoryFinished() { - var allUnfinished = AthleteRepository.getAllUnfinishedCategories(); - String code = c.getCode(); - boolean contains = allUnfinished.contains(code); - return !contains; - } - - @Override - public Boolean isCategoryFinished() { - return getCategoryFinished(); - } - - @Override - public void setCategoryFinished(Boolean done) { - a.setCategoryFinished(done); + public PAthlete(Participation p) { + this.a = p.getAthlete(); + this.c = p.getCategory(); + this.p = new Participation(p, this.a, this.c); + this.originalParticipation = p; } /** @@ -173,6 +155,16 @@ public LocalDateTime getBestCleanJerkAttemptTime() { return this.a.getBestCleanJerkAttemptTime(); } + @Override + public int getBestLifterRank() { + return this.a.getBestLifterRank(); + } + + @Override + public Double getBestLifterScore() { + return this.a.getBestLifterScore(); + } + @Override public int getBestResultAttemptNumber() { return this.a.getBestResultAttemptNumber(); @@ -219,6 +211,19 @@ public String getCategoryCode() { return category != null ? category.getCode() : null; } + @Override + public Boolean getCategoryFinished() { + var allUnfinished = AthleteRepository.getAllUnfinishedCategories(); + String code = this.c.getCode(); + boolean contains = allUnfinished.contains(code); + return !contains; + } + + @Override + public int getCategoryScoreRank() { + return this.p.getCategoryScoreRank(); + } + @Override public Double getCategorySinclair() { return this.a.getCategorySinclair(); @@ -592,6 +597,16 @@ public LocalDateTime getPreviousLiftTime() { return this.a.getPreviousLiftTime(); } + @Override + public Double getQAge() { + return this.a.getQAge(); + } + + @Override + public int getqAgeRank() { + return this.a.getqAgeRank(); + } + @Override public Integer getQualifyingTotal() { return this.a.getQualifyingTotal(); @@ -632,16 +647,6 @@ public String getRoundedBodyWeight() { return this.a.getRoundedBodyWeight(); } - @Override - public Double getBestLifterScore() { - return this.a.getBestLifterScore(); - } - - @Override - public int getBestLifterRank() { - return this.a.getBestLifterRank(); - } - @Override public String getSessionPattern() { return this.a.getSessionPattern(); @@ -682,19 +687,14 @@ public Integer getSinclairRank() { return this.a.getSinclairRank(); } - @Override - public Double getSmhfForDelta() { - return this.a.getSmhfForDelta(); - } - @Override public Double getSmhf() { return this.a.getSmhf(); } @Override - public Double getQAge() { - return this.a.getQAge(); + public Double getSmhfForDelta() { + return this.a.getSmhfForDelta(); } @Override @@ -702,11 +702,6 @@ public int getSmhfRank() { return this.a.getSmhfRank(); } - @Override - public int getqAgeRank() { - return this.a.getqAgeRank(); - } - @Override public String getSnatch1ActualLift() { String snatch1ActualLift = this.a.getSnatch1ActualLift(); @@ -903,11 +898,6 @@ public int getTotalRank() { return this.p.getTotalRank(); } - @Override - public int getCategoryScoreRank() { - return this.p.getCategoryScoreRank(); - } - @Override public Integer getYearOfBirth() { return this.a.getYearOfBirth(); @@ -926,6 +916,11 @@ public boolean isATeamMember() { return this.a.isATeamMember(); } + @Override + public Boolean isCategoryFinished() { + return getCategoryFinished(); + } + @Override public int isDeclaring() { return this.a.isDeclaring(); @@ -966,6 +961,11 @@ public String longDump() { return this.a.longDump(); } + @Override + public void setCategoryFinished(Boolean done) { + this.a.setCategoryFinished(done); + } + @Override public void setCatSinclairRank(int i) { this.a.setCatSinclairRank(i); @@ -1001,6 +1001,11 @@ public void setPersonalBestTotal(Integer personalBestTotal) { this.a.setPersonalBestTotal(personalBestTotal); } + @Override + public void setqAgeRank(int i) { + this.a.setqAgeRank(i); + } + @Override public void setRobiRank(Integer robiRank) { this.a.setRobiRank(robiRank); @@ -1021,11 +1026,6 @@ public void setSmhfRank(int i) { this.a.setSmhfRank(i); } - @Override - public void setqAgeRank(int i) { - this.a.setqAgeRank(i); - } - @Override public void setTeamCleanJerkRank(Integer teamCJRank) { this.p.setTeamCleanJerkRank(teamCJRank); diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/RAthlete.java b/owlcms/src/main/java/app/owlcms/spreadsheet/RAthlete.java index ab2faeed4d..2aa5fe3c48 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/RAthlete.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/RAthlete.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -49,8 +49,8 @@ public class RAthlete { } public RAthlete() { - a = new Athlete(); - a.setCategoryFinished(false); + this.a = new Athlete(); + this.a.setCategoryFinished(false); } public Athlete getAthlete() { @@ -92,80 +92,6 @@ public void setCategory(String s) throws Exception { } - private void doLegacyParts(String s, String[] parts) throws Exception { - if (parts.length >= 1) { - boolean teamMember = false; - String catName = parts[0].trim(); - if (!Config.getCurrent().featureSwitch("explicitTeams")) { - // teams are implicitly selected, check for team exclusion marker. - teamMember = true; - if (catName.endsWith(NoTeamMarker)) { - catName = catName.substring(0, s.length() - NoTeamMarker.length()); - teamMember = false; - } else if (catName.endsWith("/")) { - catName = catName.substring(0, s.length() - "/".length()); - teamMember = false; - } - } - - Category c; - String catCode = Category.codeFromName(catName); - // logger.debug("catCode {} active {}",catCode,RCompetition.getActiveCategories().keySet()); - if ((c = RCompetition.getActiveCategories().get(catCode)) != null) { - // exact match for a category. This is the athlete's registration category. - processEligibilityAndTeams(parts, c, teamMember); - } else { - if (parts.length == 1) { - // we have a short form category. infer from age and category limit - setCategoryHeuristics(catName); - final var tm = teamMember; - this.a.getParticipations().stream().forEach(p -> p.setTeamMember(tm)); - } else { - throw new Exception( - Translator.translate("Upload.CategoryNotFoundByName", catName.trim())); - } - - } - } - } - - private void getPartsWithSeparator(String s) throws Exception { - if (s == null || s.isBlank()) { - return; - } - // create a parts as in the legacy - if (Config.getCurrent().featureSwitch("usawSessionBlocks")) { - s = s.replaceAll("(\\d+)\\s?kg", "$1"); - } - - String[] allParts = s.split(",|;|\\/"); - List partsList = Arrays.asList(allParts).stream() - .filter(s1 -> (s1 != null && !s1.isBlank())) - .map(s1 -> s1.trim()) - .toList(); - // logger.debug("partsList {}",partsList); - - String[] parts; - if (partsList.size() == 1) { - parts = new String[1]; - parts[0] = partsList.get(0); - doLegacyParts(s, parts); - } else if (partsList.size() >= 1) { - parts = new String[2]; - parts[0] = partsList.get(0); - // brain-dead logic to reuse existing code. Should fix old to use new instead... - StringBuffer sb = new StringBuffer(); - for (int i = 1; i < partsList.size(); i++) { - if (i > 1) { - sb.append(";"); - } - sb.append(partsList.get(i).trim()); - } - parts[1] = sb.toString(); - doLegacyParts(s, parts); - } - } - /** * @param s */ @@ -388,6 +314,43 @@ private boolean addIfEligible(Set eligibleCategories, Set te return added; } + private void doLegacyParts(String s, String[] parts) throws Exception { + if (parts.length >= 1) { + boolean teamMember = false; + String catName = parts[0].trim(); + if (!Config.getCurrent().featureSwitch("explicitTeams")) { + // teams are implicitly selected, check for team exclusion marker. + teamMember = true; + if (catName.endsWith(NoTeamMarker)) { + catName = catName.substring(0, s.length() - NoTeamMarker.length()); + teamMember = false; + } else if (catName.endsWith("/")) { + catName = catName.substring(0, s.length() - "/".length()); + teamMember = false; + } + } + + Category c; + String catCode = Category.codeFromName(catName); + // logger.debug("catCode {} active {}",catCode,RCompetition.getActiveCategories().keySet()); + if ((c = RCompetition.getActiveCategories().get(catCode)) != null) { + // exact match for a category. This is the athlete's registration category. + processEligibilityAndTeams(parts, c, teamMember); + } else { + if (parts.length == 1) { + // we have a short form category. infer from age and category limit + setCategoryHeuristics(catName); + final var tm = teamMember; + this.a.getParticipations().stream().forEach(p -> p.setTeamMember(tm)); + } else { + throw new Exception( + Translator.translate("Upload.CategoryNotFoundByName", catName.trim())); + } + + } + } + } + private Category findByAgeBW(Matcher legacyResult, double searchBodyWeight, int age, int qualifyingTotal) throws Exception { // List found = CategoryRepository.findByGenderAgeBW(a.getGender(), age, searchBodyWeight); @@ -435,6 +398,43 @@ private Pattern getLegacyPattern() { return this.legacyPattern; } + private void getPartsWithSeparator(String s) throws Exception { + if (s == null || s.isBlank()) { + return; + } + // create a parts as in the legacy + if (Config.getCurrent().featureSwitch("usawSessionBlocks")) { + s = s.replaceAll("(\\d+)\\s?kg", "$1"); + } + + String[] allParts = s.split(",|;|\\/"); + List partsList = Arrays.asList(allParts).stream() + .filter(s1 -> (s1 != null && !s1.isBlank())) + .map(s1 -> s1.trim()) + .toList(); + // logger.debug("partsList {}",partsList); + + String[] parts; + if (partsList.size() == 1) { + parts = new String[1]; + parts[0] = partsList.get(0); + doLegacyParts(s, parts); + } else if (partsList.size() >= 1) { + parts = new String[2]; + parts[0] = partsList.get(0); + // brain-dead logic to reuse existing code. Should fix old to use new instead... + StringBuffer sb = new StringBuffer(); + for (int i = 1; i < partsList.size(); i++) { + if (i > 1) { + sb.append(";"); + } + sb.append(partsList.get(i).trim()); + } + parts[1] = sb.toString(); + doLegacyParts(s, parts); + } + } + private void processEligibilityAndTeams(String[] parts, Category c, boolean mainCategoryTeamMember) throws Exception { Set eligibleCategories = new LinkedHashSet<>(); @@ -493,7 +493,7 @@ private void setCategoryHeuristics(String categoryName) throws Exception { } this.a.setCategory(category); return; - } else { + } else { fixLegacyGender(legacyResult); if (!legacyResult.group(2).isEmpty() || !legacyResult.group(4).isEmpty()) { // > or + diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/RCompetition.java b/owlcms/src/main/java/app/owlcms/spreadsheet/RCompetition.java index 890418ce80..aae12c3952 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/RCompetition.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/RCompetition.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -27,6 +27,7 @@ public class RCompetition { static Map activeGroups = new HashMap<>(); static Map> athleteToEligibles = new HashMap<>(); static Map> athleteToTeams = new HashMap<>(); + static Logger logger = (Logger) LoggerFactory.getLogger(RCompetition.class); public static Map getActiveCategories() { return activeCategories; @@ -54,7 +55,7 @@ public static void resetActiveCategories() { public static void resetActiveGroups() { activeGroups.clear(); GroupRepository.findAll().forEach(g -> { - //logger.debug("adding group {}",g.getName()); + // logger.debug("adding group {}",g.getName()); activeGroups.put(g.getName(), g); }); } @@ -68,7 +69,6 @@ public static void resetAthleteToTeams() { } Competition c = new Competition(); - static Logger logger = (Logger) LoggerFactory.getLogger(RCompetition.class); public void addGroup(Group g) { activeGroups.put(g.getName(), g); diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/RGroup.java b/owlcms/src/main/java/app/owlcms/spreadsheet/RGroup.java index 968b660acc..e8f0063103 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/RGroup.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/RGroup.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXAgeGroupsExport.java b/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXAgeGroupsExport.java index 0dab1fc212..a833886f20 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXAgeGroupsExport.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXAgeGroupsExport.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.spreadsheet; import java.io.OutputStream; diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXWorkbookStreamSource.java b/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXWorkbookStreamSource.java index dbf5c70722..ce89ec1196 100644 --- a/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXWorkbookStreamSource.java +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/XLSXWorkbookStreamSource.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -21,8 +21,8 @@ import ch.qos.logback.classic.Logger; /** - * Encapsulate a spreadsheet as a StreamSource so that it can be used as a source of data when the user clicks on a - * link. This class converts the output stream to an input stream that the vaadin framework can consume. + * Encapsulate a spreadsheet as a StreamSource so that it can be used as a source of data when the user clicks on a link. This class converts the output stream + * to an input stream that the vaadin framework can consume. */ @SuppressWarnings("serial") public abstract class XLSXWorkbookStreamSource implements InputStreamFactory { diff --git a/owlcms/src/main/java/app/owlcms/uievents/AppEvent.java b/owlcms/src/main/java/app/owlcms/uievents/AppEvent.java index 034d5f3ab8..c243de582a 100644 --- a/owlcms/src/main/java/app/owlcms/uievents/AppEvent.java +++ b/owlcms/src/main/java/app/owlcms/uievents/AppEvent.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.uievents; import com.vaadin.flow.component.UI; diff --git a/owlcms/src/main/java/app/owlcms/uievents/BreakDisplay.java b/owlcms/src/main/java/app/owlcms/uievents/BreakDisplay.java index 2bc94480c2..9c97cb49fd 100644 --- a/owlcms/src/main/java/app/owlcms/uievents/BreakDisplay.java +++ b/owlcms/src/main/java/app/owlcms/uievents/BreakDisplay.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -27,7 +27,7 @@ public default String inferGroupName() { } public default String inferGroupName(CeremonyType ceremonyType) { - //logger.debug("inferGroupName {}\n{}",ceremonyType,LoggerUtils.stackTrace()); + // logger.debug("inferGroupName {}\n{}",ceremonyType,LoggerUtils.stackTrace()); FieldOfPlay fop = OwlcmsSession.getFop(); if (fop == null || ceremonyType == CeremonyType.MEDALS) { return ""; diff --git a/owlcms/src/main/java/app/owlcms/uievents/BreakType.java b/owlcms/src/main/java/app/owlcms/uievents/BreakType.java index 61d6af44e0..a263482be0 100644 --- a/owlcms/src/main/java/app/owlcms/uievents/BreakType.java +++ b/owlcms/src/main/java/app/owlcms/uievents/BreakType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 @@ -8,13 +8,12 @@ /** *

    - * A break type is either a countdown, or a ceremony taking place during a countdown. When a ceremony is taking place, a - * countdown timer MUST be running with the state that we go to when the ceremony ends. + * A break type is either a countdown, or a ceremony taking place during a countdown. When a ceremony is taking place, a countdown timer MUST be running with + * the state that we go to when the ceremony ends. *

    *

    - * Rule: because it is possible to hide/show the break dialog, the break timer shown on entry is the one already set or - * running. So the timer must be set at the end of the previous break. E.g. end of BEFORE_INTRODUCTION sets - * BEFORE_SNATCH 10:00 minutes as the duration, and pauses the timer. + * Rule: because it is possible to hide/show the break dialog, the break timer shown on entry is the one already set or running. So the timer must be set at the + * end of the previous break. E.g. end of BEFORE_INTRODUCTION sets BEFORE_SNATCH 10:00 minutes as the duration, and pauses the timer. *

    *
      *
    1. Medals for group 1 before introduction of group 2, countdown started *after* medals @@ -42,8 +41,7 @@ * CURRENT_ATHLETE_DISPLAYED *
  • * - *
  • Medals for group 1 given after the introduction of the next group 2. Officials before or after medals does not - * matter. + *
  • Medals for group 1 given after the introduction of the next group 2. Officials before or after medals does not matter. * *
      * GROUP_DONE (indefinite timer, end break = resume current group that was just done)
    @@ -73,8 +71,7 @@
      * 
  • * * - *
  • Doable even though not compliant with rules: first snatch at scheduled time, no introduction timer (introduction - * done informally) + *
  • Doable even though not compliant with rules: first snatch at scheduled time, no introduction timer (introduction done informally) * *
      * GROUP_DONE (indefinite timer, manual end break = resume current group that was just done)
    diff --git a/owlcms/src/main/java/app/owlcms/uievents/CeremonyType.java b/owlcms/src/main/java/app/owlcms/uievents/CeremonyType.java
    index b00a975ccc..c958ee744c 100644
    --- a/owlcms/src/main/java/app/owlcms/uievents/CeremonyType.java
    +++ b/owlcms/src/main/java/app/owlcms/uievents/CeremonyType.java
    @@ -1,5 +1,5 @@
     /*******************************************************************************
    - * Copyright (c) 2009-2023 Jean-François Lamy
    + * Copyright © 2009-present Jean-François Lamy
      *
      * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
      * License text at https://opensource.org/licenses/NPOSL-3.0
    diff --git a/owlcms/src/main/java/app/owlcms/uievents/DecisionEventType.java b/owlcms/src/main/java/app/owlcms/uievents/DecisionEventType.java
    index 0f3fbd0400..e565d26633 100644
    --- a/owlcms/src/main/java/app/owlcms/uievents/DecisionEventType.java
    +++ b/owlcms/src/main/java/app/owlcms/uievents/DecisionEventType.java
    @@ -1,5 +1,5 @@
     /*******************************************************************************
    - * Copyright (c) 2009-2023 Jean-François Lamy
    + * Copyright © 2009-present Jean-François Lamy
      *
      * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
      * License text at https://opensource.org/licenses/NPOSL-3.0
    diff --git a/owlcms/src/main/java/app/owlcms/uievents/JuryDeliberationEventType.java b/owlcms/src/main/java/app/owlcms/uievents/JuryDeliberationEventType.java
    index 3baf993944..098fa95589 100644
    --- a/owlcms/src/main/java/app/owlcms/uievents/JuryDeliberationEventType.java
    +++ b/owlcms/src/main/java/app/owlcms/uievents/JuryDeliberationEventType.java
    @@ -1,5 +1,5 @@
     /*******************************************************************************
    - * Copyright (c) 2009-2023 Jean-François Lamy
    + * Copyright © 2009-present Jean-François Lamy
      *
      * Licensed under the Non-Profit Open Software License version 3.0  ("NPOSL-3.0")
      * License text at https://opensource.org/licenses/NPOSL-3.0
    diff --git a/owlcms/src/main/java/app/owlcms/uievents/UIEvent.java b/owlcms/src/main/java/app/owlcms/uievents/UIEvent.java
    index beb60cc26f..45025c72e0 100644
    --- a/owlcms/src/main/java/app/owlcms/uievents/UIEvent.java
    +++ b/owlcms/src/main/java/app/owlcms/uievents/UIEvent.java
    @@ -34,9 +34,8 @@
     import ch.qos.logback.classic.Logger;
     
     /**
    - * UIEvents are triggered in response to field of play events (FOPEvents). Each field of play has an associated
    - * uiEventBus on which the user interface commands are posted. The various browsers subscribe to UIEvents and react
    - * accordingly.
    + * UIEvents are triggered in response to field of play events (FOPEvents). Each field of play has an associated uiEventBus on which the user interface commands
    + * are posted. The various browsers subscribe to UIEvents and react accordingly.
      *
      * @author owlcms
      */
    @@ -61,7 +60,7 @@ static public class BreakDone extends UIEvent {
     		 *
     		 * @param origin    the origin
     		 * @param breakType
    -		 * @param fop originating field of play
    +		 * @param fop       originating field of play
     		 */
     		public BreakDone(Object origin, BreakType breakType, FieldOfPlay fop) {
     			super(origin, fop);
    @@ -168,7 +167,7 @@ static public class BreakSetTime extends UIEvent {
     		 * @param indefinite
     		 * @param origin
     		 * @param trace
    -		 * @param fop originating field of play
    +		 * @param fop           originating field of play
     		 */
     		public BreakSetTime(BreakType bt, CountdownType ct, Integer timeRemaining, LocalDateTime end,
     		        boolean indefinite, Object origin, String trace, FieldOfPlay fop) {
    @@ -321,8 +320,9 @@ static public class CeremonyDone extends UIEvent {
     
     		/**
     		 * Instantiates a new break done.
    +		 *
     		 * @param origin    the origin
    -		 * @param fop originating field of play
    +		 * @param fop       originating field of play
     		 * @param breakType
     		 */
     		public CeremonyDone(CeremonyType ceremonyType, Object origin, FieldOfPlay fop) {
    @@ -369,14 +369,6 @@ public CeremonyStarted(CeremonyType ceremonyType, Group ceremonySession, Categor
     			}
     		}
     
    -		private void setCeremonyChampionship(Championship championship) {
    -			this.championship=championship;
    -		}
    -
    -		private void setCeremonyAgeGroup(AgeGroup ageGroup) {
    -			this.setAgeGroup(ageGroup);
    -		}
    -
     		@Override
     		public boolean equals(Object obj) {
     			if (this == obj) {
    @@ -391,6 +383,10 @@ public boolean equals(Object obj) {
     			        && this.ceremonyType == other.ceremonyType;
     		}
     
    +		public AgeGroup getAgeGroup() {
    +			return this.ageGroup;
    +		}
    +
     		public Category getCeremonyCategory() {
     			return this.ceremonyCategory;
     		}
    @@ -403,11 +399,19 @@ public CeremonyType getCeremonyType() {
     			return this.ceremonyType;
     		}
     
    +		public Championship getChampionship() {
    +			return this.championship;
    +		}
    +
     		@Override
     		public int hashCode() {
     			return Objects.hash(this.ceremonyCategory, this.ceremonySession, this.ceremonyType);
     		}
     
    +		public void setAgeGroup(AgeGroup ageGroup) {
    +			this.ageGroup = ageGroup;
    +		}
    +
     		public void setCeremonySession(Group ceremonyGroup2) {
     			this.ceremonySession = ceremonyGroup2;
     		}
    @@ -416,31 +420,27 @@ public void setCeremonyType(CeremonyType ceremonyType) {
     			this.ceremonyType = ceremonyType;
     		}
     
    +		public void setChampionship(Championship championship) {
    +			this.championship = championship;
    +		}
    +
     		@Override
     		public String toString() {
     			return "CeremonyStarted [ceremonyType=" + this.ceremonyType + ", ceremonyCategory=" + this.ceremonyCategory
     			        + ", ceremonySession=" + this.ceremonySession + "]";
     		}
     
    -		private void setCeremonyCategory(Category ceremonyCategory2) {
    -			this.ceremonyCategory = ceremonyCategory2;
    +		private void setCeremonyAgeGroup(AgeGroup ageGroup) {
    +			this.setAgeGroup(ageGroup);
     		}
     
    -		public Championship getChampionship() {
    -			return championship;
    +		private void setCeremonyCategory(Category ceremonyCategory2) {
    +			this.ceremonyCategory = ceremonyCategory2;
     		}
     
    -		public void setChampionship(Championship championship) {
    +		private void setCeremonyChampionship(Championship championship) {
     			this.championship = championship;
     		}
    -
    -		public AgeGroup getAgeGroup() {
    -			return ageGroup;
    -		}
    -
    -		public void setAgeGroup(AgeGroup ageGroup) {
    -			this.ageGroup = ageGroup;
    -		}
     	}
     
     	/**
    @@ -505,7 +505,7 @@ static public class DownSignal extends UIEvent {
     		 * Instantiates a new down signal.
     		 *
     		 * @param origin the origin
    -		 * @param fop originating field of play
    +		 * @param fop    originating field of play
     		 */
     		public DownSignal(Object origin, FieldOfPlay fop) {
     			super(origin, fop);
    @@ -530,8 +530,9 @@ static public class GroupDone extends UIEvent {
     
     		/**
     		 * Instantiates a new athlete announced.
    +		 *
     		 * @param ui      the ui
    -		 * @param fop originating field of play
    +		 * @param fop     originating field of play
     		 * @param athlete the athlete
     		 */
     		public GroupDone(Group group, UI ui, String stackTrace, FieldOfPlay fop) {
    @@ -575,8 +576,9 @@ public JuryNotification(Athlete athleteUnderReview, Object origin,
     
     		/**
     		 * Instantiates a new Notification.
    +		 *
     		 * @param origin the origin
    -		 * @param fop originating field of play
    +		 * @param fop    originating field of play
     		 */
     		public JuryNotification(Athlete a, Object origin, String notificationString, String fopEventString, FieldOfPlay fop) {
     			super(a, origin, fop);
    @@ -713,7 +715,7 @@ static public class LiftingOrderUpdated extends UIEvent {
     		 * @param displayToggle   if true, just update display according to lifting order.
     		 * @param origin          the origin
     		 * @param newWeight       newly requested weight, null if no change from previous
    -		 * @param fop originating field of play
    +		 * @param fop             originating field of play
     		 */
     		public LiftingOrderUpdated(Athlete athlete, Athlete nextAthlete, Athlete previousAthlete,
     		        Athlete changingAthlete, List liftingOrder, List displayOrder, Integer timeAllowed,
    @@ -971,7 +973,7 @@ public RefereeUpdate(Athlete a, Boolean ref1, Boolean ref2, Boolean ref3, Long l
     			if (this.trace == null || this.trace.isBlank()) {
     				this.setTrace(() -> LoggerUtils.stackTrace());
     			}
    -			logger.debug("ref update for jury {} {} {}",ref1, ref2, ref3);
    +			this.logger.debug("ref update for jury {} {} {}", ref1, ref2, ref3);
     		}
     	}
     
    @@ -982,8 +984,9 @@ static public class ResetOnNewClock extends UIEvent {
     
     		/**
     		 * Instantiates a new decision reset.
    +		 *
     		 * @param origin the origin
    -		 * @param fop originating field of play
    +		 * @param fop    originating field of play
     		 */
     		public ResetOnNewClock(Athlete a, Object origin, FieldOfPlay fop) {
     			super(a, origin, fop);
    @@ -1002,7 +1005,7 @@ static public class SetTime extends UIEvent {
     		 *
     		 * @param timeRemaining the time remaining
     		 * @param origin        the origin
    -		 * @param fop originating field of play
    +		 * @param fop           originating field of play
     		 */
     		public SetTime(Integer timeRemaining, Object origin, String trace, FieldOfPlay fop) {
     			super(origin, fop);
    @@ -1030,8 +1033,9 @@ static public class SnatchDone extends UIEvent {
     
     		/**
     		 * Instantiates a new athlete announced.
    +		 *
     		 * @param ui      the ui
    -		 * @param fop originating field of play
    +		 * @param fop     originating field of play
     		 * @param athlete the athlete
     		 */
     		public SnatchDone(Group group, UI ui, String stackTrace, FieldOfPlay fop) {
    @@ -1088,7 +1092,7 @@ static public class StartTime extends UIEvent {
     		 * @param timeRemaining the time remaining
     		 * @param origin        the origin
     		 * @param serverSound
    -		 * @param fop originating field of play
    +		 * @param fop           originating field of play
     		 */
     		public StartTime(Integer timeRemaining, Object origin, boolean serverSound, FieldOfPlay fop) {
     			super(origin, fop);
    @@ -1148,7 +1152,7 @@ static public class StopTime extends UIEvent {
     		 *
     		 * @param timeRemaining the time remaining
     		 * @param origin        the origin
    -		 * @param fop originating field of play
    +		 * @param fop           originating field of play
     		 */
     		public StopTime(int timeRemaining, Object origin, FieldOfPlay fop) {
     			super(origin, fop);
    @@ -1222,7 +1226,7 @@ static public class TimeRemaining extends UIEvent {
     		 * Instantiates a new break done.
     		 *
     		 * @param origin    the origin
    -		 * @param fop originating field of play
    +		 * @param fop       originating field of play
     		 * @param breakType
     		 */
     		public TimeRemaining(Object origin, int timeRemaining, FieldOfPlay fop) {
    @@ -1278,7 +1282,7 @@ static public class WakeUpRef extends UIEvent {
     		public int ref;
     
     		public WakeUpRef(int lastRef, boolean b, Object origin, FieldOfPlay fop) {
    -			super(origin,fop);
    +			super(origin, fop);
     			this.ref = lastRef;
     			this.on = b;
     			if (this.trace == null || this.trace.isBlank()) {
    @@ -1313,6 +1317,10 @@ public Athlete getAthlete() {
     		return this.athlete;
     	}
     
    +	public FieldOfPlay getFop() {
    +		return this.fop;
    +	}
    +
     	/**
     	 * Gets the origin.
     	 *
    @@ -1330,6 +1338,10 @@ public void setAthlete(Athlete athlete) {
     		this.athlete = athlete;
     	}
     
    +	public void setFop(FieldOfPlay fop) {
    +		this.fop = fop;
    +	}
    +
     	public void setOrigin(Object origin) {
     		this.origin = origin;
     	}
    @@ -1340,12 +1352,4 @@ protected void setTrace(Supplier stackTrace) {
     		}
     	}
     
    -	public FieldOfPlay getFop() {
    -		return fop;
    -	}
    -
    -	public void setFop(FieldOfPlay fop) {
    -		this.fop = fop;
    -	}
    -
     }
    diff --git a/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/MinMaxUnit.java b/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/MinMaxUnit.java
    index 3d875fe5d3..f784fd932f 100644
    --- a/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/MinMaxUnit.java
    +++ b/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/MinMaxUnit.java
    @@ -3,8 +3,8 @@
     import com.github.appreciated.css.interfaces.CssUnit;
     
     /**
    - * This interface is implemented by the following classes to match the following
    - * min-max standard 
    + * This interface is implemented by the following classes to match the following min-max + * standard
    * {@link com.github.appreciated.css.grid.sizes.Auto}
    * {@link com.github.appreciated.css.grid.sizes.Length}
    * {@link com.github.appreciated.css.grid.sizes.Flex}
    diff --git a/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/TemplateRowsAndColsUnit.java b/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/TemplateRowsAndColsUnit.java index 7cd487edb0..60ad945a00 100644 --- a/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/TemplateRowsAndColsUnit.java +++ b/owlcms/src/main/java/com/github/appreciated/css/grid/interfaces/TemplateRowsAndColsUnit.java @@ -5,8 +5,7 @@ /** * This interface is implemented by the following classes to match the following * grid-template-rows standard and the - * grid-template-columns standard - *
    + * grid-template-columns standard
    * {@link com.github.appreciated.css.grid.sizes.Auto}
    * {@link com.github.appreciated.css.grid.sizes.Length}
    * {@link com.github.appreciated.css.grid.sizes.Flex}
    diff --git a/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/Length.java b/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/Length.java index d33867a80d..1bf5907359 100644 --- a/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/Length.java +++ b/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/Length.java @@ -5,8 +5,8 @@ import com.github.appreciated.css.grid.interfaces.TemplateRowsAndColsUnit; /** - * A wrapper which is supposed to contain a length - * or a percentage + * A wrapper which is supposed to contain a length or a + * percentage * * */ diff --git a/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/MinMax.java b/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/MinMax.java index 7f52e46fed..2d9da22184 100644 --- a/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/MinMax.java +++ b/owlcms/src/main/java/com/github/appreciated/css/grid/sizes/MinMax.java @@ -5,8 +5,7 @@ import com.github.appreciated.css.grid.interfaces.TemplateRowsAndColsUnit; /** - * A class which is supposed to mimic the minmax - * minmax css function + * A class which is supposed to mimic the minmax minmax css function */ public class MinMax implements AutoRowAndColUnit, TemplateRowsAndColsUnit { diff --git a/owlcms/src/main/java/com/github/appreciated/layout/AreaLayout.java b/owlcms/src/main/java/com/github/appreciated/layout/AreaLayout.java index e9fb501ccf..2b515e3704 100644 --- a/owlcms/src/main/java/com/github/appreciated/layout/AreaLayout.java +++ b/owlcms/src/main/java/com/github/appreciated/layout/AreaLayout.java @@ -15,8 +15,7 @@ public class AreaLayout extends Composite implements FluentGridLayoutComponent { /** - * Shorthand to allow setting the - * grid-template-areas + * Shorthand to allow setting the grid-template-areas * * @param areas */ @@ -26,8 +25,7 @@ public AreaLayout(String[][] areas) { } /** - * Short hand to add an item and set its - * grid-area + * Short hand to add an item and set its grid-area * * @param component * @param area diff --git a/owlcms/src/main/java/com/github/appreciated/layout/FlexibleGridLayout.java b/owlcms/src/main/java/com/github/appreciated/layout/FlexibleGridLayout.java index f3bc9a4499..4ac0c0c475 100644 --- a/owlcms/src/main/java/com/github/appreciated/layout/FlexibleGridLayout.java +++ b/owlcms/src/main/java/com/github/appreciated/layout/FlexibleGridLayout.java @@ -42,8 +42,7 @@ public void setItemSize(Component component, int width, int height) { } /** - * Convenience method, for users which don't want to dive into the css-grid to set the number of row an item should - * span over + * Convenience method, for users which don't want to dive into the css-grid to set the number of row an item should span over * * @param component the component which column width should be set * @param width the number of columns the item should span over @@ -53,9 +52,8 @@ public void setItemWidth(Component component, int width) { } /** - * Sets how the grid should behave weather keeping the order or filling up unused space with smaller elements using - * this makes sense when adding differently sized elements - * grid-auto-flow. + * Sets how the grid should behave weather keeping the order or filling up unused space with smaller elements using this makes sense when adding differently + * sized elements grid-auto-flow. * * @param flow * @return @@ -66,8 +64,7 @@ public FlexibleGridLayout withAutoFlow(AutoFlow flow) { } /** - * Sets the height of the rows with the height {@link com.github.appreciated.css.grid.sizes.Auto}. By default all - * rows receive that height. + * Sets the height of the rows with the height {@link com.github.appreciated.css.grid.sizes.Auto}. By default all rows receive that height. * * @param length the size that will be set * @return this @@ -78,10 +75,8 @@ public FlexibleGridLayout withAutoRows(Length length) { } /** - * Shorthand to set the - * grid-template-columns with - * flexible columns by using the repeat - * function with an auto-repeat mode. + * Shorthand to set the grid-template-columns with flexible columns by + * using the repeat function with an auto-repeat mode. * * @param mode the auto-repeat mode. (See under auto-fill and auto-repeat of the * repeat function) @@ -143,8 +138,7 @@ public FlexibleGridLayout withItemWithSize(Component component, int width, int h } /** - * Convenience method, for users which don't want to dive into the css-grid to set the number of row an item should - * span over + * Convenience method, for users which don't want to dive into the css-grid to set the number of row an item should span over * * @param component the component which column width should be set * @param width the number of columns the item should span over diff --git a/owlcms/src/main/java/com/github/appreciated/layout/GridLayout.java b/owlcms/src/main/java/com/github/appreciated/layout/GridLayout.java index e6952c8866..9e98fed983 100644 --- a/owlcms/src/main/java/com/github/appreciated/layout/GridLayout.java +++ b/owlcms/src/main/java/com/github/appreciated/layout/GridLayout.java @@ -24,12 +24,11 @@ import com.vaadin.flow.dom.Style; /** - * GridLayout is a component container, which shows the subcomponents in the order of their addition. The - * {@link GridLayout} does not have a predefined size - its size is either defined by the components inside it, or can - * be set by using the css grid api - * Different to the {@link com.vaadin.flow.component.orderedlayout.VerticalLayout} and - * {@link com.vaadin.flow.component.orderedlayout.HorizontalLayout} a {@link GridLayout} can span its elements over - * multiple rows. + * GridLayout is a component container, which shows the subcomponents in the order of their addition. The {@link GridLayout} does not have a predefined size - + * its size is either defined by the components inside it, or can be set by using the + * css grid api Different to the + * {@link com.vaadin.flow.component.orderedlayout.VerticalLayout} and {@link com.vaadin.flow.component.orderedlayout.HorizontalLayout} a {@link GridLayout} can + * span its elements over multiple rows. */ @SuppressWarnings("serial") @Tag("grid-layout") @@ -178,9 +177,8 @@ public void setAutoColumns(Length size) { } /** - * Sets how the grid should behave weather keeping the order or filling up unused space with smaller elements using - * this makes sense when adding differently sized elements - * grid-auto-flow + * Sets how the grid should behave weather keeping the order or filling up unused space with smaller elements using this makes sense when adding differently + * sized elements grid-auto-flow * * @param autoFlow */ @@ -395,8 +393,7 @@ public void setTemplateAreas(MediaQuery queries, TemplateAreas... areas) { } /** - * Sets the column and row definition of your grid-layout. Instead of setting the sizes for rows and columns you - * define areas by using custom keywords.
    + * Sets the column and row definition of your grid-layout. Instead of setting the sizes for rows and columns you define areas by using custom keywords.
    *

    * Example:
    * 'header header header header header header'
    @@ -440,8 +437,7 @@ public void setTemplateColumns(TemplateRowsAndColsUnit... units) { * #Dynamic Number of rows
    * Other: repeat(auto-fill, minmax(250px, 1fr));
    * - * @param units "The row definition in your grid layout, can either be fixed or dynamic checkout the official css - * grid documentation for further details" + * @param units "The row definition in your grid layout, can either be fixed or dynamic checkout the official css grid documentation for further details" */ public void setTemplateRows(TemplateRowsAndColsUnit... units) { if (units == null) { diff --git a/owlcms/src/test/java/app/owlcms/data/jpa/BenchmarkDataTest.java b/owlcms/src/test/java/app/owlcms/data/jpa/BenchmarkDataTest.java index 44ace13492..12c03d7d52 100644 --- a/owlcms/src/test/java/app/owlcms/data/jpa/BenchmarkDataTest.java +++ b/owlcms/src/test/java/app/owlcms/data/jpa/BenchmarkDataTest.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.data.jpa; import org.junit.Test; diff --git a/owlcms/src/test/java/app/owlcms/tests/AgeFactorsTest.java b/owlcms/src/test/java/app/owlcms/tests/AgeFactorsTest.java index 216deffd95..bebd04be5f 100644 --- a/owlcms/src/test/java/app/owlcms/tests/AgeFactorsTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/AgeFactorsTest.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.tests; import static org.junit.Assert.assertEquals; diff --git a/owlcms/src/test/java/app/owlcms/tests/AllTests.java b/owlcms/src/test/java/app/owlcms/tests/AllTests.java index a43aadd4c3..72686b2916 100644 --- a/owlcms/src/test/java/app/owlcms/tests/AllTests.java +++ b/owlcms/src/test/java/app/owlcms/tests/AllTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/AthleteSorterTest.java b/owlcms/src/test/java/app/owlcms/tests/AthleteSorterTest.java index 4dfe423eb4..74e2f0e071 100644 --- a/owlcms/src/test/java/app/owlcms/tests/AthleteSorterTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/AthleteSorterTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/AthleteTest.java b/owlcms/src/test/java/app/owlcms/tests/AthleteTest.java index 36904a3726..d2fd5e6ac7 100644 --- a/owlcms/src/test/java/app/owlcms/tests/AthleteTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/AthleteTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/FederationStructureReaderTest.java b/owlcms/src/test/java/app/owlcms/tests/FederationStructureReaderTest.java index b2099c375a..d097ba1e80 100644 --- a/owlcms/src/test/java/app/owlcms/tests/FederationStructureReaderTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/FederationStructureReaderTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/GAMXTest.java b/owlcms/src/test/java/app/owlcms/tests/GAMXTest.java index 921b232377..f77dd6add9 100644 --- a/owlcms/src/test/java/app/owlcms/tests/GAMXTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/GAMXTest.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.tests; import static org.junit.Assert.assertEquals; diff --git a/owlcms/src/test/java/app/owlcms/tests/ICountDownTimer.java b/owlcms/src/test/java/app/owlcms/tests/ICountDownTimer.java index ec6c0491f0..140c2f76ab 100644 --- a/owlcms/src/test/java/app/owlcms/tests/ICountDownTimer.java +++ b/owlcms/src/test/java/app/owlcms/tests/ICountDownTimer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2021 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/JSONExportImportTest.java b/owlcms/src/test/java/app/owlcms/tests/JSONExportImportTest.java index 12ec8c5acd..b75c52a85b 100644 --- a/owlcms/src/test/java/app/owlcms/tests/JSONExportImportTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/JSONExportImportTest.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.tests; import static org.junit.Assert.fail; diff --git a/owlcms/src/test/java/app/owlcms/tests/LiftDefinitionTest.java b/owlcms/src/test/java/app/owlcms/tests/LiftDefinitionTest.java index 6bac32dc35..76a153dd13 100644 --- a/owlcms/src/test/java/app/owlcms/tests/LiftDefinitionTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/LiftDefinitionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/LiftingOrderReconstructionTest.java b/owlcms/src/test/java/app/owlcms/tests/LiftingOrderReconstructionTest.java index f358aa1302..c95205cade 100644 --- a/owlcms/src/test/java/app/owlcms/tests/LiftingOrderReconstructionTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/LiftingOrderReconstructionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/MockCountdownTimer.java b/owlcms/src/test/java/app/owlcms/tests/MockCountdownTimer.java index 33018cb373..abc7703f48 100644 --- a/owlcms/src/test/java/app/owlcms/tests/MockCountdownTimer.java +++ b/owlcms/src/test/java/app/owlcms/tests/MockCountdownTimer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/MovingDownTest.java b/owlcms/src/test/java/app/owlcms/tests/MovingDownTest.java index da2c0bd4cc..f7369da352 100644 --- a/owlcms/src/test/java/app/owlcms/tests/MovingDownTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/MovingDownTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/RecordDefinitionReaderTest.java b/owlcms/src/test/java/app/owlcms/tests/RecordDefinitionReaderTest.java index 8b43483d15..070273702e 100644 --- a/owlcms/src/test/java/app/owlcms/tests/RecordDefinitionReaderTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/RecordDefinitionReaderTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/RegistrationOrderComparatorTest.java b/owlcms/src/test/java/app/owlcms/tests/RegistrationOrderComparatorTest.java index 269e96ca96..fdb8ba1ba2 100644 --- a/owlcms/src/test/java/app/owlcms/tests/RegistrationOrderComparatorTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/RegistrationOrderComparatorTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/RegistrationReaderTest.java b/owlcms/src/test/java/app/owlcms/tests/RegistrationReaderTest.java index bb2ff48632..c351abc957 100644 --- a/owlcms/src/test/java/app/owlcms/tests/RegistrationReaderTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/RegistrationReaderTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/ResourceWalkerTest.java b/owlcms/src/test/java/app/owlcms/tests/ResourceWalkerTest.java index ca67452579..19db2dff21 100644 --- a/owlcms/src/test/java/app/owlcms/tests/ResourceWalkerTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/ResourceWalkerTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/RobiCategoriesTest.java b/owlcms/src/test/java/app/owlcms/tests/RobiCategoriesTest.java index 2b54159d2e..0e71e1dfd2 100644 --- a/owlcms/src/test/java/app/owlcms/tests/RobiCategoriesTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/RobiCategoriesTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/TestData.java b/owlcms/src/test/java/app/owlcms/tests/TestData.java index 306fe2130f..159e4e98c4 100644 --- a/owlcms/src/test/java/app/owlcms/tests/TestData.java +++ b/owlcms/src/test/java/app/owlcms/tests/TestData.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/owlcms/src/test/java/app/owlcms/tests/TwoMinutesRuleTest.java b/owlcms/src/test/java/app/owlcms/tests/TwoMinutesRuleTest.java index 8f4f097b13..8fa79ed613 100644 --- a/owlcms/src/test/java/app/owlcms/tests/TwoMinutesRuleTest.java +++ b/owlcms/src/test/java/app/owlcms/tests/TwoMinutesRuleTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/playwright/src/main/java/playwright/RunResults.java b/playwright/src/main/java/playwright/RunResults.java index bb4fc16ec5..9d3cb78c99 100644 --- a/playwright/src/main/java/playwright/RunResults.java +++ b/playwright/src/main/java/playwright/RunResults.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2021 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java b/publicresults/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java index 505ca5b953..f58a5000c4 100644 --- a/publicresults/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java +++ b/publicresults/src/main/java/app/owlcms/apputils/queryparameters/DisplayParameters.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java b/publicresults/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java index 57eab0fdf9..f9d77ab6d2 100644 --- a/publicresults/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java +++ b/publicresults/src/main/java/app/owlcms/apputils/queryparameters/FOPParameters.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/component/fields/LocalizedDecimalField.java b/publicresults/src/main/java/app/owlcms/component/fields/LocalizedDecimalField.java index 9ffef59192..ae5e562317 100644 --- a/publicresults/src/main/java/app/owlcms/component/fields/LocalizedDecimalField.java +++ b/publicresults/src/main/java/app/owlcms/component/fields/LocalizedDecimalField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/component/fields/ValidationTextField.java b/publicresults/src/main/java/app/owlcms/component/fields/ValidationTextField.java index a630520a1c..afdd539b6c 100644 --- a/publicresults/src/main/java/app/owlcms/component/fields/ValidationTextField.java +++ b/publicresults/src/main/java/app/owlcms/component/fields/ValidationTextField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/component/fields/WrappedTextField.java b/publicresults/src/main/java/app/owlcms/component/fields/WrappedTextField.java index 20f725dfc7..3b1bd454d0 100644 --- a/publicresults/src/main/java/app/owlcms/component/fields/WrappedTextField.java +++ b/publicresults/src/main/java/app/owlcms/component/fields/WrappedTextField.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/AthleteTimerElementPR.java b/publicresults/src/main/java/app/owlcms/components/elements/AthleteTimerElementPR.java index 19d8e13c70..7f55be5abf 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/AthleteTimerElementPR.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/AthleteTimerElementPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/BreakTimerElementPR.java b/publicresults/src/main/java/app/owlcms/components/elements/BreakTimerElementPR.java index 901b1e151a..2ec6fd9689 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/BreakTimerElementPR.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/BreakTimerElementPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/DecisionElementPR.java b/publicresults/src/main/java/app/owlcms/components/elements/DecisionElementPR.java index e7d1ae9efc..825a80bbf1 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/DecisionElementPR.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/DecisionElementPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-Fran�ois Lamy + * Copyright © 2009-present Jean-Fran�ois Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/IFopName.java b/publicresults/src/main/java/app/owlcms/components/elements/IFopName.java index b85c63400c..34f110731e 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/IFopName.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/IFopName.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/TimerElementPR.java b/publicresults/src/main/java/app/owlcms/components/elements/TimerElementPR.java index 3a68ab3fc7..a38241bb8b 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/TimerElementPR.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/TimerElementPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-Fran�ois Lamy + * Copyright © 2009-present Jean-Fran�ois Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadEventPR.java b/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadEventPR.java index 14d32aa6c8..c462cb50ea 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadEventPR.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadEventPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadListenerPR.java b/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadListenerPR.java index 83ec607b25..8916d43e82 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadListenerPR.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadListenerPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadObserverPR.java b/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadObserverPR.java index bd3bb569b1..cf291b5f64 100644 --- a/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadObserverPR.java +++ b/publicresults/src/main/java/app/owlcms/components/elements/unload/UnloadObserverPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/displays/options/DisplayOptions.java b/publicresults/src/main/java/app/owlcms/displays/options/DisplayOptions.java index c7c7a1cba3..4c788a824a 100644 --- a/publicresults/src/main/java/app/owlcms/displays/options/DisplayOptions.java +++ b/publicresults/src/main/java/app/owlcms/displays/options/DisplayOptions.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/displays/scoreboard/ResultsPR.java b/publicresults/src/main/java/app/owlcms/displays/scoreboard/ResultsPR.java index 236df290aa..367f885ff0 100644 --- a/publicresults/src/main/java/app/owlcms/displays/scoreboard/ResultsPR.java +++ b/publicresults/src/main/java/app/owlcms/displays/scoreboard/ResultsPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-Fran�ois Lamy + * Copyright © 2009-present Jean-Fran�ois Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/init/OwlcmsSession.java b/publicresults/src/main/java/app/owlcms/init/OwlcmsSession.java index 48a7d5478b..9c2bb534c8 100644 --- a/publicresults/src/main/java/app/owlcms/init/OwlcmsSession.java +++ b/publicresults/src/main/java/app/owlcms/init/OwlcmsSession.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/prutils/DebugUtils.java b/publicresults/src/main/java/app/owlcms/prutils/DebugUtils.java index 4a20efc259..d76d78fc78 100644 --- a/publicresults/src/main/java/app/owlcms/prutils/DebugUtils.java +++ b/publicresults/src/main/java/app/owlcms/prutils/DebugUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/prutils/SafeEventBusRegistrationPR.java b/publicresults/src/main/java/app/owlcms/prutils/SafeEventBusRegistrationPR.java index 21b2b74a0a..85ed8a22a2 100644 --- a/publicresults/src/main/java/app/owlcms/prutils/SafeEventBusRegistrationPR.java +++ b/publicresults/src/main/java/app/owlcms/prutils/SafeEventBusRegistrationPR.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/prutils/SoundUtils.java b/publicresults/src/main/java/app/owlcms/prutils/SoundUtils.java index 5b93551938..bee2c0418d 100644 --- a/publicresults/src/main/java/app/owlcms/prutils/SoundUtils.java +++ b/publicresults/src/main/java/app/owlcms/prutils/SoundUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/publicresults/ConfigReceiverServlet.java b/publicresults/src/main/java/app/owlcms/publicresults/ConfigReceiverServlet.java index 3144cacd07..9a01170ee3 100644 --- a/publicresults/src/main/java/app/owlcms/publicresults/ConfigReceiverServlet.java +++ b/publicresults/src/main/java/app/owlcms/publicresults/ConfigReceiverServlet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/publicresults/DecisionReceiverServlet.java b/publicresults/src/main/java/app/owlcms/publicresults/DecisionReceiverServlet.java index d6f1df9e48..22b0a5bcc7 100644 --- a/publicresults/src/main/java/app/owlcms/publicresults/DecisionReceiverServlet.java +++ b/publicresults/src/main/java/app/owlcms/publicresults/DecisionReceiverServlet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/publicresults/ExpiredServlet.java b/publicresults/src/main/java/app/owlcms/publicresults/ExpiredServlet.java index 205840f432..9811b27c5f 100644 --- a/publicresults/src/main/java/app/owlcms/publicresults/ExpiredServlet.java +++ b/publicresults/src/main/java/app/owlcms/publicresults/ExpiredServlet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/publicresults/Main.java b/publicresults/src/main/java/app/owlcms/publicresults/Main.java index 993884d8d1..7926156a82 100644 --- a/publicresults/src/main/java/app/owlcms/publicresults/Main.java +++ b/publicresults/src/main/java/app/owlcms/publicresults/Main.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/publicresults/MainView.java b/publicresults/src/main/java/app/owlcms/publicresults/MainView.java index d571be08ce..fd0411fe51 100644 --- a/publicresults/src/main/java/app/owlcms/publicresults/MainView.java +++ b/publicresults/src/main/java/app/owlcms/publicresults/MainView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/publicresults/TimerReceiverServlet.java b/publicresults/src/main/java/app/owlcms/publicresults/TimerReceiverServlet.java index 9c6c93a66e..3bfc400b36 100644 --- a/publicresults/src/main/java/app/owlcms/publicresults/TimerReceiverServlet.java +++ b/publicresults/src/main/java/app/owlcms/publicresults/TimerReceiverServlet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/publicresults/UpdateReceiverServlet.java b/publicresults/src/main/java/app/owlcms/publicresults/UpdateReceiverServlet.java index 9e66b23641..2c2ea5aa4f 100644 --- a/publicresults/src/main/java/app/owlcms/publicresults/UpdateReceiverServlet.java +++ b/publicresults/src/main/java/app/owlcms/publicresults/UpdateReceiverServlet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/ui/parameters/DarkModeParameters.java b/publicresults/src/main/java/app/owlcms/ui/parameters/DarkModeParameters.java index 86bd39a2d1..f185a82ae1 100644 --- a/publicresults/src/main/java/app/owlcms/ui/parameters/DarkModeParameters.java +++ b/publicresults/src/main/java/app/owlcms/ui/parameters/DarkModeParameters.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/ui/parameters/QueryParameterReader.java b/publicresults/src/main/java/app/owlcms/ui/parameters/QueryParameterReader.java index 9f39952795..4896cb5e48 100644 --- a/publicresults/src/main/java/app/owlcms/ui/parameters/QueryParameterReader.java +++ b/publicresults/src/main/java/app/owlcms/ui/parameters/QueryParameterReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/uievents/BreakTimerEvent.java b/publicresults/src/main/java/app/owlcms/uievents/BreakTimerEvent.java index 1655b33c8a..34f7f368f6 100644 --- a/publicresults/src/main/java/app/owlcms/uievents/BreakTimerEvent.java +++ b/publicresults/src/main/java/app/owlcms/uievents/BreakTimerEvent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/uievents/BreakType.java b/publicresults/src/main/java/app/owlcms/uievents/BreakType.java index 72321ef30b..c1cabb5310 100644 --- a/publicresults/src/main/java/app/owlcms/uievents/BreakType.java +++ b/publicresults/src/main/java/app/owlcms/uievents/BreakType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/uievents/CeremonyType.java b/publicresults/src/main/java/app/owlcms/uievents/CeremonyType.java index 843f8b638c..a6b38c5f15 100644 --- a/publicresults/src/main/java/app/owlcms/uievents/CeremonyType.java +++ b/publicresults/src/main/java/app/owlcms/uievents/CeremonyType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/uievents/DecisionEvent.java b/publicresults/src/main/java/app/owlcms/uievents/DecisionEvent.java index e6dded9647..0ec64f4854 100644 --- a/publicresults/src/main/java/app/owlcms/uievents/DecisionEvent.java +++ b/publicresults/src/main/java/app/owlcms/uievents/DecisionEvent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/uievents/DecisionEventType.java b/publicresults/src/main/java/app/owlcms/uievents/DecisionEventType.java index c9a99a6768..46ce10b5d8 100644 --- a/publicresults/src/main/java/app/owlcms/uievents/DecisionEventType.java +++ b/publicresults/src/main/java/app/owlcms/uievents/DecisionEventType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/uievents/TimerEvent.java b/publicresults/src/main/java/app/owlcms/uievents/TimerEvent.java index 35ce3850e9..46e9389c87 100644 --- a/publicresults/src/main/java/app/owlcms/uievents/TimerEvent.java +++ b/publicresults/src/main/java/app/owlcms/uievents/TimerEvent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/publicresults/src/main/java/app/owlcms/uievents/UpdateEvent.java b/publicresults/src/main/java/app/owlcms/uievents/UpdateEvent.java index e188fa2e06..f76b31cf5f 100644 --- a/publicresults/src/main/java/app/owlcms/uievents/UpdateEvent.java +++ b/publicresults/src/main/java/app/owlcms/uievents/UpdateEvent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/i18n/Translator.java b/shared/src/main/java/app/owlcms/i18n/Translator.java index f5635a59be..3485f414b4 100644 --- a/shared/src/main/java/app/owlcms/i18n/Translator.java +++ b/shared/src/main/java/app/owlcms/i18n/Translator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/servlet/EmbeddedJetty.java b/shared/src/main/java/app/owlcms/servlet/EmbeddedJetty.java index fbcfb41e8a..73e3698896 100644 --- a/shared/src/main/java/app/owlcms/servlet/EmbeddedJetty.java +++ b/shared/src/main/java/app/owlcms/servlet/EmbeddedJetty.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.servlet; import java.util.concurrent.CountDownLatch; diff --git a/shared/src/main/java/app/owlcms/servlet/FileServlet.java b/shared/src/main/java/app/owlcms/servlet/FileServlet.java index 5d92544c06..f698644ae0 100644 --- a/shared/src/main/java/app/owlcms/servlet/FileServlet.java +++ b/shared/src/main/java/app/owlcms/servlet/FileServlet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/servlet/JettyErrorHandler.java b/shared/src/main/java/app/owlcms/servlet/JettyErrorHandler.java index 753b79bcb5..c6f9989921 100644 --- a/shared/src/main/java/app/owlcms/servlet/JettyErrorHandler.java +++ b/shared/src/main/java/app/owlcms/servlet/JettyErrorHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/servlet/StopProcessingException.java b/shared/src/main/java/app/owlcms/servlet/StopProcessingException.java index 83565cf012..16c6f8eea1 100644 --- a/shared/src/main/java/app/owlcms/servlet/StopProcessingException.java +++ b/shared/src/main/java/app/owlcms/servlet/StopProcessingException.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.servlet; /** diff --git a/shared/src/main/java/app/owlcms/utils/CSSUtils.java b/shared/src/main/java/app/owlcms/utils/CSSUtils.java index 73b942e242..9b2aca2480 100644 --- a/shared/src/main/java/app/owlcms/utils/CSSUtils.java +++ b/shared/src/main/java/app/owlcms/utils/CSSUtils.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.utils; public class CSSUtils { diff --git a/shared/src/main/java/app/owlcms/utils/DateTimeUtils.java b/shared/src/main/java/app/owlcms/utils/DateTimeUtils.java index 1a9489bfd0..c991a29a32 100644 --- a/shared/src/main/java/app/owlcms/utils/DateTimeUtils.java +++ b/shared/src/main/java/app/owlcms/utils/DateTimeUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/DelayTimer.java b/shared/src/main/java/app/owlcms/utils/DelayTimer.java index 10f4db848e..32e59a7bed 100644 --- a/shared/src/main/java/app/owlcms/utils/DelayTimer.java +++ b/shared/src/main/java/app/owlcms/utils/DelayTimer.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.utils; import java.util.Timer; diff --git a/shared/src/main/java/app/owlcms/utils/IPInterfaceUtils.java b/shared/src/main/java/app/owlcms/utils/IPInterfaceUtils.java index 42cc883d0a..29533e39a6 100644 --- a/shared/src/main/java/app/owlcms/utils/IPInterfaceUtils.java +++ b/shared/src/main/java/app/owlcms/utils/IPInterfaceUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/IdUtils.java b/shared/src/main/java/app/owlcms/utils/IdUtils.java index 1d3beca00a..d1d540c5eb 100644 --- a/shared/src/main/java/app/owlcms/utils/IdUtils.java +++ b/shared/src/main/java/app/owlcms/utils/IdUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/LambdaUtils.java b/shared/src/main/java/app/owlcms/utils/LambdaUtils.java index a7dfe56268..7dd311d997 100644 --- a/shared/src/main/java/app/owlcms/utils/LambdaUtils.java +++ b/shared/src/main/java/app/owlcms/utils/LambdaUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/LoggerUtils.java b/shared/src/main/java/app/owlcms/utils/LoggerUtils.java index d8b73cec21..559bb60b95 100644 --- a/shared/src/main/java/app/owlcms/utils/LoggerUtils.java +++ b/shared/src/main/java/app/owlcms/utils/LoggerUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/MemTempUtils.java b/shared/src/main/java/app/owlcms/utils/MemTempUtils.java index ce65d81e7c..5cbb588c5d 100644 --- a/shared/src/main/java/app/owlcms/utils/MemTempUtils.java +++ b/shared/src/main/java/app/owlcms/utils/MemTempUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/OwlcmsLicense.java b/shared/src/main/java/app/owlcms/utils/OwlcmsLicense.java index 1e49268673..30f78f8b4e 100644 --- a/shared/src/main/java/app/owlcms/utils/OwlcmsLicense.java +++ b/shared/src/main/java/app/owlcms/utils/OwlcmsLicense.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.utils; import java.io.IOException; diff --git a/shared/src/main/java/app/owlcms/utils/ProcessUtils.java b/shared/src/main/java/app/owlcms/utils/ProcessUtils.java index d80e9a6a2a..4701cae6c1 100644 --- a/shared/src/main/java/app/owlcms/utils/ProcessUtils.java +++ b/shared/src/main/java/app/owlcms/utils/ProcessUtils.java @@ -1,3 +1,9 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") + * License text at https://opensource.org/licenses/NPOSL-3.0 + *******************************************************************************/ package app.owlcms.utils; import java.io.BufferedReader; diff --git a/shared/src/main/java/app/owlcms/utils/ProxyUtils.java b/shared/src/main/java/app/owlcms/utils/ProxyUtils.java index 5c13eb9c75..378132639d 100644 --- a/shared/src/main/java/app/owlcms/utils/ProxyUtils.java +++ b/shared/src/main/java/app/owlcms/utils/ProxyUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/Resource.java b/shared/src/main/java/app/owlcms/utils/Resource.java index c511a85015..e2a0e3169d 100644 --- a/shared/src/main/java/app/owlcms/utils/Resource.java +++ b/shared/src/main/java/app/owlcms/utils/Resource.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/ResourceWalker.java b/shared/src/main/java/app/owlcms/utils/ResourceWalker.java index 839553cf85..c3456f10ea 100644 --- a/shared/src/main/java/app/owlcms/utils/ResourceWalker.java +++ b/shared/src/main/java/app/owlcms/utils/ResourceWalker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/StartupUtils.java b/shared/src/main/java/app/owlcms/utils/StartupUtils.java index 109f813834..aa0b324d96 100644 --- a/shared/src/main/java/app/owlcms/utils/StartupUtils.java +++ b/shared/src/main/java/app/owlcms/utils/StartupUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/TimeZoneUtils.java b/shared/src/main/java/app/owlcms/utils/TimeZoneUtils.java index e478e2385d..86cb84df29 100644 --- a/shared/src/main/java/app/owlcms/utils/TimeZoneUtils.java +++ b/shared/src/main/java/app/owlcms/utils/TimeZoneUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/URLUtils.java b/shared/src/main/java/app/owlcms/utils/URLUtils.java index b8a97b45ce..292909c8c7 100644 --- a/shared/src/main/java/app/owlcms/utils/URLUtils.java +++ b/shared/src/main/java/app/owlcms/utils/URLUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0 diff --git a/shared/src/main/java/app/owlcms/utils/ZipUtils.java b/shared/src/main/java/app/owlcms/utils/ZipUtils.java index fc04878717..ad500a4fbc 100644 --- a/shared/src/main/java/app/owlcms/utils/ZipUtils.java +++ b/shared/src/main/java/app/owlcms/utils/ZipUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009-2023 Jean-François Lamy + * Copyright © 2009-present Jean-François Lamy * * Licensed under the Non-Profit Open Software License version 3.0 ("NPOSL-3.0") * License text at https://opensource.org/licenses/NPOSL-3.0