From dfca5f639d10edf95453b18d9ca34b655ddbbd20 Mon Sep 17 00:00:00 2001 From: "Brian M. Long" Date: Wed, 4 Oct 2023 16:55:58 -0400 Subject: [PATCH] split api/impl; v2.x --- pom.xml | 16 +- .../poststats/golf/api/impl/CourseApi.java | 73 -- .../poststats/golf/api/impl/CoursesApi.java | 80 -- .../com/poststats/golf/api/impl/EventApi.java | 122 --- .../golf/api/impl/EventFinanceApi.java | 104 --- .../golf/api/impl/EventPersonApi.java | 116 --- .../golf/api/impl/EventRoundApi.java | 291 ------- .../poststats/golf/api/impl/GolferApi.java | 49 -- .../poststats/golf/api/impl/SeriesApi.java | 66 -- .../poststats/golf/job/EventAgendaJob.java | 292 ------- .../poststats/golf/provider/GolfProvider.java | 19 - .../impl/DefaultConnectionProvider.java | 41 - .../impl/DefaultDataSourceProvider.java | 18 - .../impl/DefaultStatementProvider.java | 32 - .../provider/impl/TxConnectionProvider.java | 42 - .../provider/impl/TxStatementProvider.java | 32 - .../golf/security/AuthenticatedPerson.java | 61 -- .../AuthenticatedSecurityContext.java | 50 -- .../golf/security/EventSecurityContext.java | 62 -- .../golf/security/PersonSecurityContext.java | 58 -- .../golf/service/CourseHoleService.java | 13 - .../golf/service/CourseNineService.java | 11 - .../golf/service/CourseRatingService.java | 33 - .../poststats/golf/service/CourseService.java | 55 -- .../golf/service/EventDocumentService.java | 17 - .../golf/service/EventFinanceService.java | 82 -- .../golf/service/EventPersonService.java | 51 -- .../service/EventRoundPairingService.java | 16 - .../golf/service/EventRoundService.java | 39 - .../poststats/golf/service/EventService.java | 34 - .../golf/service/HandicapIndexService.java | 35 - .../golf/service/HandicapScoreService.java | 37 - .../golf/service/PersonRoundService.java | 92 --- .../poststats/golf/service/PersonService.java | 53 -- .../golf/service/SeriesPersonService.java | 13 - .../poststats/golf/service/SeriesService.java | 35 - .../compute/AbstractHandicappingService.java | 45 -- .../AbstractPointHandicappingService.java | 242 ------ .../AbstractStrokeHandicappingService.java | 415 ---------- ...acyPostStatsPointHandicapIndexService.java | 117 --- .../PostStatsPointHandicapIndexService.java | 136 ---- .../PostStatsStrokeHandicappingService.java | 23 - .../WhsStrokeHandicapIndexService.java | 37 - .../golf/service/db/CourseServiceDAO.java | 277 ------- .../service/db/EventDocumentServiceDAO.java | 79 -- .../service/db/EventFinanceServiceDAO.java | 300 ------- .../service/db/EventPersonServiceDAO.java | 404 ---------- .../db/EventRoundPairingServiceDAO.java | 108 --- .../golf/service/db/EventRoundServiceDAO.java | 138 ---- .../golf/service/db/EventServiceDAO.java | 148 ---- .../service/db/PersonRoundServiceDAO.java | 740 ------------------ .../golf/service/db/PersonServiceDAO.java | 209 ----- .../golf/service/db/SeriesServiceDAO.java | 90 --- .../service/model/PointHandicapIndex.java | 404 ---------- .../service/model/StrokeCourseRating.java | 21 - .../telegram/TelegramEventService.java | 380 --------- .../golf/servlet/AuthenticationFilter.java | 51 -- .../poststats/golf/servlet/EventFilter.java | 63 -- .../poststats/golf/servlet/PersonFilter.java | 47 -- .../poststats/golf/servlet/SeriesFilter.java | 44 -- src/main/resources/META-INF/beans.xml | 5 - ...omputeLegacyPointCourseRatingUnitTest.java | 31 - .../ComputePointCourseRatingUnitTest.java | 124 --- .../ComputePointHandicapIndexUnitTest.java | 59 -- .../model/PointHandicapIndexUnitTest.java | 90 --- src/test/resources/log4j2.properties | 19 - src/test/resources/log4j2.xml | 24 + 67 files changed, 37 insertions(+), 7073 deletions(-) delete mode 100644 src/main/java/com/poststats/golf/api/impl/CourseApi.java delete mode 100644 src/main/java/com/poststats/golf/api/impl/CoursesApi.java delete mode 100644 src/main/java/com/poststats/golf/api/impl/EventApi.java delete mode 100644 src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java delete mode 100644 src/main/java/com/poststats/golf/api/impl/EventPersonApi.java delete mode 100644 src/main/java/com/poststats/golf/api/impl/EventRoundApi.java delete mode 100644 src/main/java/com/poststats/golf/api/impl/GolferApi.java delete mode 100644 src/main/java/com/poststats/golf/api/impl/SeriesApi.java delete mode 100644 src/main/java/com/poststats/golf/job/EventAgendaJob.java delete mode 100644 src/main/java/com/poststats/golf/provider/GolfProvider.java delete mode 100644 src/main/java/com/poststats/golf/provider/impl/DefaultConnectionProvider.java delete mode 100644 src/main/java/com/poststats/golf/provider/impl/DefaultDataSourceProvider.java delete mode 100644 src/main/java/com/poststats/golf/provider/impl/DefaultStatementProvider.java delete mode 100644 src/main/java/com/poststats/golf/provider/impl/TxConnectionProvider.java delete mode 100644 src/main/java/com/poststats/golf/provider/impl/TxStatementProvider.java delete mode 100644 src/main/java/com/poststats/golf/security/AuthenticatedPerson.java delete mode 100644 src/main/java/com/poststats/golf/security/AuthenticatedSecurityContext.java delete mode 100644 src/main/java/com/poststats/golf/security/EventSecurityContext.java delete mode 100644 src/main/java/com/poststats/golf/security/PersonSecurityContext.java delete mode 100644 src/main/java/com/poststats/golf/service/CourseHoleService.java delete mode 100644 src/main/java/com/poststats/golf/service/CourseNineService.java delete mode 100644 src/main/java/com/poststats/golf/service/CourseRatingService.java delete mode 100644 src/main/java/com/poststats/golf/service/CourseService.java delete mode 100644 src/main/java/com/poststats/golf/service/EventDocumentService.java delete mode 100644 src/main/java/com/poststats/golf/service/EventFinanceService.java delete mode 100644 src/main/java/com/poststats/golf/service/EventPersonService.java delete mode 100644 src/main/java/com/poststats/golf/service/EventRoundPairingService.java delete mode 100644 src/main/java/com/poststats/golf/service/EventRoundService.java delete mode 100644 src/main/java/com/poststats/golf/service/EventService.java delete mode 100644 src/main/java/com/poststats/golf/service/HandicapIndexService.java delete mode 100755 src/main/java/com/poststats/golf/service/HandicapScoreService.java delete mode 100644 src/main/java/com/poststats/golf/service/PersonRoundService.java delete mode 100644 src/main/java/com/poststats/golf/service/PersonService.java delete mode 100644 src/main/java/com/poststats/golf/service/SeriesPersonService.java delete mode 100644 src/main/java/com/poststats/golf/service/SeriesService.java delete mode 100644 src/main/java/com/poststats/golf/service/compute/AbstractHandicappingService.java delete mode 100644 src/main/java/com/poststats/golf/service/compute/AbstractPointHandicappingService.java delete mode 100644 src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicappingService.java delete mode 100644 src/main/java/com/poststats/golf/service/compute/LegacyPostStatsPointHandicapIndexService.java delete mode 100644 src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java delete mode 100644 src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicappingService.java delete mode 100644 src/main/java/com/poststats/golf/service/compute/WhsStrokeHandicapIndexService.java delete mode 100644 src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/EventDocumentServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/EventFinanceServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/EventPersonServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/EventRoundPairingServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/EventServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/db/SeriesServiceDAO.java delete mode 100644 src/main/java/com/poststats/golf/service/model/PointHandicapIndex.java delete mode 100644 src/main/java/com/poststats/golf/service/model/StrokeCourseRating.java delete mode 100644 src/main/java/com/poststats/golf/service/telegram/TelegramEventService.java delete mode 100644 src/main/java/com/poststats/golf/servlet/AuthenticationFilter.java delete mode 100644 src/main/java/com/poststats/golf/servlet/EventFilter.java delete mode 100644 src/main/java/com/poststats/golf/servlet/PersonFilter.java delete mode 100644 src/main/java/com/poststats/golf/servlet/SeriesFilter.java delete mode 100644 src/main/resources/META-INF/beans.xml delete mode 100644 src/test/java/com/poststats/golf/service/compute/ComputeLegacyPointCourseRatingUnitTest.java delete mode 100644 src/test/java/com/poststats/golf/service/compute/ComputePointCourseRatingUnitTest.java delete mode 100644 src/test/java/com/poststats/golf/service/compute/ComputePointHandicapIndexUnitTest.java delete mode 100644 src/test/java/com/poststats/golf/service/model/PointHandicapIndexUnitTest.java delete mode 100644 src/test/resources/log4j2.properties create mode 100644 src/test/resources/log4j2.xml diff --git a/pom.xml b/pom.xml index aba9aff..bfc26bc 100644 --- a/pom.xml +++ b/pom.xml @@ -2,8 +2,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.poststats.golf - golf-api - 1.0-SNAPSHOT + golf-rs-api + 2.0-SNAPSHOT jar @@ -40,10 +40,20 @@ 5.9.2 test + + org.apache.logging.log4j + log4j-slf4j2-impl + 2.20.0 + test + - + + + maven-surefire-plugin + 3.1.2 + io.swagger.core.v3 swagger-maven-plugin-jakarta diff --git a/src/main/java/com/poststats/golf/api/impl/CourseApi.java b/src/main/java/com/poststats/golf/api/impl/CourseApi.java deleted file mode 100644 index 80216ba..0000000 --- a/src/main/java/com/poststats/golf/api/impl/CourseApi.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.poststats.golf.api.impl; - -import org.slf4j.Logger; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.api.model.Course; -import com.poststats.golf.api.model.CourseNine; -import com.poststats.golf.service.CourseNineService; -import com.poststats.golf.service.CourseService; -import com.poststats.service.FacilityService; -import com.poststats.transformer.impl.DaoConverter; - -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response.Status; - -/** - * @author brian.long@poststats.com - */ -@RequestScoped -public class CourseApi implements com.poststats.golf.api.CourseApi { - - @Inject - private Logger logger; - - @Inject - private CourseService courseService; - - @Inject - private CourseNineService courseNineService; - - @Inject - private FacilityService facilityService; - - @Inject - private DaoConverter converter; - - @Override - public Course get(int courseId) { - FlexMap row = this.courseService.get(courseId); - if (row == null) - throw new WebApplicationException("Course not found", Status.NOT_FOUND); - this.logger.trace("found: {}", courseId); - - this.facilityService.inject("facilityID", row, "facility"); - return this.converter.convertValue(row, Course.class); - } - - @Override - public CourseNine getNine(int courseId, String name) { - FlexMap row = this.courseNineService.getNine(courseId, name); - if (row == null) - throw new WebApplicationException("Course nine not found", Status.NOT_FOUND); - this.logger.trace("found: {}", courseId); - - this.courseService.injectDeep("courseID", row, "course"); - return this.converter.convertValue(row, CourseNine.class); - } - - @Override - public CourseNine getNine(int courseId, long courseNineId) { - FlexMap row = this.courseNineService.getNine(courseNineId); - if (row == null) - throw new WebApplicationException("Course nine not found", Status.NOT_FOUND); - if (courseId != row.getInteger("courseID")) - throw new WebApplicationException("Course nine not found", Status.NOT_FOUND); - this.logger.trace("found: {}", courseNineId); - - return this.converter.convertValue(row, CourseNine.class); - } - -} diff --git a/src/main/java/com/poststats/golf/api/impl/CoursesApi.java b/src/main/java/com/poststats/golf/api/impl/CoursesApi.java deleted file mode 100644 index 6302628..0000000 --- a/src/main/java/com/poststats/golf/api/impl/CoursesApi.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.poststats.golf.api.impl; - -import java.util.List; - -import org.slf4j.Logger; - -import com.brianlong.util.FlexMap; -import com.brianlong.util.SubList; -import com.poststats.api.model.PagedCollection; -import com.poststats.api.model.Pagination; -import com.poststats.golf.api.model.Course; -import com.poststats.golf.service.CourseService; -import com.poststats.transformer.impl.DaoConverter; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response.Status; - -/** - * @author brian.long@poststats.com - */ -@RequestScoped -public class CoursesApi implements com.poststats.golf.api.CoursesApi { - - @Inject - private Logger logger; - - @Inject - private CourseService courseService; - - @Inject - private DaoConverter converter; - - @PostConstruct - public void init() { - this.logger.debug("CoursesApi init"); - } - - @Override - public PagedCollection> searchByName(String name, Pagination paging) { - SubList rows = this.courseService.findByName(name, paging.getPage(), paging.getPerPage()); - if (rows.isEmpty()) - throw new WebApplicationException("No matching courses found", Status.NOT_FOUND); - this.logger.trace("found: {} [{}-{}] of {}", rows.size(), rows.getStartIndex() + 1, rows.getEndIndex(), - rows.getTotal()); - - return this.converter.convertValue(rows, Course.class).withPage(paging.getPage()) - .withPerPage(paging.getPerPage()); - } - - @Override - public PagedCollection> searchByJurisdiction(String country, String state, Pagination paging) { - SubList rows = this.courseService.findByJurisdiction(country, state, paging.getPage(), - paging.getPerPage()); - if (rows.isEmpty()) - throw new WebApplicationException("No matching golf courses found", Status.NOT_FOUND); - this.logger.trace("found: {} [{}-{}] of {}", rows.size(), rows.getStartIndex() + 1, rows.getEndIndex(), - rows.getTotal()); - - return this.converter.convertValue(rows, Course.class).withPage(paging.getPage()) - .withPerPage(paging.getPerPage()); - } - - @Override - public PagedCollection> searchByJurisdiction(double latitude, double longitude, Integer radiusInMiles, - Pagination paging) { - SubList rows = this.courseService.findByLocation(latitude, longitude, radiusInMiles, - paging.getPage(), paging.getPerPage()); - if (rows.isEmpty()) - throw new WebApplicationException("No matching facilities found", Status.NOT_FOUND); - this.logger.trace("found: {} [{}-{}] of {}", rows.size(), rows.getStartIndex() + 1, rows.getEndIndex(), - rows.getTotal()); - - return this.converter.convertValue(rows, Course.class).withPage(paging.getPage()) - .withPerPage(paging.getPerPage()); - } - -} diff --git a/src/main/java/com/poststats/golf/api/impl/EventApi.java b/src/main/java/com/poststats/golf/api/impl/EventApi.java deleted file mode 100644 index edc11e3..0000000 --- a/src/main/java/com/poststats/golf/api/impl/EventApi.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.poststats.golf.api.impl; - -import java.io.IOException; -import java.math.BigInteger; -import java.sql.SQLException; -import java.util.Collections; -import java.util.Map; - -import org.slf4j.Logger; - -import com.brianlong.cache.CacheRetrievalException; -import com.brianlong.util.FlexMap; -import com.poststats.golf.api.model.Event; -import com.poststats.golf.job.EventAgendaJob; -import com.poststats.golf.service.EventDocumentService; -import com.poststats.golf.service.EventPersonService; -import com.poststats.golf.service.EventService; -import com.poststats.golf.service.SeriesService; -import com.poststats.transformer.impl.DaoConverter; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.mail.MessagingException; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response.Status; - -/** - * @author brian.long@poststats.com - */ -@RequestScoped -public class EventApi implements com.poststats.golf.api.EventApi { - - @Inject - private Logger logger; - - @Inject - private EventService eventService; - - @Inject - private EventDocumentService eventDocumentService; - - @Inject - private EventPersonService eventPersonService; - - @Inject - private EventAgendaJob eventAgendaJob; - - @Inject - private SeriesService seriesService; - - @Inject - private DaoConverter converter; - - @PostConstruct - public void init() { - this.logger.debug("EventApi init"); - } - - @Override - public Event get(long eventId) { - FlexMap row = this.eventService.get(eventId); - if (row == null) - throw new WebApplicationException("Event not found", Status.NOT_FOUND); - return this.converter.convertValue(row, Event.class); - } - - @Override - public Event getDetail(long eventId) { - FlexMap row = this.eventService.get(eventId); - if (row == null) - throw new WebApplicationException("Event not found", Status.NOT_FOUND); - - this.seriesService.inject("seriesID", row, "series"); - return this.converter.convertValue(row, Event.class); - } - - @Override - public void sendDocument(long eventId, long documentId) { - FlexMap document = this.eventDocumentService.get(eventId, documentId); - if (document == null) - throw new WebApplicationException("Document not found", Status.NOT_FOUND); - - switch (document.getString("type")) { - case "agenda": - try { - this.eventAgendaJob.send(document); - } catch (CacheRetrievalException | SQLException | MessagingException | IOException e) { - throw new WebApplicationException(e); - } - break; - default: - throw new WebApplicationException("Document is not an agenda", Status.UNSUPPORTED_MEDIA_TYPE); - } - } - - @Override - public void sendTestDocument(long eventId, long documentId, long personId) { - FlexMap document = this.eventDocumentService.get(eventId, documentId); - if (document == null) - throw new WebApplicationException("Document not found", Status.NOT_FOUND); - - FlexMap eperson = this.eventPersonService.get(eventId, personId); - if (eperson == null) - throw new WebApplicationException("Person not found", Status.NOT_FOUND); - - Map recipientIds = Collections.singletonMap(personId, eperson.getBigInteger("epersonID")); - - switch (document.getString("type")) { - case "agenda": - try { - this.eventAgendaJob.send(document, recipientIds); - } catch (CacheRetrievalException | SQLException | MessagingException | IOException e) { - throw new WebApplicationException(e); - } - break; - default: - throw new WebApplicationException("Document is not an agenda", Status.UNSUPPORTED_MEDIA_TYPE); - } - } - -} diff --git a/src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java b/src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java deleted file mode 100644 index cf4b44d..0000000 --- a/src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.poststats.golf.api.impl; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.csv.CSVFormat; -import org.apache.commons.csv.CSVPrinter; - -import com.brianlong.sql.DataSet; -import com.poststats.golf.service.EventFinanceService; - -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.StreamingOutput; - -@RequestScoped -public class EventFinanceApi implements com.poststats.golf.api.EventFinanceApi { - - @Inject - private EventFinanceService eventFinanceService; - - @Override - public List> getBalanceByPersonsAsJson(long eventId, Float minBalance, Float maxBalance) { - Map personsBalances = this.eventFinanceService.getPersonsBalances(eventId, minBalance, - maxBalance); - - List> personsBalancesJson = new ArrayList<>(personsBalances.size()); - for (DataSet personBalance : personsBalances.values()) { - Map personBalanceJson = new HashMap<>(5); - personBalanceJson.put("personId", personBalance.getLong("personID")); - personBalanceJson.put("expense", personBalance.getFloat("expense")); - personBalanceJson.put("paid", personBalance.getFloat("paid")); - personBalanceJson.put("balance", personBalance.getFloat("balance")); - personsBalancesJson.add(personBalanceJson); - } - - return personsBalancesJson; - } - - @Override - public StreamingOutput getBalanceByPersonsAsCsv(long eventId) { - Map personsBalances = this.eventFinanceService.getPersonsBalances(eventId); - - return new StreamingOutput() { - @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - PrintStream pstream = new PrintStream(output); - CSVPrinter personsBalancesCsvPrinter = new CSVPrinter(pstream, CSVFormat.DEFAULT); - try { - personsBalancesCsvPrinter.printRecord("personID", "lname", "fname", "suffix", "expense", "paid", - "balance"); - - for (DataSet personBalance : personsBalances.values()) { - personsBalancesCsvPrinter.printRecord(personBalance.getLong("personID"), - personBalance.getString("lname"), personBalance.getString("fname"), - personBalance.getString("suffix"), personBalance.getFloat("expense"), - personBalance.getFloat("paid"), personBalance.getFloat("balance")); - } - - personsBalancesCsvPrinter.flush(); - } finally { - personsBalancesCsvPrinter.close(); - } - } - }; - } - - @Override - public Map getBalanceByPersonsAsJson(long eventId, long personId) { - DataSet personBalance = this.eventFinanceService.getPersonBalance(eventId, personId); - - Map personBalanceJson = new HashMap<>(5); - personBalanceJson.put("personId", personBalance.getLong("personID")); - personBalanceJson.put("expense", personBalance.getFloat("expense")); - personBalanceJson.put("paid", personBalance.getFloat("paid")); - personBalanceJson.put("balance", personBalance.getFloat("balance")); - - return personBalanceJson; - } - - @Override - public List> getSeriesBalanceByPersonsAsJson(long eventId) { - Map personsBalances = this.eventFinanceService.getSeriesPersonsPreviousBalances(eventId); - - List> personsBalancesJson = new ArrayList<>(personsBalances.size()); - for (DataSet personBalance : personsBalances.values()) { - Map personBalanceJson = new HashMap<>(5); - personBalanceJson.put("personId", personBalance.getLong("personID")); - personBalanceJson.put("expense", personBalance.getFloat("expense")); - personBalanceJson.put("paid", personBalance.getFloat("paid")); - personBalanceJson.put("balance", personBalance.getFloat("balance")); - personsBalancesJson.add(personBalanceJson); - } - - return personsBalancesJson; - } - -} diff --git a/src/main/java/com/poststats/golf/api/impl/EventPersonApi.java b/src/main/java/com/poststats/golf/api/impl/EventPersonApi.java deleted file mode 100644 index 82867eb..0000000 --- a/src/main/java/com/poststats/golf/api/impl/EventPersonApi.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.poststats.golf.api.impl; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.csv.CSVFormat; -import org.apache.commons.csv.CSVPrinter; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.api.model.EventPerson; -import com.poststats.golf.service.EventPersonService; -import com.poststats.golf.service.EventService; -import com.poststats.golf.service.PersonService; -import com.poststats.transformer.impl.DaoConverter; - -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.core.StreamingOutput; - -@RequestScoped -public class EventPersonApi implements com.poststats.golf.api.EventPersonApi { - - @Inject - private EventService eventService; - - @Inject - private EventPersonService eventPersonService; - - @Inject - private PersonService golferService; - - @Inject - private DaoConverter converter; - - @Override - public List get(long eventId) { - return this.converter.convertValue(this.eventPersonService.getPeople(eventId), EventPerson.class); - } - - @Override - public List getDetail(long eventId) { - List persons = this.eventPersonService.getPeople(eventId); - this.golferService.injectDeep("personID", persons, "golfer"); - return this.converter.convertValue(persons, EventPerson.class); - } - - @Override - public StreamingOutput getAsCsv(long eventId) { - List persons = this.eventPersonService.getPeople(eventId); - return this.toCsv(persons); - } - - @Override - public List getParticipants(long eventId) { - List participants = this.eventPersonService.getParticipants(eventId); - this.golferService.injectDeep("personID", participants, "golfer"); - return this.converter.convertValue(participants, EventPerson.class); - } - - @Override - public StreamingOutput getParticipantsAsCsv(long eventId) { - List persons = this.eventPersonService.getParticipants(eventId); - return this.toCsv(persons); - } - - @Override - public Set getSeriesParticipants(long eventId) { - int seriesId = this.eventService.getSeriesId(eventId); - Set eventIds = this.eventService.getIdsBySeriesId(seriesId); - - Set personIds = new HashSet<>(); - for (long otherEventId : eventIds) { - List tmpPersons = this.eventPersonService.getParticipants(otherEventId); - for (FlexMap person : tmpPersons) - personIds.add(person.getLong(com.poststats.sql.Constants.PERSON_ID)); - } - - return personIds; - } - - private StreamingOutput toCsv(List persons) { - this.golferService.injectDeep("personID", persons, "golfer"); - - return new StreamingOutput() { - @Override - public void write(OutputStream output) throws IOException { - PrintStream pstream = new PrintStream(output); - CSVPrinter personsCsvPrinter = new CSVPrinter(pstream, CSVFormat.DEFAULT); - try { - personsCsvPrinter.printRecord("ID", "Prefix", "Last Name", "First Name", "Suffix", "Email Address", - "Mobile Phone", "Address Lines", "City", "State", "Country", "Postal Code"); - - for (FlexMap eperson : persons) { - FlexMap golfer = (FlexMap) eperson.get("golfer"); - FlexMap person = (FlexMap) golfer.get("person"); - - personsCsvPrinter.printRecord(person.getLong("personID"), person.getString("prefix"), - person.getString("lname"), person.getString("fname"), person.getString("suffix"), - person.getString("email"), person.getString("cellphone"), person.getString("addrlines"), - person.getString("addrcity"), person.getString("addrstate"), - person.getString("addrcountry"), person.getString("addrzip")); - } - - personsCsvPrinter.flush(); - } finally { - personsCsvPrinter.close(); - } - } - }; - } - -} diff --git a/src/main/java/com/poststats/golf/api/impl/EventRoundApi.java b/src/main/java/com/poststats/golf/api/impl/EventRoundApi.java deleted file mode 100644 index 16af6c7..0000000 --- a/src/main/java/com/poststats/golf/api/impl/EventRoundApi.java +++ /dev/null @@ -1,291 +0,0 @@ -package com.poststats.golf.api.impl; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -import org.apache.commons.csv.CSVFormat; -import org.apache.commons.csv.CSVPrinter; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; - -import com.brianlong.util.FlexMap; -import com.poststats.formatter.PersonFormatter; -import com.poststats.formatter.PersonsFormatter; -import com.poststats.golf.api.model.EventRound; -import com.poststats.golf.api.model.EventRoundPairing; -import com.poststats.golf.api.model.EventRoundPairingOrder; -import com.poststats.golf.formatter.GolfCourseFormatter; -import com.poststats.golf.service.CourseService; -import com.poststats.golf.service.EventRoundPairingService; -import com.poststats.golf.service.EventRoundService; -import com.poststats.golf.service.PersonService; -import com.poststats.transformer.impl.DaoConverter; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response.Status; -import jakarta.ws.rs.core.StreamingOutput; - -/** - * @author brian.long@poststats.com - */ -@RequestScoped -public class EventRoundApi implements com.poststats.golf.api.EventRoundApi { - - @Inject - private Logger logger; - - @Inject - private PersonService golferService; - - @Inject - private EventRoundService roundService; - - @Inject - private EventRoundPairingService pairingService; - - @Inject - private CourseService courseService; - - @Inject - private DaoConverter converter; - - @PostConstruct - public void init() { - this.logger.debug("EventRoundApi init"); - } - - @Override - public List getNext(long eventId) { - List rows = this.roundService.getUpcoming(eventId); - if (rows == null || rows.isEmpty()) - throw new WebApplicationException("No event round was found", Status.NOT_FOUND); - - this.courseService.injectDeep("courseID", rows, "course"); - return this.converter.convertValue(rows, EventRound.class); - } - - @Override - public EventRound getOne(long eventId, long eroundId) { - FlexMap row = this.roundService.get(eroundId); - if (row == null) - throw new WebApplicationException("Event round not found", Status.NOT_FOUND); - if (eventId != row.getLong("eventID")) { - this.logger.warn("The event round {} was requested without the appropriate event ID {}", eroundId, eventId); - throw new WebApplicationException("Event round not found", Status.NOT_FOUND); - } - - this.courseService.injectDeep("courseID", row, "course"); - return this.converter.convertValue(row, EventRound.class); - } - - @Override - public List getAll(long eventId) { - Map rows = this.roundService.getByEventId(eventId); - if (rows.isEmpty()) - throw new WebApplicationException("No event rounds found", Status.NOT_FOUND); - - return this.converter.convertValue(rows.values(), EventRound.class); - } - - @Override - public List getPairings(long eventId, long eroundId) { - List rows = this.pairingService.getByRoundId(eroundId); - if (rows == null || rows.isEmpty()) - throw new WebApplicationException("No pairings found", Status.NOT_FOUND); - - this.courseService.inject("courseID", rows, "course"); - return this.converter.convertValue(rows, EventRoundPairing.class); - } - - @Override - public StreamingOutput getPairingsAsCsv(long eventId, long eroundId, List orderBys, - boolean lastNameFirst) { - this.logger.debug("getPairingsAsCsv({}, {})", eroundId, lastNameFirst); - - List rows = this.pairingService.getParticipantsByRoundId(eroundId); - if (rows == null || rows.isEmpty()) - throw new WebApplicationException("No pairings found", Status.NOT_FOUND); - this.logger.debug("Found {} pairings in round: {}", rows.size(), eroundId); - - this.golferService.injectDeep("personID", rows, "golfer"); - - PersonFormatter personFormatter = new PersonFormatter(); - personFormatter.withNameReversal(lastNameFirst); - GolfCourseFormatter courseFormatter = new GolfCourseFormatter(); - - for (FlexMap row : rows) { - FlexMap golfer = row.get("golfer", FlexMap.class); - FlexMap person = golfer.get("person", FlexMap.class); - row.put("name", personFormatter.format(person)); - - FlexMap pairing = row.get("pairing", FlexMap.class); - this.courseService.inject("courseID", pairing, "course"); - - FlexMap course = pairing.get("course", FlexMap.class); - if (course != null) - pairing.put("courseName", courseFormatter.format(course)); - } - - this.sort(rows, orderBys); - return this.toCsv(rows, lastNameFirst); - } - - @Override - public EventRoundPairing getPairing(long eventId, long eroundId, BigInteger pairingId) { - FlexMap row = this.pairingService.get(pairingId); - if (row == null) - throw new WebApplicationException("No pairing was found", Status.NOT_FOUND); - if (eroundId != row.getLong("eroundID")) { - this.logger.warn("The event round pairing {} was requested without the appropriate event round ID {}", - pairingId, eroundId); - throw new WebApplicationException("No pairing was found", Status.NOT_FOUND); - } - - this.courseService.inject("courseID", row, "course"); - return this.converter.convertValue(row, EventRoundPairing.class); - } - - private void sort(List persons, List orderBys) { - final List orders = new LinkedList<>((orderBys == null || orderBys.isEmpty()) - ? Arrays.asList(EventRoundPairingOrder.Pairing, EventRoundPairingOrder.FormattedName) - : orderBys); - this.logger.debug("Sorting by: {}", orders); - - ListIterator i = orders.listIterator(); - while (i.hasNext()) { - EventRoundPairingOrder order = i.next(); - if (order == EventRoundPairingOrder.Pairing) { - i.remove(); - i.add(EventRoundPairingOrder.TeeTime); - i.add(EventRoundPairingOrder.Course); - i.add(EventRoundPairingOrder.CourseNine); - i.add(EventRoundPairingOrder.HoleNumber); - } - } - - Collections.sort(persons, new Comparator() { - @Override - public int compare(FlexMap person1, FlexMap person2) { - if (person1 == null && person2 == null) { - return 0; - } else if (person1 == null) { - return -1; - } else if (person2 == null) { - return 1; - } else { - for (EventRoundPairingOrder order : orders) { - int compare = 0; - FlexMap pairing1 = person1.get("pairing", FlexMap.class); - FlexMap pairing2 = person2.get("pairing", FlexMap.class); - - switch (order) { - case FormattedName: - compare = person1.getString("name").compareTo(person2.getString("name")); - break; - case LastName: - compare = person1.get("golfer", FlexMap.class).get("person", FlexMap.class) - .getString("lname").compareTo(person2.get("golfer", FlexMap.class) - .get("person", FlexMap.class).getString("lname")); - break; - case FirstName: - compare = person1.get("golfer", FlexMap.class).get("person", FlexMap.class) - .getString("fname").compareTo(person2.get("golfer", FlexMap.class) - .get("person", FlexMap.class).getString("fname")); - break; - case Course: - if (!pairing1.isNotEmpty("course") && !pairing2.isNotEmpty("course")) { - } else if (!pairing1.isNotEmpty("course")) { - return -1; - } else if (!pairing2.isNotEmpty("course")) { - return 1; - } else { - compare = StringUtils.compare( - pairing1.get("course", FlexMap.class).getString("nine"), - pairing2.get("course", FlexMap.class).getString("nine")); - } - break; - case CourseNine: - if (!pairing1.isNotEmpty("nine") && !pairing2.isNotEmpty("nine")) { - } else if (!pairing1.isNotEmpty("nine")) { - return -1; - } else if (!pairing2.isNotEmpty("nine")) { - return 1; - } else { - compare = StringUtils.compare(pairing1.get("nine", FlexMap.class).getString("nine"), - pairing2.get("nine", FlexMap.class).getString("nine")); - } - break; - case HoleNumber: - compare = compareTo(pairing1.getByte("number"), pairing2.getByte("number")); - break; - case TeeTime: - compare = compareTo(pairing1.getTime("teetime"), pairing2.getTime("teetime")); - break; - default: - throw new IllegalArgumentException(); - } - - if (compare != 0) - return compare; - } - - return 0; - } - } - }); - } - - private StreamingOutput toCsv(List persons, boolean lastNameFirst) { - return new StreamingOutput() { - @Override - public void write(OutputStream output) throws IOException { - PersonsFormatter personsFormatter = new PersonsFormatter<>(); - personsFormatter.withNameReversal(lastNameFirst); - - PrintStream pstream = new PrintStream(output); - CSVPrinter personsCsvPrinter = new CSVPrinter(pstream, CSVFormat.DEFAULT); - try { - personsCsvPrinter.printRecord("Name", "Tee Time", "Course", "Course Nine", "Hole Number"); - - for (FlexMap eperson : persons) { - FlexMap pairing = eperson.get("pairing", FlexMap.class); - FlexMap nine = pairing.get("nine", FlexMap.class); - - personsCsvPrinter.printRecord(eperson.getString("name"), pairing.getTime("teetime"), - pairing.getString("courseName"), nine == null ? null : nine.getString("nine"), - pairing.getByte("number")); - } - - personsCsvPrinter.flush(); - } finally { - personsCsvPrinter.close(); - } - } - }; - } - - private > int compareTo(T c1, T c2) { - if (c1 == null && c2 == null) { - return 0; - } else if (c1 == null) { - return -1; - } else if (c2 == null) { - return 1; - } else { - return c1.compareTo(c2); - } - } - -} diff --git a/src/main/java/com/poststats/golf/api/impl/GolferApi.java b/src/main/java/com/poststats/golf/api/impl/GolferApi.java deleted file mode 100644 index b1b15a3..0000000 --- a/src/main/java/com/poststats/golf/api/impl/GolferApi.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.poststats.golf.api.impl; - -import org.slf4j.Logger; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.api.model.Golfer; -import com.poststats.golf.service.PersonService; -import com.poststats.transformer.impl.DaoConverter; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response.Status; - -/** - * @author brian.long@poststats.com - */ -@RequestScoped -public class GolferApi extends com.poststats.golf.api.GolferApi { - - @Inject - private Logger logger; - - @Inject - private PersonService personService; - - @Inject - private com.poststats.service.PersonService poststatsPersonService; - - @Inject - private DaoConverter converter; - - @PostConstruct - public void init() { - this.logger.debug("GolferApi init: {}", this.getPersonId()); - } - - @Override - public Golfer get() { - FlexMap row = this.personService.get(this.getPersonId()); - if (row == null) - throw new WebApplicationException("Event not found", Status.NOT_FOUND); - - this.poststatsPersonService.inject("personID", row, "person"); - return this.converter.convertValue(row, Golfer.class); - } - -} diff --git a/src/main/java/com/poststats/golf/api/impl/SeriesApi.java b/src/main/java/com/poststats/golf/api/impl/SeriesApi.java deleted file mode 100644 index 55d5269..0000000 --- a/src/main/java/com/poststats/golf/api/impl/SeriesApi.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.poststats.golf.api.impl; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.api.model.Event; -import com.poststats.golf.api.model.Series; -import com.poststats.golf.service.EventService; -import com.poststats.golf.service.SeriesService; -import com.poststats.transformer.impl.DaoConverter; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response.Status; - -/** - * @author brian.long@poststats.com - */ -@RequestScoped -public class SeriesApi extends com.poststats.golf.api.SeriesApi { - - @Inject - private Logger logger; - - @Inject - private SeriesService seriesService; - - @Inject - private EventService eventService; - - @Inject - private DaoConverter converter; - - @PostConstruct - public void init() { - this.logger.debug("SeriesApi init: {}", this.getSeriesId()); - } - - @Override - public Series get() { - FlexMap row = this.seriesService.get(this.getSeriesId()); - if (row == null) - throw new WebApplicationException("Series not found", Status.NOT_FOUND); - - return this.converter.convertValue(row, Series.class); - } - - @Override - public List getEvents(Boolean reverse) { - Map rows = this.eventService.getBySeriesId(this.getSeriesId()); - if (rows.isEmpty()) - throw new WebApplicationException("Series or events not found", Status.NOT_FOUND); - - List events = this.converter.convertValue(rows.values(), Event.class); - if (Boolean.TRUE.equals(reverse)) - Collections.reverse(events); - return events; - } - -} diff --git a/src/main/java/com/poststats/golf/job/EventAgendaJob.java b/src/main/java/com/poststats/golf/job/EventAgendaJob.java deleted file mode 100644 index c3d95d3..0000000 --- a/src/main/java/com/poststats/golf/job/EventAgendaJob.java +++ /dev/null @@ -1,292 +0,0 @@ -package com.poststats.golf.job; - -import java.io.IOException; -import java.math.BigInteger; -import java.sql.SQLException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.io.IOUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.methods.RequestBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.message.BasicNameValuePair; -import org.slf4j.Logger; - -import com.brianlong.cache.CacheRetrievalException; -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.DateTimeFormatter; -import com.brianlong.util.FlexMap; -import com.poststats.golf.formatter.EventFormatter; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.EventPersonService; -import com.poststats.golf.service.EventService; -import com.poststats.golf.sql.EventAutolist; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.PersonService; -import com.poststats.service.file.EnvironmentConfiguration; -import com.poststats.util.CompositeTexter; -import com.poststats.util.Contact; -import com.poststats.util.Emailer; - -import jakarta.annotation.PostConstruct; -import jakarta.ejb.Schedule; -import jakarta.ejb.Singleton; -import jakarta.inject.Inject; -import jakarta.mail.MessagingException; - -@Singleton -public class EventAgendaJob { - - private final DateTimeFormatter weekdayFormatter = new DateTimeFormatter("EEEE"); - - @Inject - private Logger logger; - - @Inject - private EnvironmentConfiguration envConfig; - - @Inject - private PersonService personService; - - @Inject - private EventService eventService; - - @Inject - private EventPersonService eventPersonService; - - private String baseGolfUrl; - private CompositeTexter texter; - - @PostConstruct - public void init() { - this.baseGolfUrl = this.envConfig.getString("golf.url") - + "/c"; - this.texter = new CompositeTexter(this.envConfig); - } - - @Schedule(hour = "21", timezone = "EDT") - protected void nightly() throws CacheRetrievalException, SQLException, MessagingException, IOException { - this.logger.trace("run()"); - - // if executed after 6p, then agendas should be for following day - LocalDateTime now = LocalDateTime.now(); // (2016, 6, 7, 22, 0); - LocalDate date = now.plusHours(6).toLocalDate(); - - this.logger.info("Sending agendas for {}", date); - - List agendas = this.getAgendas(date); - if (agendas.isEmpty()) { - this.logger.debug("No agenda items to send: {}", date); - return; - } - - for (DataSet agenda : agendas) - this.send(agenda); - } - - private List getAgendas(LocalDate date) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectAgendas.buildPreparedStatement(); - try { - fps.setDate(1, date); - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } - - public void send(FlexMap agenda) throws CacheRetrievalException, SQLException, MessagingException, IOException { - Long eventID = agenda.getLong("eventID"); - Map recipientIDs = EventAutolist.getInstance().getPersonIDMap("signed", eventID.longValue()); - this.send(agenda, recipientIDs); - } - - public void send(FlexMap agenda, Map recipientIDs) - throws CacheRetrievalException, SQLException, MessagingException, IOException { - boolean doEmailLink = Boolean.TRUE.equals(agenda.getBoolean("sendEmailWithLink")); - boolean doEmail = Boolean.TRUE.equals(agenda.getBoolean("sendEmailWithContent")); - boolean doTextLink = Boolean.TRUE.equals(agenda.getBoolean("sendTextWithLink")); - boolean doText = Boolean.TRUE.equals(agenda.getBoolean("sendTextWithContent")); - if (!doTextLink && !doText && !doEmailLink && !doEmail) - return; - - Long eventId = agenda.getLong("eventID"); - Long documentId = agenda.getLong("documentID"); - LocalDate day = agenda.getDate("day"); - - this.logger.debug("Sending agenda with document ID: {}", documentId); - - FlexMap event = this.eventService.get(eventId); - String subject = new EventFormatter().format(event) - + " Agenda for " - + this.weekdayFormatter.format(day); - - Set textedPersonIDs = Collections.emptySet(); - - if (doTextLink) { - textedPersonIDs = this.textLink(eventId, documentId, recipientIDs, subject); - } else if (doText) { - textedPersonIDs = this.text(eventId, documentId, recipientIDs, subject); - } - - if (doEmailLink) { - this.emailLink(eventId, documentId, recipientIDs, textedPersonIDs, subject); - } else if (doEmail) { - this.email(eventId, documentId, recipientIDs, textedPersonIDs, subject); - } - } - - private Set textLink(long eventID, long documentID, Map recipientIDs, String subject) - throws SQLException, MessagingException { - this.logger.debug("Sending agenda links by text with document ID: {}", documentID); - - List recipients = this.personService.getContacts(recipientIDs.keySet(), false, true); - - String baseUrl = baseGolfUrl - + "?n=documentAgenda&eventID=" - + eventID - + "&documentID=" - + documentID - + "&epersonID="; - - Set textedPersonIDs = new HashSet(recipientIDs.size()); - - for (Contact recipient : recipients) { - long personId = recipient.getPersonId(); - this.logger.debug("Sending agenda to: {}", personId); - String message = baseUrl + recipientIDs.get(personId); - this.texter.send(Arrays.asList(recipient), subject, message); - - textedPersonIDs.add(personId); - } - - return textedPersonIDs; - } - - private Set text(long eventID, long documentID, Map recipientIDs, String subject) - throws SQLException, MessagingException, IOException { - this.logger.debug("Sending agenda links by text with document ID: {}", documentID); - - List recipients = this.personService.getContacts(recipientIDs.keySet(), false, true); - - NameValuePair[] params = new NameValuePair[] { - new BasicNameValuePair("n", "documentAgendaMarkdown"), - new BasicNameValuePair("eventID", String.valueOf(eventID)), - new BasicNameValuePair("documentID", String.valueOf(documentID)) - }; - - Set textedPersonIDs = new HashSet(recipientIDs.size()); - - for (Contact recipient : recipients) { - long personId = recipient.getPersonId(); - this.logger.debug("Sending agenda to: {}", personId); - - HttpUriRequest request = RequestBuilder.get(this.baseGolfUrl).addParameters(params) - .addParameter("epersonID", recipientIDs.get(personId).toString()).build(); - - CloseableHttpClient hclient = HttpClientBuilder.create().build(); - CloseableHttpResponse response = hclient.execute(request); - try { - if (response.getStatusLine().getStatusCode() / 100 == 2) { - String markdown = IOUtils.toString(response.getEntity().getContent(), "utf-8"); - this.texter.send(Arrays.asList(recipient), subject, markdown.trim()); - textedPersonIDs.add(personId); - } else { - this.logger.warn("The URL could not be loaded properly: {}", request.getURI()); - } - } finally { - response.close(); - } - } - - return textedPersonIDs; - } - - private void emailLink(long eventID, long documentID, Map recipientIDs, - Set excludePersonIDs, String subject) throws SQLException, MessagingException { - this.logger.debug("Sending agenda links by email with document ID: {}", documentID); - - List recipients = this.personService.getContacts(recipientIDs.keySet(), true, false); - - String baseUrl = this.baseGolfUrl - + "?n=documentAgenda&eventID=" - + eventID - + "&documentID=" - + documentID - + "&epersonID="; - for (Contact recipient : recipients) { - long personId = recipient.getPersonId(); - if (excludePersonIDs.contains(personId)) - continue; - if (logger.isDebugEnabled()) - logger.debug("Sending agenda to: {}", personId); - String message = "

" - + baseUrl - + recipientIDs.get(personId) - + "

"; - Emailer.getInstance(this.envConfig).send(Arrays.asList(recipient), subject, message); - } - } - - private void email(long eventID, long documentID, Map recipientIDs, Set excludePersonIDs, - String subject) throws SQLException, MessagingException, IOException { - this.logger.debug("Sending agenda contents with document ID: {}", documentID); - - List recipients = this.personService.getContacts(recipientIDs.keySet(), true, false); - - NameValuePair[] params = new NameValuePair[] { - new BasicNameValuePair("n", "documentAgendaMinimal"), - new BasicNameValuePair("eventID", String.valueOf(eventID)), - new BasicNameValuePair("documentID", String.valueOf(documentID)) - }; - - for (Contact recipient : recipients) { - long personId = recipient.getPersonId(); - this.logger.debug("Sending agenda to: {}", personId); - - HttpUriRequest request = RequestBuilder.get(this.baseGolfUrl).addParameters(params) - .addParameter("epersonID", recipientIDs.get(personId).toString()).build(); - - CloseableHttpClient hclient = HttpClientBuilder.create().build(); - CloseableHttpResponse response = hclient.execute(request); - try { - if (response.getStatusLine().getStatusCode() / 100 == 2) { - String html = IOUtils.toString(response.getEntity().getContent(), "utf-8"); - Emailer.getInstance(this.envConfig).send(Arrays.asList(recipient), subject, html); - } else { - this.logger.warn("The URL could not be loaded properly: {}", request.getURI()); - } - } finally { - response.close(); - } - } - } - - - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT ED.* " - + "FROM ~g~.EventDocument ED " - + "WHERE ED.day=? " - + " AND (ED.sendEmailWithLink IS TRUE OR ED.sendEmailWithContent IS TRUE OR ED.sendTextWithLink IS TRUE)" - ) - private StatementProvider sqlSelectAgendas; - -} diff --git a/src/main/java/com/poststats/golf/provider/GolfProvider.java b/src/main/java/com/poststats/golf/provider/GolfProvider.java deleted file mode 100644 index 06da0ba..0000000 --- a/src/main/java/com/poststats/golf/provider/GolfProvider.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.poststats.golf.provider; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import jakarta.inject.Qualifier; - -@Qualifier -@Target({ - ElementType.TYPE, ElementType.PARAMETER, ElementType.FIELD -}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface GolfProvider { - -} diff --git a/src/main/java/com/poststats/golf/provider/impl/DefaultConnectionProvider.java b/src/main/java/com/poststats/golf/provider/impl/DefaultConnectionProvider.java deleted file mode 100644 index 27654f0..0000000 --- a/src/main/java/com/poststats/golf/provider/impl/DefaultConnectionProvider.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.poststats.golf.provider.impl; - -import java.sql.Connection; - -import com.poststats.golf.provider.GolfProvider; -import com.poststats.provider.ConnectionProvider; -import com.poststats.provider.DataSourceProvider; -import com.poststats.provider.NonTransactionalProvider; - -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -@NonTransactionalProvider -@GolfProvider -public class DefaultConnectionProvider implements ConnectionProvider { - - @Inject - @GolfProvider - private DataSourceProvider dsp; - - private Connection dbcon; - - @PostConstruct - public void acquire() { - this.dbcon = this.dsp.get().acquire(true); - } - - @PreDestroy - public void release() { - this.dsp.get().release(this.dbcon); - } - - @Override - public Connection get() { - return this.dbcon; - } - -} diff --git a/src/main/java/com/poststats/golf/provider/impl/DefaultDataSourceProvider.java b/src/main/java/com/poststats/golf/provider/impl/DefaultDataSourceProvider.java deleted file mode 100644 index 297b33d..0000000 --- a/src/main/java/com/poststats/golf/provider/impl/DefaultDataSourceProvider.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.poststats.golf.provider.impl; - -import com.brianlong.sql.DataSource; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.sql.GolfDataSource; -import com.poststats.provider.impl.AbstractDataSourceProvider; - -import jakarta.enterprise.context.ApplicationScoped; - -@ApplicationScoped -@GolfProvider -public class DefaultDataSourceProvider extends AbstractDataSourceProvider { - - public DataSource createDataSource() { - return GolfDataSource.getInstance(); - } - -} diff --git a/src/main/java/com/poststats/golf/provider/impl/DefaultStatementProvider.java b/src/main/java/com/poststats/golf/provider/impl/DefaultStatementProvider.java deleted file mode 100644 index 7528fdc..0000000 --- a/src/main/java/com/poststats/golf/provider/impl/DefaultStatementProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.poststats.golf.provider.impl; - -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.sql.GolfSQL; -import com.poststats.provider.ConnectionProvider; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.impl.AbstractStatementProvider; - -import jakarta.enterprise.context.Dependent; -import jakarta.inject.Inject; - -@Dependent -@NonTransactionalProvider -@GolfProvider -public class DefaultStatementProvider extends AbstractStatementProvider { - - @Inject - @NonTransactionalProvider - @GolfProvider - private ConnectionProvider cp; - - @Override - protected ConnectionProvider getConnectionProvider() { - return this.cp; - } - - @Override - protected String transformSchema(String sql) { - return GolfSQL.changeSchema(sql); - } - -} diff --git a/src/main/java/com/poststats/golf/provider/impl/TxConnectionProvider.java b/src/main/java/com/poststats/golf/provider/impl/TxConnectionProvider.java deleted file mode 100644 index 7b4b8a4..0000000 --- a/src/main/java/com/poststats/golf/provider/impl/TxConnectionProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.poststats.golf.provider.impl; - -import java.io.Serializable; -import java.sql.Connection; - -import com.poststats.golf.provider.GolfProvider; -import com.poststats.provider.ConnectionProvider; -import com.poststats.provider.DataSourceProvider; -import com.poststats.provider.TransactionalProvider; - -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; -import jakarta.inject.Inject; -import jakarta.transaction.TransactionScoped; - -@TransactionScoped -@TransactionalProvider -@GolfProvider -public class TxConnectionProvider implements ConnectionProvider, Serializable { - - @Inject - @GolfProvider - private DataSourceProvider dsp; - - private Connection dbcon; - - @PostConstruct - public void acquire() { - this.dbcon = this.dsp.get().acquireTX(true); - } - - @PreDestroy - public void release() { - this.dsp.get().releaseTX(this.dbcon); - } - - @Override - public Connection get() { - return this.dbcon; - } - -} diff --git a/src/main/java/com/poststats/golf/provider/impl/TxStatementProvider.java b/src/main/java/com/poststats/golf/provider/impl/TxStatementProvider.java deleted file mode 100644 index ceceea7..0000000 --- a/src/main/java/com/poststats/golf/provider/impl/TxStatementProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.poststats.golf.provider.impl; - -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.sql.GolfSQL; -import com.poststats.provider.ConnectionProvider; -import com.poststats.provider.TransactionalProvider; -import com.poststats.provider.impl.AbstractStatementProvider; - -import jakarta.enterprise.context.Dependent; -import jakarta.inject.Inject; - -@Dependent -@TransactionalProvider -@GolfProvider -public class TxStatementProvider extends AbstractStatementProvider { - - @Inject - @TransactionalProvider - @GolfProvider - private ConnectionProvider cp; - - @Override - protected ConnectionProvider getConnectionProvider() { - return this.cp; - } - - @Override - protected String transformSchema(String sql) { - return GolfSQL.changeSchema(sql); - } - -} diff --git a/src/main/java/com/poststats/golf/security/AuthenticatedPerson.java b/src/main/java/com/poststats/golf/security/AuthenticatedPerson.java deleted file mode 100644 index 7bfb6e2..0000000 --- a/src/main/java/com/poststats/golf/security/AuthenticatedPerson.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.poststats.golf.security; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -public class AuthenticatedPerson extends com.poststats.security.AuthenticatedPerson { - - private final Set buddyIds; - private final Set acSids; - private final Map> eventAcSids; - - public AuthenticatedPerson(com.poststats.security.AuthenticatedPerson person, Set buddyIds, - Set acSids, Map> eventAcSids) { - super(person); - this.buddyIds = buddyIds; - this.acSids = acSids; - this.eventAcSids = eventAcSids; - } - - public Set getBuddyIds() { - return Collections.unmodifiableSet(this.buddyIds); - } - - public Set getAccessControls() { - return Collections.unmodifiableSet(this.acSids); - } - - public Set getEventAccessControls(long eventId) { - Set roles = this.eventAcSids.get(eventId); - return roles == null ? null : Collections.unmodifiableSet(roles); - } - - public Set getAllAccessControls() { - Set roles = new HashSet<>(); - roles.addAll(this.acSids); - for (Entry> eroles : this.eventAcSids.entrySet()) - for (String role : eroles.getValue()) - roles.add(eroles.getKey() - + ":" - + role); - return roles == null ? null : Collections.unmodifiableSet(roles); - } - - @Override - public boolean hasAccessControl(String ac) { - return this.acSids.contains(ac); - } - - public boolean hasBuddy(long buddyId) { - return this.buddyIds.contains(buddyId); - } - - public boolean hasAccessControl(String ac, long eventId) { - Set sids = this.eventAcSids.get(eventId); - return sids != null && sids.contains(ac); - } - -} diff --git a/src/main/java/com/poststats/golf/security/AuthenticatedSecurityContext.java b/src/main/java/com/poststats/golf/security/AuthenticatedSecurityContext.java deleted file mode 100644 index bf92659..0000000 --- a/src/main/java/com/poststats/golf/security/AuthenticatedSecurityContext.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.poststats.golf.security; - -import java.security.Principal; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.ws.rs.core.SecurityContext; - -public class AuthenticatedSecurityContext implements SecurityContext { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - private final SecurityContext securityContext; - private final AuthenticatedPerson authPerson; - - public AuthenticatedSecurityContext(SecurityContext securityContext, AuthenticatedPerson authPerson) { - if (securityContext == null) - throw new IllegalArgumentException(); - this.securityContext = securityContext; - this.authPerson = authPerson; - } - - @Override - public Principal getUserPrincipal() { - return this.authPerson; - } - - @Override - public boolean isUserInRole(String role) { - this.logger.trace("isUserInRole({}, {})", this.getUserPrincipal(), role); - - if (this.authPerson.hasAccessControl(role)) { - this.logger.debug("user '{}' is in role '{}'", this.authPerson, role); - return true; - } - - return this.securityContext.isUserInRole(role); - } - - @Override - public String getAuthenticationScheme() { - return this.securityContext.getAuthenticationScheme(); - } - - @Override - public boolean isSecure() { - return this.securityContext.isSecure(); - } - -} diff --git a/src/main/java/com/poststats/golf/security/EventSecurityContext.java b/src/main/java/com/poststats/golf/security/EventSecurityContext.java deleted file mode 100644 index 948d7bb..0000000 --- a/src/main/java/com/poststats/golf/security/EventSecurityContext.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.poststats.golf.security; - -import java.security.Principal; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.poststats.golf.api.Constants; - -import jakarta.ws.rs.core.SecurityContext; - -public class EventSecurityContext implements SecurityContext { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - private final SecurityContext securityContext; - private final long eventId; - - public EventSecurityContext(SecurityContext securityContext, long eventId) { - if (securityContext == null) - throw new IllegalArgumentException(); - this.securityContext = securityContext; - this.eventId = eventId; - } - - @Override - public Principal getUserPrincipal() { - return this.securityContext.getUserPrincipal(); - } - - @Override - public boolean isUserInRole(String role) { - this.logger.trace("isUserInRole({}, {}, {})", this.getUserPrincipal(), role, this.eventId); - - if (role.startsWith(Constants.EVENT_ROLE_PREFIX)) { - if (this.getUserPrincipal() instanceof AuthenticatedPerson) { - AuthenticatedPerson authPerson = (AuthenticatedPerson) this.getUserPrincipal(); - String eventRole = role.substring(Constants.EVENT_ROLE_PREFIX.length()); - this.logger.trace("checking if user '{}' has role '{}' in event {}", this.getUserPrincipal(), eventRole, - this.eventId); - - if (authPerson.hasAccessControl(eventRole, this.eventId)) { - this.logger.debug("user '{}' has role '{}' in event {}", this.getUserPrincipal(), eventRole, - this.eventId); - return true; - } - } - } - - return this.securityContext.isUserInRole(role); - } - - @Override - public String getAuthenticationScheme() { - return this.securityContext.getAuthenticationScheme(); - } - - @Override - public boolean isSecure() { - return this.securityContext.isSecure(); - } - -} diff --git a/src/main/java/com/poststats/golf/security/PersonSecurityContext.java b/src/main/java/com/poststats/golf/security/PersonSecurityContext.java deleted file mode 100644 index 3b3eed8..0000000 --- a/src/main/java/com/poststats/golf/security/PersonSecurityContext.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.poststats.golf.security; - -import java.security.Principal; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.poststats.golf.api.Constants; - -import jakarta.ws.rs.core.SecurityContext; - -public class PersonSecurityContext implements SecurityContext { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - private final SecurityContext securityContext; - private final long personId; - - public PersonSecurityContext(SecurityContext securityContext, long personId) { - if (securityContext == null) - throw new IllegalArgumentException(); - this.securityContext = securityContext; - this.personId = personId; - } - - @Override - public Principal getUserPrincipal() { - return this.securityContext.getUserPrincipal(); - } - - @Override - public boolean isUserInRole(String role) { - this.logger.trace("isUserInRole({}, {}, {})", this.getUserPrincipal(), role, this.personId); - - if (role.equals(Constants.BUDDY_ROLE)) { - if (this.getUserPrincipal() instanceof AuthenticatedPerson) { - AuthenticatedPerson authPerson = (AuthenticatedPerson) this.getUserPrincipal(); - this.logger.trace("checking if user '{}' is buddy of {}", this.getUserPrincipal(), this.personId); - if (authPerson.hasBuddy(this.personId)) { - this.logger.debug("user '{}' is buddy of {}", this.getUserPrincipal(), this.personId); - return true; - } - } - } - - return this.securityContext.isUserInRole(role); - } - - @Override - public String getAuthenticationScheme() { - return this.securityContext.getAuthenticationScheme(); - } - - @Override - public boolean isSecure() { - return this.securityContext.isSecure(); - } - -} diff --git a/src/main/java/com/poststats/golf/service/CourseHoleService.java b/src/main/java/com/poststats/golf/service/CourseHoleService.java deleted file mode 100644 index c90ce1e..0000000 --- a/src/main/java/com/poststats/golf/service/CourseHoleService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.poststats.golf.service; - -import java.util.List; - -import com.brianlong.util.FlexMap; - -public interface CourseHoleService { - - List getHolesByNineTee(long nineteeId); - - List getHolesByEighteenTee(long eighteenteeId); - -} diff --git a/src/main/java/com/poststats/golf/service/CourseNineService.java b/src/main/java/com/poststats/golf/service/CourseNineService.java deleted file mode 100644 index 86e85fc..0000000 --- a/src/main/java/com/poststats/golf/service/CourseNineService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.poststats.golf.service; - -import com.brianlong.util.FlexMap; - -public interface CourseNineService { - - FlexMap getNine(long courseNineId); - - FlexMap getNine(int courseId, String name); - -} diff --git a/src/main/java/com/poststats/golf/service/CourseRatingService.java b/src/main/java/com/poststats/golf/service/CourseRatingService.java deleted file mode 100644 index 7e07536..0000000 --- a/src/main/java/com/poststats/golf/service/CourseRatingService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.poststats.golf.service; - -public interface CourseRatingService { - - /** - * This method computes a golf course eighteen/tee combination's difficulty - * rating as of today, inclusive. - * - * In some cases, there is no computation, but a simple fetch from an external - * resource. In other cases the ratings will need to be computed. In other - * cases, a rating cannot be determined. - * - * @param etratingId A unique identifier for a golf course eighteen/tee - * combination (gender) rating. - * @return A rating for the course; `null` if one cannot be determined. - */ - R computeEighteenTeeRatingIndex(long etratingId); - - /** - * This method computes a golf course nine/tee combination's difficulty rating - * as of today, inclusive. - * - * In some cases, there is no computation, but a simple fetch from an external - * resource. In other cases the ratings will need to be computed. In other - * cases, a rating cannot be determined. - * - * @param ntratingId A unique identifier for a golf course nine/tee combination - * (gender) rating. - * @return A rating for the course; `null` if one cannot be determined. - */ - R computeNineTeeRatingIndex(long ntratingId); - -} diff --git a/src/main/java/com/poststats/golf/service/CourseService.java b/src/main/java/com/poststats/golf/service/CourseService.java deleted file mode 100644 index 8c4344c..0000000 --- a/src/main/java/com/poststats/golf/service/CourseService.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.poststats.golf.service; - -import java.util.Collection; -import java.util.Map; - -import com.brianlong.util.FlexMap; -import com.brianlong.util.SubList; -import com.poststats.service.CacheableService; - -public interface CourseService extends CacheableService { - - /** - * This method retrieves meta-data about the specified course. - * - * This retrieves the facility meta-data as well. - * - * @param courseId A unique identifier for the course. - * @return A map of meta-data specific to the course. - */ - FlexMap get(int courseId); - - /** - * This method retrieves meta-data about the specified courses. - * - * This retrieves the facility meta-data as well. - * - * @param courseIds Unique identifier for the coursees. - * @return A map of unique identifiers to meta-data specific to the coursees. - */ - Map get(Collection courseIds); - - default SubList findByName(String name) { - return this.findByName(name, 1, 10); - } - - SubList findByName(String name, int page, int perPage); - - default SubList findByJurisdiction(String country, String state) { - return this.findByJurisdiction(country, state, 1, 50); - } - - SubList findByJurisdiction(String country, String state, int page, int perPage); - - default SubList findByLocation(double latitude, double longitude) { - return this.findByLocation(latitude, longitude, 10, 1, 25); - } - - default SubList findByLocation(double latitude, double longitude, int radiusInMiles) { - return this.findByLocation(latitude, longitude, radiusInMiles, 1, 25); - } - - SubList findByLocation(double latitude, double longitude, int radiusInMiles, int page, - int perPage); - -} diff --git a/src/main/java/com/poststats/golf/service/EventDocumentService.java b/src/main/java/com/poststats/golf/service/EventDocumentService.java deleted file mode 100644 index fb4a7aa..0000000 --- a/src/main/java/com/poststats/golf/service/EventDocumentService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.poststats.golf.service; - -import com.brianlong.util.FlexMap; -import com.poststats.service.CacheableService; - -public interface EventDocumentService extends CacheableService { - - /** - * This method retrieves meta-data about the specified event document. - * - * @param eventId A unique identifier for the event. - * @param eventId A unique identifier for the document. - * @return A map of meta-data specific to the event document. - */ - FlexMap get(long eventId, long documentId); - -} diff --git a/src/main/java/com/poststats/golf/service/EventFinanceService.java b/src/main/java/com/poststats/golf/service/EventFinanceService.java deleted file mode 100644 index eb329f6..0000000 --- a/src/main/java/com/poststats/golf/service/EventFinanceService.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.poststats.golf.service; - -import java.util.Map; - -import com.brianlong.sql.DataSet; - -/** - * This service provides financial metadata about the event, series, associated - * people, or a combination of those. - * - * The balance metadata includes money `paid`, `expenses`, and `balance`. The - * balance numerically consistent with the perspective of the person, not the - * event organizers. That means it is positive when the person paid more than - * they should owe and negative if they owe money. - * - * @author brian - */ -public interface EventFinanceService { - - /** - * Computes and retrieves the person balances for those associated with the - * specified event. - * - * @param eventId The unique identifier of an event. - * @return A map of `personId` to balance metadata. - */ - Map getPersonsBalances(long eventId); - - /** - * Computes and retrieves the person balances for those associated with the - * specified event. - * - * @param eventId The unique identifier of an event. - * @param minBalance The minimum balance for returned balances; `0.01` for those - * that have paid more than they owe; `null` for no - * constraint. - * @param maxBalance The maximum balance for returned balances; `-0.01` for - * those that owe; `null` for no constraint. - * @return A map of `personId` to balance metadata. - */ - Map getPersonsBalances(long eventId, Float minBalance, Float maxBalance); - - /** - * Computes and retrieves the specified person's balance for the specified - * event. - * - * @param eventId The unique identifier of an event. - * @param personId The unique identifier of a person. - * @return Balance metadata. - */ - DataSet getPersonBalance(long eventId, long personId); - - /** - * Computes and retrieves all associated persons' cumulative balance for all - * events in the series before the specified event. - * - * @param eventId The unique identifier of an event. - * @return A map of `personId` to balance metadata. - */ - Map getSeriesPersonsPreviousBalances(long eventId); - - /** - * Computes and retrieves the specified person's balances for all events in the - * specified series. - * - * @param seriesId The unique identifier of a series. - * @param personId The unique identifier of a person. - * @return A map of `eventId` to balance metadata. - */ - Map getSeriesPersonBalances(int seriesId, long personId); - - /** - * Computes and retrieves the specified person's balances for all events in the - * series before the specified event. - * - * @param eventId The unique identifier of an event. - * @param personId The unique identifier of a person. - * @return A map of `eventId` to balance metadata. - */ - Map getSeriesPersonPreviousBalances(long eventId, long personId); - -} diff --git a/src/main/java/com/poststats/golf/service/EventPersonService.java b/src/main/java/com/poststats/golf/service/EventPersonService.java deleted file mode 100644 index b161534..0000000 --- a/src/main/java/com/poststats/golf/service/EventPersonService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.poststats.golf.service; - -import java.math.BigInteger; -import java.util.List; -import java.util.Set; - -import com.brianlong.util.FlexMap; -import com.poststats.service.CacheableService; -import com.poststats.util.Contact; - -public interface EventPersonService extends CacheableService { - - FlexMap get(BigInteger epersonId); - - FlexMap get(long eventId, long personId); - - List getPeople(long eventId); - - List getParticipants(long eventId); - - Set getSeriesEventFellowParticipantIds(int seriesId, long personId); - - /** - * This method retrieves contacts appropriate to the specified parameters. - * - * If both `allowEmail` and `allowText` are specified, only `allowText` will be - * used for users with email and text capability. - * - * @param eventId The unique identifier of an event. - * @param listId The unique identifier of a contact list. - * @param allowEmail `true` to allow email contact with each person. - * @param allowText `true` to allow text contact with each person. - * @return A map of meta-data specific to the person. - */ - List getContactsByListId(long eventId, long listId, boolean allowEmail, boolean allowText); - - /** - * This method retrieves contacts appropriate to the specified parameters. - * - * If both `allowEmail` and `allowText` are specified, only `allowText` will be - * used for users with email and text capability. - * - * @param eventId The unique identifier of an event. - * @param autolist The unique identifier of a contact list. - * @param allowEmail `true` to allow email contact with each person. - * @param allowText `true` to allow text contact with each person. - * @return A map of meta-data specific to the person. - */ - List getContactsByAutolist(long eventId, String autolist, boolean allowEmail, boolean allowText); - -} diff --git a/src/main/java/com/poststats/golf/service/EventRoundPairingService.java b/src/main/java/com/poststats/golf/service/EventRoundPairingService.java deleted file mode 100644 index bd37051..0000000 --- a/src/main/java/com/poststats/golf/service/EventRoundPairingService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.poststats.golf.service; - -import java.math.BigInteger; -import java.util.List; - -import com.brianlong.util.FlexMap; - -public interface EventRoundPairingService { - - FlexMap get(BigInteger pairingId); - - List getByRoundId(long eroundId); - - List getParticipantsByRoundId(long eroundId); - -} diff --git a/src/main/java/com/poststats/golf/service/EventRoundService.java b/src/main/java/com/poststats/golf/service/EventRoundService.java deleted file mode 100644 index b0c7dfd..0000000 --- a/src/main/java/com/poststats/golf/service/EventRoundService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.poststats.golf.service; - -import java.util.List; -import java.util.Map; - -import com.brianlong.util.FlexMap; - -public interface EventRoundService { - - /** - * This method retrieves meta-data about the specified event round. - * - * @param eroundId A unique identifier for the event round. - * @return A map of meta-data specific to the event round. - */ - FlexMap get(long eroundId); - - /** - * This method retrieves meta-data about the next event round in the specified - * event. - * - * It will only return more than one event round if the next date has more than - * one round. It will return today's round(s) until 6p EST. - * - * @param eventId A unique identifier for the event. - * @return A list of meta-data about each event round. - */ - List getUpcoming(long eventId); - - /** - * This method retrieves meta-data about the specified event rounds. - * - * @param eventId A unique identifier for the event. - * @return A map of unique identifiers to meta-data specific to each event - * round. - */ - Map getByEventId(long eventId); - -} diff --git a/src/main/java/com/poststats/golf/service/EventService.java b/src/main/java/com/poststats/golf/service/EventService.java deleted file mode 100644 index 8fe3dba..0000000 --- a/src/main/java/com/poststats/golf/service/EventService.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.poststats.golf.service; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import com.brianlong.util.FlexMap; -import com.poststats.service.CacheableService; - -public interface EventService extends CacheableService { - - /** - * This method retrieves meta-data about the specified event. - * - * @param eventId A unique identifier for the event. - * @return A map of meta-data specific to the event. - */ - FlexMap get(long eventId); - - /** - * This method retrieves meta-data about the specified event. - * - * @param eventIds Unique identifiers for the event. - * @return A map of unique identifiers to meta-data specific to each event. - */ - Map get(Collection eventIds); - - Set getIdsBySeriesId(int seriesId); - - Map getBySeriesId(int seriesId); - - Integer getSeriesId(long eventId); - -} diff --git a/src/main/java/com/poststats/golf/service/HandicapIndexService.java b/src/main/java/com/poststats/golf/service/HandicapIndexService.java deleted file mode 100644 index 0fe03a9..0000000 --- a/src/main/java/com/poststats/golf/service/HandicapIndexService.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.poststats.golf.service; - -import java.time.LocalDate; - -public interface HandicapIndexService { - - /** - * This method computes a golfer's handicap index as of today, inclusive. - * - * This will consider the use of all individually played non-event and event - * rounds. Each implementation may exclude more rounds, like unsigned or unrated - * courses. - * - * @param personId A unique identifier for the golfer. - * @return A handicap for the golfer. - */ - default I computeGolferIndex(long personId) { - return this.computeGolferIndex(personId, LocalDate.now().plusDays(1L)); - } - - /** - * This method computes a golfer's handicap index as of the specified date, - * inclusive. - * - * This will consider the use of all individually played non-event and event - * rounds. Each implementation may exclude more rounds, like unsigned or unrated - * courses. - * - * @param personId A unique identifier for the golfer. - * @param beforeDay A date to exclude all rounds on or after. - * @return A handicap for the golfer. - */ - I computeGolferIndex(long personId, LocalDate beforeDay); - -} diff --git a/src/main/java/com/poststats/golf/service/HandicapScoreService.java b/src/main/java/com/poststats/golf/service/HandicapScoreService.java deleted file mode 100755 index 61800d8..0000000 --- a/src/main/java/com/poststats/golf/service/HandicapScoreService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.poststats.golf.service; - -import java.math.BigInteger; - -public interface HandicapScoreService { - - /** - * This method computes a non-event round's score. - * - * The score depends on the handicap system. For instance, the simple - * stroke (non-handicap) system, it will be strokes-minus-par. For the - * world handicap system (WHS), it will be your adjusted strokes-to-par, - * applying the course rating, your handicap, hole handicaps, and course - * condition adjustment. For point handicap systems, it will be your - * points, including the course adjustment. - * - * @param roundId A unique identifier for the non-event round. - * @return A score for the round. - */ - S computeRoundScore(BigInteger roundId); - - /** - * This method computes a person's event round score. - * - * The score depends on the handicap system. For instance, the simple - * stroke (non-handicap) system, it will be strokes-minus-par. For the - * world handicap system (WHS), it will be your adjusted strokes-to-par, - * applying the course rating, your handicap, hole handicaps, and course - * condition adjustment. For point handicap systems, it will be your - * points, including the course adjustment. - * - * @param proundId A unique identifier for the event/person round. - * @return A score for the round. - */ - S computeEventRoundScore(BigInteger proundId); - -} diff --git a/src/main/java/com/poststats/golf/service/PersonRoundService.java b/src/main/java/com/poststats/golf/service/PersonRoundService.java deleted file mode 100644 index ed43e28..0000000 --- a/src/main/java/com/poststats/golf/service/PersonRoundService.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.poststats.golf.service; - -import java.math.BigInteger; -import java.time.LocalDate; -import java.util.List; - -import com.brianlong.util.FlexMap; - -public interface PersonRoundService { - - public enum Selection { ScoreToPar, StrokeHandicapIndex } - - public enum Filter { AttestedOnly, CourseRatedOnly } - - /** - * This method retrieves meta-data about the specified non-event round. - * - * @param roundId A unique identifier for the non-event round. - * @param selection Include `ScoreToPar` or `StrokeHandicapIndex` values in the - * results. - * @param filter An array of filters. - * @return A non-event round and its meta-data. - */ - FlexMap fetchNonEvent(BigInteger roundId, Selection selection, Filter... filters); - - /** - * This method retrieves meta-data about the specified golfer's event round. - * - * @param proundId A unique identifier for a golfer's event round. - * @param selection Include `ScoreToPar` or `StrokeHandicapIndex` values in the - * results. - * @param filter An array of filters. - * @return A golfer's event round and its meta-data. - */ - FlexMap fetchEvent(BigInteger proundId, Selection selection, Filter... filters); - - /** - * This method retrieves scores for all holes played in the specified non-event round. - * - * @param roundId A unique identifier for the non-event round. - * @param selection Include `ScoreToPar` or `StrokeHandicapIndex` values in the - * results. - * @return A list of holes and associated scores. - */ - List fetchNonEventHoles(BigInteger roundId, Selection selection); - - /** - * This method retrieves scores for all holes played in the specified golfer's event round. - * - * @param proundId A unique identifier for the golfer's event round. - * @param selection Include `ScoreToPar` or `StrokeHandicapIndex` values in the - * results. - * @return A list of holes and associated scores. - */ - List fetchEventHoles(BigInteger proundId, Selection selection); - - /** - * This method retrieves recent round meta-data about the specified golfer. - * - * The rounds are retrieved in reverse chronological order. Both Non-event and - * event rounds are included. - * - * @param personId A unique identifier for the golfer. - * @param roundCount A maximum number of rounds to return. - * @param selection Include `ScoreToPar` or `StrokeHandicapIndex` values in the - * results. - * @param filter An array of filters. - * @return A list of recent rounds played by the golfer. - */ - default List findRecent(long personId, short roundCount, Selection selection, - Filter... filters) { - return this.findBefore(personId, LocalDate.now().plusDays(1L), roundCount, selection, filters); - } - - /** - * This method retrieves recent round meta-data about the specified golfer. - * - * The rounds are retrieved in reverse chronological order. Both Non-event and - * event rounds are included. - * - * @param personId A unique identifier for the golfer. - * @param beforeDay A date to start excluding rounds on or after. - * @param roundCount A maximum number of rounds to return. - * @param selection Include `ScoreToPar` or `StrokeHandicapIndex` values in the - * results. - * @param filter An array of filters. - * @return A list of recent rounds played by the golfer. - */ - List findBefore(long personId, LocalDate beforeDay, short roundCount, Selection selection, - Filter... filters); - -} diff --git a/src/main/java/com/poststats/golf/service/PersonService.java b/src/main/java/com/poststats/golf/service/PersonService.java deleted file mode 100644 index f043023..0000000 --- a/src/main/java/com/poststats/golf/service/PersonService.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.poststats.golf.service; - -import java.util.Collection; -import java.util.Map; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.security.AuthenticatedPerson; -import com.poststats.service.CacheableService; - -public interface PersonService extends CacheableService { - - /** - * This method builds a `UserPrincipal` object about the golfer. - * - * Unlike the non-golf `PersonService`, this will include golfer and event - * roles. - * - * @param person A non-golf `UserPrincipal` object. - * @return A golfer `UserPrincipal` object. - */ - AuthenticatedPerson getUserPrincipal(com.poststats.security.AuthenticatedPerson person); - - /** - * This method retrieves meta-data about the specified golfer. - * - * If you want meta-data information about only the person, use the non-golf - * `PersonService`. - * - * This retrieves everything from the non-golf `PersonService` and supplements - * it with simple golfer meta-data, like stroke handicaps. It does not include - * related data like point handicap or round counts. - * - * @param personId A unique identifier for the golfer. - * @return A map of meta-data specific to the golfer. - */ - FlexMap get(long personId); - - /** - * This method retrieves meta-data about the specified golfers. - * - * If you want meta-data information about only the person, use the non-golf - * `PersonService`. - * - * This retrieves everything from the non-golf `PersonService` and supplements - * it with simple golfer meta-data, like stroke handicaps. It does not include - * related data like point handicap or round counts. - * - * @param personIds Unique identifiers for the golfers. - * @return A map of unique identifiers to meta-data specific to each golfer. - */ - Map get(Collection personIds); - -} diff --git a/src/main/java/com/poststats/golf/service/SeriesPersonService.java b/src/main/java/com/poststats/golf/service/SeriesPersonService.java deleted file mode 100644 index b2f219a..0000000 --- a/src/main/java/com/poststats/golf/service/SeriesPersonService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.poststats.golf.service; - -import java.util.List; - -import com.brianlong.sql.DataSet; - -public interface SeriesPersonService { - - List getSeriesPeople(int seriesId); - - List getSeriesParticipants(int seriesId); - -} diff --git a/src/main/java/com/poststats/golf/service/SeriesService.java b/src/main/java/com/poststats/golf/service/SeriesService.java deleted file mode 100644 index 0e1d39d..0000000 --- a/src/main/java/com/poststats/golf/service/SeriesService.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.poststats.golf.service; - -import java.util.Collection; -import java.util.Map; - -import com.brianlong.util.FlexMap; -import com.poststats.service.CacheableService; - -public interface SeriesService extends CacheableService { - - /** - * This method retrieves meta-data about the specified series. - * - * @param seriesId A unique identifier for the series. - * @return A map of meta-data specific to the series. - */ - FlexMap get(int seriesId); - - /** - * This method retrieves meta-data about the specified series. - * - * @param seriesIds Unique identifiers for the series. - * @return A map of unique identifiers to meta-data specific to each series. - */ - Map get(Collection seriesIds); - - /** - * This method retrieves series meta-data about the specified event. - * - * @param eventId A unique identifier for the event. - * @return A map of meta-data specific to the series. - */ - FlexMap getByEventId(long eventId); - -} diff --git a/src/main/java/com/poststats/golf/service/compute/AbstractHandicappingService.java b/src/main/java/com/poststats/golf/service/compute/AbstractHandicappingService.java deleted file mode 100644 index 448f1d9..0000000 --- a/src/main/java/com/poststats/golf/service/compute/AbstractHandicappingService.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.poststats.golf.service.compute; - -import java.time.LocalDate; -import java.util.List; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.service.CourseRatingService; -import com.poststats.golf.service.HandicapIndexService; -import com.poststats.golf.service.HandicapScoreService; -import com.poststats.golf.service.PersonRoundService; -import com.poststats.golf.service.PersonRoundService.Filter; -import com.poststats.golf.service.PersonRoundService.Selection; - -import jakarta.inject.Inject; - -public abstract class AbstractHandicappingService implements HandicapIndexService, CourseRatingService, HandicapScoreService { - - @Inject - protected PersonRoundService personRoundService; - - protected short getMinimumRounds() { - return 1; - } - - protected abstract short getMaximumRounds(); - - protected abstract Selection getRoundSelection(); - - protected Filter[] getRoundFilter() { - return new Filter[0]; - } - - @Override - public I computeGolferIndex(long personId, LocalDate beforeDay) { - List rounds = this.personRoundService.findBefore(personId, beforeDay, - this.getMaximumRounds(), this.getRoundSelection(), this.getRoundFilter()); - if (rounds.size() < this.getMinimumRounds()) - throw new IllegalStateException("The person does not have enough rounds to compute a handicap index"); - - return this.compute(rounds); - } - - public abstract I compute(List rounds); - -} diff --git a/src/main/java/com/poststats/golf/service/compute/AbstractPointHandicappingService.java b/src/main/java/com/poststats/golf/service/compute/AbstractPointHandicappingService.java deleted file mode 100644 index 1b3fd06..0000000 --- a/src/main/java/com/poststats/golf/service/compute/AbstractPointHandicappingService.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.poststats.golf.service.compute; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.brianlong.util.FlexMap; -import com.brianlong.util.MapUtil; -import com.poststats.golf.service.PersonRoundService.Selection; -import com.poststats.golf.service.model.PointHandicapIndex; - -public abstract class AbstractPointHandicappingService extends AbstractHandicappingService { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Override - protected short getMaximumRounds() { - return 15; - } - - protected short getBestRoundsToToss(short roundCount) { - return 0; - } - - protected abstract short getWorstRoundsToToss(short roundCount); - - protected abstract short getPointTarget(); - - protected abstract float getAccelerant(); - - protected float getHomeCourseZeroRate() { - return 0.25f; - } - - protected float getHomeCourseMultiplier() { - return 4f; - } - - @Override - protected Selection getRoundSelection() { - return Selection.ScoreToPar; - } - - @Override - public PointHandicapIndex compute(List rounds) { - short target = this.getPointTarget(); - short bestRoundsToToss = this.getBestRoundsToToss((short) rounds.size()); - short worstRoundsToToss = this.getWorstRoundsToToss((short) rounds.size()); - short roundsToCount = (short) (rounds.size() - bestRoundsToToss - worstRoundsToToss); - float forgiveness = 0.5f; - - Map computedPoints = new HashMap<>(); - PointHandicapIndex bestLowPhi = null; - PointHandicapIndex bestHighPhi = null; - - Pair homeCourseAdj = this.computeHomeCourseAdjustment(rounds); - this.logger.debug("Computed home course adjustment: {}", homeCourseAdj); - - short[] scoreToParCounts = this.computeScoreToParCounts(rounds); - byte[] mostCommonScoreToPar = this.determineMostCommonStoresToPar(scoreToParCounts, (byte) 2); - this.logger.debug("Determined most common score-to-par: {}", mostCommonScoreToPar); - - PointHandicapIndex phi = this.generateIndexBy2MostCommon(mostCommonScoreToPar[0], - scoreToParCounts[(mostCommonScoreToPar[0] + 10) % 10], mostCommonScoreToPar[1], - scoreToParCounts[(mostCommonScoreToPar[1] + 10) % 10], target, this.getAccelerant()); - this.logger.debug("Base point handicap index: {}", phi); - - byte lastHighScoreToPar = 6; - byte lastLowScoreToPar = -4; - - while (true) { - List roundsPoints = new ArrayList<>(rounds.size()); - for (FlexMap round : rounds) { - int points = round.getByte("bogey5") * phi.getQuintupleBogeyPoints() - + round.getByte("bogey4") * phi.getQuadrupleBogeyPoints() - + round.getByte("bogey3") * phi.getTripleBogeyPoints() - + round.getByte("bogey2") * phi.getDoubleBogeyPoints() - + round.getByte("bogey") * phi.getBogeyPoints() + round.getByte("par") * phi.getParPoints() - + round.getByte("birdie") * phi.getBirdiePoints() - + round.getByte("eagle") * phi.getEaglePoints() - + round.getByte("alby") * phi.getAlbatrossPoints() + round.getByte("pointAdj"); - if (round.getInteger("courseID").equals(homeCourseAdj.getKey())) { - // always negative, so we are making the course seem easier for the home course - // player - points += homeCourseAdj.getValue().intValue(); - } - - roundsPoints.add(points); - } - - Collections.sort(roundsPoints); - float points = 0f; - for (Integer roundPoints : roundsPoints.subList(worstRoundsToToss, roundsPoints.size() - bestRoundsToToss)) - points += roundPoints.floatValue(); - points /= roundsToCount; - computedPoints.put(phi.getId(), points); - this.logger.debug("Computed {} points with index: {}", points, phi); - - if (Math.abs(points - target) < forgiveness) { - System.out.println(points); - return phi; - } - forgiveness += 0.02f; - - if (points > target) { - this.logger.debug("{} points are higher than the target {}; trying something lower", points, target); - if (lastHighScoreToPar < -2) - lastHighScoreToPar = 6; - lastHighScoreToPar--; - phi = phi.decrement(lastHighScoreToPar); - } else { - this.logger.debug("{} points are lower than the target {}; trying something higher", points, target); - if (lastLowScoreToPar > 4) - lastLowScoreToPar = -4; - lastLowScoreToPar++; - phi = phi.increment(lastLowScoreToPar); - } - - // make sure we are not guaranteed to be outside the bounds of the best low/high - // if the best low/high with nothing possible in between, pick the one that is - // closest - } - } - - - - @Override - public Short computeRoundScore(BigInteger roundId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Short computeEventRoundScore(BigInteger proundId) { - // TODO Auto-generated method stub - return null; - } - - - - private PointHandicapIndex generateIndexBy2MostCommon(byte mostCommonScoreToParIndex, - short mostCommonScoreToParCount, byte nextMostCommonScoreToParIndex, short nextMostCommonScoreToParCount, - short pointTarget, float accelerant) { - boolean roundDown = nextMostCommonScoreToParIndex < mostCommonScoreToParCount; - float targetPerHole = pointTarget / 18f; - int[] pointsForScoreToPar = new int[10]; - int targetScoreToParIndex = (mostCommonScoreToParIndex + 10) % 10; - double factor = Math.pow(Math.E, accelerant); - - // floor the target, so we target low - byte lastPointsForScoreToPar = roundDown ? (byte) targetPerHole : (byte) Math.ceil(targetPerHole); - pointsForScoreToPar[targetScoreToParIndex] = lastPointsForScoreToPar; - - // go forward: higher scores; lower points; eventually 0 points - for (byte scoreToPar = (byte) (mostCommonScoreToParIndex + 1); scoreToPar < 6; scoreToPar++) { - int scoreToParIndex = (scoreToPar + 10) % 10; - lastPointsForScoreToPar = (byte) Math.max(0, - Math.min(lastPointsForScoreToPar - 1, Math.ceil(lastPointsForScoreToPar / factor))); - pointsForScoreToPar[scoreToParIndex] = lastPointsForScoreToPar; - } - - lastPointsForScoreToPar = (byte) pointsForScoreToPar[targetScoreToParIndex]; - - // go backwards; lower scores; higher points - for (byte scoreToPar = (byte) (mostCommonScoreToParIndex - 1); scoreToPar > -4; scoreToPar--) { - int scoreToParIndex = (scoreToPar + 10) % 10; - lastPointsForScoreToPar = (byte) Math.max(lastPointsForScoreToPar + 1, - Math.floor(lastPointsForScoreToPar * factor)); - pointsForScoreToPar[scoreToParIndex] = lastPointsForScoreToPar; - } - - return new PointHandicapIndex(pointsForScoreToPar); - } - - protected Pair computeHomeCourseAdjustment(List rounds) { - Pair maxHomeCourseAdj = Pair.of(null, 0f); - float zeroRate = this.getHomeCourseMultiplier() * this.getHomeCourseZeroRate(); - - Map courseIdCounts = MapUtil.countKeys(rounds, "courseID", Integer.class); - for (Entry courseIdCount : courseIdCounts.entrySet()) { - float homeCourseAdj = courseIdCount.getValue() * -this.getHomeCourseMultiplier() / rounds.size() + zeroRate; - if (homeCourseAdj < maxHomeCourseAdj.getRight()) - maxHomeCourseAdj = Pair.of(courseIdCount.getKey(), homeCourseAdj); - if (homeCourseAdj <= -1f) - // over 50%; we are done - break; - } - - return maxHomeCourseAdj; - } - - protected short[] computeScoreToParCounts(List rounds) { - short[] scoreToParTotalHoles = new short[10]; - - for (FlexMap round : rounds) { - scoreToParTotalHoles[5] += round.getByte("bogey5"); - scoreToParTotalHoles[4] += round.getByte("bogey4"); - scoreToParTotalHoles[3] += round.getByte("bogey3"); - scoreToParTotalHoles[2] += round.getByte("bogey2"); - scoreToParTotalHoles[1] += round.getByte("bogey"); - scoreToParTotalHoles[0] += round.getByte("par"); - scoreToParTotalHoles[9] += round.getByte("birdie"); - scoreToParTotalHoles[8] += round.getByte("eagle"); - scoreToParTotalHoles[7] += round.getByte("alby"); - } - - return scoreToParTotalHoles; - } - - protected byte[] determineMostCommonStoresToPar(short[] scoreToParCounts, byte xNumberOfMostCommonIndex) { - byte[] maxScoreToPar = new byte[xNumberOfMostCommonIndex]; - for (byte i = 0; i < xNumberOfMostCommonIndex; i++) - maxScoreToPar[i] = 6; // unused and always 0 - - for (byte scoreToPar = 0; scoreToPar < 10; scoreToPar++) { - for (int i = 0; i < xNumberOfMostCommonIndex; i++) { - if (scoreToParCounts[maxScoreToPar[i]] < scoreToParCounts[scoreToPar]) { - for (int i2 = xNumberOfMostCommonIndex - 1; i2 > 0; i2--) { - maxScoreToPar[i2] = maxScoreToPar[i2 - 1]; - break; - } - - maxScoreToPar[i] = scoreToPar; - break; - } - } - } - - for (int i = 0; i < maxScoreToPar.length; i++) - maxScoreToPar[i] = maxScoreToPar[i] < 0 ? (byte) (maxScoreToPar[i] - 10) : maxScoreToPar[i]; - return maxScoreToPar; - } - -} diff --git a/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicappingService.java b/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicappingService.java deleted file mode 100644 index c48b5f1..0000000 --- a/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicappingService.java +++ /dev/null @@ -1,415 +0,0 @@ -package com.poststats.golf.service.compute; - -import java.math.BigInteger; -import java.sql.SQLException; -import java.time.LocalDateTime; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; - -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.PersonRoundService.Selection; -import com.poststats.golf.service.PersonService; -import com.poststats.golf.service.model.StrokeCourseRating; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.provider.TransactionalProvider; -import com.poststats.service.ServiceException; - -import jakarta.inject.Inject; - -public abstract class AbstractStrokeHandicappingService - extends AbstractHandicappingService { - - @Inject - private Logger logger; - - @Inject - private PersonService personService; - - private final Comparator roundComparator; - - public AbstractStrokeHandicappingService() { - this.roundComparator = new Comparator() { - @Override - public int compare(FlexMap round1, FlexMap round2) { - Float sh1 = round1.getFloat(getStrokeHandicapColumn()); - Float sh2 = round2.getFloat(getStrokeHandicapColumn()); - return sh1.compareTo(sh2); - } - }; - } - - protected abstract String getStrokeHandicapColumn(); - - protected abstract String getHoleHandicapColumn(); - - @Override - protected Selection getRoundSelection() { - return Selection.StrokeHandicapIndex; - } - - protected short getRoundsToCount(short rounds) { - switch (rounds) { - case 0: - throw new IllegalArgumentException(); - case 1: - case 2: - case 3: - case 4: - case 5: - return 1; - case 6: - case 7: - case 8: - return 2; - case 9: - case 10: - case 11: - return 3; - case 12: - case 13: - case 14: - return 4; - case 15: - case 16: - return 5; - case 17: - case 18: - return 6; - case 19: - return 7; - case 20: - return 8; - default: - throw new IllegalArgumentException(); - } - } - - @Override - public Float compute(List rounds) { - Collections.sort(rounds, this.roundComparator); - short roundsToCount = this.getRoundsToCount((short) rounds.size()); - return this.compute(rounds.subList(0, roundsToCount), (short) rounds.size()); - } - - public Float compute(List rounds, short roundsConsidered) { - float sh = 0f; - for (FlexMap round : rounds) - sh += round.getFloat(this.getStrokeHandicapColumn()); - sh /= rounds.size(); - - float adjustment = this.getHandicapAdjustment(roundsConsidered); - return sh + adjustment; - } - - protected float getHandicapAdjustment(short rounds) { - switch (rounds) { - case 0: - throw new IllegalArgumentException(); - case 1: - return -3f; - case 2: - case 3: - return -2f; - case 4: - case 6: - return -1f; - default: - return 0f; - } - } - - - - @Override - public StrokeCourseRating computeNineTeeRatingIndex(long ntratingId) { - FlexMap ntrating = this.getNineTeeRating(ntratingId); - if (ntrating == null) - return null; - - LocalDateTime syncd = ntrating.getDateTime("syncd"); - if (LocalDateTime.now().getYear() == syncd.getYear() && LocalDateTime.now().minusMonths(3).isBefore(syncd)) - // assume it hasn't changed if sync'd within the last 3 months and still the same calendar year - return new StrokeCourseRating(ntrating.getShort("slopeRating"), ntrating.getFloat("courseRating")); - - CourseMetadata courseMeta = this.fetchNineTeeRating(ntratingId); - if (courseMeta == null) - return null; - - this.updateNineTeeRating(ntratingId, courseMeta); - - throw new UnsupportedOperationException(); - // FIXME return new StrokeCourseRating(courseMeta.getSlopeRating(), courseMeta.getCourseRating()); - } - - @Override - public StrokeCourseRating computeEighteenTeeRatingIndex(long etratingId) { - FlexMap etrating = this.getNineTeeRating(etratingId); - if (etrating == null) - return null; - - LocalDateTime syncd = etrating.getDateTime("syncd"); - if (LocalDateTime.now().getYear() == syncd.getYear() && LocalDateTime.now().minusMonths(3).isBefore(syncd)) - // assume it hasn't changed if sync'd within the last 3 months and still the same calendar year - return new StrokeCourseRating(etrating.getShort("slopeRating"), etrating.getFloat("courseRating")); - - CourseMetadata courseMeta = this.fetchEighteenTeeRating(etratingId); - if (courseMeta == null) - return null; - - this.updateEighteenTeeRating(etratingId, courseMeta); - - throw new UnsupportedOperationException(); - // FIXME return new StrokeCourseRating(courseMeta.getSlopeRating(), courseMeta.getCourseRating()); - } - - - - public Float computeEighteenTeeRatingHandicap(long etratingId, long personId) { - FlexMap person = this.personService.get(personId); - Float strokeHandicap = person.getFloat(this.getStrokeHandicapColumn()); - if (strokeHandicap == null) - return null; - - CourseMetadata courseMeta = this.fetchEighteenTeeRating(etratingId); - - float handicap = strokeHandicap.floatValue(); - if (courseMeta.getSlopeRating() != null) - handicap = handicap * courseMeta.getSlopeRating() / 113f; - if (courseMeta.getCourseRating() != null) - handicap += courseMeta.getCourseRating() - courseMeta.getPar(); - return handicap; - } - - public Float computeNineTeeRatingHandicap(long ntratingId, long personId) { - FlexMap person = this.personService.get(personId); - Float strokeHandicap = person.getFloat(this.getStrokeHandicapColumn()); - if (strokeHandicap == null) - return null; - - CourseMetadata courseMeta = this.fetchNineTeeRating(ntratingId); - - float handicap = strokeHandicap.floatValue() / 2f; - if (courseMeta.getSlopeRating() != null) - handicap = handicap * courseMeta.getSlopeRating() / 113f; - if (courseMeta.getCourseRating() != null) - handicap += courseMeta.getCourseRating() - courseMeta.getPar(); - return handicap; - } - - @Override - public Float computeRoundScore(BigInteger roundId) { - FlexMap round = this.personRoundService.fetchNonEvent(roundId, this.getRoundSelection(), this.getRoundFilter()); - if (round == null) { - this.logger.debug("The round does not exist or does not meeting the requirements to be handicap scored: {}", roundId); - return null; - } - - List holes = this.personRoundService.fetchNonEventHoles(roundId, this.getRoundSelection()); - if (holes.size() != 18) { - this.logger.debug("The round does not have 18 scored holes; cannot compute handicap score: {}", roundId); - return null; - } - - return this.computeRoundScore(round, holes, roundId, "round"); - } - - @Override - public Float computeEventRoundScore(BigInteger proundId) { - FlexMap pround = this.personRoundService.fetchEvent(proundId, this.getRoundSelection(), this.getRoundFilter()); - if (pround == null) { - // the round either doesn't exist or it is not eligible for handicap computation - return null; - } - - int totalHolesNeeded = pround.isNotEmpty("ntratingID") ? 9 : 18; - List holes = this.personRoundService.fetchEventHoles(proundId, this.getRoundSelection()); - if (holes.size() != totalHolesNeeded) { - this.logger.debug("The pround does not have {} scored holes; cannot compute handicap score: {}", totalHolesNeeded, proundId); - return null; - } - - return this.computeRoundScore(pround, holes, proundId, "pround"); - } - - private Float computeRoundScore(FlexMap round, List holes, Object roundId, String msgName) { - // prepare for equitable stroke control - Pair esc = this.computeEquitableStrokeControl(round.getLong("personID")); - - int escStrokes = 0; - for (FlexMap hole : holes) { - Byte strokeIndex = hole.getByte(this.getHoleHandicapColumn()); - if (strokeIndex == null) { - this.logger.debug("The course for the {} does not have the appropriate hole handicaps to compute the handicap with equitable stroke control: {}", msgName, roundId); - return null; - } - - int scoreToPar = hole.getByte("strokes") - hole.getByte("par"); - if (strokeIndex.byteValue() <= esc.getRight().byteValue()) { - scoreToPar = Math.min(scoreToPar, esc.getLeft() + 1); - } else { - scoreToPar = Math.min(scoreToPar, esc.getLeft()); - } - - escStrokes += scoreToPar + hole.getByte("par"); - } - - float adjStrokes = (float) escStrokes; - if (round.getFloat("courseRating") != null) { - adjStrokes -= round.getFloat("courseRating").floatValue(); - } else { - adjStrokes -= round.getByte("par").floatValue(); - } - - if (round.getShort("slopeRating") != null) - adjStrokes = adjStrokes * 113 / round.getShort("slopeRating").floatValue(); - - return adjStrokes; - } - - private Pair computeEquitableStrokeControl(long personId) { - byte netDoubleBogey = 5; - byte netDoubleBogeyRemainder = 0; - FlexMap person = this.personService.get(personId); - Float strokeHandicap = person.getFloat(this.getStrokeHandicapColumn()); - if (strokeHandicap != null) { - byte baseHandicap = (byte) Math.round(strokeHandicap.floatValue()); - netDoubleBogey = (byte) (baseHandicap / 18 + 2); - netDoubleBogeyRemainder = (byte) (baseHandicap % 18); - } - - return Pair.of(netDoubleBogey, netDoubleBogeyRemainder); - } - - - - - private CourseMetadata fetchNineTeeRating(long ntratingId) { - // TODO call WHS service for the information - return null; - } - - private CourseMetadata fetchEighteenTeeRating(long etratingId) { - // TODO call WHS service for the information - return null; - } - - private FlexMap getNineTeeRating(long ntratingId) { - try { - FlexPreparedStatement fps = this.sqlSelectCourseNineTeeRating.buildPreparedStatement(); - try { - fps.setIntegerU(1, ntratingId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT CNTR.*, CNT.par, CNT.yards " - + "FROM ~g~.CourseNineTeeRating CNTR " - + " INNER JOIN ~g~.CourseNineTee CNT ON (CNTR.nineteeID=CNT.nineteeID) " - + "WHERE CNTR.ntratingID=? " - ) - private StatementProvider sqlSelectCourseNineTeeRating; - - private FlexMap getEighteenTeeRating(long etratingId) { - try { - FlexPreparedStatement fps = this.sqlSelectCourseEighteenTeeRating.buildPreparedStatement(); - try { - fps.setIntegerU(1, etratingId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT CETR.*, CET.par, CET.yards " - + "FROM ~g~.CourseEighteenTeeRating CETR " - + " INNER JOIN ~g~.CourseEighteenTee CET ON (CETR.eighteenteeID=CET.eighteenteeID) " - + "WHERE CETR.etratingID=? " - ) - private StatementProvider sqlSelectCourseEighteenTeeRating; - - private void updateNineTeeRating(long ntratingId, CourseMetadata courseMeta) { - try { - FlexPreparedStatement fps = this.sqlUpdateCourseNineTeeRating.buildPreparedStatement(); - try { - //fps.setTinyintU(1, courseMeta.getSlopeRating()); - //fps.setTinyintU(2, courseMeta.getCourseRating()); - fps.setIntegerU(3, ntratingId); - fps.executeUpdate(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @TransactionalProvider - @GolfProvider - @Statement( - sql = "UPDATE ~g~.CourseNineTeeRating " - + "SET slopeRating=?, courseRating=? " - + "WHERE ntratingID=? " - ) - private StatementProvider sqlUpdateCourseNineTeeRating; - - private void updateEighteenTeeRating(long etratingId, CourseMetadata courseMeta) { - try { - FlexPreparedStatement fps = this.sqlUpdateCourseEighteenTeeRating.buildPreparedStatement(); - try { - //fps.setTinyintU(1, courseMeta.getSlopeRating()); - //fps.setTinyintU(2, courseMeta.getCourseRating()); - fps.setIntegerU(3, etratingId); - fps.executeUpdate(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @TransactionalProvider - @GolfProvider - @Statement( - sql = "UPDATE ~g~.CourseEighteenTeeRating " - + "SET slopeRating=?, courseRating=? " - + "WHERE etratingID=? " - ) - private StatementProvider sqlUpdateCourseEighteenTeeRating; - - - - private interface CourseMetadata { - // TODO replace with WHS model - Short getSlopeRating(); - Float getCourseRating(); - byte getPar(); - } - -} diff --git a/src/main/java/com/poststats/golf/service/compute/LegacyPostStatsPointHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/LegacyPostStatsPointHandicapIndexService.java deleted file mode 100644 index 19363e7..0000000 --- a/src/main/java/com/poststats/golf/service/compute/LegacyPostStatsPointHandicapIndexService.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.poststats.golf.service.compute; - -import com.brianlong.util.FlexMap; - -import jakarta.enterprise.context.ApplicationScoped; - -@ApplicationScoped -public class LegacyPostStatsPointHandicapIndexService extends AbstractPointHandicappingService { - - @Override - protected float getAccelerant() { - return 0.6f; - } - - @Override - protected short getPointTarget() { - return 60; - } - - @Override - protected short getWorstRoundsToToss(short roundCount) { - switch (roundCount) { - case 0: - case 1: - case 2: - case 3: - return 0; - case 4: - case 5: - case 6: - case 7: - return 1; - case 8: - case 9: - case 10: - case 11: - return 2; - case 12: - case 13: - case 14: - return 3; - case 15: - return 4; - default: - throw new IllegalArgumentException(); - } - } - - @Override - protected short getBestRoundsToToss(short roundCount) { - return (short) (roundCount < 13 ? 0 : 1); - } - - @Override - public Byte computeEighteenTeeRatingIndex(long etratingId) { - FlexMap etrating = this.courseRatingService.getEighteenTeeRating(etratingId); - return this.computeEighteenTeeRatingIndex(etrating); - } - - protected Byte computeEighteenTeeRatingIndex(FlexMap etrating) { - Short slopeRating = etrating.getShort("slopeRating"); - Float courseRating = etrating.getFloat("courseRating"); - char gender = etrating.getString("gender").charAt(0); - short yards = etrating.getShort("yards"); - byte par = etrating.getByte("par"); - return this.computeRatingIndex(slopeRating, courseRating, gender, yards, par); - } - - @Override - public Byte computeNineTeeRatingIndex(long ntratingId) { - FlexMap ntrating = this.courseRatingService.getNineTeeRating(ntratingId); - return this.computeNineTeeRatingIndex(ntrating); - } - - protected Byte computeNineTeeRatingIndex(FlexMap ntrating) { - Short slopeRating = ntrating.getShort("slopeRating"); - Float courseRating = ntrating.getFloat("courseRating"); - char gender = ntrating.getString("gender").charAt(0); - short yards = ntrating.getShort("yards"); - byte par = ntrating.getByte("par"); - return this.computeRatingIndex(slopeRating, courseRating, gender, yards, par); - } - - protected Byte computeRatingIndex(Short slopeRating, Float courseRating, char gender, short yards, byte par) { - // A par X hole assumes (X-2) non-putts and 2 putts to complete par - // So an 18 hole course assumes 36 putts and (X-36) non-putts to complete par - int nonPuttPar = par - 36; - // we normalize those (X-2) full strokes, so par 60 courses get a normalization - // ratio of 36/24 or 1.5 - // that means we need to 1.5x any yards/par/ratings to make it look like a - // standard par 72 course - double normalizedRatioNonPuttPar = 36.0 / nonPuttPar; - // we normalize the yards to look like a standard par 72 course - double normalizedYards = yards * normalizedRatioNonPuttPar; - - // we are linearly applying the yards, where: - // 6000 yd par 72 has 0 points - // 6350 yd par 72 has 6 points - // 6500 yd par 70 has 9 points - // 7000 yd par 71 has 18 points - // 3000 yd par 54 has 0 points - // 2000 yd par 54 has -34 points - int genderYards = gender == 'M' ? 6000 : 5000; - double adjYards = normalizedYards - genderYards; - byte yardBonus = (byte) (adjYards * 3.0 / 175.0); - - if (slopeRating == null) - return (byte) (yardBonus * 2); - - // a 130 slope course has 10 points - // a 155 slope (max) course has 21 points - // a 55 slope (min) course has -21 points - byte slopeBonus = (byte) ((slopeRating - 105) * 3 / 7); - return (byte) (yardBonus + slopeBonus); - } - -} diff --git a/src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java deleted file mode 100644 index 56d355b..0000000 --- a/src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.poststats.golf.service.compute; - -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.service.CourseHoleService; -import com.poststats.golf.service.CourseRatingService; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class PostStatsPointHandicapIndexService extends AbstractPointHandicappingService { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Inject - private CourseRatingService courseRatingService; - - @Inject - private CourseHoleService courseHoleService; - - @Override - protected float getAccelerant() { - return 0.5f; - } - - @Override - protected short getPointTarget() { - return 100; - } - - @Override - protected short getWorstRoundsToToss(short roundCount) { - switch (roundCount) { - case 0: - case 1: - case 2: - return 0; - case 3: - case 4: - case 5: - case 6: - return 1; - case 7: - case 8: - case 9: - case 10: - return 2; - case 11: - case 12: - case 13: - case 14: - return 3; - case 15: - return 4; - default: - throw new IllegalArgumentException(); - } - } - - @Override - protected short getBestRoundsToToss(short roundCount) { - return (short) (roundCount < 10 ? 0 : 1); - } - - @Override - public Byte computeEighteenTeeRatingIndex(long etratingId) { - FlexMap etrating = this.courseRatingService.getEighteenTeeRating(etratingId); - List holes = this.courseHoleService.getHolesByEighteenTee(etrating.getLong("eighteenteeID")); - return this.computeRatingIndex(etrating, holes); - } - - @Override - public Byte computeNineTeeRatingIndex(long ntratingId) { - FlexMap ntrating = this.courseRatingService.getNineTeeRating(ntratingId); - List holes = this.courseHoleService.getHolesByEighteenTee(ntrating.getLong("nineteeID")); - return this.computeRatingIndex(ntrating, holes); - } - - protected Byte computeRatingIndex(FlexMap netrating, List holes) { - // M normalized to 150 yd (150 + 3 * 8) par 3s - // F normalized to 125 yd (125 + 3 * 8) par 3s - char gender = netrating.getString("gender").charAt(0); - float divisorBase = gender == 'M' ? 165f : 140f; - - // capture running total for points - float points = 0; - - for (FlexMap hole : holes) { - short yards = hole.getShort("yards"); - byte par = hole.getByte("par"); - - // par assumes 2 putts per hole - int nonPuttPar = par - 2; - float nonPuttYardsPerStroke = 1f * yards / nonPuttPar; - - // make longer par 4s/5s correlate with shorter par 3s, as it is harder to - // "score" (birdies/eagles) on par 3s than par 5s - float exponentDivisor = divisorBase - (par * 5); - - // 80 yd par 3 will be -3.89 pts - // 100 yd par 3 will be -3.16 pts - // 125 yd par 3 (272/4 or 446/5) will be -2.1 pts - // 150 yd par 3 (326/4 or 536/5) will be -0.85 pts - // 200 yd par 3 (435/4 or 714/5) will be +2.38 pts - // 225 yd par 3 (489/4 or 804/5) will be +4.45 pts - points += Math.pow(Math.E, nonPuttYardsPerStroke / exponentDivisor) * 3f - 9f; - } - - if (netrating.isNotEmpty("etratingID")) { - this.logger.debug("computed course rating: et #{} => {}", netrating.get("etratingID"), points); - } else { - this.logger.debug("computed course rating: nt #{} => {}", netrating.get("ntratingID"), points); - } - - Float courseRating = netrating.getFloat("courseRating"); - if (courseRating == null) - return (byte) points; - - byte par = netrating.getByte("par"); - float difficulty = courseRating - par; - - // 69 rating on par 72 gets -9 pts - // 72 rating on par 72 gets +0 pts - // 73 rating on par 72 gets +3 pts - // 75 rating on par 72 gets +9 pts - double ratingAdj = 3 * difficulty; - - return (byte) (points + ratingAdj); - } - -} diff --git a/src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicappingService.java b/src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicappingService.java deleted file mode 100644 index fe78c3e..0000000 --- a/src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicappingService.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.poststats.golf.service.compute; - -import jakarta.enterprise.context.ApplicationScoped; - -@ApplicationScoped -public class PostStatsStrokeHandicappingService extends AbstractStrokeHandicappingService { - - @Override - protected short getMaximumRounds() { - return 20; - } - - @Override - protected String getStrokeHandicapColumn() { - return "strokeHandicapIndex"; - } - - @Override - protected String getHoleHandicapColumn() { - return "handicap"; - } - -} diff --git a/src/main/java/com/poststats/golf/service/compute/WhsStrokeHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/WhsStrokeHandicapIndexService.java deleted file mode 100644 index 826660b..0000000 --- a/src/main/java/com/poststats/golf/service/compute/WhsStrokeHandicapIndexService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.poststats.golf.service.compute; - -import com.poststats.golf.service.PersonRoundService.Filter; - -import jakarta.enterprise.context.ApplicationScoped; - -@ApplicationScoped -public class WhsStrokeHandicapIndexService extends AbstractStrokeHandicappingService { - - @Override - protected short getMinimumRounds() { - return 3; - } - - @Override - protected short getMaximumRounds() { - return 20; - } - - @Override - protected String getStrokeHandicapColumn() { - return "whsStrokeHandicapIndex"; - } - - @Override - protected String getHoleHandicapColumn() { - return "whsHandicap"; - } - - @Override - protected Filter[] getRoundFilter() { - return new Filter[] { - Filter.AttestedOnly, Filter.CourseRatedOnly - }; - } - -} diff --git a/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java b/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java deleted file mode 100644 index 309e321..0000000 --- a/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java +++ /dev/null @@ -1,277 +0,0 @@ -package com.poststats.golf.service.db; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexManyToOneDef; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.sql.ResultSubSetFeature; -import com.brianlong.util.FlexMap; -import com.brianlong.util.SubList; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.CourseHoleService; -import com.poststats.golf.service.CourseNineService; -import com.poststats.golf.service.CourseService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.FacilityService; -import com.poststats.service.ServiceException; -import com.poststats.service.db.CacheableServiceDAO; -import com.poststats.sql.PostStatsSQL; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class CourseServiceDAO extends CacheableServiceDAO - implements CourseService, CourseNineService, CourseHoleService { - - private final int defaultCacheExpirationInSeconds = 600; - private final FlexManyToOneDef facilityManyToOneDef = new FlexManyToOneDef("facilityID", "facility"); - - @Inject - private FacilityService facilityService; - - @Override - public FlexMap get(int courseId) { - return this.get(Integer.valueOf(courseId)); - } - - @Override - public FlexMap injectDeep(String idKey, FlexMap parentMap, String mapKey) { - FlexMap map = this.inject(idKey, parentMap, mapKey); - return this.facilityService.inject("facilityID", map, "facility"); - } - - @Override - public Collection injectDeep(String idKey, Collection parentMaps, - String mapKey) { - Collection maps = this.inject(idKey, parentMaps, mapKey); - return this.facilityService.inject("facilityID", maps, "facility"); - } - - @Override - public SubList findByName(String name, int page, int perPage) { - try { - FlexPreparedStatement fps = this.sqlSelectByName.buildPreparedStatement(); - try { - fps.setVarchar(1, "%" - + name - + "%"); - fps.setVarchar(2, "%" - + name - + "%"); - fps.setSmallintU(3, (page - 1) * perPage); - fps.setSmallintU(4, perPage); - return (SubList) fps.executeQuery().getAllRows(this.facilityManyToOneDef); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - feature = ResultSubSetFeature.class, - sql = "SELECT C.courseID, C.course, C.access, CP.prefix, " - + " F.*, FP.prefix, FS.suffix, FS.suffixAbbrev " - + "FROM ~g~.Course C " - + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " - + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " - + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " - + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " - + "WHERE C.course LIKE ? OR F.facility LIKE ? " - ) - private StatementProvider sqlSelectByName; - - @Override - public SubList findByJurisdiction(String country, String state, int page, int perPage) { - try { - FlexPreparedStatement fps = this.sqlSelectByJurisdiction.buildPreparedStatement(); - try { - fps.setVarchar(1, country); - fps.setVarchar(2, state); - fps.setSmallintU(3, (page - 1) * perPage); - fps.setSmallintU(4, perPage); - return (SubList) fps.executeQuery().getAllRows(this.facilityManyToOneDef); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - feature = ResultSubSetFeature.class, - sql = "SELECT C.courseID, C.course, C.access, CP.prefix, " - + " F.*, FP.prefix, FS.suffix, FS.suffixAbbrev " - + "FROM ~g~.Course C " - + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " - + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " - + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " - + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " - + "WHERE F.addrcountry=? AND F.addrstate=? " - + " AND C.deadline IS NULL " - ) - private StatementProvider sqlSelectByJurisdiction; - - @Override - public SubList findByLocation(double latitude, double longitude, int radiusInMiles, int page, - int perPage) { - double degrees = PostStatsSQL.miles2degrees(radiusInMiles); - - try { - FlexPreparedStatement fps = this.sqlSelectByGeolocation.buildPreparedStatement(); - try { - fps.setDouble(1, latitude - degrees); - fps.setDouble(2, latitude + degrees); - fps.setDouble(3, longitude - degrees); - fps.setDouble(4, longitude + degrees); - fps.setSmallintU(5, (page - 1) * perPage); - fps.setSmallintU(6, perPage); - return (SubList) fps.executeQuery().getAllRows(this.facilityManyToOneDef); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - feature = ResultSubSetFeature.class, - sql = "SELECT C.courseID, C.course, C.access, CP.prefix, " - + " F.*, FP.prefix, FS.suffix, FS.suffixAbbrev " - + "FROM ~g~.Course C " - + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " - + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " - + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " - + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " - + "WHERE F.latitude>=? AND F.latitude<=? AND F.longitude>=? AND F.longitude<=? " - + " AND C.deadline IS NULL " - ) - private StatementProvider sqlSelectByGeolocation; - - @Override - protected long getCacheExpirationInSeconds() { - return this.defaultCacheExpirationInSeconds; - } - - @Override - protected DataSet fetchOne(Integer courseId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectCourse.buildPreparedStatement(); - try { - fps.setSmallintU(1, courseId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT CP.*, C.* " - + "FROM ~g~.Course C " - + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " - + "WHERE C.courseID=? " - ) - private StatementProvider sqlSelectCourse; - - @Override - protected Map fetchBulk(Collection courseIds) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectCourses.buildPreparedStatement(courseIds); - try { - return fps.executeQuery().getAllRows("courseID", Integer.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT CP.*, C.* " - + "FROM ~g~.Course C " - + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " - + "WHERE C.courseID IN (??) " - ) - private StatementProvider sqlSelectCourses; - - - - @Override - public FlexMap getNine(long nineId) { - try { - FlexPreparedStatement fps = this.sqlSelectCourseNine.buildPreparedStatement(); - try { - fps.setIntegerU(1, nineId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.CourseNine WHERE nineID=? ") - private StatementProvider sqlSelectCourseNine; - - @Override - public FlexMap getNine(int courseId, String name) { - try { - FlexPreparedStatement fps = this.sqlSelectCourseNineByName.buildPreparedStatement(); - try { - fps.setSmallintU(1, courseId); - fps.setVarchar(2, name); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.CourseNine WHERE courseID=? AND nine=? AND deadline IS NULL ") - private StatementProvider sqlSelectCourseNineByName; - - - - @Override - public List getHolesByEighteenTee(long eighteenteeId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public List getHolesByNineTee(long nineteeId) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/src/main/java/com/poststats/golf/service/db/EventDocumentServiceDAO.java b/src/main/java/com/poststats/golf/service/db/EventDocumentServiceDAO.java deleted file mode 100644 index 6dbd482..0000000 --- a/src/main/java/com/poststats/golf/service/db/EventDocumentServiceDAO.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.poststats.golf.service.db; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.Map; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.EventDocumentService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.db.CacheableServiceDAO; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class EventDocumentServiceDAO extends CacheableServiceDAO implements EventDocumentService { - - private final long defaultCacheExpirationInSeconds = 3600; - - @Override - public FlexMap get(long eventId, long documentId) { - FlexMap document = this.get(documentId); - if (document != null && eventId != document.getLong("eventID")) - return null; - return document; - } - - @Override - protected long getCacheExpirationInSeconds() { - return this.defaultCacheExpirationInSeconds; - } - - @Override - protected DataSet fetchOne(Long documentId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEventDocument.buildPreparedStatement(); - try { - fps.setIntegerU(1, documentId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT ED.* " - + "FROM ~g~.EventDocument ED " - + "WHERE ED.documentId=? " - ) - private StatementProvider sqlSelectEventDocument; - - @Override - protected Map fetchBulk(Collection documentIds) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEvents.buildPreparedStatement(documentIds); - try { - return fps.executeQuery().getAllRows("documentID", Long.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT ED.* " - + "FROM ~g~.EventDocument ED " - + "WHERE ED.documentId IN (??) " - ) - private StatementProvider sqlSelectEvents; - -} diff --git a/src/main/java/com/poststats/golf/service/db/EventFinanceServiceDAO.java b/src/main/java/com/poststats/golf/service/db/EventFinanceServiceDAO.java deleted file mode 100644 index 5735c6c..0000000 --- a/src/main/java/com/poststats/golf/service/db/EventFinanceServiceDAO.java +++ /dev/null @@ -1,300 +0,0 @@ -package com.poststats.golf.service.db; - -import java.sql.SQLException; -import java.time.LocalDate; -import java.util.Map; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.EventFinanceService; -import com.poststats.golf.service.EventService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.ServiceException; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class EventFinanceServiceDAO implements EventFinanceService { - - @Inject - private EventService eventService; - - @Override - public Map getPersonsBalances(long eventId) { - return this.getPersonsBalances(eventId, null, null); - } - - @Override - public Map getPersonsBalances(long eventId, Float minBalance, Float maxBalance) { - try { - FlexPreparedStatement fps = this.sqlSelectBalances.buildPreparedStatement(); - try { - for (int i = 1; i <= 5; i++) - fps.setIntegerU(i, eventId); - fps.setFloat(6, minBalance == null ? -1e20f : minBalance); - fps.setFloat(7, maxBalance == null ? 1e20f : maxBalance); - return fps.executeQuery().getAllRows("personID", Long.class); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public DataSet getPersonBalance(long eventId, long personId) { - try { - FlexPreparedStatement fps = this.sqlSelectPersonBalances.buildPreparedStatement(); - try { - for (int i = 1; i <= 10; i += 2) { - fps.setIntegerU(i, eventId); - fps.setIntegerU(i + 1, personId); - } - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public Map getSeriesPersonsPreviousBalances(long eventId) { - FlexMap event = this.eventService.get(eventId); - int seriesId = event.getInteger("seriesID"); - LocalDate liveline = event.getDate("liveline"); - - try { - FlexPreparedStatement fps = this.sqlSelectSeriesBalances.buildPreparedStatement(); - try { - for (int i = 1; i <= 15; i += 3) { - fps.setSmallintU(i, seriesId); - fps.setIntegerU(i + 1, eventId); - fps.setDate(i + 2, liveline); - } - return fps.executeQuery().getAllRows("personID", Long.class); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public Map getSeriesPersonBalances(int seriesId, long personId) { - return this.getSeriesPersonBalances(seriesId, null, null, personId); - } - - @Override - public Map getSeriesPersonPreviousBalances(long eventId, long personId) { - FlexMap event = this.eventService.get(eventId); - int seriesId = event.getInteger("seriesID"); - LocalDate liveline = event.getDate("liveline"); - return this.getSeriesPersonBalances(seriesId, eventId, liveline, personId); - } - - private Map getSeriesPersonBalances(int seriesId, Long eventId, LocalDate liveline, long personId) { - if (eventId == null) - eventId = -1L; - if (liveline == null) - liveline = LocalDate.now().plusYears(10L); - - try { - FlexPreparedStatement fps = this.sqlSelectSeriesPersonEventBalances.buildPreparedStatement(); - try { - for (int i = 1; i <= 20; i += 4) { - fps.setSmallintU(i, seriesId); - fps.setIntegerU(i + 1, eventId); - fps.setDate(i + 2, liveline); - fps.setIntegerU(i + 3, personId); - } - return fps.executeQuery().getAllRows("personID", Long.class); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT TT.personID, TT.epersonID, SUM(TT.expenses) expenses, SUM(TT.paid) paid, (SUM(TT.paid)-SUM(TT.expenses)) balance " - + "FROM (" - + " SELECT ALL EP.personID, EP.epersonID, IF(EB.projectedValue IS NULL, 0, EB.projectedValue) expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " LEFT JOIN ~g~.EventBudget EB ON (EP.eventID=EB.eventID) " - + " WHERE EP.eventID=? " - + " UNION ALL " - + " SELECT ALL EP.personID, EP.epersonID, EO.amount expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) " - + " INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) " - + " WHERE EP.eventID=? AND EPO.answer='Y' AND EO.amount IS NOT NULL AND EO.waive IS FALSE " - + " UNION ALL " - + " SELECT ALL EP.personID, EP.epersonID, EO.amount expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) " - + " INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) " - + " WHERE EP.eventID=? AND EPO.itemID IS NOT NULL " - + " AND (EO.multiple IS FALSE OR EO.funded='option' OR EO.static IS NOT NULL) " - + " AND EO.amount IS NOT NULL AND EO.waive IS FALSE " - + " UNION ALL " - + " SELECT ALL EP.personID, EP.epersonID, EOI.amount expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) " - + " INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) " - + " INNER JOIN ~g~.EventOptionItem EOI ON (EPO.itemID=EOI.itemID) " - + " WHERE EP.eventID=? AND EO.waive IS FALSE AND EO.funded='selection' AND EOI.amount IS NOT NULL " - + " UNION ALL " - + " SELECT ALL EPP.personID, EP.epersonID, 0 expenses, EPP.amount paid " - + " FROM ~g~.EventPersonPayment EPP " - + " LEFT JOIN ~g~.EventPerson EP ON (EPP.eventID=EP.eventID AND EPP.personID=EP.personID) " - + " WHERE EPP.eventID=?) TT " - + "GROUP BY TT.personID " - + "HAVING (SUM(TT.paid)-SUM(TT.expenses))>=? AND (SUM(TT.paid)-SUM(TT.expenses))<=? " - ) - private StatementProvider sqlSelectBalances; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT SUM(TT.expenses) expenses, SUM(TT.paid) paid, (SUM(TT.paid)-SUM(TT.expenses)) balance " - + "FROM (" - + " SELECT ALL EP.personID, EP.epersonID, IF(EB.projectedValue IS NULL, 0, EB.projectedValue) expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " LEFT JOIN ~g~.EventBudget EB ON (EP.eventID=EB.eventID) " - + " WHERE EP.eventID=? AND EP.personID=? " - + " UNION ALL " - + " SELECT ALL EP.personID, EP.epersonID, EO.amount expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) " - + " INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) " - + " WHERE EP.eventID=? AND EP.personID=? AND EPO.answer='Y' AND EO.amount IS NOT NULL AND EO.waive IS FALSE " - + " UNION ALL " - + " SELECT ALL EP.personID, EP.epersonID, EO.amount expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) " - + " INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) " - + " WHERE EP.eventID=? AND EP.personID=? AND EPO.itemID IS NOT NULL " - + " AND (EO.multiple IS FALSE OR EO.funded='option' OR EO.static IS NOT NULL) " - + " AND EO.amount IS NOT NULL AND EO.waive IS FALSE " - + " UNION ALL " - + " SELECT ALL EP.personID, EP.epersonID, EOI.amount expenses, 0 paid " - + " FROM ~g~.EventPerson EP " - + " INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) " - + " INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) " - + " INNER JOIN ~g~.EventOptionItem EOI ON (EPO.itemID=EOI.itemID) " - + " WHERE EP.eventID=? AND EP.personID=? AND EO.waive IS FALSE AND EO.funded='selection' AND EOI.amount IS NOT NULL " - + " UNION ALL " - + " SELECT ALL EPP.personID, EP.epersonID, 0 expenses, EPP.amount paid " - + " FROM ~g~.EventPersonPayment EPP " - + " LEFT JOIN ~g~.EventPerson EP ON (EPP.eventID=EP.eventID AND EPP.personID=EP.personID) " - + " WHERE EPP.eventID=? AND EPP.personID=?) TT " - ) - private StatementProvider sqlSelectPersonBalances; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT TT.personID, TT.epersonID, SUM(TT.expenses) expenses, SUM(TT.paid) paid, (SUM(TT.paid)-SUM(TT.expenses)) balance " - + "FROM (" - + " SELECT ALL EP.personID, EP.epersonID, IF(EB.projectedValue IS NULL, 0, EB.projectedValue) expenses, 0 paid " - + " FROM ~g~.Event E " - + " INNER JOIN ~g~.EventPerson EP ON (E.eventID=EP.eventID) " - + " INNER JOIN ~g~.EventBudget EB ON (EP.eventID=EB.eventID) " - + " WHERE E.seriesID=? AND E.eventID<>? AND E.liveline? AND E.liveline? AND E.liveline? AND E.liveline? AND E.liveline? AND E.liveline? AND E.liveline? AND E.liveline? AND E.liveline? AND E.liveline implements EventPersonService { - - @Inject - private EventFinanceService eventFinanceService; - - @Override - public FlexMap get(long eventId, long personId) { - try { - FlexPreparedStatement fps = this.sqlSelectEventPersonByEventIdPersonId.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - fps.setIntegerU(2, personId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.EventPerson WHERE eventID=? AND personID=?") - private StatementProvider sqlSelectEventPersonByEventIdPersonId; - - @Override - public List getPeople(long eventId) { - try { - return this.query(this.sqlSelectPersons, eventId, 2); - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT EP.* FROM ~g~.EventPerson EP WHERE EP.eventID=? " - + "UNION " - + "SELECT DISTINCT NULL, personID " - + "FROM ~g~.EventPersonAccessControl EPAC " - + " LEFT JOIN ~g~.EventPerson EP ON (EPAC.eventID=EP.eventID AND EPAC.personID=EP.personID) " - + "WHERE EPAC.eventID=? AND EP.personID IS NULL " - ) - private StatementProvider sqlSelectPersons; - - @Override - public List getParticipants(long eventId) { - try { - return this.query(this.sqlSelectParticipantIds, eventId, 1); - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.EventPerson WHERE eventID=? AND pending IS FALSE") - private StatementProvider sqlSelectParticipantIds; - - @Override - public Set getSeriesEventFellowParticipantIds(int seriesId, long personId) { - try { - FlexPreparedStatement fps = this.sqlSelectFellowParticipants.buildPreparedStatement(); - try { - fps.setSmallintU(1, seriesId); - fps.setIntegerU(2, personId); - return fps.executeQuery().getFirstColumn(Long.class, new HashSet<>()); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT DISTINCT EP2.personID " - + "FROM ~g~.EventPerson EP1 " - + " INNER JOIN Event E ON (EP1.eventID=E.eventID) " - + " INNER JOIN EventPerson EP2 ON (E.eventID=EP2.eventID) " - + "WHERE EP1.personID=? AND EP1.pending IS FALSE AND E.seriesID=? AND EP2.pending IS FALSE " - ) - private StatementProvider sqlSelectFellowParticipants; - - private List query(StatementProvider provider, long eventId, int parameterCount) - throws SQLException { - FlexPreparedStatement fps = provider.buildPreparedStatement(); - try { - for (int i = 1; i <= parameterCount; i++) - fps.setIntegerU(i, eventId); - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } - - @Override - public List getContactsByListId(long eventId, long listId, boolean allowEmail, boolean allowText) { - try { - List persons = this.getByContactListIds(eventId, listId); - - List contacts = new ArrayList<>(persons.size()); - for (FlexMap person : persons) - contacts.add(new Contact(person, allowEmail, allowText)); - return contacts; - } catch (MessagingException me) { - throw new ServiceException(me); - } - } - - @Override - public List getContactsByAutolist(long eventId, String autolist, boolean allowEmail, boolean allowText) { - try { - List persons = this.getByAutolist(eventId, autolist); - - List contacts = new ArrayList<>(persons.size()); - for (FlexMap person : persons) - contacts.add(new Contact(person, allowEmail, allowText)); - return contacts; - } catch (MessagingException me) { - throw new ServiceException(me); - } - } - - public List getByContactListIds(long eventId, long listId) { - try { - FlexPreparedStatement fps = this.sqlSelectByListId.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - fps.setIntegerU(2, listId); - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT P.* " - + "FROM ~g~.EventContactList ECL " - + " INNER JOIN ~p~.ContactListPerson CLP ON (ECL.listID=CLP.listID) " - + " INNER JOIN ~p~.Person P ON (CLP.personID=P.personID) " - + "WHERE ECL.eventID=? AND ECL.listID=? " - ) - private StatementProvider sqlSelectByListId; - - public List getByAutolist(long eventId, String autolist) { - switch (autolist) { - case "balance": - Map balances = this.eventFinanceService.getPersonsBalances(eventId, null, -0.01f); - return new ArrayList<>(balances.values()); - default: - } - - StatementProvider statementProvider = this.getStatementProviderByAutolist(autolist); - try { - FlexPreparedStatement fps = this.getStatementByAutolist(statementProvider, eventId, autolist); - try { - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - private StatementProvider getStatementProviderByAutolist(String autolist) { - switch (autolist) { - case "all": - return this.sqlSelectEventAllIds; - case "signed": - return this.sqlSelectEventParticipantIds; - case "unsigned": - return this.sqlSelectEventRumormillIds; - case "rookies": - return this.sqlSelectEventRookieIds; - case "rookies-refs": - return this.sqlSelectEventRookieReferralIds; - case "options": - return this.sqlSelectEventParticipantIdsWithUnansweredOptions; - default: - } - - if (autolist.startsWith("previous")) { - if (autolist.length() > "previous".length()) { - return this.sqlSelectRecentSeriesParticipantIds; - } else { - return this.sqlSelectSeriesParticipantIds; - } - } else { - throw new IllegalArgumentException(); - } - } - - private FlexPreparedStatement getStatementByAutolist(StatementProvider statementProvider, long eventId, - String autolist) throws SQLException { - int weeks = -1; - if (autolist.startsWith("previous") && autolist.length() > "previous".length()) - weeks = Integer.parseInt(autolist.substring("previous".length() + 1)); - - FlexPreparedStatement fps = statementProvider.buildPreparedStatement(); - try { - int c = 1; - fps.setIntegerU(c++, eventId); - if (weeks >= 0) { - fps.setIntegerU(c++, eventId); - fps.setSmallintU(c++, weeks); - fps.setSmallintU(c++, weeks); - } - if (autolist.equals("all") || autolist.equals("rookies-refs") || autolist.startsWith("previous")) { - fps.setIntegerU(c++, eventId); - } - - return fps; - } catch (SQLException se) { - fps.close(); - throw se; - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT personID, epersonID FROM ~g~.EventPerson WHERE eventID=?") - private StatementProvider sqlSelectEventParticipantIds; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT personID, NULL epersonID FROM ~g~.EventPersonContract WHERE eventID=?") - private StatementProvider sqlSelectEventRumormillIds; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT personID, epersonID FROM ~g~.EventPerson WHERE eventID=? " - + "UNION " - + "SELECT personID, NULL epersonID FROM ~g~.EventPersonContract WHERE eventID=? " - ) - private StatementProvider sqlSelectEventAllIds; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT DISTINCT EP.personID, EP.epersonID " - + "FROM ~g~.EventPerson EP " - + " LEFT JOIN ~g~.EventPerson EP2 ON (EP.eventID<>EP2.eventID AND EP.personID=EP2.personID) " - + "WHERE EP.eventID=? AND EP2.epersonID IS NULL" - ) - private StatementProvider sqlSelectEventRookieIds; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT DISTINCT EP.personID " - + "FROM ~g~.EventPerson EP " - + " LEFT JOIN ~g~.EventPerson EP2 ON (EP.eventID<>EP2.eventID AND EP.personID=EP2.personID) " - + "WHERE EP.eventID=? AND EP2.epersonID IS NULL " - + "UNION " - + "SELECT DISTINCT P.referralPersonID " - + "FROM ~g~.EventPerson EP " - + " LEFT JOIN ~g~.EventPerson EP2 ON (EP.eventID<>EP2.eventID AND EP.personID=EP2.personID) " - + " INNER JOIN ~p~.Person P ON (EP.personID=P.personID) " - + "WHERE EP.eventID=? AND EP2.epersonID IS NULL AND P.referralPersonID IS NOT NULL" - ) - private StatementProvider sqlSelectEventRookieReferralIds; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT EP.personID, EP.epersonID " - + "FROM ~g~.EventPerson EP " - + " INNER JOIN ?TT? TT1 ON (EP.personID=TT1.personID) " - + "WHERE EP.eventID=? " - + "GROUP BY EP.personID HAVING SUM(TT1.balance) < 0 " - ) - private StatementProvider sqlSelectEventParticipantIdsWithBalance; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT DISTINCT EP.personID, EP.epersonID " - + "FROM ~g~.EventOption EO " - + " INNER JOIN ~g~.EventPerson EP ON (EO.eventID=EP.eventID) " - + " LEFT JOIN ~g~.EventPersonOption EPO ON (EO.optionID=EPO.optionID AND EP.epersonID=EPO.epersonID) " - + "WHERE EO.eventID=? " - + " AND (EO.liveline IS NULL OR EO.liveline<=CURRENT_DATE) " - + " AND (EO.deadline IS NULL OR EO.deadline>=CURRENT_DATE) " - + " AND EPO.optionID IS NULL " - ) - private StatementProvider sqlSelectEventParticipantIdsWithUnansweredOptions; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT DISTINCT EP.personID " - + "FROM ~g~.Event E " - + " INNER JOIN ~g~.Event E2 ON (E.seriesID=E2.seriesID) " - + " INNER JOIN ~g~.EventPerson EP ON (E2.eventID=EP.eventID) " - + "WHERE E.eventID=? AND E2.eventID<>? " - + "UNION DISTINCT " - + "SELECT personID FROM ~g~.EventPersonContract WHERE eventID=? " - ) - private StatementProvider sqlSelectSeriesParticipantIds; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT DISTINCT EP.personID " - + "FROM ~g~.Event E " - + " INNER JOIN ~g~.Event E2 ON (E.seriesID=E2.seriesID) " - + " INNER JOIN ~g~.EventPerson EP ON (E2.eventID=EP.eventID) " - + "WHERE E.eventID=? AND E2.eventID<>? " - + " AND ((E2.deadline IS NOT NULL AND DATE_ADD(E2.deadline, INTERVAL ? WEEK)>=CURRENT_DATE) " - + " OR (E2.liveline IS NOT NULL AND DATE_ADD(E2.liveline, INTERVAL ? WEEK)>=CURRENT_DATE)) " - + "UNION DISTINCT " - + "SELECT personID FROM ~g~.EventPersonContract WHERE eventID=? " - ) - private StatementProvider sqlSelectRecentSeriesParticipantIds; - - @Override - protected DataSet fetchOne(BigInteger epersonId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEventPersonByIds.buildPreparedStatement(); - try { - fps.setBigintU(1, epersonId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.EventPerson WHERE epersonID=?") - private StatementProvider sqlSelectEventPersonById; - - @Override - protected Map fetchBulk(Collection epersonIds) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEventPersonByIds.buildPreparedStatement(epersonIds); - try { - return fps.executeQuery().getAllRows("epersonID", BigInteger.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.EventPerson WHERE epersonID IN (??)") - private StatementProvider sqlSelectEventPersonByIds; - -} diff --git a/src/main/java/com/poststats/golf/service/db/EventRoundPairingServiceDAO.java b/src/main/java/com/poststats/golf/service/db/EventRoundPairingServiceDAO.java deleted file mode 100644 index cb5c751..0000000 --- a/src/main/java/com/poststats/golf/service/db/EventRoundPairingServiceDAO.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.poststats.golf.service.db; - -import java.math.BigInteger; -import java.sql.SQLException; -import java.util.List; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexManyToOneDef; -import com.brianlong.sql.FlexPreparedStatement; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.EventRoundPairingService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.ServiceException; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class EventRoundPairingServiceDAO implements EventRoundPairingService { - - @Override - public DataSet get(BigInteger pairingId) { - try { - FlexPreparedStatement fps = this.sqlSelect.buildPreparedStatement(); - try { - fps.setBigintU(1, pairingId); - return fps.executeQuery().getNextRow(new FlexManyToOneDef("nineID", "nine")); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT ERP.pairingID, ERP.teetime, ERP.eroundID, ERP.courseID, ERP.number, " - + " CN.nineID, CN.nine, CN.courseID " - + "FROM ~g~.EventRoundPairing ERP " - + " LEFT JOIN ~g~.CourseNine CN ON (ERP.nineID=CN.nineID) " - + "WHERE ERP.pairingID=? " - ) - private StatementProvider sqlSelect; - - @Override - public List getByRoundId(long eroundId) { - try { - FlexPreparedStatement fps = this.sqlSelectByRoundId.buildPreparedStatement(); - try { - fps.setIntegerU(1, eroundId); - return fps.executeQuery().getAllRows(new FlexManyToOneDef("nineID", "nine")); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT ERP.pairingID, ERP.teetime, ERP.eroundID, ERP.courseID, ERP.number, " - + " CN.nineID, CN.nine, CN.courseID " - + "FROM ~g~.EventRoundPairing ERP " - + " LEFT JOIN ~g~.CourseNine CN ON (ERP.nineID=CN.nineID) " - + "WHERE ERP.eroundID=? " - ) - private StatementProvider sqlSelectByRoundId; - - @Override - public List getParticipantsByRoundId(long eroundId) { - try { - FlexPreparedStatement fps = this.sqlSelectParticipantsByRoundId.buildPreparedStatement(); - try { - fps.setIntegerU(1, eroundId); - return fps.executeQuery().getAllRows(new FlexManyToOneDef("pairingID", "pairing"), - new FlexManyToOneDef("nineID", "pairing", "nine")); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT EPR.epersonID, EP.personID, " - + " ERP.pairingID, ERP.teetime, ERP.eroundID, ERP.courseID, ERP.number, " - + " CN.nineID, CN.nine, CN.courseID " - + "FROM ~g~.EventRoundPairing ERP " - + " INNER JOIN ~g~.EventPersonRound EPR ON (ERP.pairingID=EPR.pairingID) " - + " INNER JOIN ~g~.EventPerson EP ON (EPR.epersonID=EP.epersonID) " - + " LEFT JOIN ~g~.CourseNine CN ON (ERP.nineID=CN.nineID) " - + "WHERE ERP.eroundID=? " - ) - private StatementProvider sqlSelectParticipantsByRoundId; - -} diff --git a/src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java b/src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java deleted file mode 100644 index e2a0d70..0000000 --- a/src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.poststats.golf.service.db; - -import java.sql.SQLException; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.EventRoundService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.ServiceException; -import com.poststats.service.db.CacheableServiceDAO; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class EventRoundServiceDAO extends CacheableServiceDAO implements EventRoundService { - - private final long defaultCacheExpirationInSeconds = 3600; - - @Override - public FlexMap get(long eroundId) { - return this.get(Long.valueOf(eroundId)); - } - - @Override - public List getUpcoming(long eventId) { - LocalDateTime now = LocalDateTime.now(); - if (now.getHour() > 17) - now.plusDays(1); - - try { - FlexPreparedStatement fps = this.sqlSelectUpcoming.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - fps.setDate(2, now.toLocalDate()); - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT TF.*, ER.* " - + "FROM ~g~.EventRound ER " - + " LEFT JOIN ~g~.TeeFormat TF ON (ER.teeFormatID=TF.teeFormatID) " - + "WHERE ER.eventID=? AND ER.date>=? AND MIN(ER.date)=ER.date " - ) - private StatementProvider sqlSelectUpcoming; - - @Override - public Map getByEventId(long eventId) { - try { - FlexPreparedStatement fps = this.sqlSelectByEventId.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - return fps.executeQuery().getAllRows("eroundID", Long.class); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT TF.*, ER.* " - + "FROM ~g~.EventRound ER " - + " LEFT JOIN ~g~.TeeFormat TF ON (ER.teeFormatID=TF.teeFormatID) " - + "WHERE ER.eventID=? " - ) - private StatementProvider sqlSelectByEventId; - - @Override - protected long getCacheExpirationInSeconds() { - return this.defaultCacheExpirationInSeconds; - } - - @Override - protected DataSet fetchOne(Long eroundId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelect.buildPreparedStatement(); - try { - fps.setIntegerU(1, eroundId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT TF.*, ER.* " - + "FROM ~g~.EventRound ER " - + " LEFT JOIN ~g~.TeeFormat TF ON (ER.teeFormatID=TF.teeFormatID) " - + "WHERE ER.eroundID=? " - ) - private StatementProvider sqlSelect; - - @Override - protected Map fetchBulk(Collection eroundIds) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectManys.buildPreparedStatement(eroundIds); - try { - return fps.executeQuery().getAllRows("eroundID", Long.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT TF.*, ER.* " - + "FROM ~g~.EventRound ER " - + " LEFT JOIN ~g~.TeeFormat TF ON (ER.teeFormatID=TF.teeFormatID) " - + "WHERE ER.eroundID IN (??) " - ) - private StatementProvider sqlSelectManys; - -} diff --git a/src/main/java/com/poststats/golf/service/db/EventServiceDAO.java b/src/main/java/com/poststats/golf/service/db/EventServiceDAO.java deleted file mode 100644 index 174c6a5..0000000 --- a/src/main/java/com/poststats/golf/service/db/EventServiceDAO.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.poststats.golf.service.db; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.EventService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.ServiceException; -import com.poststats.service.db.CacheableServiceDAO; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class EventServiceDAO extends CacheableServiceDAO implements EventService { - - private final long defaultCacheExpirationInSeconds = 3600; - - @Override - public FlexMap get(long eventId) { - return this.get(Long.valueOf(eventId)); - } - - @Override - public Set getIdsBySeriesId(int seriesId) { - try { - FlexPreparedStatement fps = this.sqlSelectIdsBySeriesId.buildPreparedStatement(); - try { - fps.setSmallintU(1, seriesId); - return fps.executeQuery().getFirstColumn(Long.class, new HashSet<>()); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT eventId FROM ~g~.Event WHERE seriesID=? ") - private StatementProvider sqlSelectIdsBySeriesId; - - @Override - public Map getBySeriesId(int seriesId) { - try { - FlexPreparedStatement fps = this.sqlSelectBySeriesId.buildPreparedStatement(); - try { - fps.setSmallintU(1, seriesId); - return fps.executeQuery().getAllRows("eventID", Long.class); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.Event WHERE seriesID=? ORDER BY liveline DESC ") - private StatementProvider sqlSelectBySeriesId; - - @Override - public Integer getSeriesId(long eventId) { - FlexMap event = this.getIfHit(eventId); - if (event != null) - return event.getInteger("seriesID"); - - try { - FlexPreparedStatement fps = this.sqlSelectSeriesId.buildPreparedStatement(); - try { - fps.setSmallintU(1, eventId); - return fps.executeQuery().getOne(Integer.class); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT seriesID FROM ~g~.Event WHERE eventID=? ") - private StatementProvider sqlSelectSeriesId; - - @Override - protected long getCacheExpirationInSeconds() { - return this.defaultCacheExpirationInSeconds; - } - - @Override - protected DataSet fetchOne(Long eventId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEvent.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT EF.*, E.* " - + "FROM ~g~.Event E " - + " INNER JOIN ~g~.EventFeature EF ON (E.eventID=EF.eventID) " - + "WHERE E.eventID=? " - ) - private StatementProvider sqlSelectEvent; - - @Override - protected Map fetchBulk(Collection eventIds) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEvents.buildPreparedStatement(eventIds); - try { - return fps.executeQuery().getAllRows("eventID", Long.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT EF.*, E.* " - + "FROM ~g~.Event E " - + " INNER JOIN ~g~.EventFeature EF ON (E.eventID=EF.eventID) " - + "WHERE E.eventID IN (??) " - ) - private StatementProvider sqlSelectEvents; - -} diff --git a/src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java b/src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java deleted file mode 100644 index 8537d96..0000000 --- a/src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java +++ /dev/null @@ -1,740 +0,0 @@ -package com.poststats.golf.service.db; - -import java.math.BigInteger; -import java.sql.SQLException; -import java.time.LocalDate; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.PersonRoundService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.ServiceException; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class PersonRoundServiceDAO implements PersonRoundService { - - @Override - public FlexMap fetchNonEvent(BigInteger roundId, Selection selection, Filter... filters) { - StatementProvider stmt = this.getNonEventRoundStatementProvider(selection, filters); - - try { - FlexPreparedStatement fps = stmt.buildPreparedStatement(); - try { - for (int c = 1; c <= fps.getPreparedStatement().getParameterMetaData().getParameterCount(); c++) - fps.setBigintU(c, roundId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public FlexMap fetchEvent(BigInteger proundId, Selection selection, Filter... filters) { - StatementProvider stmt = this.getEventRoundStatementProvider(selection, filters); - - try { - FlexPreparedStatement fps = stmt.buildPreparedStatement(); - try { - for (int c = 1; c <= fps.getPreparedStatement().getParameterMetaData().getParameterCount(); c++) - fps.setBigintU(c, proundId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public List fetchNonEventHoles(BigInteger roundId, Selection selection) { - StatementProvider stmt = this.getNonEventRoundHolesStatementProvider(selection); - - try { - FlexPreparedStatement fps = stmt.buildPreparedStatement(); - try { - for (int c = 1; c <= fps.getPreparedStatement().getParameterMetaData().getParameterCount(); c++) - fps.setBigintU(c, roundId); - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public List fetchEventHoles(BigInteger proundId, Selection selection) { - StatementProvider stmt = this.getEventRoundHolesStatementProvider(selection); - - try { - FlexPreparedStatement fps = stmt.buildPreparedStatement(); - try { - for (int c = 1; c <= fps.getPreparedStatement().getParameterMetaData().getParameterCount(); c++) - fps.setBigintU(c, proundId); - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public List findBefore(long personId, LocalDate beforeDay, short roundCount, Selection selection, - Filter... filters) { - StatementProvider stmt = this.getRoundsStatementProvider(selection, filters); - - try { - FlexPreparedStatement fps = stmt.buildPreparedStatement(); - try { - fps.setIntegerU(1, personId); // for non-event rounds - fps.setDate(2, beforeDay); - fps.setIntegerU(3, personId); // for 18-hole event rounds - fps.setDate(4, beforeDay); - fps.setIntegerU(5, personId); // for 9-hole event rounds - fps.setDate(6, beforeDay); - fps.setSmallint(7, roundCount); // limit - return fps.executeQuery().getAllRows(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - private StatementProvider getNonEventRoundStatementProvider(Selection selection, Filter... filters) { - Set filterSet = new HashSet<>(); - for (Filter filter : filters) - filterSet.add(filter); - - switch (selection) { - case StrokeHandicapIndex: - if (filterSet.contains(Filter.AttestedOnly)) { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectSignedRatedNonEventRoundWithStrokeHandicap; - } else { - return this.sqlSelectSignedNonEventRoundWithStrokeHandicap; - } - } else { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectRatedNonEventRoundWithStrokeHandicap; - } else { - return this.sqlSelectNonEventRoundWithStrokeHandicap; - } - } - case ScoreToPar: - if (filterSet.contains(Filter.AttestedOnly)) { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectSignedRatedNonEventRoundWithScoreToPar; - } else { - return this.sqlSelectSignedNonEventRoundWithScoreToPar; - } - } else { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectRatedNonEventRoundWithScoreToPar; - } else { - return this.sqlSelectNonEventRoundWithScoreToPar; - } - } - default: - throw new IllegalArgumentException(); - } - } - - private StatementProvider getEventRoundStatementProvider(Selection selection, Filter... filters) { - Set filterSet = new HashSet<>(); - for (Filter filter : filters) - filterSet.add(filter); - - switch (selection) { - case StrokeHandicapIndex: - if (filterSet.contains(Filter.AttestedOnly)) { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectSignedRatedEventRoundWithStrokeHandicap; - } else { - return this.sqlSelectSignedEventRoundWithStrokeHandicap; - } - } else { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectRatedEventRoundWithStrokeHandicap; - } else { - return this.sqlSelectEventRoundWithStrokeHandicap; - } - } - case ScoreToPar: - if (filterSet.contains(Filter.AttestedOnly)) { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectSignedRatedEventRoundWithScoreToPar; - } else { - return this.sqlSelectSignedEventRoundWithScoreToPar; - } - } else { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectRatedEventRoundWithScoreToPar; - } else { - return this.sqlSelectEventRoundWithScoreToPar; - } - } - default: - throw new IllegalArgumentException(); - } - } - - private StatementProvider getNonEventRoundHolesStatementProvider(Selection selection) { - switch (selection) { - case StrokeHandicapIndex: - return this.sqlSelectNonEventRoundHolesWithStrokeHandicap; - case ScoreToPar: - return this.sqlSelectNonEventRoundHolesWithScoreToPar; - default: - throw new IllegalArgumentException(); - } - } - - private StatementProvider getEventRoundHolesStatementProvider(Selection selection) { - switch (selection) { - case StrokeHandicapIndex: - return this.sqlSelectEventRoundHolesWithStrokeHandicap; - case ScoreToPar: - return this.sqlSelectEventRoundHolesWithScoreToPar; - default: - throw new IllegalArgumentException(); - } - } - - private StatementProvider getRoundsStatementProvider(Selection selection, Filter... filters) { - Set filterSet = new HashSet<>(); - for (Filter filter : filters) - filterSet.add(filter); - - switch (selection) { - case StrokeHandicapIndex: - if (filterSet.contains(Filter.AttestedOnly)) { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectSignedRatedRoundsWithStrokeHandicap; - } else { - return this.sqlSelectSignedRoundsWithStrokeHandicap; - } - } else { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectRatedRoundsWithStrokeHandicap; - } else { - return this.sqlSelectRoundsWithStrokeHandicap; - } - } - case ScoreToPar: - if (filterSet.contains(Filter.AttestedOnly)) { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectSignedRatedRoundsWithScoreToPar; - } else { - return this.sqlSelectSignedRoundsWithScoreToPar; - } - } else { - if (filterSet.contains(Filter.CourseRatedOnly)) { - return this.sqlSelectRatedRoundsWithScoreToPar; - } else { - return this.sqlSelectRoundsWithScoreToPar; - } - } - default: - throw new IllegalArgumentException(); - } - } - - private final static String nonEventRoundSqlSelectClause = "SELECT R.roundID, NULL proundID, NULL linkProundID, R.personID, R.etratingID, R.courseID, R.teedate, R.teetime, R.strokes, "; - private final static String nonEventRoundSqlFromClause = "FROM ~g~.Round R " - + " INNER JOIN ~p~.Person P ON (R.personID=P.personID) "; - private final static String nonEventRoundSqlWhereClause = "WHERE R.roundID=? "; - private final static String nonEventRoundsSqlWhereClause = "WHERE R.personID=? AND R.complete IS TRUE AND R.teedateP.healthSetback) "; - - private final static String event18RoundSqlSelectClause = "SELECT NULL roundID, EPR.proundID, NULL linkProundID, EP.personID, EPR.etratingID, EPR.courseID, ER.date, ERP.teetime, EPR.strokes, "; - private final static String event18RoundSqlFromClause = "FROM ~g~.EventPersonRound EPR " - + " INNER JOIN ~g~.EventRound ER ON (EPR.eroundID=ER.eroundID) " - + " INNER JOIN ~g~.EventPerson EP ON (EPR.epersonID=EP.epersonID) " - + " INNER JOIN ~p~.Person P ON (EP.personID=P.personID) " - + " LEFT JOIN ~g~.EventRoundPairing ERP ON (EPR.pairingID=ERP.pairingID) "; - private final static String event18RoundSqlWhereClause = "WHERE EPR.proundID=? "; - private final static String event18RoundsSqlWhereClause = "WHERE EP.personID=? AND EPR.complete IS TRUE AND EPR.etratingID IS NOT NULL AND ER.dateP.healthSetback) "; - - private final static String event9RoundSqlSelectClause = "SELECT NULL roundID, EPR.proundID, EPR.linkProundID, EP.personID, CETR.etratingID, EPR.courseID, ER.date, ERP.teetime, " - + " (EPR.strokes+EPR2.strokes) strokes, "; - private final static String event9RoundSqlFromClause = "FROM ~g~.EventPersonRound EPR " - + " INNER JOIN ~g~.EventPersonRound EPR2 ON (EPR.linkProundID=EPR2.proundID AND EPR.proundID>EPR2.proundID) " - + " INNER JOIN ~g~.CourseNineTeeRating CNTR1 ON (EPR.ntratingID=CNTR1.ntratingID) " - + " INNER JOIN ~g~.CourseNineTeeRating CNTR2 ON (EPR2.ntratingID=CNTR2.ntratingID) " - + " INNER JOIN ~g~.CourseEighteenTee CET ON ((CNTR1.nineteeID=CET.nineteeID1 AND CNTR2.nineteeID=CET.nineteeID2) " - + " OR (CNTR2.nineteeID=CET.nineteeID1 AND CNTR1.nineteeID=CET.nineteeID2)) " - + " INNER JOIN ~g~.CourseEighteenTeeRating CETR ON (CET.eighteenteeID=CETR.eighteenteeID " - + " AND CNTR1.gender=CETR.gender " - + " AND CETR.liveline<=ER.date AND (CETR.deadline IS NULL OR ER.date<=CETR.deadline)) " - + " INNER JOIN ~g~.EventRound ER ON (EPR.eroundID=ER.eroundID) " - + " INNER JOIN ~g~.EventPerson EP ON (EPR.epersonID=EP.epersonID) " - + " INNER JOIN ~p~.Person P ON (EP.personID=P.personID) " - + " LEFT JOIN ~g~.EventRoundPairing ERP ON (EPR.pairingID=ERP.pairingID) "; - private final static String event9RoundSqlWhereClause = "WHERE EPR.proundID=? "; - private final static String event9RoundsSqlWhereClause = "WHERE EP.personID=? AND EPR.complete IS TRUE AND ER.dateP.healthSetback) "; - - private final static String nonEventRoundSqlSelectStrokeHandicap = nonEventRoundSqlSelectClause - + " R.strokeHandicapIndex, R.whsStrokeHandicapIndex " - + nonEventRoundSqlFromClause - + nonEventRoundSqlWhereClause; - private final static String nonEventRoundsSqlSelectStrokeHandicap = nonEventRoundSqlSelectClause - + " R.strokeHandicapIndex, R.whsStrokeHandicapIndex " - + nonEventRoundSqlFromClause - + nonEventRoundsSqlWhereClause; - - private final static String event18RoundSqlSelectStrokeHandicap = event18RoundSqlSelectClause - + " EPR.strokeHandicapIndex, EPR.whsStrokeHandicapIndex " - + event18RoundSqlFromClause - + event18RoundSqlWhereClause; - private final static String event18RoundsSqlSelectStrokeHandicap = event18RoundSqlSelectClause - + " EPR.strokeHandicapIndex, EPR.whsStrokeHandicapIndex " - + event18RoundSqlFromClause - + event18RoundsSqlWhereClause; - - private final static String event9RoundSqlSelectStrokeHandicap = event9RoundSqlSelectClause - + " (EPR.strokeHandicapIndex+EPR2.strokeHandicapIndex) strokeHandicapIndex, " - + " (EPR.whsStrokeHandicapIndex+EPR2.whsStrokeHandicapIndex) whsStrokeHandicapIndex " - + event9RoundSqlFromClause - + event9RoundSqlWhereClause; - private final static String event9RoundsSqlSelectStrokeHandicap = event9RoundSqlSelectClause - + " (EPR.strokeHandicapIndex+EPR2.strokeHandicapIndex) strokeHandicapIndex, " - + " (EPR.whsStrokeHandicapIndex+EPR2.whsStrokeHandicapIndex) whsStrokeHandicapIndex " - + event9RoundSqlFromClause - + event9RoundsSqlWhereClause; - - private final static String nonEventRoundSqlSelectPointsClause = - " SUM(CASE WHEN (RX.strokes - CNTH.par) = 5 THEN 1 ELSE 0 END) bogey5, " - + " SUM(CASE WHEN (RX.strokes - CNTH.par) = 4 THEN 1 ELSE 0 END) bogey4, " - + " SUM(CASE WHEN (RX.strokes - CNTH.par) = 3 THEN 1 ELSE 0 END) bogey3, " - + " SUM(CASE WHEN (RX.strokes - CNTH.par) = 2 THEN 1 ELSE 0 END) bogey2, " - + " SUM(CASE WHEN (RX.strokes - CNTH.par) = 1 THEN 1 ELSE 0 END) bogey, " - + " SUM(CASE WHEN RX.strokes = CNTH.par THEN 1 ELSE 0 END) par, " - + " SUM(CASE WHEN (CNTH.par - RX.strokes) = 1 THEN 1 ELSE 0 END) birdie, " - + " SUM(CASE WHEN (CNTH.par - RX.strokes) = 2 THEN 1 ELSE 0 END) eagle, " - + " SUM(CASE WHEN (CNTH.par - RX.strokes) = 3 THEN 1 ELSE 0 END) alby, "; - private final static String nonEventRoundSqlFromPointsClause = - " INNER JOIN ~g~.RoundScore RX ON (R.roundID=RX.roundID) " - + " INNER JOIN ~g~.CourseNineTeeHole CNTH ON (RX.holeID=CNTH.holeID) " - + " INNER JOIN ~g~.CourseEighteenTeeRating CETR ON (R.etratingID=CETR.etratingID) "; - private final static String nonEventRoundSqlSelectScoreToPar = nonEventRoundSqlSelectClause - + nonEventRoundSqlSelectPointsClause - + " CETR.pointAdj " - + nonEventRoundSqlFromClause - + nonEventRoundSqlFromPointsClause - + nonEventRoundSqlWhereClause - + "GROUP BY R.roundID "; - private final static String nonEventRoundsSqlSelectScoreToPar = nonEventRoundSqlSelectClause - + nonEventRoundSqlSelectPointsClause - + " CETR.pointAdj " - + nonEventRoundSqlFromClause - + nonEventRoundSqlFromPointsClause - + nonEventRoundsSqlWhereClause - + "GROUP BY R.roundID "; - - private final static String eventRoundSqlSelectPointsClause = - "SUM(CASE WHEN (EPRS.strokes - CNTH.par) = 5 THEN 1 ELSE 0 END) bogey5, " - + " SUM(CASE WHEN (EPRS.strokes - CNTH.par) = 4 THEN 1 ELSE 0 END) bogey4, " - + " SUM(CASE WHEN (EPRS.strokes - CNTH.par) = 3 THEN 1 ELSE 0 END) bogey3, " - + " SUM(CASE WHEN (EPRS.strokes - CNTH.par) = 2 THEN 1 ELSE 0 END) bogey2, " - + " SUM(CASE WHEN (EPRS.strokes - CNTH.par) = 1 THEN 1 ELSE 0 END) bogey, " - + " SUM(CASE WHEN EPRS.strokes = CNTH.par THEN 1 ELSE 0 END) par, " - + " SUM(CASE WHEN (CNTH.par - EPRS.strokes) = 1 THEN 1 ELSE 0 END) birdie, " - + " SUM(CASE WHEN (CNTH.par - EPRS.strokes) = 2 THEN 1 ELSE 0 END) eagle, " - + " SUM(CASE WHEN (CNTH.par - EPRS.strokes) = 3 THEN 1 ELSE 0 END) alby, "; - private final static String event18RoundSqlFromPointsClause = - " INNER JOIN ~g~.EventPersonRoundScore EPRS ON (EPR.proundID=EPRS.proundID) " - + " INNER JOIN ~g~.CourseNineTeeHole CNTH ON (EPRS.holeID=CNTH.holeID) " - + " INNER JOIN ~g~.CourseEighteenTeeRating CETR ON (EPR.etratingID=CETR.etratingID) "; - private final static String event9RoundSqlFromPointsClause = - " INNER JOIN ~g~.EventPersonRoundScore EPRS ON (EPR.proundID=EPRS.proundID OR EPR.linkProundID=EPRS.proundID) " - + " INNER JOIN ~g~.CourseNineTeeHole CNTH ON (EPRS.holeID=CNTH.holeID) " - + " INNER JOIN ~g~.CourseNineTeeRating CNTR ON (EPR.ntratingID=CNTR.ntratingID) "; - - private final static String event18RoundSqlSelectScoreToPar = event18RoundSqlSelectClause - + eventRoundSqlSelectPointsClause - + " CETR.pointAdj " - + event18RoundSqlFromClause - + event18RoundSqlFromPointsClause - + event18RoundSqlWhereClause - + "GROUP BY EPR.proundID "; - private final static String event18RoundsSqlSelectScoreToPar = event18RoundSqlSelectClause - + eventRoundSqlSelectPointsClause - + " CETR.pointAdj " - + event18RoundSqlFromClause - + event18RoundSqlFromPointsClause - + event18RoundsSqlWhereClause - + "GROUP BY EPR.proundID "; - - private final static String event9RoundSqlSelectScoreToPar = event9RoundSqlSelectClause - + eventRoundSqlSelectPointsClause - + " CNTR.pointAdj " - + event9RoundSqlFromClause - + event9RoundSqlFromPointsClause - + event9RoundSqlWhereClause - + "GROUP BY EPR.proundID "; - private final static String event9RoundsSqlSelectScoreToPar = event9RoundSqlSelectClause - + eventRoundSqlSelectPointsClause - + " CNTR.pointAdj " - + event9RoundSqlFromClause - + event9RoundSqlFromPointsClause - + event9RoundsSqlWhereClause - + "GROUP BY EPR.proundID "; - - private final static String nonEventRoundHoleSqlSelectClause = "SELECT RX.holeID, RX.strokes, CNTH.par, "; - private final static String nonEventRoundHoleSqlFromClause = - "FROM ~g~.RoundScore RX " - + " INNER JOIN ~g~.CourseNineTeeHole CNTH ON (RX.holeID=CNTH.holeID) "; - private final static String nonEventRoundHolesSqlSelectStrokeHandicap = - nonEventRoundHoleSqlSelectClause - + " CNTH.handicap, CNTH.whsHandicap " - + nonEventRoundHoleSqlFromClause - + "WHERE RX.roundID=? "; - private final static String nonEventRoundHolesSqlSelectScoreToPar = - nonEventRoundHoleSqlSelectClause - + nonEventRoundHoleSqlFromClause - + "WHERE RX.roundID=? "; - - private final static String eventRoundHoleSqlSelectClause = "SELECT EPRS.holeID, EPRS.strokes, CNTH.par, "; - private final static String eventRoundHoleSqlFromClause = - "FROM ~g~.EventPersonRoundScore EPRS " - + " INNER JOIN ~g~.CourseNineTeeHole CNTH ON (EPRS.holeID=CNTH.holeID) " - + " INNER JOIN ~g~.EventPersonRound EPR ON (EPRS.proundID=EPR.proundID) "; - private final static String eventRoundHolesSqlSelectStrokeHandicap = - eventRoundHoleSqlSelectClause - + " CNTH.handicap, CNTH.whsHandicap " - + eventRoundHoleSqlFromClause - + "WHERE EPRS.proundID=? "; - private final static String eventRoundHolesSqlSelectScoreToPar = - eventRoundHoleSqlSelectClause - + eventRoundHoleSqlFromClause - + "WHERE EPRS.roundID=? "; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = nonEventRoundSqlSelectStrokeHandicap) - private StatementProvider sqlSelectNonEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundsSqlSelectStrokeHandicap - + "UNION " - + event9RoundsSqlSelectStrokeHandicap - ) - private StatementProvider sqlSelectEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectStrokeHandicap - + "UNION " - + event18RoundsSqlSelectStrokeHandicap - + "UNION " - + event9RoundsSqlSelectStrokeHandicap - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectRoundsWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectStrokeHandicap - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - ) - private StatementProvider sqlSelectRatedNonEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundsSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundsSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - ) - private StatementProvider sqlSelectRatedEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectStrokeHandicap - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event18RoundsSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundsSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectRatedRoundsWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundSqlSelectStrokeHandicap - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - ) - private StatementProvider sqlSelectSignedNonEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundSqlSelectStrokeHandicap - + "UNION " - + event9RoundSqlSelectStrokeHandicap - ) - private StatementProvider sqlSelectSignedEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectStrokeHandicap - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - + "UNION " - + event18RoundsSqlSelectStrokeHandicap - + "UNION " - + event9RoundsSqlSelectStrokeHandicap - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectSignedRoundsWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundSqlSelectStrokeHandicap - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - ) - private StatementProvider sqlSelectSignedRatedNonEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - ) - private StatementProvider sqlSelectSignedRatedEventRoundWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectStrokeHandicap - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - + "UNION " - + event18RoundsSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundsSqlSelectStrokeHandicap - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectSignedRatedRoundsWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = nonEventRoundSqlSelectScoreToPar) - private StatementProvider sqlSelectNonEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundSqlSelectScoreToPar - + "UNION " - + event9RoundSqlSelectScoreToPar - ) - private StatementProvider sqlSelectEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectScoreToPar - + "UNION " - + event18RoundsSqlSelectScoreToPar - + "UNION " - + event9RoundsSqlSelectScoreToPar - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectRoundsWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundSqlSelectScoreToPar - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - ) - private StatementProvider sqlSelectRatedNonEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - ) - private StatementProvider sqlSelectRatedEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectScoreToPar - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event18RoundsSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundsSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectRatedRoundsWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundSqlSelectScoreToPar - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - ) - private StatementProvider sqlSelectSignedNonEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundSqlSelectScoreToPar - + "UNION " - + event9RoundSqlSelectScoreToPar - ) - private StatementProvider sqlSelectSignedEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectScoreToPar - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - + "UNION " - + event18RoundsSqlSelectScoreToPar - + "UNION " - + event9RoundsSqlSelectScoreToPar - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectSignedRoundsWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundSqlSelectScoreToPar - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - ) - private StatementProvider sqlSelectSignedRatedNonEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = event18RoundSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - ) - private StatementProvider sqlSelectSignedRatedEventRoundWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundsSqlSelectScoreToPar - + " AND R.whsStrokeHandicapIndex IS NOT NULL " - + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - + "UNION " - + event18RoundsSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "UNION " - + event9RoundsSqlSelectScoreToPar - + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectSignedRatedRoundsWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = nonEventRoundHolesSqlSelectStrokeHandicap) - private StatementProvider sqlSelectNonEventRoundHolesWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = eventRoundHolesSqlSelectStrokeHandicap) - private StatementProvider sqlSelectEventRoundHolesWithStrokeHandicap; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = nonEventRoundHolesSqlSelectScoreToPar) - private StatementProvider sqlSelectNonEventRoundHolesWithScoreToPar; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = eventRoundHolesSqlSelectScoreToPar) - private StatementProvider sqlSelectEventRoundHolesWithScoreToPar; - -} diff --git a/src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java b/src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java deleted file mode 100644 index f1f4267..0000000 --- a/src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.poststats.golf.service.db; - -import java.io.IOException; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.brianlong.cache.CacheException; -import com.brianlong.cache.CacheableFetcher; -import com.brianlong.cache.ClusterAwareMemoryCacher; -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.sql.FlexStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.security.AuthenticatedPerson; -import com.poststats.golf.service.PersonService; -import com.poststats.golf.sql.GolfDataSource; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.ServiceException; -import com.poststats.service.db.CacheableServiceDAO; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class PersonServiceDAO extends CacheableServiceDAO implements PersonService { - - @Inject - private com.poststats.service.PersonService poststatsPersonService; - - private final int roleCacheExpirationInSeconds = 300; - private final int infoCacheExpirationInSeconds = 120; - - private ClusterAwareMemoryCacher principalCacher; - - @PostConstruct - private void initCache() { - this.principalCacher = new ClusterAwareMemoryCacher( - this.roleCacheExpirationInSeconds * 1000L, this.clusterService.getHazelcastInstance()); - } - - @Override - protected long getCacheExpirationInSeconds() { - return this.infoCacheExpirationInSeconds; - } - - @Override - public AuthenticatedPerson getUserPrincipal(com.poststats.security.AuthenticatedPerson person) { - try { - return this.principalCacher.get(person.getId(), new PrincipalCacheableFetcher() { - @Override - public com.poststats.security.AuthenticatedPerson getPerson() { - return person; - } - }); - } catch (CacheException ce) { - throw new ServiceException(ce); - } - } - - @Override - public FlexMap get(long personId) { - return this.get(Long.valueOf(personId)); - } - - @Override - public FlexMap injectDeep(String idKey, FlexMap parentMap, String mapKey) { - FlexMap map = this.inject(idKey, parentMap, mapKey); - return this.poststatsPersonService.inject("personID", map, "person"); - } - - @Override - public Collection injectDeep(String idKey, Collection parentMaps, - String mapKey) { - Collection maps = this.inject(idKey, parentMaps, mapKey); - return this.poststatsPersonService.inject("personID", maps, "person"); - } - - private abstract class PrincipalCacheableFetcher implements CacheableFetcher { - - public abstract com.poststats.security.AuthenticatedPerson getPerson(); - - @Override - public AuthenticatedPerson get(Long personId) throws SQLException { - Connection dbcon = GolfDataSource.getInstance().acquire(true); - try { - return new AuthenticatedPerson(this.getPerson(), queryBuddies(personId), queryAccessControls(personId), - queryEventAccessControls(personId)); - } finally { - GolfDataSource.getInstance().release(dbcon); - } - } - - @Override - public Map get(Collection personIds) throws SQLException, IOException { - throw new UnsupportedOperationException(); - } - - private Set queryBuddies(long personId) throws SQLException { - FlexPreparedStatement fps = sqlSelectBuddyIds.buildPreparedStatement(); - try { - fps.setIntegerU(1, personId); - - Set set = new HashSet<>(); - fps.executeQuery().getFirstColumn(Long.class, set); - return set; - } finally { - fps.close(); - } - } - - private Set queryAccessControls(long personId) throws SQLException { - FlexPreparedStatement fps = sqlSelectAcs.buildPreparedStatement(); - try { - fps.setIntegerU(1, personId); - - Set set = new HashSet<>(); - fps.executeQuery().getFirstColumn(String.class, set); - return set; - } finally { - fps.close(); - } - } - - private Map> queryEventAccessControls(long personId) throws SQLException { - FlexPreparedStatement fps = sqlSelectEventAcs.buildPreparedStatement(); - try { - fps.setIntegerU(1, personId); - return fps.executeQuery().getFirstTwoColumnsOneToMany(Long.class, String.class); - } finally { - fps.close(); - } - } - }; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT PS1.personID " - + "FROM ~g~.PersonSpectator PS1 " - + " INNER JOIN ~g~.PersonSpectator PS2 ON (PS1.personID=PS2.watchedPersonID AND PS1.watchedPersonID=PS2.personID) " - + "WHERE PS1.watchedPersonID=?" - ) - private StatementProvider sqlSelectBuddyIds; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT AC.acSID " - + "FROM ~g~.PersonAccessControl PAC " - + " INNER JOIN ~p~.AccessControl AC ON (PAC.acID=AC.acID) " - + "WHERE PAC.personID=?" - ) - private StatementProvider sqlSelectAcs; - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = "SELECT EPAC.eventID, AC.acSID " - + "FROM ~g~.EventPersonAccessControl EPAC " - + " INNER JOIN ~p~.AccessControl AC ON (EPAC.acID=AC.acID) " - + "WHERE EPAC.personID=?" - ) - private StatementProvider sqlSelectEventAcs; - - @Override - protected DataSet fetchOne(Long personId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectPerson.buildPreparedStatement(); - try { - fps.setIntegerU(1, personId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT GP.* FROM ~g~.Person GP WHERE GP.personID=?") - private StatementProvider sqlSelectPerson; - - @Override - protected Map fetchBulk(Collection personIds) throws SQLException { - FlexStatement fs = this.sqlSelectPersons.buildStatement(personIds); - try { - return fs.executeQuery().getAllRows("personID", Long.class); - } finally { - fs.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT GP.* FROM ~g~.Person GP WHERE GP.personID IN (??)") - private StatementProvider sqlSelectPersons; - -} diff --git a/src/main/java/com/poststats/golf/service/db/SeriesServiceDAO.java b/src/main/java/com/poststats/golf/service/db/SeriesServiceDAO.java deleted file mode 100644 index 653c97a..0000000 --- a/src/main/java/com/poststats/golf/service/db/SeriesServiceDAO.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.poststats.golf.service.db; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.Map; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.brianlong.util.FlexMap; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.SeriesService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.service.ServiceException; -import com.poststats.service.db.CacheableServiceDAO; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class SeriesServiceDAO extends CacheableServiceDAO implements SeriesService { - - private final long defaultCacheExpirationInSeconds = 3600; - - @Override - public FlexMap get(int seriesId) { - return this.get(Integer.valueOf(seriesId)); - } - - @Override - public DataSet getByEventId(long eventId) { - try { - FlexPreparedStatement fps = this.sqlSelectByEventId.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT * FROM ~g~.Series WHERE eventID=? ") - private StatementProvider sqlSelectByEventId; - - @Override - protected long getCacheExpirationInSeconds() { - return this.defaultCacheExpirationInSeconds; - } - - @Override - protected DataSet fetchOne(Integer seriesId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectSeries.buildPreparedStatement(); - try { - fps.setSmallintU(1, seriesId); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT S.* FROM ~g~.Series S WHERE seriesID=? ") - private StatementProvider sqlSelectSeries; - - @Override - protected Map fetchBulk(Collection seriesIds) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectSerieses.buildPreparedStatement(seriesIds); - try { - return fps.executeQuery().getAllRows("seriesID", Integer.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT S.* FROM ~g~.Series S WHERE seriesID IN (??) ") - private StatementProvider sqlSelectSerieses; - -} diff --git a/src/main/java/com/poststats/golf/service/model/PointHandicapIndex.java b/src/main/java/com/poststats/golf/service/model/PointHandicapIndex.java deleted file mode 100644 index bba2419..0000000 --- a/src/main/java/com/poststats/golf/service/model/PointHandicapIndex.java +++ /dev/null @@ -1,404 +0,0 @@ -package com.poststats.golf.service.model; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PointHandicapIndex implements Comparable { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - private final int pointIndexId; - - public PointHandicapIndex(int pointIndexId) { - this.pointIndexId = pointIndexId; - } - - public PointHandicapIndex(byte alby, byte eagle, byte birdie, byte par, byte bogey, byte bogey2, byte bogey3, - byte bogey4, byte bogey5) { - int pointIndexId = 0; - - if (bogey5 > 1) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 5); - pointIndexId += bogey5; - - if (bogey4 > 3 || bogey4 > 0 && bogey5 >= bogey4) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 4); - pointIndexId += bogey4; - - if (bogey3 > 3 || bogey3 > 0 && bogey4 >= bogey3) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 3); - pointIndexId += bogey3; - - if (bogey2 > 7 || bogey2 > 0 && bogey3 >= bogey2) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 2); - pointIndexId += bogey2; - - if (bogey > 7 || bogey > 0 && bogey2 >= bogey) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 1); - pointIndexId += bogey; - - if (par > 15 || par > 0 && bogey >= par) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 0); - pointIndexId += par; - - if (birdie > 15 || birdie > 0 && par >= birdie) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) -1); - pointIndexId += birdie; - - if (eagle > 31 || eagle > 0 && birdie >= eagle) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) -2); - pointIndexId += eagle; - - if (alby > 63 || alby > 0 && eagle >= alby) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) -3); - pointIndexId += alby; - - this.pointIndexId = pointIndexId; - } - - public PointHandicapIndex(int alby, int eagle, int birdie, int par, int bogey, int bogey2, int bogey3, int bogey4, - int bogey5) { - int pointIndexId = 0; - - if (bogey5 > 1) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 5); - pointIndexId += bogey5; - - if (bogey4 > 3 || bogey4 > 0 && bogey5 >= bogey4) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 4); - pointIndexId += bogey4; - - if (bogey3 > 3 || bogey3 > 0 && bogey4 >= bogey3) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 3); - pointIndexId += bogey3; - - if (bogey2 > 7 || bogey2 > 0 && bogey3 >= bogey2) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 2); - pointIndexId += bogey2; - - if (bogey > 7 || bogey > 0 && bogey2 >= bogey) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 1); - pointIndexId += bogey; - - if (par > 15 || par > 0 && bogey >= par) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) 0); - pointIndexId += par; - - if (birdie > 15 || birdie > 0 && par >= birdie) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) -1); - pointIndexId += birdie; - - if (eagle > 31 || eagle > 0 && birdie >= eagle) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) -2); - pointIndexId += eagle; - - if (alby > 63 || alby > 0 && eagle >= alby) - throw new IllegalArgumentException(); - pointIndexId <<= this.getBits((byte) -3); - pointIndexId += alby; - - this.pointIndexId = pointIndexId; - } - - public PointHandicapIndex(int[] scoresToPar) { - this(scoresToPar[7], scoresToPar[8], scoresToPar[9], scoresToPar[0], scoresToPar[1], scoresToPar[2], - scoresToPar[3], scoresToPar[4], scoresToPar[5]); - } - - public int getId() { - return this.pointIndexId; - } - - public byte getPointsWithScoreToPar(byte scoreToPar) { - int shift = this.getShift(scoreToPar); - int bits = this.getBits(scoreToPar); - int mask = ((1 << bits) - 1) << (shift - bits); - return (byte) ((this.pointIndexId & mask) >> (shift - bits)); - } - - public byte getQuintupleBogeyPoints() { - return this.getPointsWithScoreToPar((byte) 5); - } - - public byte getQuadrupleBogeyPoints() { - return this.getPointsWithScoreToPar((byte) 4); - } - - public byte getTripleBogeyPoints() { - return this.getPointsWithScoreToPar((byte) 3); - } - - public byte getDoubleBogeyPoints() { - return this.getPointsWithScoreToPar((byte) 2); - } - - public byte getBogeyPoints() { - return this.getPointsWithScoreToPar((byte) 1); - } - - public byte getParPoints() { - return this.getPointsWithScoreToPar((byte) 0); - } - - public byte getBirdiePoints() { - return this.getPointsWithScoreToPar((byte) -1); - } - - public byte getEaglePoints() { - return this.getPointsWithScoreToPar((byte) -2); - } - - public byte getAlbatrossPoints() { - return this.getPointsWithScoreToPar((byte) -3); - } - - private int getShift(byte scoreToPar) { - if (scoreToPar < -2) { - return 6; // 0-63 - } else switch (scoreToPar) { - case -2: - return 11; // 0-31 - case -1: - return 15; // 0-15 - case 0: - return 19; // 0-15 - case 1: - return 22; // 0-7 - case 2: - return 25; // 0-7 - case 3: - return 27; // 0-3 - case 4: - return 29; // 0-3 - case 5: - return 30; // 0-1 - default: - return 31; // 0 - } - } - - private int getBits(byte scoreToPar) { - if (scoreToPar < -2) { - return 6; // 0-63 - } else switch (scoreToPar) { - case -2: - return 5; // 0-31 - case -1: - return 4; // 0-15 - case 0: - return 4; // 0-15 - case 1: - return 3; // 0-7 - case 2: - return 3; // 0-7 - case 3: - return 2; // 0-3 - case 4: - return 2; // 0-3 - case 5: - return 1; // 0-1 - default: - return 0; // 0 - } - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PointHandicapIndex)) - return false; - return this.getId() == ((PointHandicapIndex) obj).getId(); - } - - @Override - public int hashCode() { - return this.getId(); - } - - @Override - public String toString() { - return new StringBuilder().append(this.getQuintupleBogeyPoints()).append('/') - .append(this.getQuadrupleBogeyPoints()).append('/').append(this.getTripleBogeyPoints()).append('/') - .append(this.getDoubleBogeyPoints()).append('/').append(this.getBogeyPoints()).append('/') - .append(this.getParPoints()).append('/').append(this.getBirdiePoints()).append('/') - .append(this.getEaglePoints()).append('/').append(this.getAlbatrossPoints()).toString(); - } - - @Override - public int compareTo(PointHandicapIndex o) { - float compare = this.diff(o); - if (Float.isNaN(compare)) { - return 0; - } else if (compare == 0f) { - return 0; - } else if (compare < 0f) { - return (int) Math.floor(compare); - } else { - return (int) Math.ceil(compare); - } - } - - private float diff(PointHandicapIndex o) { - if (this.getId() == o.getId()) - return 0f; - - boolean pos = false; - boolean neg = false; - - int compare = Byte.compare(this.getAlbatrossPoints(), o.getAlbatrossPoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - - compare = Byte.compare(this.getEaglePoints(), o.getEaglePoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - if (neg && pos) - return Float.NaN; - - compare = Byte.compare(this.getBirdiePoints(), o.getBirdiePoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - if (neg && pos) - return Float.NaN; - - compare = Byte.compare(this.getParPoints(), o.getParPoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - if (neg && pos) - return Float.NaN; - - compare = Byte.compare(this.getBogeyPoints(), o.getBogeyPoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - if (neg && pos) - return Float.NaN; - - compare = Byte.compare(this.getDoubleBogeyPoints(), o.getDoubleBogeyPoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - if (neg && pos) - return Float.NaN; - - compare = Byte.compare(this.getTripleBogeyPoints(), o.getTripleBogeyPoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - if (neg && pos) - return Float.NaN; - - compare = Byte.compare(this.getQuadrupleBogeyPoints(), o.getQuadrupleBogeyPoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - if (neg && pos) - return Float.NaN; - - compare = Byte.compare(this.getQuintupleBogeyPoints(), o.getQuintupleBogeyPoints()); - if (compare < 0) - neg = true; - else if (compare > 0) - pos = true; - - if (neg && pos) { - return Float.NaN; - } else if (neg) { - return -1; - } else if (pos) { - return 1; - } else { - this.logger.warn("This should never happen"); - return 0; - } - } - - public PointHandicapIndex decrement(byte scoreToPar) { - return this.minus(scoreToPar, (byte) 1); - } - - public PointHandicapIndex increment(byte scoreToPar) { - return this.plus(scoreToPar, (byte) 1); - } - - public PointHandicapIndex minus(byte scoreToPar, byte points) { - return this.plus(scoreToPar, (byte) -points); - } - - public PointHandicapIndex plus(byte scoreToPar, byte points) { - int shift = this.getShift(scoreToPar); - int bits = this.getBits(scoreToPar); - int mask = ((1 << bits) - 1) << (shift - bits); - int oldPointIndexMasked = this.pointIndexId & mask; - byte oldPoints = (byte) (oldPointIndexMasked >> (shift - bits)); - - if (points < 0) { - if (oldPoints == 0) - return this; - } else { - if (oldPoints + points >= this.getPointsWithScoreToPar((byte) (scoreToPar - 1))) - return this; - } - - if (oldPoints + points >= Math.pow(2, bits)) - throw new IllegalArgumentException(); - int pointIndexMasked = (oldPoints + points) << (shift - bits); - - return new PointHandicapIndex(this.pointIndexId - oldPointIndexMasked + pointIndexMasked); - } - - public PointHandicapIndex avg(PointHandicapIndex phi, int roundingBias) { - return new PointHandicapIndex( - this.computeAvg(this.getAlbatrossPoints(), phi.getAlbatrossPoints(), roundingBias), - this.computeAvg(this.getEaglePoints(), phi.getEaglePoints(), roundingBias), - this.computeAvg(this.getBirdiePoints(), phi.getBirdiePoints(), roundingBias), - this.computeAvg(this.getParPoints(), phi.getParPoints(), roundingBias), - this.computeAvg(this.getBogeyPoints(), phi.getBogeyPoints(), roundingBias), - this.computeAvg(this.getDoubleBogeyPoints(), phi.getDoubleBogeyPoints(), roundingBias), - this.computeAvg(this.getTripleBogeyPoints(), phi.getTripleBogeyPoints(), roundingBias), - this.computeAvg(this.getQuadrupleBogeyPoints(), phi.getQuadrupleBogeyPoints(), roundingBias), - this.computeAvg(this.getQuintupleBogeyPoints(), phi.getQuintupleBogeyPoints(), roundingBias)); - } - - private byte computeAvg(byte points1, byte points2, int roundingBias) { - if (points1 == points2) - return points1; - float avg = (points1 + points2) / 2f; - if (roundingBias == 0) { - return (byte) Math.round(avg); - } else if (roundingBias < 0) { - return (byte) Math.floor(avg); - } else { - return (byte) Math.ceil(avg); - } - } - -} diff --git a/src/main/java/com/poststats/golf/service/model/StrokeCourseRating.java b/src/main/java/com/poststats/golf/service/model/StrokeCourseRating.java deleted file mode 100644 index 65debbb..0000000 --- a/src/main/java/com/poststats/golf/service/model/StrokeCourseRating.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.poststats.golf.service.model; - -public class StrokeCourseRating { - - private final short slopeRating; - private final float courseRating; - - public StrokeCourseRating(short slopeRating, float courseRating) { - this.slopeRating = slopeRating; - this.courseRating = courseRating; - } - - public short getSlopeRating() { - return this.slopeRating; - } - - public float getCourseRating() { - return this.courseRating; - } - -} diff --git a/src/main/java/com/poststats/golf/service/telegram/TelegramEventService.java b/src/main/java/com/poststats/golf/service/telegram/TelegramEventService.java deleted file mode 100644 index 01b91be..0000000 --- a/src/main/java/com/poststats/golf/service/telegram/TelegramEventService.java +++ /dev/null @@ -1,380 +0,0 @@ -package com.poststats.golf.service.telegram; - -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.apache.http.client.HttpResponseException; -import org.slf4j.Logger; -import org.telegram.telegrambots.meta.api.methods.groupadministration.CreateChatInviteLink; -import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChat; -import org.telegram.telegrambots.meta.api.methods.send.SendMessage; -import org.telegram.telegrambots.meta.api.objects.Chat; -import org.telegram.telegrambots.meta.api.objects.ChatInviteLink; -import org.telegram.telegrambots.meta.api.objects.ChatMemberUpdated; -import org.telegram.telegrambots.meta.api.objects.Message; -import org.telegram.telegrambots.meta.api.objects.chatmember.ChatMemberAdministrator; -import org.telegram.telegrambots.meta.api.objects.chatmember.ChatMemberBanned; -import org.telegram.telegrambots.meta.api.objects.chatmember.ChatMemberLeft; -import org.telegram.telegrambots.meta.api.objects.chatmember.ChatMemberMember; - -import com.brianlong.sql.DataSet; -import com.brianlong.sql.FlexPreparedStatement; -import com.poststats.golf.provider.GolfProvider; -import com.poststats.golf.service.PersonService; -import com.poststats.provider.NonTransactionalProvider; -import com.poststats.provider.PostStatsProvider; -import com.poststats.provider.Statement; -import com.poststats.provider.StatementProvider; -import com.poststats.provider.TransactionalProvider; -import com.poststats.service.ConfigurationAccessor; -import com.poststats.service.ServiceException; -import com.poststats.service.TelegramChannelManager; -import com.poststats.service.TelegramChannelSubscriber; -import com.poststats.service.TelegramPushService; -import com.poststats.service.TelegramUpdateSubscriber.TelegramMessageReplier; -import com.poststats.service.model.TelegramCommand; -import com.poststats.transformer.JacksonObjectMapper; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; -import jakarta.transaction.Transactional.TxType; - -@ApplicationScoped -public class TelegramEventService implements TelegramChannelSubscriber, TelegramChannelManager { - - @Inject - private Logger logger; - - @Inject - private PersonService personService; - - @Inject - private JacksonObjectMapper om; - - @Inject - private ConfigurationAccessor config; - - @Inject - private TelegramPushService telegramService; - - private final List helpLines = Arrays.asList("`/event_sub {shared_secret}`", "`/event_unsub`"); - - @Override - public Collection getCommandLines() { - return this.helpLines; - } - - @Override - public void memberStatusReceived(ChatMemberUpdated member, TelegramMessageReplier replier) { - if (Boolean.TRUE.equals(member.getNewChatMember().getUser().getIsBot())) { - if (!"poststats_bot".equals(member.getNewChatMember().getUser().getUserName())) { - this.logger.debug("Ignoring unregulated bot: {}", member.getNewChatMember().getUser().getUserName()); - } else { - switch (member.getNewChatMember().getStatus()) { - case ChatMemberBanned.STATUS: - case ChatMemberLeft.STATUS: - this.unsetInDatabase(member.getChat().getId()); - break; - } - } - } else { - switch (member.getNewChatMember().getStatus()) { - case ChatMemberBanned.STATUS: - case ChatMemberLeft.STATUS: - this.setInChannelInDatabase(member.getNewChatMember().getUser().getId(), member.getChat().getId(), - false); - break; - case ChatMemberMember.STATUS: - case ChatMemberAdministrator.STATUS: - this.setInChannelInDatabase(member.getNewChatMember().getUser().getId(), member.getChat().getId(), - true); - break; - } - } - } - - @Override - public void messageReceived(Message message, TelegramMessageReplier replier) { - // ignore - } - - @Override - @Transactional(TxType.REQUIRED) - public boolean commandReceived(TelegramCommand command, TelegramMessageReplier replier) { - switch (command.getCommand()) { - case "event_sub": - if (command.getText() != null) { - if (this.setInDatabase(command.getUserId(), command.getChannelId(), command.getText())) { - replier.reply("You have successfully subscribed this channel to your PostStats Event!"); - } else { - replier.reply("The supplied shared secret or Event authority is not valid."); - } - return true; - } - break; - case "event_unsub": - if (this.unsetInDatabase(command.getUserId())) { - replier.reply( - "You have successfully unsubscribed this channel from PostStats Event communications."); - } else { - replier.reply( - "This channel was not and continue to not be subscribed to PostStats Event communications."); - } - return true; - case "start": - default: - } - - return false; - } - - @Override - public boolean addUserToChannel(Long eventId, long personId) { - try { - Long channelId = this.findEventChannelId(eventId); - if (channelId == null) { - this.logger.warn("The event is not linked to a Telegram channel"); - return false; - } - - Long userId = this.findPersonUserId(personId); - if (userId == null) { - this.logger.debug("An channel invite cannot be created for users without a linked Telegram account"); - return false; - } - - Chat chat = this.telegramService.callEndpoint(GetChat.builder().chatId(channelId).build()); - if (chat == null) { - this.logger.warn("The channel could not be found"); - return false; - } - - ChatInviteLink inviteLink = this.telegramService - .callEndpoint(CreateChatInviteLink.builder().chatId(channelId).build()); - if (inviteLink == null) - throw new ServiceException("An invite could not be created"); - - SendMessage sendMessage = SendMessage.builder().allowSendingWithoutReply(true).chatId(userId) - .text("You have been invited to join the " - + chat.getTitle() - + " channel: " - + inviteLink.getInviteLink()) - .build(); - this.telegramService.callEndpoint(sendMessage); - - return true; - } catch (HttpResponseException hre) { - throw new ServiceException(hre); - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public boolean removeUserFromChannel(Long eventId, long personId) { - try { - Long channelId = this.findEventChannelId(eventId); - if (channelId == null) - return false; - - Long userId = this.findPersonUserId(personId); - if (userId == null) { - this.logger.debug("An channel invite cannot be created for users without a linked Telegram account"); - return false; - } - - throw new UnsupportedOperationException(); - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Override - public boolean reconcileChannelMembers(Long poststatsId) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean reconcileChannels(long personId) { - throw new UnsupportedOperationException(); - } - - private boolean setInDatabase(long telegramUserId, long channelId, String sharedSecret) { - try { - DataSet row = this.querySharedSecretByCode(sharedSecret); - if (row == null) { - this.logger.debug("A shared secret was provided but not found: {}", sharedSecret); - return false; - } else if (row.isNotEmpty("eventID")) { - long eventId = row.getLong("eventID"); - if (!this.checkAuthority(telegramUserId, eventId)) - return false; - this.updateEvent(eventId, channelId); - this.deleteSharedSecret(row.getLong("sharedSecretId")); - } else { - this.logger.warn("A shared secret was shared by {} for something other than an 'event'", - telegramUserId); - return false; - } - - return true; - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - private DataSet querySharedSecretByCode(String sharedSecret) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectSharedSecret.buildPreparedStatement(); - try { - fps.setVarchar(1, sharedSecret); - return fps.executeQuery().getNextRow(); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @PostStatsProvider - @Statement(sql = "SELECT * FROM ~p~.SharedSecret WHERE sharedSecret=? AND expiration>NOW()") - private StatementProvider sqlSelectSharedSecret; - - private void deleteSharedSecret(long sharedSecretId) throws SQLException { - FlexPreparedStatement fps = this.sqlDeleteSharedSecret.buildPreparedStatement(); - try { - fps.setIntegerU(1, sharedSecretId); - fps.executeUpdate(); - } finally { - fps.close(); - } - } - - @Inject - @TransactionalProvider - @PostStatsProvider - @Statement(sql = "DELETE FROM ~p~.SharedSecret WHERE sharedSecretId=?") - private StatementProvider sqlDeleteSharedSecret; - - private boolean checkAuthority(long telegramUserId, long eventId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectAuthority.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - fps.setBigint(2, telegramUserId); - return fps.executeQuery().getOne(Integer.class) > 0; - } finally { - fps.close(); - } - } - - @Inject - @TransactionalProvider - @PostStatsProvider - @Statement( - sql = "SELECT COUNT(*) " - + "FROM ~g~.EventPersonAccessControl EPAC " - + " INNER JOIN ~p~.Person P ON (EPAC.personID=P.personID) " - + " INNER JOIN ~p~.AccessControl AC ON (EPAC.acID=AC.acID) " - + "WHERE EPAC.eventID=? AND P.telegramUserId=? AND AC.acSID IN ('admin', 'communicate')" - ) - private StatementProvider sqlSelectAuthority; - - private Long findEventChannelId(long eventId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEventChannel.buildPreparedStatement(); - try { - fps.setIntegerU(1, eventId); - return fps.executeQuery().getOne(Long.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement(sql = "SELECT telegramChannelId FROM ~g~.Event WHERE eventId=?") - private StatementProvider sqlSelectEventChannel; - - private Long findPersonUserId(long personId) throws SQLException { - FlexPreparedStatement fps = this.sqlSelectEventChannel.buildPreparedStatement(); - try { - fps.setIntegerU(1, personId); - return fps.executeQuery().getOne(Long.class); - } finally { - fps.close(); - } - } - - @Inject - @NonTransactionalProvider - @PostStatsProvider - @Statement(sql = "SELECT telegramUserId FROM ~p~.Person WHERE personId=?") - private StatementProvider sqlSelectPersonUser; - - private void updateEvent(long eventId, long telegramChannelId) throws SQLException { - FlexPreparedStatement fps = this.sqlUpdateEvent.buildPreparedStatement(); - try { - fps.setBigint(1, telegramChannelId); - fps.setIntegerU(2, eventId); - fps.executeUpdate(); - } finally { - fps.close(); - } - } - - @Inject - @TransactionalProvider - @GolfProvider - @Statement(sql = "UPDATE ~g~.Event SET telegramChannelId=? WHERE eventID=?") - private StatementProvider sqlUpdateEvent; - - private boolean unsetInDatabase(long telegramChannelId) { - try { - FlexPreparedStatement fps = this.sqlUpdateEventUnset.buildPreparedStatement(); - try { - fps.setBigint(1, telegramChannelId); - return fps.executeUpdate() > 0; - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @TransactionalProvider - @GolfProvider - @Statement(sql = "UPDATE ~g~.Event SET telegramChannelId=NULL WHERE telegramChannelId=?") - private StatementProvider sqlUpdateEventUnset; - - private boolean setInChannelInDatabase(long telegramUserId, long channelId, boolean in) { - try { - FlexPreparedStatement fps = this.sqlUpdateEventPersonSet.buildPreparedStatement(); - try { - fps.setBoolean(1, in); - fps.setBigint(2, channelId); - fps.setBigint(3, telegramUserId); - return fps.executeUpdate() > 0; - } finally { - fps.close(); - } - } catch (SQLException se) { - throw new ServiceException(se); - } - } - - @Inject - @TransactionalProvider - @GolfProvider - @Statement( - sql = "UPDATE ~g~.EventPerson " - + "SET inTelegramChannel=? " - + "WHERE eventID IN (SELECT eventID FROM ~g~.Event WHERE telegramChannelId=?) " - + " AND personID IN (SELECT personID FROM ~p~.Person WHERE telegramUserId=?) " - ) - private StatementProvider sqlUpdateEventPersonSet; - -} diff --git a/src/main/java/com/poststats/golf/servlet/AuthenticationFilter.java b/src/main/java/com/poststats/golf/servlet/AuthenticationFilter.java deleted file mode 100644 index 74854ec..0000000 --- a/src/main/java/com/poststats/golf/servlet/AuthenticationFilter.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.poststats.golf.servlet; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.poststats.golf.security.AuthenticatedSecurityContext; -import com.poststats.golf.service.PersonService; -import com.poststats.security.AuthenticatedPerson; - -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.Priorities; -import jakarta.ws.rs.container.ContainerRequestContext; -import jakarta.ws.rs.container.ContainerRequestFilter; -import jakarta.ws.rs.core.SecurityContext; -import jakarta.ws.rs.ext.Provider; - -@ApplicationScoped -@Provider -@Priority(Priorities.AUTHENTICATION + 5) -public class AuthenticationFilter implements ContainerRequestFilter { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Inject - private PersonService personService; - - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { - SecurityContext scontext = requestContext.getSecurityContext(); - if (scontext == null || scontext.getUserPrincipal() == null) - return; - - AuthenticatedPerson authPerson = (AuthenticatedPerson) scontext.getUserPrincipal(); - - this.logger.debug("Gathering roles for golf: {}", authPerson); - - com.poststats.golf.security.AuthenticatedPerson gauthPerson = this.personService.getUserPrincipal(authPerson); - - if (this.logger.isTraceEnabled()) - this.logger.trace("Authorized roles: {} => {}", gauthPerson.getId(), gauthPerson.getAllAccessControls()); - - scontext = new AuthenticatedSecurityContext(scontext, gauthPerson); - - requestContext.setSecurityContext(scontext); - } - -} diff --git a/src/main/java/com/poststats/golf/servlet/EventFilter.java b/src/main/java/com/poststats/golf/servlet/EventFilter.java deleted file mode 100644 index c02313c..0000000 --- a/src/main/java/com/poststats/golf/servlet/EventFilter.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.poststats.golf.servlet; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.brianlong.util.StringUtil; -import com.poststats.golf.api.Constants; -import com.poststats.golf.security.AuthenticatedPerson; -import com.poststats.golf.security.EventSecurityContext; - -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.ws.rs.Priorities; -import jakarta.ws.rs.container.ContainerRequestContext; -import jakarta.ws.rs.container.ContainerRequestFilter; -import jakarta.ws.rs.core.SecurityContext; -import jakarta.ws.rs.ext.Provider; - -@ApplicationScoped -@Provider -@Priority(Priorities.AUTHORIZATION - 5) -public class EventFilter implements ContainerRequestFilter { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { - String eventIdStr = requestContext.getUriInfo().getPathParameters().getFirst(Constants.EVENT_ID); - eventIdStr = StringUtil.getInstance().trim(eventIdStr); - - if (eventIdStr == null) { - eventIdStr = requestContext.getUriInfo().getQueryParameters().getFirst(Constants.EVENT_ID); - eventIdStr = StringUtil.getInstance().trim(eventIdStr); - } - - if (eventIdStr == null) - return; - - this.logger.debug("Entering event context: {}", eventIdStr); - - long eventId = Long.valueOf(eventIdStr); - requestContext.setProperty(Constants.EVENT_ID, eventId); - - SecurityContext scontext = requestContext.getSecurityContext(); - if (scontext.getUserPrincipal() == null) - return; - - this.logger.debug("Narrowing authorization for event: {} => {}", scontext.getUserPrincipal(), eventId); - - EventSecurityContext epscontext = new EventSecurityContext(scontext, eventId); - - if (this.logger.isTraceEnabled()) { - AuthenticatedPerson person = (AuthenticatedPerson) epscontext.getUserPrincipal(); - this.logger.trace("Authorized event roles: {} => {}", person.getId(), - person.getEventAccessControls(eventId)); - } - - requestContext.setSecurityContext(epscontext); - } - -} diff --git a/src/main/java/com/poststats/golf/servlet/PersonFilter.java b/src/main/java/com/poststats/golf/servlet/PersonFilter.java deleted file mode 100644 index 57f7de8..0000000 --- a/src/main/java/com/poststats/golf/servlet/PersonFilter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.poststats.golf.servlet; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.poststats.golf.api.Constants; -import com.poststats.golf.security.PersonSecurityContext; -import com.poststats.golf.service.PersonService; - -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.Priorities; -import jakarta.ws.rs.container.ContainerRequestContext; -import jakarta.ws.rs.container.ContainerRequestFilter; -import jakarta.ws.rs.core.SecurityContext; -import jakarta.ws.rs.ext.Provider; - -@ApplicationScoped -@Provider -@Priority(Priorities.AUTHORIZATION - 8) -public class PersonFilter implements ContainerRequestFilter { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Inject - private PersonService personService; - - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { - Long personId = (Long) requestContext.getProperty(Constants.PERSON_ID); - if (personId == null) - return; - - SecurityContext scontext = requestContext.getSecurityContext(); - if (scontext == null || scontext.getUserPrincipal() == null) - return; - - this.logger.debug("Entering golfer context: {}", personId); - - scontext = new PersonSecurityContext(scontext, personId); - requestContext.setSecurityContext(scontext); - } - -} diff --git a/src/main/java/com/poststats/golf/servlet/SeriesFilter.java b/src/main/java/com/poststats/golf/servlet/SeriesFilter.java deleted file mode 100644 index e3e144e..0000000 --- a/src/main/java/com/poststats/golf/servlet/SeriesFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.poststats.golf.servlet; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.brianlong.util.StringUtil; -import com.poststats.golf.api.Constants; - -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.ws.rs.Priorities; -import jakarta.ws.rs.container.ContainerRequestContext; -import jakarta.ws.rs.container.ContainerRequestFilter; -import jakarta.ws.rs.ext.Provider; - -@ApplicationScoped -@Provider -@Priority(Priorities.HEADER_DECORATOR + 10) -public class SeriesFilter implements ContainerRequestFilter { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { - String seriesIdStr = requestContext.getUriInfo().getPathParameters().getFirst(Constants.EVENT_SERIES_ID); - seriesIdStr = StringUtil.getInstance().trim(seriesIdStr); - - if (seriesIdStr == null) { - seriesIdStr = requestContext.getUriInfo().getQueryParameters().getFirst(Constants.EVENT_SERIES_ID); - seriesIdStr = StringUtil.getInstance().trim(seriesIdStr); - } - - if (seriesIdStr == null) - return; - - this.logger.debug("Entering series context: {}", seriesIdStr); - - int seriesId = Integer.valueOf(seriesIdStr); - requestContext.setProperty(Constants.EVENT_SERIES_ID, seriesId); - } - -} diff --git a/src/main/resources/META-INF/beans.xml b/src/main/resources/META-INF/beans.xml deleted file mode 100644 index a50c2f8..0000000 --- a/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/src/test/java/com/poststats/golf/service/compute/ComputeLegacyPointCourseRatingUnitTest.java b/src/test/java/com/poststats/golf/service/compute/ComputeLegacyPointCourseRatingUnitTest.java deleted file mode 100644 index cc75d89..0000000 --- a/src/test/java/com/poststats/golf/service/compute/ComputeLegacyPointCourseRatingUnitTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.poststats.golf.service.compute; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class ComputeLegacyPointCourseRatingUnitTest { - - private static LegacyPostStatsPointHandicapIndexService service; - - @BeforeAll - public static void stage() { - service = new LegacyPostStatsPointHandicapIndexService(); - } - - @Test - public void cypressLandingGold() { - Assertions.assertEquals(-4f, service.computeRatingIndex((short) 117, 66.8f, 'M', (short) 5473, (byte) 72), 1f); - } - - @Test - public void cypressLandingWhite() { - Assertions.assertEquals(12f, service.computeRatingIndex((short) 127, 69.7f, 'M', (short) 6124, (byte) 72), 1f); - } - - @Test - public void cypressLandingBlue() { - Assertions.assertEquals(19f, service.computeRatingIndex((short) 131, 71.1f, 'M', (short) 6442, (byte) 72), 1f); - } - -} diff --git a/src/test/java/com/poststats/golf/service/compute/ComputePointCourseRatingUnitTest.java b/src/test/java/com/poststats/golf/service/compute/ComputePointCourseRatingUnitTest.java deleted file mode 100644 index d9e7764..0000000 --- a/src/test/java/com/poststats/golf/service/compute/ComputePointCourseRatingUnitTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.poststats.golf.service.compute; - -import java.util.Arrays; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import com.brianlong.util.FlexMap; - -public class ComputePointCourseRatingUnitTest { - - private static PostStatsPointHandicapIndexService service; - - @BeforeAll - public static void stage() { - service = new PostStatsPointHandicapIndexService(); - } - - @Test - public void cypressLandingGold() { - Assertions.assertEquals(-25f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 72, 66.8f), - Arrays.asList(this.mockHole(301, 4), this.mockHole(295, 4), this.mockHole(136, 3), - this.mockHole(297, 4), this.mockHole(460, 5), this.mockHole(349, 4), this.mockHole(140, 3), - this.mockHole(492, 5), this.mockHole(323, 4), this.mockHole(314, 4), this.mockHole(118, 3), - this.mockHole(461, 5), this.mockHole(301, 4), this.mockHole(351, 4), this.mockHole(113, 3), - this.mockHole(279, 4), this.mockHole(450, 5), this.mockHole(293, 4))), - 1f); - } - - @Test - public void cypressLandingWhite() { - Assertions.assertEquals(5f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 72, 69.7f), - Arrays.asList(this.mockHole(345, 4), this.mockHole(316, 4), this.mockHole(136, 3), - this.mockHole(371, 4), this.mockHole(503, 5), this.mockHole(404, 4), this.mockHole(184, 3), - this.mockHole(501, 5), this.mockHole(348, 4), this.mockHole(341, 4), this.mockHole(166, 3), - this.mockHole(532, 5), this.mockHole(318, 4), this.mockHole(385, 4), this.mockHole(129, 3), - this.mockHole(303, 4), this.mockHole(489, 5), this.mockHole(353, 4))), - 1f); - } - - @Test - public void cypressLandingBlue() { - Assertions.assertEquals(22f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 72, 71.1f), - Arrays.asList(this.mockHole(373, 4), this.mockHole(316, 4), this.mockHole(166, 3), - this.mockHole(389, 4), this.mockHole(520, 5), this.mockHole(412, 4), this.mockHole(203, 3), - this.mockHole(520, 5), this.mockHole(366, 4), this.mockHole(374, 4), this.mockHole(185, 3), - this.mockHole(554, 5), this.mockHole(319, 4), this.mockHole(406, 4), this.mockHole(144, 3), - this.mockHole(318, 4), this.mockHole(489, 5), this.mockHole(388, 4))), - 1f); - } - - @Test - public void heronGlenBlue() { - Assertions.assertEquals(26f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 72, 71.7f), - Arrays.asList(this.mockHole(395, 4), this.mockHole(581, 5), this.mockHole(424, 4), - this.mockHole(361, 4), this.mockHole(179, 3), this.mockHole(371, 4), this.mockHole(146, 3), - this.mockHole(512, 5), this.mockHole(378, 4), this.mockHole(545, 5), this.mockHole(308, 4), - this.mockHole(155, 3), this.mockHole(514, 5), this.mockHole(378, 4), this.mockHole(204, 3), - this.mockHole(473, 5), this.mockHole(158, 3), this.mockHole(449, 4))), - 1f); - } - - @Test - public void metamoreFieldsBlue() { - Assertions.assertEquals(17f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 71, 70f), - Arrays.asList(this.mockHole(388, 4), this.mockHole(121, 3), this.mockHole(523, 5), - this.mockHole(326, 4), this.mockHole(170, 3), this.mockHole(526, 5), this.mockHole(338, 4), - this.mockHole(181, 3), this.mockHole(427, 4), this.mockHole(392, 4), this.mockHole(152, 3), - this.mockHole(485, 5), this.mockHole(344, 4), this.mockHole(164, 3), this.mockHole(385, 4), - this.mockHole(504, 5), this.mockHole(382, 4), this.mockHole(401, 4))), - 1f); - } - - @Test - public void pinonHillsBlue() { - Assertions.assertEquals(35f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 72, 71.7f), - Arrays.asList(this.mockHole(387, 4), this.mockHole(398, 4), this.mockHole(412, 4), - this.mockHole(178, 3), this.mockHole(331, 4), this.mockHole(198, 3), this.mockHole(395, 4), - this.mockHole(537, 5), this.mockHole(572, 5), this.mockHole(404, 4), this.mockHole(397, 4), - this.mockHole(200, 3), this.mockHole(505, 5), this.mockHole(321, 4), this.mockHole(140, 3), - this.mockHole(405, 4), this.mockHole(520, 5), this.mockHole(446, 4))), - 1f); - } - - @Test - public void worthingtonHillsBlue() { - Assertions.assertEquals(48f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 71, 72.7f), - Arrays.asList(this.mockHole(419, 4), this.mockHole(388, 4), this.mockHole(187, 3), - this.mockHole(520, 5), this.mockHole(420, 4), this.mockHole(560, 5), this.mockHole(200, 3), - this.mockHole(351, 4), this.mockHole(430, 4), this.mockHole(441, 4), this.mockHole(345, 4), - this.mockHole(192, 3), this.mockHole(365, 4), this.mockHole(398, 4), this.mockHole(172, 3), - this.mockHole(448, 4), this.mockHole(364, 4), this.mockHole(521, 5))), - 1f); - } - - @Test - public void darbyCreekBlue() { - Assertions.assertEquals(34f, service.computeRatingIndex(this.mockEighteenTeeRating('M', (byte) 72, 72.2f), - Arrays.asList(this.mockHole(350, 4), this.mockHole(374, 4), this.mockHole(169, 3), - this.mockHole(529, 5), this.mockHole(339, 4), this.mockHole(486, 5), this.mockHole(144, 3), - this.mockHole(418, 4), this.mockHole(438, 4), this.mockHole(309, 4), this.mockHole(168, 3), - this.mockHole(411, 4), this.mockHole(435, 4), this.mockHole(492, 5), this.mockHole(419, 4), - this.mockHole(188, 3), this.mockHole(540, 5), this.mockHole(452, 4))), - 1f); - } - - private FlexMap mockEighteenTeeRating(char gender, int par, float courseRating) { - FlexMap map = new FlexMap(); - map.put("etratingID", 0L); - map.put("gender", String.valueOf(gender)); - map.put("par", (byte) par); - map.put("courseRating", courseRating); - return map; - } - - private FlexMap mockHole(int yards, int par) { - FlexMap map = new FlexMap(); - map.put("yards", (short) yards); - map.put("par", (byte) par); - return map; - } - -} diff --git a/src/test/java/com/poststats/golf/service/compute/ComputePointHandicapIndexUnitTest.java b/src/test/java/com/poststats/golf/service/compute/ComputePointHandicapIndexUnitTest.java deleted file mode 100644 index dc8ca50..0000000 --- a/src/test/java/com/poststats/golf/service/compute/ComputePointHandicapIndexUnitTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.poststats.golf.service.compute; - -import java.util.Arrays; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.service.model.PointHandicapIndex; - -public class ComputePointHandicapIndexUnitTest { - - private static PostStatsPointHandicapIndexService service; - - @BeforeAll - public static void stage() { - service = new PostStatsPointHandicapIndexService(); - } - - @Test - public void brian() { - PointHandicapIndex phi = service.compute(Arrays.asList(this.mockRound(0, 22, 0, 0, 1, 5, 5, 6, 1, 0, 0), - this.mockRound(0, 22, 0, 1, 2, 5, 6, 4, 0, 0, 0), this.mockRound(0, 22, 0, 0, 1, 3, 7, 7, 0, 0, 0), - this.mockRound(0, 22, 0, 2, 2, 4, 8, 1, 1, 0, 0), this.mockRound(1, 26, 0, 0, 1, 5, 5, 6, 1, 0, 0), - this.mockRound(2, 17, 0, 1, 0, 4, 7, 6, 0, 0, 0), this.mockRound(2, 17, 0, 1, 2, 4, 5, 6, 0, 0, 0), - this.mockRound(2, 17, 0, 2, 0, 2, 7, 6, 1, 0, 0), this.mockRound(2, 17, 1, 0, 0, 3, 4, 8, 2, 0, 0), - this.mockRound(3, 35, 0, 3, 2, 2, 6, 4, 1, 0, 0), this.mockRound(3, 35, 0, 0, 1, 5, 4, 8, 0, 0, 0), - this.mockRound(3, 35, 1, 1, 3, 3, 3, 6, 1, 0, 0), this.mockRound(3, 35, 0, 2, 2, 5, 5, 4, 0, 0, 0))); - System.out.println(phi); - } - - @Test - public void ridgeway() { - PointHandicapIndex phi = service.compute(Arrays.asList(this.mockRound(0, 22, 0, 0, 0, 0, 7, 9, 2, 0, 0), - this.mockRound(0, 22, 0, 0, 0, 4, 5, 7, 2, 0, 0), this.mockRound(0, 22, 0, 0, 0, 0, 5, 11, 2, 0, 0), - this.mockRound(1, 48, 0, 0, 0, 2, 5, 9, 2, 0, 0), this.mockRound(2, 34, 0, 0, 0, 1, 3, 8, 6, 0, 0), - this.mockRound(1, 48, 0, 0, 0, 1, 4, 11, 2, 0, 0), this.mockRound(2, 34, 0, 0, 0, 1, 2, 12, 3, 0, 0), - this.mockRound(2, 34, 0, 0, 0, 2, 4, 8, 4, 0, 0), this.mockRound(3, 17, 0, 0, 0, 0, 4, 10, 4, 0, 0), - this.mockRound(3, 17, 0, 0, 0, 0, 3, 11, 4, 0, 0), this.mockRound(3, 17, 0, 0, 0, 0, 5, 10, 3, 0, 0))); - System.out.println(phi); - } - - private FlexMap mockRound(int courseId, int pointAdj, int... scoreToParCounts) { - FlexMap map = new FlexMap(); - map.put("courseID", courseId); - map.put("pointAdj", (byte) pointAdj); - map.put("bogey5", (byte) scoreToParCounts[0]); - map.put("bogey4", (byte) scoreToParCounts[1]); - map.put("bogey3", (byte) scoreToParCounts[2]); - map.put("bogey2", (byte) scoreToParCounts[3]); - map.put("bogey", (byte) scoreToParCounts[4]); - map.put("par", (byte) scoreToParCounts[5]); - map.put("birdie", (byte) scoreToParCounts[6]); - map.put("eagle", (byte) scoreToParCounts[7]); - map.put("alby", (byte) scoreToParCounts[8]); - return map; - } - -} diff --git a/src/test/java/com/poststats/golf/service/model/PointHandicapIndexUnitTest.java b/src/test/java/com/poststats/golf/service/model/PointHandicapIndexUnitTest.java deleted file mode 100644 index 597ec3e..0000000 --- a/src/test/java/com/poststats/golf/service/model/PointHandicapIndexUnitTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.poststats.golf.service.model; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class PointHandicapIndexUnitTest { - - @Test - public void zero() { - PointHandicapIndex phi = new PointHandicapIndex(0, 0, 0, 0, 0, 0, 0, 0, 0); - Assertions.assertEquals(0, phi.getId()); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) -10)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) -3)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 5)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 10)); - } - - @Test - public void alby1() { - PointHandicapIndex phi = new PointHandicapIndex(1, 0, 0, 0, 0, 0, 0, 0, 0); - Assertions.assertEquals(1, phi.getPointsWithScoreToPar((byte) -3)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) -2)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 5)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 10)); - } - - @Test - public void alby2eagle1() { - PointHandicapIndex phi = new PointHandicapIndex(2, 1, 0, 0, 0, 0, 0, 0, 0); - Assertions.assertEquals(2, phi.getPointsWithScoreToPar((byte) -3)); - Assertions.assertEquals(1, phi.getPointsWithScoreToPar((byte) -2)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) -1)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 5)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 10)); - } - - @Test - public void typicalScratch() { - PointHandicapIndex phi = new PointHandicapIndex(25, 14, 9, 2, 0, 0, 0, 0, 0); - Assertions.assertEquals(25, phi.getPointsWithScoreToPar((byte) -3)); - Assertions.assertEquals(14, phi.getPointsWithScoreToPar((byte) -2)); - Assertions.assertEquals(9, phi.getPointsWithScoreToPar((byte) -1)); - Assertions.assertEquals(2, phi.getPointsWithScoreToPar((byte) 0)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 1)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 5)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 10)); - } - - @Test - public void typicalBogey() { - PointHandicapIndex phi = new PointHandicapIndex(25, 16, 7, 4, 2, 1, 0, 0, 0); - Assertions.assertEquals(25, phi.getPointsWithScoreToPar((byte) -3)); - Assertions.assertEquals(16, phi.getPointsWithScoreToPar((byte) -2)); - Assertions.assertEquals(7, phi.getPointsWithScoreToPar((byte) -1)); - Assertions.assertEquals(4, phi.getPointsWithScoreToPar((byte) 0)); - Assertions.assertEquals(2, phi.getPointsWithScoreToPar((byte) 1)); - Assertions.assertEquals(1, phi.getPointsWithScoreToPar((byte) 2)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 4)); - } - - @Test - public void typicalBad() { - PointHandicapIndex phi = new PointHandicapIndex(40, 18, 10, 6, 4, 3, 1, 0, 0); - Assertions.assertEquals(40, phi.getPointsWithScoreToPar((byte) -3)); - Assertions.assertEquals(18, phi.getPointsWithScoreToPar((byte) -2)); - Assertions.assertEquals(10, phi.getPointsWithScoreToPar((byte) -1)); - Assertions.assertEquals(6, phi.getPointsWithScoreToPar((byte) 0)); - Assertions.assertEquals(4, phi.getPointsWithScoreToPar((byte) 1)); - Assertions.assertEquals(3, phi.getPointsWithScoreToPar((byte) 2)); - Assertions.assertEquals(1, phi.getPointsWithScoreToPar((byte) 3)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 4)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 5)); - Assertions.assertEquals(0, phi.getPointsWithScoreToPar((byte) 10)); - } - - @Test - public void plusBogey() { - PointHandicapIndex basephi = new PointHandicapIndex(40, 18, 10, 6, 4, 3, 1, 0, 0); - PointHandicapIndex phi = basephi.plus((byte) 1, (byte) 1); - Assertions.assertEquals(5, phi.getPointsWithScoreToPar((byte) 1)); - } - - @Test - public void plus2Birdie() { - PointHandicapIndex basephi = new PointHandicapIndex(40, 18, 10, 6, 4, 3, 1, 0, 0); - PointHandicapIndex phi = basephi.plus((byte) -1, (byte) 2); - Assertions.assertEquals(12, phi.getPointsWithScoreToPar((byte) -1)); - } - -} diff --git a/src/test/resources/log4j2.properties b/src/test/resources/log4j2.properties deleted file mode 100644 index 490c375..0000000 --- a/src/test/resources/log4j2.properties +++ /dev/null @@ -1,19 +0,0 @@ -rootLogger.level = debug -rootLogger.appenderRef.stdout.ref = api - -appender.rolling.type = RollingFile -appender.rolling.name = api -appender.rolling.fileName = ${catalina.base}/logs/api.log -appender.rolling.filePattern = ${catalina.base}/logs/api-%d{MM-dd-yyyy}.log.gz -appender.rolling.layout.type = PatternLayout -appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n -appender.rolling.policies.type = Policies -appender.rolling.policies.time.type = TimeBasedTriggeringPolicy -appender.rolling.strategy.type = DefaultRolloverStrategy -appender.rolling.strategy.max = 10 - -logger.brianlong.name = com.brianlong -logger.brianlong.level = debug - -logger.poststats.name = com.poststats -logger.poststats.level = debug diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml new file mode 100644 index 0000000..cd75c77 --- /dev/null +++ b/src/test/resources/log4j2.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + +