diff --git a/src/main/java/com/poststats/golf/api/CourseApi.java b/src/main/java/com/poststats/golf/api/CourseApi.java index 4ad6689..afb58cc 100644 --- a/src/main/java/com/poststats/golf/api/CourseApi.java +++ b/src/main/java/com/poststats/golf/api/CourseApi.java @@ -30,7 +30,7 @@ public interface CourseApi { description = "Retreives name, location, and other direct meta-data about the specified course." ) public abstract Course get(@Parameter(description = "A unique identifier for a golf course") - @NotNull @Positive @PathParam("courseId") int courseId); + @NotNull @Positive @PathParam("courseId") int courseId); @GET @Path("/nine/byName/{name}") @@ -40,8 +40,7 @@ public interface CourseApi { description = "Retreives name, location, and other direct meta-data about the specified course." ) public abstract CourseNine getNine(@Parameter(description = "A unique identifier for a golf course") - @NotNull @Positive @PathParam("courseId") int courseId, - @PathParam("name") String name); + @NotNull @Positive @PathParam("courseId") int courseId, @PathParam("name") String name); @GET @Path("/nine/{nineId:[0-9]+}") @@ -51,7 +50,6 @@ public interface CourseApi { description = "Retreives name, location, and other direct meta-data about the specified course." ) public abstract CourseNine getNine(@Parameter(description = "A unique identifier for a golf course") - @NotNull @Positive @PathParam("courseId") int courseId, - @PathParam("nineId") long courseNineId); + @NotNull @Positive @PathParam("courseId") int courseId, @PathParam("nineId") long courseNineId); } diff --git a/src/main/java/com/poststats/golf/api/EventApi.java b/src/main/java/com/poststats/golf/api/EventApi.java index 61549ed..4543a2b 100644 --- a/src/main/java/com/poststats/golf/api/EventApi.java +++ b/src/main/java/com/poststats/golf/api/EventApi.java @@ -33,7 +33,8 @@ public interface EventApi { @ApiResponse(responseCode = "200", description = "Success"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - Event get(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + Event get(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/detail") @@ -46,7 +47,8 @@ public interface EventApi { @ApiResponse(responseCode = "200", description = "Success"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - Event getDetail(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + Event getDetail(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @POST @Path("/document/{documentId}/send") @@ -66,8 +68,11 @@ public interface EventApi { description = "An event or document with the specified ID could not be found" ) }) - void sendDocument(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @Parameter(description = "A unique identifier for an event document") @NotNull @Positive @PathParam("documentId") long documentId); + void sendDocument( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, + @Parameter(description = "A unique identifier for an event document") + @NotNull @Positive @PathParam("documentId") long documentId); @POST @Path("/document/{documentId}/sendTest/{personId}") @@ -87,8 +92,12 @@ public interface EventApi { description = "An event, document, or person with the specified ID could not be found" ) }) - void sendTestDocument(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @Parameter(description = "A unique identifier for an event document") @NotNull @Positive @PathParam("documentId") long documentId, - @Parameter(description = "A unique identifier for a person") @NotNull @Positive @PathParam("personId") long personId); + void sendTestDocument( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, + @Parameter(description = "A unique identifier for an event document") + @NotNull @Positive @PathParam("documentId") long documentId, + @Parameter(description = "A unique identifier for a person") + @NotNull @Positive @PathParam("personId") long personId); } diff --git a/src/main/java/com/poststats/golf/api/EventFinanceApi.java b/src/main/java/com/poststats/golf/api/EventFinanceApi.java index 55d11a4..1f71694 100644 --- a/src/main/java/com/poststats/golf/api/EventFinanceApi.java +++ b/src/main/java/com/poststats/golf/api/EventFinanceApi.java @@ -38,8 +38,9 @@ public interface EventFinanceApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - List> getBalanceByPersonsAsJson(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @QueryParam("minBalance") Float minBalance, + List> getBalanceByPersonsAsJson( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, @QueryParam("minBalance") Float minBalance, @QueryParam("maxBalance") Float maxBalance); @GET @@ -57,7 +58,8 @@ public interface EventFinanceApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - StreamingOutput getBalanceByPersonsAsCsv(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + StreamingOutput getBalanceByPersonsAsCsv(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/balance/person/{personId}") @@ -77,8 +79,11 @@ public interface EventFinanceApi { description = "An event or person with the specified IDs could not be found" ) }) - Map getBalanceByPersonsAsJson(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @Parameter(description = "A unique identifier for a person") @NotNull @Positive @PathParam("personId") long personId); + Map getBalanceByPersonsAsJson( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, + @Parameter(description = "A unique identifier for a person") + @NotNull @Positive @PathParam("personId") long personId); @GET @Path("/series/balance/persons") @@ -95,6 +100,8 @@ public interface EventFinanceApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - List> getSeriesBalanceByPersonsAsJson(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + List> getSeriesBalanceByPersonsAsJson( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); } diff --git a/src/main/java/com/poststats/golf/api/EventPersonApi.java b/src/main/java/com/poststats/golf/api/EventPersonApi.java index eaebf38..0acce48 100644 --- a/src/main/java/com/poststats/golf/api/EventPersonApi.java +++ b/src/main/java/com/poststats/golf/api/EventPersonApi.java @@ -23,7 +23,7 @@ import jakarta.ws.rs.core.StreamingOutput; @Path("/golf/event/{eventId}") @Tag(name = "Event Participant API") public interface EventPersonApi { - + @GET @Path("/people") @RolesAllowed( @@ -39,7 +39,8 @@ public interface EventPersonApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - List get(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + List get(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/people/detail") @@ -56,7 +57,8 @@ public interface EventPersonApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - List getDetail(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + List getDetail(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/people/csv") @@ -73,7 +75,8 @@ public interface EventPersonApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - StreamingOutput getAsCsv(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + StreamingOutput getAsCsv(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/participants") @@ -83,7 +86,8 @@ public interface EventPersonApi { @ApiResponse(responseCode = "200", description = "Success"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - List getParticipants(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + List getParticipants(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/participants/csv") @@ -100,7 +104,8 @@ public interface EventPersonApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - StreamingOutput getParticipantsAsCsv(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + StreamingOutput getParticipantsAsCsv(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/series/participants") @@ -117,6 +122,7 @@ public interface EventPersonApi { @ApiResponse(responseCode = "403", description = "Authenticated, but not permitted"), @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") }) - Set getSeriesParticipants(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + Set getSeriesParticipants(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); } diff --git a/src/main/java/com/poststats/golf/api/EventRoundApi.java b/src/main/java/com/poststats/golf/api/EventRoundApi.java index 53d5041..b92818f 100644 --- a/src/main/java/com/poststats/golf/api/EventRoundApi.java +++ b/src/main/java/com/poststats/golf/api/EventRoundApi.java @@ -43,7 +43,8 @@ public interface EventRoundApi { description = "An event with the specified ID or upcoming event rounds could not be found" ) }) - List getNext(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + List getNext(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/round/{eroundId:[0-9]+}") @@ -59,8 +60,11 @@ public interface EventRoundApi { description = "An event or event round with the specified ID could not be found" ) }) - EventRound getOne(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @Parameter(description = "A unique identifier for an event round") @NotNull @Positive @PathParam("eroundId") long eroundId); + EventRound getOne( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, + @Parameter(description = "A unique identifier for an event round") + @NotNull @Positive @PathParam("eroundId") long eroundId); @GET @Path("/rounds") @@ -76,7 +80,8 @@ public interface EventRoundApi { description = "An event with the specified ID or any event rounds could not be found" ) }) - List getAll(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId); + List getAll(@Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId); @GET @Path("/round/{eroundId:[0-9]+}/pairings") @@ -89,8 +94,11 @@ public interface EventRoundApi { description = "An event or its round with the specified ID could not be found" ) }) - List getPairings(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @Parameter(description = "A unique identifier for an event round") @NotNull @Positive @PathParam("eroundId") long eroundId); + List getPairings( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, + @Parameter(description = "A unique identifier for an event round") + @NotNull @Positive @PathParam("eroundId") long eroundId); @GET @Path("/round/{eroundId:[0-9]+}/pairings/csv") @@ -103,8 +111,11 @@ public interface EventRoundApi { description = "An event or its round with the specified ID could not be found" ) }) - StreamingOutput getPairingsAsCsv(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @Parameter(description = "A unique identifier for an event round") @NotNull @Positive @PathParam("eroundId") long eroundId, + StreamingOutput getPairingsAsCsv( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, + @Parameter(description = "A unique identifier for an event round") + @NotNull @Positive @PathParam("eroundId") long eroundId, @QueryParam("orderBy") List orderBys, @QueryParam("lastNameFirst") boolean lastNameFirst); @@ -119,8 +130,10 @@ public interface EventRoundApi { description = "An event with the specified ID or upcoming event rounds could not be found" ) }) - EventRoundPairing getPairing(@Parameter(description = "A unique identifier for an event") @NotNull @Positive @PathParam("eventId") long eventId, - @Parameter(description = "A unique identifier for an event round") @NotNull @Positive @PathParam("eroundId") long eroundId, - @PathParam("pairingID") BigInteger pairingId); + EventRoundPairing getPairing( + @Parameter(description = "A unique identifier for an event") + @NotNull @Positive @PathParam("eventId") long eventId, + @Parameter(description = "A unique identifier for an event round") + @NotNull @Positive @PathParam("eroundId") long eroundId, @PathParam("pairingID") BigInteger pairingId); } diff --git a/src/main/java/com/poststats/golf/api/impl/EventApi.java b/src/main/java/com/poststats/golf/api/impl/EventApi.java index e03297c..edc11e3 100644 --- a/src/main/java/com/poststats/golf/api/impl/EventApi.java +++ b/src/main/java/com/poststats/golf/api/impl/EventApi.java @@ -62,8 +62,6 @@ public class EventApi implements com.poststats.golf.api.EventApi { 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); } diff --git a/src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java b/src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java index bb2c5b4..cf4b44d 100644 --- a/src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java +++ b/src/main/java/com/poststats/golf/api/impl/EventFinanceApi.java @@ -86,8 +86,7 @@ public class EventFinanceApi implements com.poststats.golf.api.EventFinanceApi { @Override public List> getSeriesBalanceByPersonsAsJson(long eventId) { - Map personsBalances = this.eventFinanceService - .getSeriesPersonsPreviousBalances(eventId); + Map personsBalances = this.eventFinanceService.getSeriesPersonsPreviousBalances(eventId); List> personsBalancesJson = new ArrayList<>(personsBalances.size()); for (DataSet personBalance : personsBalances.values()) { diff --git a/src/main/java/com/poststats/golf/service/CourseRatingService.java b/src/main/java/com/poststats/golf/service/CourseRatingService.java index 3b91f37..7e07536 100644 --- a/src/main/java/com/poststats/golf/service/CourseRatingService.java +++ b/src/main/java/com/poststats/golf/service/CourseRatingService.java @@ -1,11 +1,33 @@ package com.poststats.golf.service; -import com.brianlong.util.FlexMap; +public interface CourseRatingService { -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); - FlexMap getNineTeeRating(long ntratingId); - - FlexMap getEighteenTeeRating(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/HandicapIndexService.java b/src/main/java/com/poststats/golf/service/HandicapIndexService.java index c95cbba..0fe03a9 100644 --- a/src/main/java/com/poststats/golf/service/HandicapIndexService.java +++ b/src/main/java/com/poststats/golf/service/HandicapIndexService.java @@ -2,7 +2,7 @@ package com.poststats.golf.service; import java.time.LocalDate; -public interface HandicapIndexService { +public interface HandicapIndexService { /** * This method computes a golfer's handicap index as of today, inclusive. @@ -32,32 +32,4 @@ public interface HandicapIndexService { */ I computeGolferIndex(long personId, LocalDate beforeDay); - /** - * 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/HandicapScoreService.java b/src/main/java/com/poststats/golf/service/HandicapScoreService.java new file mode 100755 index 0000000..61800d8 --- /dev/null +++ b/src/main/java/com/poststats/golf/service/HandicapScoreService.java @@ -0,0 +1,37 @@ +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 index 1a7cb1e..ed43e28 100644 --- a/src/main/java/com/poststats/golf/service/PersonRoundService.java +++ b/src/main/java/com/poststats/golf/service/PersonRoundService.java @@ -1,5 +1,6 @@ package com.poststats.golf.service; +import java.math.BigInteger; import java.time.LocalDate; import java.util.List; @@ -11,6 +12,48 @@ public interface PersonRoundService { 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. * diff --git a/src/main/java/com/poststats/golf/service/compute/AbstractHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/AbstractHandicappingService.java similarity index 78% rename from src/main/java/com/poststats/golf/service/compute/AbstractHandicapIndexService.java rename to src/main/java/com/poststats/golf/service/compute/AbstractHandicappingService.java index da944d4..448f1d9 100644 --- a/src/main/java/com/poststats/golf/service/compute/AbstractHandicapIndexService.java +++ b/src/main/java/com/poststats/golf/service/compute/AbstractHandicappingService.java @@ -4,17 +4,19 @@ 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 AbstractHandicapIndexService implements HandicapIndexService { +public abstract class AbstractHandicappingService implements HandicapIndexService, CourseRatingService, HandicapScoreService { @Inject - private PersonRoundService personRoundService; + protected PersonRoundService personRoundService; protected short getMinimumRounds() { return 1; diff --git a/src/main/java/com/poststats/golf/service/compute/AbstractPointHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/AbstractPointHandicappingService.java similarity index 95% rename from src/main/java/com/poststats/golf/service/compute/AbstractPointHandicapIndexService.java rename to src/main/java/com/poststats/golf/service/compute/AbstractPointHandicappingService.java index 6ab5f29..1b3fd06 100644 --- a/src/main/java/com/poststats/golf/service/compute/AbstractPointHandicapIndexService.java +++ b/src/main/java/com/poststats/golf/service/compute/AbstractPointHandicappingService.java @@ -1,5 +1,6 @@ package com.poststats.golf.service.compute; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -16,7 +17,7 @@ import com.brianlong.util.MapUtil; import com.poststats.golf.service.PersonRoundService.Selection; import com.poststats.golf.service.model.PointHandicapIndex; -public abstract class AbstractPointHandicapIndexService extends AbstractHandicapIndexService { +public abstract class AbstractPointHandicappingService extends AbstractHandicappingService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -128,6 +129,22 @@ public abstract class AbstractPointHandicapIndexService extends AbstractHandicap // 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, diff --git a/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicapIndexService.java deleted file mode 100644 index 2249024..0000000 --- a/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicapIndexService.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.poststats.golf.service.compute; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import com.brianlong.util.FlexMap; -import com.poststats.golf.service.PersonRoundService.Selection; -import com.poststats.golf.service.model.StrokeCourseRating; - -public abstract class AbstractStrokeHandicapIndexService - extends AbstractHandicapIndexService { - - private final Comparator roundComparator; - - public AbstractStrokeHandicapIndexService() { - 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(); - - @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; - } - - @Override - public StrokeCourseRating computeEighteenTeeRatingIndex(long etratingId) { - // TODO call WHS service for the information - return null; - } - - @Override - public StrokeCourseRating computeNineTeeRatingIndex(long ntratingId) { - // TODO call WHS service for the information - return null; - } - - 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; - } - } - -} diff --git a/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicappingService.java b/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicappingService.java new file mode 100644 index 0000000..c48b5f1 --- /dev/null +++ b/src/main/java/com/poststats/golf/service/compute/AbstractStrokeHandicappingService.java @@ -0,0 +1,415 @@ +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 index b4b65a3..19363e7 100644 --- a/src/main/java/com/poststats/golf/service/compute/LegacyPostStatsPointHandicapIndexService.java +++ b/src/main/java/com/poststats/golf/service/compute/LegacyPostStatsPointHandicapIndexService.java @@ -1,16 +1,11 @@ package com.poststats.golf.service.compute; import com.brianlong.util.FlexMap; -import com.poststats.golf.service.CourseRatingService; import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; @ApplicationScoped -public class LegacyPostStatsPointHandicapIndexService extends AbstractPointHandicapIndexService { - - @Inject - private CourseRatingService courseRatingService; +public class LegacyPostStatsPointHandicapIndexService extends AbstractPointHandicappingService { @Override protected float getAccelerant() { diff --git a/src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java index 5e2a985..56d355b 100644 --- a/src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java +++ b/src/main/java/com/poststats/golf/service/compute/PostStatsPointHandicapIndexService.java @@ -13,7 +13,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @ApplicationScoped -public class PostStatsPointHandicapIndexService extends AbstractPointHandicapIndexService { +public class PostStatsPointHandicapIndexService extends AbstractPointHandicappingService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); diff --git a/src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicapIndexService.java b/src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicappingService.java similarity index 59% rename from src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicapIndexService.java rename to src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicappingService.java index 2527dd7..fe78c3e 100644 --- a/src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicapIndexService.java +++ b/src/main/java/com/poststats/golf/service/compute/PostStatsStrokeHandicappingService.java @@ -3,7 +3,7 @@ package com.poststats.golf.service.compute; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped -public class PostStatsStrokeHandicapIndexService extends AbstractStrokeHandicapIndexService { +public class PostStatsStrokeHandicappingService extends AbstractStrokeHandicappingService { @Override protected short getMaximumRounds() { @@ -15,4 +15,9 @@ public class PostStatsStrokeHandicapIndexService extends AbstractStrokeHandicapI 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 index 757d75c..826660b 100644 --- a/src/main/java/com/poststats/golf/service/compute/WhsStrokeHandicapIndexService.java +++ b/src/main/java/com/poststats/golf/service/compute/WhsStrokeHandicapIndexService.java @@ -5,7 +5,7 @@ import com.poststats.golf.service.PersonRoundService.Filter; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped -public class WhsStrokeHandicapIndexService extends AbstractStrokeHandicapIndexService { +public class WhsStrokeHandicapIndexService extends AbstractStrokeHandicappingService { @Override protected short getMinimumRounds() { @@ -22,6 +22,11 @@ public class WhsStrokeHandicapIndexService extends AbstractStrokeHandicapIndexSe return "whsStrokeHandicapIndex"; } + @Override + protected String getHoleHandicapColumn() { + return "whsHandicap"; + } + @Override protected Filter[] getRoundFilter() { return new Filter[] { diff --git a/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java b/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java index 8f15a7e..309e321 100644 --- a/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java +++ b/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java @@ -14,7 +14,6 @@ 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.CourseRatingService; import com.poststats.golf.service.CourseService; import com.poststats.provider.NonTransactionalProvider; import com.poststats.provider.Statement; @@ -29,7 +28,7 @@ import jakarta.inject.Inject; @ApplicationScoped public class CourseServiceDAO extends CacheableServiceDAO - implements CourseService, CourseNineService, CourseRatingService, CourseHoleService { + implements CourseService, CourseNineService, CourseHoleService { private final int defaultCacheExpirationInSeconds = 600; private final FlexManyToOneDef facilityManyToOneDef = new FlexManyToOneDef("facilityID", "facility"); @@ -263,58 +262,6 @@ public class CourseServiceDAO extends CacheableServiceDAO - @Override - public 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; - - @Override - public 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; - @Override public List getHolesByEighteenTee(long eighteenteeId) { // TODO Auto-generated method stub diff --git a/src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java b/src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java index 84f6c34..8537d96 100644 --- a/src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java +++ b/src/main/java/com/poststats/golf/service/db/PersonRoundServiceDAO.java @@ -1,5 +1,6 @@ package com.poststats.golf.service.db; +import java.math.BigInteger; import java.sql.SQLException; import java.time.LocalDate; import java.util.HashSet; @@ -21,10 +22,82 @@ 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.getRoundStatementProvider(selection, filters); + StatementProvider stmt = this.getRoundsStatementProvider(selection, filters); try { FlexPreparedStatement fps = stmt.buildPreparedStatement(); @@ -45,7 +118,107 @@ public class PersonRoundServiceDAO implements PersonRoundService { } } - private StatementProvider getRoundStatementProvider(Selection selection, Filter... filters) { + 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); @@ -84,28 +257,27 @@ public class PersonRoundServiceDAO implements PersonRoundService { } } - private final static String nonEventRoundSqlSelectClause = "SELECT R.roundID, NULL proundID, NULL linkProundID, R.etratingID, R.courseID, R.teedate, R.teetime, R.strokes, "; + 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.personID=? AND R.complete IS TRUE AND R.teedateP.healthSetback) "; - private final static String event18RoundSqlSelectClause = "SELECT NULL roundID, EPR.proundID, NULL linkProundID, EPR.etratingID, EPR.courseID, ER.date, ERP.teetime, EPR.strokes, "; + 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 EP.personID=? AND EPR.complete IS TRUE AND EPR.etratingID IS NOT NULL AND ER.dateP.healthSetback) "; + 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, CETR.etratingID, EPR.courseID, ER.date, ERP.teetime, " + 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) " // don't - // include - // 9-hole - // twice + + " 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) " @@ -117,103 +289,208 @@ public class PersonRoundServiceDAO implements PersonRoundService { + " 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 EP.personID=? AND EPR.complete IS TRUE AND ER.dateP.healthSetback) "; + 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 + private final static String event18RoundSqlSelectStrokeHandicap = event18RoundSqlSelectClause + + " EPR.strokeHandicapIndex, EPR.whsStrokeHandicapIndex " + + event18RoundSqlFromClause + + event18RoundSqlWhereClause; + private final static String event18RoundsSqlSelectStrokeHandicap = event18RoundSqlSelectClause + " EPR.strokeHandicapIndex, EPR.whsStrokeHandicapIndex " + event18RoundSqlFromClause - + event18RoundSqlWhereClause; + + event18RoundsSqlWhereClause; - private final static String event9RoundSqlSelectStrokeHandicap = event9RoundSqlSelectClause + 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 - + event9RoundSqlWhereClause; + + event9RoundsSqlWhereClause; - private final static String nonEventRoundSqlSelectScoreToPar = nonEventRoundSqlSelectClause - + " 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, " - + " CETR.pointAdj " + 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 - + " 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) " - + nonEventRoundSqlWhereClause + + nonEventRoundSqlFromPointsClause + + nonEventRoundsSqlWhereClause + "GROUP BY R.roundID "; - private final static String event18RoundSqlSelectScoreToPar = event18RoundSqlSelectClause - + " 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," - + " CETR.pointAdj " + 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 - + " 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) " - + event18RoundSqlWhereClause + + event18RoundSqlFromPointsClause + + event18RoundsSqlWhereClause + "GROUP BY EPR.proundID "; private final static String event9RoundSqlSelectScoreToPar = event9RoundSqlSelectClause - + " 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," - + " CETR.pointAdj " + + eventRoundSqlSelectPointsClause + + " CNTR.pointAdj " + event9RoundSqlFromClause - + " 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) " + + 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 = nonEventRoundSqlSelectStrokeHandicap + sql = nonEventRoundsSqlSelectStrokeHandicap + "UNION " - + event18RoundSqlSelectStrokeHandicap + + event18RoundsSqlSelectStrokeHandicap + "UNION " - + event9RoundSqlSelectStrokeHandicap + + 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 = nonEventRoundSqlSelectStrokeHandicap + sql = nonEventRoundsSqlSelectStrokeHandicap + " AND R.whsStrokeHandicapIndex IS NOT NULL " + "UNION " - + event18RoundSqlSelectStrokeHandicap + + event18RoundsSqlSelectStrokeHandicap + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " + "UNION " - + event9RoundSqlSelectStrokeHandicap + + event9RoundsSqlSelectStrokeHandicap + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " + "ORDER BY teedate DESC, teetime DESC " + "LIMIT ?" @@ -226,95 +503,238 @@ public class PersonRoundServiceDAO implements PersonRoundService { @Statement( sql = nonEventRoundSqlSelectStrokeHandicap + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " - + "UNION " - + event18RoundSqlSelectStrokeHandicap - + "UNION " - + event9RoundSqlSelectStrokeHandicap - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" ) - private StatementProvider sqlSelectSignedRoundsWithStrokeHandicap; + 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 = nonEventRoundSqlSelectStrokeHandicap + sql = nonEventRoundsSqlSelectStrokeHandicap + " AND R.whsStrokeHandicapIndex IS NOT NULL " + " AND EXISTS (SELECT RS.signerID FROM ~g~.RoundSigning RS WHERE RS.roundID=R.roundID) " + "UNION " - + event18RoundSqlSelectStrokeHandicap + + event18RoundsSqlSelectStrokeHandicap + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " + "UNION " - + event9RoundSqlSelectStrokeHandicap + + event9RoundsSqlSelectStrokeHandicap + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " + "ORDER BY teedate DESC, teetime DESC " + "LIMIT ?" ) private StatementProvider sqlSelectSignedRatedRoundsWithStrokeHandicap; - @Inject - @NonTransactionalProvider - @GolfProvider - @Statement( - sql = nonEventRoundSqlSelectScoreToPar - + "UNION " - + event18RoundSqlSelectScoreToPar - + "UNION " - + event9RoundSqlSelectScoreToPar - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectRoundsWithScoreToPar; + @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 = nonEventRoundSqlSelectScoreToPar + 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 " - + event18RoundSqlSelectScoreToPar + + event18RoundsSqlSelectScoreToPar + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " + "UNION " - + event9RoundSqlSelectScoreToPar + + 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) " - + "UNION " - + event18RoundSqlSelectScoreToPar - + "UNION " - + event9RoundSqlSelectScoreToPar - + "ORDER BY teedate DESC, teetime DESC " - + "LIMIT ?" - ) - private StatementProvider sqlSelectSignedRoundsWithScoreToPar; + @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 = nonEventRoundSqlSelectScoreToPar + 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 " - + event18RoundSqlSelectScoreToPar + + event18RoundsSqlSelectScoreToPar + " AND EPR.whsStrokeHandicapIndex IS NOT NULL " + "UNION " - + event9RoundSqlSelectScoreToPar + + 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; + }