]> git.laktatnebel.de Git - pacecalc.git/commitdiff
Initial project version
authorOle B. Rosentreter <ole@laktatnebel.de>
Sat, 28 Sep 2024 20:32:43 +0000 (22:32 +0200)
committerOle B. Rosentreter <ole@laktatnebel.de>
Sat, 28 Sep 2024 20:32:43 +0000 (22:32 +0200)
15 files changed:
pom.xml [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/Hello.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/AbstractCalculator.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/Calculators.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/ServletInitializer.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/output/OutPutter.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/run/RunPace.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/run/RunPrediction.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/run/SplitTimes.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/util/Converter.java [new file with mode: 0644]
src/main/java/de/laktatnebel/product/tools/calculators/util/Time.java [new file with mode: 0644]
src/main/resources/application.properties [new file with mode: 0644]
src/main/resources/log4j.xml [new file with mode: 0644]
src/main/webapp/index.html [new file with mode: 0644]
src/test/java/de/laktatnebel/product/tools/calculators/CalculatorApplicationTests.java [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
new file mode 100644 (file)
index 0000000..3ceb6f7
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <groupId>de.laktatnebel.product.tools</groupId>
+       <artifactId>Calculators</artifactId>
+       <version>0.0.1-SNAPSHOT</version>
+       <packaging>war</packaging>
+
+       <parent>
+               <groupId>org.springframework.boot</groupId>
+               <artifactId>spring-boot-starter-parent</artifactId>
+               <version>2.4.3</version>
+               <relativePath /> <!-- lookup parent from repository -->
+       </parent>
+
+       <name>Calculators</name>
+       <description>Calculates Sport Issues</description>
+
+       <properties>
+               <java.version>15</java.version>
+               <jaxb-api.version>2.3.1</jaxb-api.version>
+               <utillib.version>2.1.0</utillib.version>
+       </properties>
+
+       <dependencyManagement>
+               <dependencies>
+                       <dependency>
+                               <groupId>javax.xml.bind</groupId>
+                               <artifactId>jaxb-api</artifactId>
+                               <version>${jaxb-api.version}</version>
+                       </dependency>
+                       <dependency>
+                               <groupId>de.laktatnebel.libs</groupId>
+                               <artifactId>utillib</artifactId>
+                               <version>${utillib.version}</version>
+                       </dependency>
+               </dependencies>
+       </dependencyManagement>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-web</artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-devtools</artifactId>
+                       <scope>runtime</scope>
+                       <optional>true</optional>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-tomcat</artifactId>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-test</artifactId>
+                       <scope>test</scope>
+               </dependency>
+
+               <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
+               <dependency>
+                       <groupId>javax.xml.bind</groupId>
+                       <artifactId>jaxb-api</artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>de.laktatnebel.libs</groupId>
+                       <artifactId>utillib</artifactId>
+                       <exclusions>
+                               <exclusion>
+                                       <groupId>org.slf4j</groupId>
+                                       <artifactId>slf4j-api</artifactId>
+                               </exclusion>
+                               <exclusion>
+                                       <groupId>org.slf4j</groupId>
+                                       <artifactId>slf4j-log4j12</artifactId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               <artifactId>spring-boot-maven-plugin</artifactId>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
diff --git a/src/main/java/de/laktatnebel/product/tools/Hello.java b/src/main/java/de/laktatnebel/product/tools/Hello.java
new file mode 100644 (file)
index 0000000..c4b0e78
--- /dev/null
@@ -0,0 +1,38 @@
+package de.laktatnebel.product.tools;
+
+/*
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+*/
+
+//@Path("/hello")
+public class Hello {
+// This method is called if TEXT_PLAIN is request
+    //@GET
+   // @Produces(MediaType.TEXT_PLAIN)
+    public String sayPlainTextHello() {
+        return "Hello Jersey";
+    }
+
+// This method is called if XML is request
+    //@GET
+    //@Produces(MediaType.TEXT_XML)
+    public String sayXMLHello() {
+        return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>";
+    }
+
+// This method is called if HTML is request
+    //@GET
+    //@Produces(MediaType.TEXT_HTML)
+    public String sayHtmlHello() {
+        return "<html> " + "<title>" + "Hello Jersey" + "</title>"
+                + "<body><h1>" + "Hello Jersey" + "</body></h1>" + "</html> ";
+    }
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/AbstractCalculator.java b/src/main/java/de/laktatnebel/product/tools/calculators/AbstractCalculator.java
new file mode 100644 (file)
index 0000000..b8f61e1
--- /dev/null
@@ -0,0 +1,44 @@
+package de.laktatnebel.product.tools.calculators;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractCalculator {
+
+       /** Logger logger field */
+       private static Logger logger = LoggerFactory.getLogger(AbstractCalculator.class);
+
+       {
+               logger = null;
+       }
+
+       /**
+        * @param clazz Class
+        * @return Logger
+        */
+       public static Logger getLogger(Class<?> clazz) {
+               if (AbstractCalculator.logger == null) {
+                       AbstractCalculator.logger = LoggerFactory.getLogger(clazz);
+               }
+               return AbstractCalculator.logger;
+       }
+       /**
+        *
+        * @param logger Logger
+        * @param string String
+        */
+       public static void log(Logger logger, String string) {
+               if (logger.isTraceEnabled()) {
+                       logger.trace(string);
+               } else if (logger.isDebugEnabled()) {
+                       logger.debug(string);
+               } else if (logger.isInfoEnabled()) {
+                       logger.info(string);
+               } else if (logger.isWarnEnabled()) {
+                       logger.warn(string);
+               } else if (logger.isErrorEnabled()) {
+                       logger.error(string);
+               }
+       }
+       
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/Calculators.java b/src/main/java/de/laktatnebel/product/tools/calculators/Calculators.java
new file mode 100644 (file)
index 0000000..78ac347
--- /dev/null
@@ -0,0 +1,13 @@
+package de.laktatnebel.product.tools.calculators;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Calculators {
+
+       public static void main(String[] args) {
+               SpringApplication.run(Calculators.class, args);
+       }
+
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/ServletInitializer.java b/src/main/java/de/laktatnebel/product/tools/calculators/ServletInitializer.java
new file mode 100644 (file)
index 0000000..6cca604
--- /dev/null
@@ -0,0 +1,13 @@
+package de.laktatnebel.product.tools.calculators;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+public class ServletInitializer extends SpringBootServletInitializer {
+
+       @Override
+       protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+               return application.sources(Calculators.class);
+       }
+
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/output/OutPutter.java b/src/main/java/de/laktatnebel/product/tools/calculators/output/OutPutter.java
new file mode 100644 (file)
index 0000000..664e541
--- /dev/null
@@ -0,0 +1,89 @@
+package de.laktatnebel.product.tools.calculators.output;
+
+import java.io.StringWriter;
+import java.util.HashMap;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class OutPutter {
+
+       private Document doc = null;
+
+       public OutPutter() {
+
+               DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+               DocumentBuilder builder = null;
+               try {
+                       builder = factory.newDocumentBuilder();
+               } catch (ParserConfigurationException e) {
+                       e.printStackTrace();
+                       throw new RuntimeException("Error converting to String", e);
+               }
+               Document doc = builder.newDocument();
+
+               Element root = doc.createElementNS("laktatnebel.de", "result");
+               doc.appendChild(root);
+
+               this.doc = doc;
+       }
+
+       public void setNodeNameValue(String nodeName, String nodeValue) {
+               NodeList elementsByTagName = this.doc.getElementsByTagName("result");
+
+               Element e = getNodeNameValue(nodeName, nodeValue);
+
+               elementsByTagName.item(0).appendChild(e);
+       }
+
+       public Element getNodeNameValue(String nodeName, String nodeValue) {
+               Element e = this.doc.createElement(nodeName);
+               e.appendChild(this.doc.createTextNode(nodeValue));
+
+               return e;
+       }
+
+       public void setNodeList(String nodeName, HashMap<String, String> nameValueList) {
+               NodeList elementsByTagName = this.doc.getElementsByTagName("result");
+
+               Element mother = this.doc.createElement(nodeName);
+
+               Element newChild = null;
+               for (String keyValue : nameValueList.keySet()) {
+
+                       newChild = getNodeNameValue(keyValue, nameValueList.get(keyValue));
+                       mother.appendChild(newChild);
+                       elementsByTagName.item(0).appendChild(mother);
+               }
+       }
+
+       @Override
+       public String toString() {
+               try {
+                       StringWriter sw = new StringWriter();
+
+                       TransformerFactory tf = TransformerFactory.newInstance();
+                       Transformer transformer = tf.newTransformer();
+                       transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+                       transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+                       transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+                       transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+
+                       transformer.transform(new DOMSource(this.doc), new StreamResult(sw));
+                       return sw.toString();
+               } catch (Exception ex) {
+                       throw new RuntimeException("Error converting to String", ex);
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/run/RunPace.java b/src/main/java/de/laktatnebel/product/tools/calculators/run/RunPace.java
new file mode 100644 (file)
index 0000000..9290e5d
--- /dev/null
@@ -0,0 +1,49 @@
+package de.laktatnebel.product.tools.calculators.run;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import de.laktatnebel.product.tools.calculators.AbstractCalculator;
+import de.laktatnebel.product.tools.calculators.output.OutPutter;
+import de.laktatnebel.product.tools.calculators.util.Converter;
+import de.laktatnebel.product.tools.calculators.util.Time;
+
+@RestController
+public class RunPace extends AbstractCalculator {
+       @SuppressWarnings("unused")
+
+       /**
+        * Default constructor.
+        */
+       public RunPace() {
+               // TODO Auto-generated constructor stub
+       }
+
+       @RequestMapping(value = "/hello", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
+       ResponseEntity<String> helloWorld() {
+               return new ResponseEntity<String>("Hello World!", HttpStatus.OK);
+       }
+
+       @RequestMapping(value = "/pace/{dist}/{hour}/{min}/{sec}", method = RequestMethod.GET, produces = MediaType.TEXT_XML_VALUE)
+       @ResponseBody
+       ResponseEntity<String> getPace(@PathVariable(name = "dist") Double distance,
+                       @PathVariable(name = "hour") Integer hours, @PathVariable(name = "min") Integer minutes,
+                       @PathVariable(name = "sec") Integer seconds) {
+
+               Time originTime = new Time(hours, minutes, seconds);
+               Double kmPerHours = Converter.getKmPerHours(distance, originTime);
+               String pace = Converter.getPace(originTime, distance);
+
+               OutPutter output = new OutPutter();
+               output.setNodeNameValue("pace", pace);
+               output.setNodeNameValue("speed", Double.toString(kmPerHours));
+
+               return new ResponseEntity<String>(output.toString(), HttpStatus.OK);
+       }
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/run/RunPrediction.java b/src/main/java/de/laktatnebel/product/tools/calculators/run/RunPrediction.java
new file mode 100644 (file)
index 0000000..ec967f0
--- /dev/null
@@ -0,0 +1,124 @@
+package de.laktatnebel.product.tools.calculators.run;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import de.laktatnebel.product.tools.calculators.AbstractCalculator;
+import de.laktatnebel.product.tools.calculators.output.OutPutter;
+import de.laktatnebel.product.tools.calculators.util.Converter;
+import de.laktatnebel.product.tools.calculators.util.Time;
+
+@RestController
+public class RunPrediction extends AbstractCalculator {
+       private static final double VDOT_PRECISION = 0.000125;
+
+       @SuppressWarnings("unused")
+
+       /**
+        * Default constructor.
+        */
+       public RunPrediction() {
+               // TODO Auto-generated constructor stub
+       }
+
+       @RequestMapping(value = "/predict/{dist}/{hour}/{min}/{sec}/{disttopredict}", method = RequestMethod.GET, produces = MediaType.TEXT_XML_VALUE)
+       @ResponseBody
+       ResponseEntity<String> getPace(@PathVariable(name = "dist") Double distance,
+                       @PathVariable(name = "hour") Integer hours, @PathVariable(name = "min") Integer minutes,
+                       @PathVariable(name = "sec") Integer seconds, @PathVariable(name = "disttopredict") Double distancetopredict) {
+
+               Time originTime = new Time(hours, minutes, seconds);
+               getLogger(RunPrediction.class).debug("originTime\t" + originTime.toString());
+               getLogger(RunPrediction.class).debug("originTime\t" + originTime.toFormattedString());
+
+               JackDaniels originJD = new JackDaniels (originTime, distance);
+               getLogger(RunPrediction.class).debug("originJD\t" + originJD.toString());
+
+               String originPace = Converter.getPace(originTime, distance);
+               
+               Time estimatedTime = new Time();
+               estimatedTime.setTimeMinutes(originTime.getMinutes() * Math.pow(distancetopredict / distance, 1.06));
+               getLogger(RunPrediction.class).debug("estimatedTime\t" + estimatedTime.toString());
+               getLogger(RunPrediction.class).debug("estimatedTime\t" + estimatedTime.toFormattedString());
+
+               JackDaniels estimatedJD = new JackDaniels(estimatedTime, distancetopredict);            
+               getLogger(RunPrediction.class).debug("estimatedJD\t" + estimatedJD.toString());
+
+               String estimatedPace = Converter.getPace(estimatedTime, distancetopredict);
+               
+               int i=0;
+               Time predictedTime = new Time();
+               predictedTime.setTimeHours(estimatedTime.getHours());
+               JackDaniels predictedJD = new JackDaniels(estimatedTime, distancetopredict);
+               while (Math.abs(predictedJD.getVdot() / originJD.getVdot() - 1) > VDOT_PRECISION) {
+                       if (estimatedJD.getVdot() > originJD.getVdot()) {
+                               predictedTime.addSeconds(1);
+                       } else {
+                               predictedTime.addSeconds(-1);
+                       }
+                       
+                       getLogger(RunPrediction.class).debug("predictedTime\t" + predictedTime.toString());
+                       getLogger(RunPrediction.class).debug("predictedTime\t" + predictedTime.toFormattedString());
+
+                       predictedJD = new JackDaniels(predictedTime, distancetopredict);
+                       getLogger(RunPrediction.class).debug("predictedJD\t" + predictedJD.toString());
+                       
+                       if (++i >= 100 ) break;
+               }
+
+               String predictedPace = Converter.getPace(predictedTime, distancetopredict);
+               
+               Double kmPerHours = Converter.getKmPerHours(distance, originTime);
+               Double meterPerMin = Converter.getMeterPerMin(distance, originTime);
+               
+               OutPutter output = new OutPutter();
+               output.setNodeNameValue("pace_min-km", originPace);
+               output.setNodeNameValue("speed_km-h", Double.toString(kmPerHours));
+               output.setNodeNameValue("meter-per-min", Double.toString(meterPerMin));
+               output.setNodeNameValue("vO2", Double.toString(originJD.getVo2()));
+               output.setNodeNameValue("fvO2", Double.toString(originJD.getFvo2()));
+               output.setNodeNameValue("vdot", Double.toString(originJD.vdot));
+               output.setNodeNameValue("distancetopredict", Double.toString(distancetopredict));
+               output.setNodeNameValue("estimatedTime", estimatedTime.toFormattedString());
+               output.setNodeNameValue("estimatedPace_min-km", estimatedPace);
+               output.setNodeNameValue("predictedTime", predictedTime.toFormattedString());
+               output.setNodeNameValue("predictedPace_min-km", predictedPace);
+
+               return new ResponseEntity<String>(output.toString(), HttpStatus.OK);
+       }
+
+       private class JackDaniels {
+               private Double vo2 = 0.0;
+               private Double fvo2 = 0.0;
+               private Double vdot = 0.0;
+               
+               public JackDaniels(Time originTime, Double distance) {
+                       this.vo2 = 0.000104 * Math.pow(Converter.getMeterPerMin(distance, originTime), 2) + 0.182258 * Converter.getMeterPerMin(distance, originTime) - 4.60;
+                       this.fvo2 = 0.80 + 0.298956 * Math.pow(Math.E, (-0.193261*originTime.getMinutes())) + 0.189438 * Math.pow(Math.E, (-0.012778*originTime.getMinutes()));
+                       this.vdot = getVo2() / getFvo2();
+               }
+               
+               public Double getVo2() {
+                       return vo2;
+               }
+
+               public Double getFvo2() {
+                       return fvo2;
+               }
+
+               public Double getVdot() {
+                       return vdot;
+               }
+
+               @Override
+               public String toString() {
+                       return "JackDaniels [vo2=" + vo2 + ", fvo2=" + fvo2 + ", vdot=" + vdot + "]";
+               }
+       }
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/run/SplitTimes.java b/src/main/java/de/laktatnebel/product/tools/calculators/run/SplitTimes.java
new file mode 100644 (file)
index 0000000..f038840
--- /dev/null
@@ -0,0 +1,95 @@
+package de.laktatnebel.product.tools.calculators.run;
+
+import java.util.HashMap;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import de.laktatnebel.product.tools.calculators.AbstractCalculator;
+import de.laktatnebel.product.tools.calculators.output.OutPutter;
+import de.laktatnebel.product.tools.calculators.util.Converter;
+import de.laktatnebel.product.tools.calculators.util.Time;
+
+@RestController
+public class SplitTimes extends AbstractCalculator {
+
+       public SplitTimes() {
+               super();
+               // TODO Auto-generated constructor stub
+       }
+
+       @RequestMapping(value = "/splits/{dist}/{hour}/{min}/{sec}", method = RequestMethod.GET, produces = MediaType.TEXT_XML_VALUE)
+       @ResponseBody
+       ResponseEntity<String> getAllSplits(@PathVariable(name = "dist") Double distance,
+                       @PathVariable(name = "hour") Integer hours, @PathVariable(name = "min") Integer minutes,
+                       @PathVariable(name = "sec") Integer seconds) {
+
+               Time originTime = new Time(hours, minutes, seconds);
+               Double kmPerHours = Converter.getKmPerHours(distance, originTime);
+               String pace = Converter.getPace(originTime, distance);
+
+               OutPutter output = new OutPutter();
+
+               output.setNodeNameValue("pace", pace);
+               output.setNodeNameValue("speed", Double.toString(kmPerHours));
+               getLogger(RunPrediction.class).debug("speed\t" + kmPerHours);
+
+               Double split = 0.0;
+               while (split < distance) {
+                       getLogger(RunPrediction.class).debug("split\t" + split);
+
+                       Time splitTime = new Time();
+                       splitTime.setTimeHours(split * originTime.getHours() / distance);
+
+                       HashMap<String, String> splits = new HashMap<String, String>();
+                       splits.put("km", Double.toString(split));
+                       splits.put("time", splitTime.toFormattedString());
+
+                       output.setNodeList("split", splits);
+                       split++;
+               }
+
+               HashMap<String, String> splits = new HashMap<String, String>();
+               splits.put("km", Double.toString(distance));
+               splits.put("time", originTime.toFormattedString());
+
+               output.setNodeList("split", splits);
+
+               return new ResponseEntity<String>(output.toString(), HttpStatus.OK);
+       }
+
+       @RequestMapping(value = "/splits/{dist}/{hour}/{min}/{sec}/{specialsplit}", method = RequestMethod.GET, produces = MediaType.TEXT_XML_VALUE)
+       @ResponseBody
+       ResponseEntity<String> getSpecialSplit(@PathVariable(name = "dist") Double distance,
+                       @PathVariable(name = "hour") Integer hours, @PathVariable(name = "min") Integer minutes,
+                       @PathVariable(name = "sec") Integer seconds, @PathVariable(name = "specialsplit") Double specialsplit) {
+
+               Time originTime = new Time(hours, minutes, seconds);
+               Double kmPerHours = Converter.getKmPerHours(distance, originTime);
+               String pace = Converter.getPace(originTime, distance);
+
+               OutPutter output = new OutPutter();
+
+               output.setNodeNameValue("pace", pace);
+               output.setNodeNameValue("speed", Double.toString(kmPerHours));
+               getLogger(RunPrediction.class).debug("speed\t" + kmPerHours);
+
+               Time splitTime = new Time();
+               splitTime.setTimeHours(originTime.getHours() * specialsplit / distance);
+
+               HashMap<String, String> splits = new HashMap<String, String>();
+               splits.put("km", Double.toString(specialsplit));
+               splits.put("time", splitTime.toFormattedString());
+
+               output.setNodeList("split", splits);
+
+               return new ResponseEntity<String>(output.toString(), HttpStatus.OK);
+       }
+
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/util/Converter.java b/src/main/java/de/laktatnebel/product/tools/calculators/util/Converter.java
new file mode 100644 (file)
index 0000000..2fb4f1c
--- /dev/null
@@ -0,0 +1,27 @@
+package de.laktatnebel.product.tools.calculators.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class Converter {
+
+       public static String getPace(Time time, Double distance) {
+               Date dateFromTimeInSeconds = new Date(Math.round(60L * 60L * 1000L * time.getHours() / distance));
+
+               SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss,SS");
+               sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+               return sdf.format(dateFromTimeInSeconds);
+       }
+
+       public static Double getKmPerHours(Double distance, Time time) {
+               return distance / time.getHours();
+       }
+
+       public static Double getMeterPerMin(Double distance, Time time) {
+               return distance * 1000 / time.getMinutes();
+       }
+
+
+}
diff --git a/src/main/java/de/laktatnebel/product/tools/calculators/util/Time.java b/src/main/java/de/laktatnebel/product/tools/calculators/util/Time.java
new file mode 100644 (file)
index 0000000..e8bb6ae
--- /dev/null
@@ -0,0 +1,75 @@
+package de.laktatnebel.product.tools.calculators.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class Time {
+
+       private Double seconds = 0.0;
+       private Double minutes = 0.0;
+       private Double hours = 0.0;
+
+       public Time(Integer hours, Integer minutes, Integer seconds) {
+               super();
+               setTime(hours, minutes, seconds);
+       }
+       
+       public void addSeconds(int secondsToAdd) {
+               setTimeSeconds(this.seconds + (double) secondsToAdd/10);
+       }
+
+       public String toFormattedString() {
+               Date dateFromTimeInSeconds = new Date(Math.round(1000L * seconds));
+               
+               SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss,SS");
+               sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+               
+               return sdf.format(dateFromTimeInSeconds);
+       }
+
+       public Time() {
+               super();
+       }
+
+       public Double getSeconds() {
+               return seconds;
+       }
+       
+       public Double getMinutes() {
+               return minutes;
+       }
+
+       public Double getHours() {
+               return hours;
+       }
+
+       public void setTimeSeconds(Double seconds) {
+               this.seconds = seconds;
+               this.minutes = seconds / 60;
+               this.hours = seconds / 3600;
+       }
+       
+       public void setTimeMinutes(Double minutes) {
+               this.seconds = minutes * 60;
+               this.minutes = minutes;
+               this.hours = minutes / 60;
+       }
+       
+       public void setTimeHours(Double hours) {
+               this.seconds = hours * 3600;
+               this.minutes = hours * 60;
+               this.hours = hours;
+       }
+       
+       public void setTime(Integer hours, Integer minutes, Integer seconds) {
+               this.seconds = (double) hours * 3600 + (double) minutes * 60 + (double) seconds;
+               this.minutes = (double) hours * 60 + (double) minutes + (double) seconds / 60;
+               this.hours = (double) hours + (double) minutes / 60 + (double) seconds / 3600;
+       }
+
+       @Override
+       public String toString() {
+               return "Time [seconds=" + seconds + ", minutes=" + minutes + ", hours=" + hours + "]";
+       }
+}
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644 (file)
index 0000000..dc7c72e
--- /dev/null
@@ -0,0 +1,3 @@
+logging.level.root=TRACE
+logging.level.org.springframework.web=DEBUG
+logging.level.org.hibernate=ERROR
diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml
new file mode 100644 (file)
index 0000000..f04bbed
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">\r
+\r
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">\r
+\r
+       <appender name="appender" class="org.apache.log4j.ConsoleAppender">\r
+               <layout class="org.apache.log4j.PatternLayout">\r
+                       <param name="ConversionPattern" value="%d [%t] %p - %m%n" />\r
+               </layout>\r
+       </appender>\r
+\r
+       <root>\r
+               <priority value="trace" />\r
+               <appender-ref ref="appender" />\r
+       </root>\r
+\r
+</log4j:configuration>\r
diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html
new file mode 100644 (file)
index 0000000..adf7f11
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+something ...
+</body>
+</html>
\ No newline at end of file
diff --git a/src/test/java/de/laktatnebel/product/tools/calculators/CalculatorApplicationTests.java b/src/test/java/de/laktatnebel/product/tools/calculators/CalculatorApplicationTests.java
new file mode 100644 (file)
index 0000000..934fca3
--- /dev/null
@@ -0,0 +1,13 @@
+package de.laktatnebel.product.tools.calculators;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class CalculatorApplicationTests {
+
+       @Test
+       void contextLoads() {
+       }
+
+}