diff --git a/installtools/.classpath b/installtools/.classpath index 73accf64d4..388b55cd82 100644 --- a/installtools/.classpath +++ b/installtools/.classpath @@ -1,5 +1,6 @@ + diff --git a/owlcms-docker/.classpath b/owlcms-docker/.classpath index 59a22644cf..867db10d1e 100644 --- a/owlcms-docker/.classpath +++ b/owlcms-docker/.classpath @@ -36,22 +36,5 @@ - - - - - - - - - - - - - - - - - diff --git a/owlcms-windows/.classpath b/owlcms-windows/.classpath index 977bb34842..a012d978d7 100644 --- a/owlcms-windows/.classpath +++ b/owlcms-windows/.classpath @@ -36,22 +36,5 @@ - - - - - - - - - - - - - - - - - diff --git a/owlcms/pom.xml b/owlcms/pom.xml index 4dfd523404..67f439bb3c 100644 --- a/owlcms/pom.xml +++ b/owlcms/pom.xml @@ -194,11 +194,26 @@ commons-io 2.14.0 + + commons-fileupload + commons-fileupload + 1.5 + + + org.apache.commons + commons-compress + 1.21 + org.apache.commons commons-text 1.10.0 + + org.apache.commons + commons-compress + 1.26.0 + diff --git a/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialReader.java b/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialReader.java index 64dce3a4b6..079fec62fc 100644 --- a/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialReader.java +++ b/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialReader.java @@ -25,6 +25,7 @@ public class TechnicalOfficialReader { private static final String FEDERATION_ID = "FederationId"; public static List importFromXLS(InputStream is) { + logger.warn("importFromXLS"); List officials = new ArrayList<>(); try { @@ -41,9 +42,14 @@ public static List importFromXLS(InputStream is) { Row row = sheet.getRow(i); if (row == null) continue; + logger.warn("row[{}] {}", i, colIndices); TechnicalOfficial official = readRow(row, colIndices); + if (official != null) { - officials.add(official); + var mergedOff = TechnicalOfficialRepository.save(official); + officials.add(mergedOff); + } else { + break; } } workbook.close(); @@ -74,15 +80,17 @@ private static int[] findColumnIndices(Row headerRow) { private static TechnicalOfficial readRow(Row row, int[] colIndices) { // Check required fields - if (isEmptyCell(row.getCell(colIndices[0])) || - isEmptyCell(row.getCell(colIndices[1])) || - isEmptyCell(row.getCell(colIndices[2]))) { + if (isEmptyCell(row.getCell(colIndices[0]))) { return null; } String lastName = getCellValueAsString(row.getCell(colIndices[0])); String firstName = getCellValueAsString(row.getCell(colIndices[1])); - TOLevel level = TOLevel.valueOf(getCellValueAsString(row.getCell(colIndices[2]))); + TOLevel level = null; + try { + level = TOLevel.valueOf(getCellValueAsString(row.getCell(colIndices[2]))); + } catch (IllegalArgumentException e) { + } String iwfId = getCellValueAsString(row.getCell(colIndices[3])); String federation = getCellValueAsString(row.getCell(colIndices[4])); String federationId = getCellValueAsString(row.getCell(colIndices[5])); diff --git a/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialRepository.java b/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialRepository.java index 173de3809c..1d90486319 100644 --- a/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialRepository.java +++ b/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialRepository.java @@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory; import app.owlcms.data.jpa.JPAService; +import app.owlcms.utils.LoggerUtils; import ch.qos.logback.classic.Logger; /** @@ -33,6 +34,7 @@ public static void delete(TechnicalOfficial to) { } public static List findAll() { + logger.warn("====== findall {}",LoggerUtils.stackTrace()); return JPAService .runInTransaction(em -> em.createQuery("select c from TechnicalOfficial c order by c.id", TechnicalOfficial.class) .getResultList()); @@ -52,10 +54,11 @@ public static TechnicalOfficial getById(Long id, EntityManager em) { TechnicalOfficial.class); query.setParameter("id", id); - return (TechnicalOfficial) query.getResultList().stream().findFirst().orElse(null); + return query.getResultList().stream().findFirst().orElse(null); } public static TechnicalOfficial save(TechnicalOfficial technicalOfficial) { + logger.warn("saving {}", technicalOfficial); TechnicalOfficial nTechnicalOfficial = JPAService.runInTransaction(em -> em.merge(technicalOfficial)); return nTechnicalOfficial; } diff --git a/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialWriter.java b/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialWriter.java new file mode 100644 index 0000000000..5282010af3 --- /dev/null +++ b/owlcms/src/main/java/app/owlcms/data/technicalofficial/TechnicalOfficialWriter.java @@ -0,0 +1,70 @@ +package app.owlcms.data.technicalofficial; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Logger; + +public class TechnicalOfficialWriter { + private final static Logger logger = (Logger) LoggerFactory.getLogger(TechnicalOfficialWriter.class); + + public static InputStream write() { + try (Workbook workbook = new XSSFWorkbook()) { + Sheet sheet = workbook.createSheet("Technical Officials"); + + // Create header style + CellStyle headerStyle = workbook.createCellStyle(); + Font headerFont = workbook.createFont(); + headerFont.setBold(true); + headerStyle.setFont(headerFont); + + // Create headers + Row headerRow = sheet.createRow(0); + String[] headers = {"LastName", "FirstName", "Level", "IWFId", "Federation", "FederationId"}; + for (int i = 0; i < headers.length; i++) { + Cell cell = headerRow.createCell(i); + cell.setCellValue(headers[i]); + cell.setCellStyle(headerStyle); + } + + // Add data rows + List officials = TechnicalOfficialRepository.findAll(); + int rowNum = 1; + for (TechnicalOfficial official : officials) { + Row row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue(official.getLastName() != null ? official.getLastName() : ""); + row.createCell(1).setCellValue(official.getFirstName() != null ? official.getFirstName() : ""); + row.createCell(2).setCellValue(official.getLevel() != null ? official.getLevel().toString() : ""); + row.createCell(3).setCellValue(official.getIwfId() != null ? official.getIwfId() : ""); + row.createCell(4).setCellValue(official.getFederation() != null ? official.getFederation() : ""); + row.createCell(5).setCellValue(official.getFederationId() != null ? official.getFederationId() : ""); + } + + // Autosize columns + for (int i = 0; i < headers.length; i++) { + sheet.autoSizeColumn(i); + } + + // Write to byte array + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + workbook.write(outputStream); + return new ByteArrayInputStream(outputStream.toByteArray()); + + } catch (IOException e) { + logger.error("Error writing technical officials: {}", e); + return null; + } + } +} diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/TechnicalOfficialContent.java b/owlcms/src/main/java/app/owlcms/nui/preparation/TechnicalOfficialContent.java index 719875366d..19bbfee959 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/TechnicalOfficialContent.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/TechnicalOfficialContent.java @@ -16,6 +16,7 @@ import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.Hr; import com.vaadin.flow.component.html.NativeLabel; import com.vaadin.flow.component.icon.Icon; import com.vaadin.flow.component.icon.VaadinIcon; @@ -32,9 +33,10 @@ import app.owlcms.nui.crudui.OwlcmsCrudFormFactory; import app.owlcms.nui.crudui.OwlcmsCrudGrid; import app.owlcms.nui.crudui.OwlcmsGridLayout; +import app.owlcms.nui.shared.DownloadButtonFactory; import app.owlcms.nui.shared.OwlcmsContent; import app.owlcms.nui.shared.OwlcmsLayout; -import app.owlcms.spreadsheet.JXLSExportRecords; +import app.owlcms.spreadsheet.JXLSExportTechnicalOfficials; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; @@ -54,14 +56,14 @@ public class TechnicalOfficialContent extends BaseContent implements CrudListene private OwlcmsCrudFormFactory editingFormFactory; private OwlcmsLayout routerLayout; private FlexLayout topBar; + private GridCrud crud; /** * Instantiates the TechnicalOfficial crudGrid. */ public TechnicalOfficialContent() { OwlcmsCrudFormFactory crudFormFactory = createFormFactory(); - GridCrud crud = createGrid(crudFormFactory); - // defineFilters(crudGrid); + crud = createGrid(crudFormFactory); fillHW(crud, this); } @@ -78,23 +80,30 @@ public TechnicalOfficial add(TechnicalOfficial domainObjectToAdd) { public FlexLayout createMenuArea() { this.topBar = new FlexLayout(); + // Export current officials button using the age groups pattern + Div exportOfficials = DownloadButtonFactory.createDynamicXLSXDownloadButton( + "TechnicalOfficials", + Translator.translate("TechnicalOfficials.Export"), + new XLSXTechnicalOfficialsExport()); + exportOfficials.getStyle().set("margin-left", "1em"); + Button uploadCustom = new Button(Translator.translate("TechnicalOfficials.Upload"), new Icon(VaadinIcon.UPLOAD_ALT), buttonClickEvent -> { - AgeGroupsFileUploadDialog ageGroupsFileUploadDialog = new AgeGroupsFileUploadDialog(); - ageGroupsFileUploadDialog.setCallback(() -> loadOfficials()); - ageGroupsFileUploadDialog.open(); + TechnicalOfficialsUploadDialog dialog = new TechnicalOfficialsUploadDialog(); + dialog.setCallback(() -> loadOfficials()); + dialog.open(); }); - var recordsWriter1 = new JXLSExportRecords(UI.getCurrent(), true, true); + var toAssignmentsWriter = new JXLSExportTechnicalOfficials(UI.getCurrent(), true, true); JXLSDownloader dd1 = new JXLSDownloader( () -> { - return recordsWriter1; + return toAssignmentsWriter; }, - "/templates/records", + "/templates/toAssignments", Competition::getComputedTechnicalOfficialsTemplateFileName, Competition::setTechnicalOfficialsTemplateFileName, - Translator.translate("Records.exportCurrentRecordsTitle"), + Translator.translate("TechnicalOfficials.ExportAssignementReports"), Translator.translate("Download")); Div allRecords1 = new Div(); Button downloadButton = dd1.createDownloadButton(); @@ -102,8 +111,12 @@ public FlexLayout createMenuArea() { allRecords1.add(downloadButton); FlexLayout buttons = new FlexLayout( - new NativeLabel(Translator.translate("AgeGroups.Custom")), - allRecords1, uploadCustom); + new NativeLabel(Translator.translate("TechnicalOfficials.ImportExport")), + exportOfficials, + uploadCustom, + hr(), + new NativeLabel(Translator.translate("TechnicalOfficials.AssignmentReports")), + allRecords1); buttons.getStyle().set("flex-wrap", "wrap"); buttons.getStyle().set("gap", "1ex"); buttons.getStyle().set("margin-left", "5em"); @@ -117,11 +130,20 @@ public FlexLayout createMenuArea() { return this.topBar; } - private Object loadOfficials() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'loadOfficials'"); + private Hr hr() { + Hr hr = new Hr(); + hr.setWidthFull(); + hr.getStyle().set("margin", "0"); + hr.getStyle().set("padding", "0"); + return hr; } + private Object loadOfficials() { + logger.warn("refreshing"); + crud.refreshGrid(); + return null; + } + @Override public void delete(TechnicalOfficial domainObjectToDelete) { this.editingFormFactory.delete(domainObjectToDelete); diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/TechnicalOfficialsUploadDialog.java b/owlcms/src/main/java/app/owlcms/nui/preparation/TechnicalOfficialsUploadDialog.java new file mode 100644 index 0000000000..e2a041327c --- /dev/null +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/TechnicalOfficialsUploadDialog.java @@ -0,0 +1,48 @@ +package app.owlcms.nui.preparation; + +import java.io.InputStream; + +import org.slf4j.LoggerFactory; + +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.dialog.Dialog; +import com.vaadin.flow.component.html.NativeLabel; +import com.vaadin.flow.component.upload.Upload; +import com.vaadin.flow.component.upload.receivers.MemoryBuffer; + +import app.owlcms.data.technicalofficial.TechnicalOfficialReader; +import app.owlcms.i18n.Translator; +import ch.qos.logback.classic.Logger; + +@SuppressWarnings("serial") +public class TechnicalOfficialsUploadDialog extends Dialog { + Logger logger = (Logger) LoggerFactory.getLogger(TechnicalOfficialsUploadDialog.class); + private Runnable callback; + private MemoryBuffer buffer = new MemoryBuffer(); + private Upload upload; + + public TechnicalOfficialsUploadDialog() { + Button uploadButton = new Button(Translator.translate("TechnicalOfficials.Upload")); + upload = new Upload(buffer); + upload.setUploadButton(uploadButton); + upload.setDropLabel(new NativeLabel(Translator.translate("TechnicalOfficials.UploadDropZone"))); + upload.addSucceededListener(e -> { + try { + InputStream is = buffer.getInputStream(); + TechnicalOfficialReader.importFromXLS(is); + logger.warn("imported"); + close(); + if (callback != null) { + callback.run(); + } + } catch (Exception ex) { + // Handle error + } + }); + add(upload); + } + + public void setCallback(Runnable callback) { + this.callback = callback; + } +} diff --git a/owlcms/src/main/java/app/owlcms/nui/preparation/XLSXTechnicalOfficialsExport.java b/owlcms/src/main/java/app/owlcms/nui/preparation/XLSXTechnicalOfficialsExport.java index 626116f920..806f4779fc 100644 --- a/owlcms/src/main/java/app/owlcms/nui/preparation/XLSXTechnicalOfficialsExport.java +++ b/owlcms/src/main/java/app/owlcms/nui/preparation/XLSXTechnicalOfficialsExport.java @@ -1,16 +1,75 @@ package app.owlcms.nui.preparation; +import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.LoggerFactory; + +import app.owlcms.data.technicalofficial.TechnicalOfficial; +import app.owlcms.data.technicalofficial.TechnicalOfficialRepository; import app.owlcms.spreadsheet.XLSXWorkbookStreamSource; +import ch.qos.logback.classic.Logger; @SuppressWarnings("serial") public class XLSXTechnicalOfficialsExport extends XLSXWorkbookStreamSource { + final private static Logger logger = (Logger) LoggerFactory.getLogger(XLSXTechnicalOfficialsExport.class); + @Override protected void writeStream(OutputStream stream) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'writeStream'"); - } + Workbook workbook = new XSSFWorkbook(); + try { + Sheet sheet = workbook.createSheet("Technical Officials"); + + // Create header style + CellStyle headerStyle = workbook.createCellStyle(); + Font headerFont = workbook.createFont(); + headerFont.setBold(true); + headerStyle.setFont(headerFont); + + // Create headers + Row headerRow = sheet.createRow(0); + String[] headers = {"LastName", "FirstName", "Level", "IWFId", "Federation", "FederationId"}; + for (int i = 0; i < headers.length; i++) { + Cell cell = headerRow.createCell(i); + cell.setCellValue(headers[i]); + cell.setCellStyle(headerStyle); + } + // Add data rows + int rowNum = 1; + for (TechnicalOfficial official : TechnicalOfficialRepository.findAll()) { + Row row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue(official.getLastName() != null ? official.getLastName() : ""); + row.createCell(1).setCellValue(official.getFirstName() != null ? official.getFirstName() : ""); + row.createCell(2).setCellValue(official.getLevel() != null ? official.getLevel().toString() : ""); + row.createCell(3).setCellValue(official.getIwfId() != null ? official.getIwfId() : ""); + row.createCell(4).setCellValue(official.getFederation() != null ? official.getFederation() : ""); + row.createCell(5).setCellValue(official.getFederationId() != null ? official.getFederationId() : ""); + } + + // Autosize columns + for (int i = 0; i < headers.length; i++) { + sheet.autoSizeColumn(i); + } + + workbook.write(stream); + } catch (IOException e) { + logger.error("Error writing technical officials: {}", e); + throw new RuntimeException("Error writing technical officials", e); + } finally { + try { + workbook.close(); + } catch (IOException e) { + logger.error("Error closing workbook: {}", e); + } + } + } } diff --git a/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSExportTechnicalOfficials.java b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSExportTechnicalOfficials.java new file mode 100644 index 0000000000..9dbf2ca5a5 --- /dev/null +++ b/owlcms/src/main/java/app/owlcms/spreadsheet/JXLSExportTechnicalOfficials.java @@ -0,0 +1,231 @@ +/******************************************************************************* + * Copyright © 2009-present Jean-François Lamy + * + * 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.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ObjectUtils; +import org.slf4j.LoggerFactory; + +import com.vaadin.flow.component.UI; + +import app.owlcms.data.athlete.Athlete; +import app.owlcms.data.category.Category; +import app.owlcms.data.competition.Competition; +import app.owlcms.data.group.Group; +import app.owlcms.data.group.GroupRepository; +import app.owlcms.data.records.RecordEvent; +import app.owlcms.data.records.RecordRepository; +import app.owlcms.i18n.Translator; +import app.owlcms.utils.LoggerUtils; +import ch.qos.logback.classic.Logger; + +/** + * @author jflamy + * + */ +@SuppressWarnings("serial") +public class JXLSExportTechnicalOfficials extends JXLSWorkbookStreamSource { + + Logger logger = (Logger) LoggerFactory.getLogger(JXLSExportTechnicalOfficials.class); + Group group; + private List records; + // private List bestRecords; + private boolean allRecords; + private boolean currentOnly; + + public JXLSExportTechnicalOfficials(Group group, boolean excludeNotWeighed, UI ui) { + } + + public JXLSExportTechnicalOfficials(UI ui, boolean allRecords, boolean currentOnly) { + this.setAllRecords(allRecords); + this.currentOnly = currentOnly; + } + + @Override + public Group getGroup() { + return this.group; + } + + /** + * Must be called immediately after getSortedAthletes due to reliance on "records" variable side-effect. + * + * @param cat + * @return + */ + public List getRecords(Category cat) { + if (cat == null) { + return this.records.isEmpty() ? null : this.records; + } + this.logger.debug("category {} age >= {} <= {} bw > {} <= {}", + cat.getGender(), + cat.getAgeGroup().getMinAge(), + cat.getAgeGroup().getMaxAge(), + cat.getMinimumWeight(), + cat.getMaximumWeight()); + List catRecords = new ArrayList<>(); + for (RecordEvent record : this.records) { + Integer athleteAge = record.getAthleteAge(); + Double athleteBW = record.getAthleteBW(); + try { + if (record.getGender() == cat.getGender() + && athleteAge >= cat.getAgeGroup().getMinAge() + && athleteAge <= cat.getAgeGroup().getMaxAge() + && athleteBW > cat.getMinimumWeight() + && athleteBW <= cat.getMaximumWeight()) { + catRecords.add(record); + } + } catch (Exception e) { + this.logger.error("faulty record {}", record); + } + } + return catRecords.isEmpty() ? null : catRecords; + } + + @Override + public List getSortedAthletes() { + HashMap reportingBeans = getReportingBeans(); + + // prevent irrelevant "No Athletes" error message. + List athletes = List.of(new Athlete()); + + String groupName = this.group != null ? this.group.getName() : null; + 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.sort(sortRecords()); + } else { + this.records.sort(sortRecords()); + } + Map> grouped = groupByAgeGroup(this.records); + List>> list = new ArrayList<>(); + for (Entry> v : grouped.entrySet()) { + list.add(v); + } + reportingBeans.put("agegroups", list); + reportingBeans.put("records", this.records); + return athletes; + } + + @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() { + List athletes = getSortedAthletes(); + if (athletes != null) { + getReportingBeans().put("athletes", athletes); + getReportingBeans().put("lifters", athletes); // legacy + } + Competition competition = Competition.getCurrent(); + getReportingBeans().put("t", Translator.getMap()); + getReportingBeans().put("competition", competition); + getReportingBeans().put("session", getGroup()); // legacy + getReportingBeans().put("group", getGroup()); + + // reuse existing logic for processing records + JXLSExportTechnicalOfficials jxlsExportRecords = this; + // jxlsExportRecords.setGroup(getGroup()); + 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()); + this.logger.debug("{} records found", records.size()); + for (RecordEvent e : records) { + if (e.getBwCatUpper() > 250) { + e.setBwCatString(">" + e.getBwCatLower()); + } else { + e.setBwCatString(Integer.toString(e.getBwCatUpper())); + } + } + getReportingBeans().put("records", records); + } catch (Exception e) { + // no records + } + + getReportingBeans().put("masters", Competition.getCurrent().isMasters()); + List sessions = GroupRepository.findAll().stream().sorted((a, b) -> { + int compare = ObjectUtils.compare(a.getWeighInTime(), b.getWeighInTime(), true); + if (compare != 0) { + return compare; + } + return compare = ObjectUtils.compare(a.getPlatform(), b.getPlatform(), true); + }).collect(Collectors.toList()); + getReportingBeans().put("groups", sessions); + getReportingBeans().put("sessions", sessions); + } + + 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; + } + + private boolean isAllRecords() { + return this.allRecords; + } + + private void setAllRecords(boolean allRecords) { + // logger.debug("***** allRecords = {} {}", allRecords, LoggerUtils.whereFrom()); + this.allRecords = allRecords; + } + +} diff --git a/playwright/.classpath b/playwright/.classpath index a6e7009b01..379c3fc128 100644 --- a/playwright/.classpath +++ b/playwright/.classpath @@ -36,22 +36,5 @@ - - - - - - - - - - - - - - - - - diff --git a/publicresults-windows/.classpath b/publicresults-windows/.classpath index 977bb34842..a012d978d7 100644 --- a/publicresults-windows/.classpath +++ b/publicresults-windows/.classpath @@ -36,22 +36,5 @@ - - - - - - - - - - - - - - - - - diff --git a/publicresults/.classpath b/publicresults/.classpath index ce4f474237..1b228dacc8 100644 --- a/publicresults/.classpath +++ b/publicresults/.classpath @@ -42,22 +42,5 @@ - - - - - - - - - - - - - - - - - diff --git a/shared/.classpath b/shared/.classpath index 273f587ba5..c329ff24c8 100644 --- a/shared/.classpath +++ b/shared/.classpath @@ -36,22 +36,5 @@ - - - - - - - - - - - - - - - - -