Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

["Kodtest"]: Assignment ready for review #1

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

/.idea/
/harry-kart.iml
/target/
.DS_Store
186 changes: 175 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@
<artifactId>harry-kart</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Brussels-SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<parent>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Brussels-SR5</version>
<relativePath/>
</parent>

<repositories>
<repository>
<id>central</id>
<url>http://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand All @@ -31,14 +34,59 @@
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.5-b10</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>

<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
</dependency>

</dependencies>

<build>
<plugins>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
Expand All @@ -48,7 +96,123 @@
<target>1.8</target>
</configuration>
</plugin>

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>

<packageName>se.atg.service.harrykart.models.xjc</packageName>

<sources>
<source>src/main/resources</source>
</sources>

<xjcSourceExcludeFilters>
<filter implementation="org.codehaus.mojo.jaxb2.shared.filters.pattern.PatternFileFilter">
<patterns>
<pattern>\.xml</pattern>
<pattern>\.html</pattern>
<pattern>\.css</pattern>
<pattern>\.js</pattern>
<pattern>\.ico</pattern>
</patterns>
</filter>
</xjcSourceExcludeFilters>

</configuration>
</plugin>

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<configuration>
<excludes>
<exclude>se/atg/service/harrykart/models/xjc/**/*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-report-integration</id>
<goals>
<goal>report-integration</goal>
</goals>
</execution>
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.60</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>

</plugins>
</build>

<reporting>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<!-- select non-aggregate reports -->
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
<outputDirectory>target/surefire-reports</outputDirectory>
</reporting>

</project>
6 changes: 5 additions & 1 deletion src/main/java/se/atg/service/harrykart/HarryKartApp.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package se.atg.service.harrykart;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HarryKartApp {
public static void main(String ... args) {
private final static Logger logger = LoggerFactory.getLogger(HarryKartApp.class);
public static void main(final String ... args) {
logger.info("Starting HarryKartApp application with args \"{}\"", new Object[]{args});
SpringApplication.run(HarryKartApp.class, args);
}
}
9 changes: 9 additions & 0 deletions src/main/java/se/atg/service/harrykart/HarryKartService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package se.atg.service.harrykart;

import se.atg.service.harrykart.models.xjc.HarryKartType;
import se.atg.service.harrykart.models.RaceResult;

public interface HarryKartService {

RaceResult computeResult(final HarryKartType harryKart);
}
35 changes: 35 additions & 0 deletions src/main/java/se/atg/service/harrykart/HarryKartServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package se.atg.service.harrykart;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import se.atg.service.harrykart.models.Race;
import se.atg.service.harrykart.models.RaceFactory;
import se.atg.service.harrykart.models.RaceResult;
import se.atg.service.harrykart.models.xjc.HarryKartType;
import se.atg.service.harrykart.models.xjc.LoopType;
import se.atg.service.harrykart.models.xjc.ParticipantType;

import java.util.List;

@Service
public class HarryKartServiceImpl implements HarryKartService {
private final static Logger logger = LoggerFactory.getLogger(HarryKartServiceImpl.class);

@Override
public RaceResult computeResult(final HarryKartType harryKart) {
logger.info("Extracting data from HarryKartType instance");
final int loopCount = harryKart.getNumberOfLoops().intValue();
final List<ParticipantType> participants = harryKart.getStartList().getParticipant();
final List<LoopType> loops = harryKart.getPowerUps().getLoop();

logger.info("Creating Race instance");
final Race race = new RaceFactory(loopCount, participants, loops).createRace();
final ResultEvaluator evaluator = new ResultEvaluator(race.getRaceTimes());

logger.info("Evaluating RaceResult");
final RaceResult result = evaluator.getResult();
logger.info("Returning result {}", result);
return result;
}
}
63 changes: 63 additions & 0 deletions src/main/java/se/atg/service/harrykart/ResultEvaluator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package se.atg.service.harrykart;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.atg.service.harrykart.models.RacePosition;
import se.atg.service.harrykart.models.RaceResult;
import se.atg.service.harrykart.models.RaceTime;

import java.util.Comparator;
import java.util.List;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.toList;

class ResultEvaluator {
private final static Logger logger = LoggerFactory.getLogger(ResultEvaluator.class);

private final List<RaceTime> raceTimes;

ResultEvaluator(List<RaceTime> raceTimes) {
this.raceTimes = raceTimes;
}

RaceResult getResult() {
return new RaceResult(fixNeckAndNeckPositions(getRanking()));
}

private List<RacePosition> getRanking() {
logger.info("Sorting race times {}", raceTimes);
List<RaceTime> winnersSorted = raceTimes.stream().sorted(Comparator.comparing(RaceTime::getTime))
.collect(toList()).subList(0, Math.min(3, raceTimes.size()));
logger.info("Ranked winners {}", winnersSorted);
return winnersSorted.stream().map(rt -> new RacePosition(rt.getHorse(), winnersSorted.indexOf(rt) + 1))
.collect(toList());
}

private List<RacePosition> fixNeckAndNeckPositions(final List<RacePosition> ranking) {
logger.info("Checking tie-breakers: {}", ranking);
return IntStream.range(0, ranking.size()).mapToObj(i -> fixRanking(ranking, i)).collect(toList());
}

/**
* Correct the RacePosition in the supplied ranking at the supplied index so that if any horses have the
* same race time, they are awarded the same position.
* @param ranking the calculated ranking before correction
* @param index the index of the RacePosition to examine
* @return a corrected copy of the existing RacePosition, or the existing one if it didn't need correction
*/
private RacePosition fixRanking(final List<RacePosition> ranking, final int index) {
if (index == 0) return ranking.get(0);
final RaceTime second = raceTimes.get(index);
final RaceTime first = raceTimes.get(index - 1);

if (second.getTime().equals(first.getTime())) {
final RacePosition toFix = ranking.get(index);
final RacePosition tiedWith = ranking.get(index - 1);
logger.info("Fixing tie-break position for {}, tied with {}", toFix, tiedWith);
return new RacePosition(toFix.getHorse(), fixRanking(ranking, index - 1).getPosition());
} else {
return ranking.get(index);
}
}
}
Loading