+ Working WeekOverview
+ Cleanup + Documentation Signed-off-by: Johannes Theiner <j.theiner@live.de> #SPM-11: add work 2h development #SPM-11: add work 30m documentation
This commit is contained in:
parent
c34639bd3a
commit
0b36985e6c
|
@ -44,7 +44,7 @@
|
|||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
<module name="LineLength">
|
||||
<property name="max" value="100"/>
|
||||
<property name="max" value="200"/>
|
||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
||||
</module>
|
||||
<module name="AvoidStarImport"/>
|
||||
|
@ -55,13 +55,14 @@
|
|||
<property name="tokens"
|
||||
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||
</module>
|
||||
<module name="NeedBraces"/>
|
||||
<module name="NeedBraces">
|
||||
<property name="tokens" value="LITERAL_DO"/>
|
||||
</module>
|
||||
<module name="LeftCurly"/>
|
||||
<module name="RightCurly">
|
||||
<property name="id" value="RightCurlySame"/>
|
||||
<property name="tokens"
|
||||
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
|
||||
LITERAL_DO"/>
|
||||
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_DO, LITERAL_IF, LITERAL_ELSE"/>
|
||||
</module>
|
||||
<module name="RightCurly">
|
||||
<property name="id" value="RightCurlyAlone"/>
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package de.hsel.spm.baudas.analysis;
|
||||
|
||||
/**
|
||||
* Indexes for all attributes.
|
||||
*
|
||||
* @author Johannes Theiner
|
||||
* @version 0.1
|
||||
* @since 0.1
|
||||
**/
|
||||
public class Attribute {
|
||||
class Attribute {
|
||||
|
||||
static final int SEX = 0;
|
||||
static final int AGE = 1;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package de.hsel.spm.baudas.analysis;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import weka.clusterers.SimpleKMeans;
|
||||
import weka.core.Instances;
|
||||
import weka.filters.Filter;
|
||||
|
@ -31,51 +32,51 @@ public class Cluster implements Analysis<Map<Integer, Map<String, String>>> {
|
|||
*/
|
||||
@Override
|
||||
public Map<Integer, Map<String, String>> getResult() {
|
||||
if(result == null) {
|
||||
result = new HashMap<>();
|
||||
//TODO: anpassen wenn #SPM-17 gemerged ist.
|
||||
int[] keepIndexes = new int[]{0, 1, 3, 5, 6, 7};
|
||||
Remove remove = new Remove();
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
result = new HashMap<>();
|
||||
int[] keepIndexes = new int[]{Attribute.SEX, Attribute.AGE, Attribute.MARITAL_STATUS, Attribute.SHOPPING_DAY, Attribute.SHOPPING_HOUR, Attribute.RESIDENCE};
|
||||
Remove remove = new Remove();
|
||||
|
||||
try {
|
||||
remove.setAttributeIndicesArray(keepIndexes);
|
||||
remove.setInvertSelection(true);
|
||||
remove.setInputFormat(instances);
|
||||
instances = Filter.useFilter(instances, remove);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
remove.setAttributeIndicesArray(keepIndexes);
|
||||
remove.setInvertSelection(true);
|
||||
remove.setInputFormat(instances);
|
||||
instances = Filter.useFilter(instances, remove);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//creating a single cluster to get average, weka has no way to get that from a bigger one.
|
||||
SimpleKMeans fullMeans = new SimpleKMeans();
|
||||
Instances fullCentroids = null;
|
||||
try {
|
||||
fullMeans.setNumClusters(1);
|
||||
fullMeans.setPreserveInstancesOrder(true);
|
||||
fullMeans.buildClusterer(instances);
|
||||
fullCentroids = fullMeans.getClusterCentroids();
|
||||
//creating a single cluster to get average, weka has no way to get that from a bigger one.
|
||||
SimpleKMeans averageMeans = new SimpleKMeans();
|
||||
Instances averageCentroids = null;
|
||||
try {
|
||||
averageMeans.setNumClusters(1);
|
||||
averageMeans.setPreserveInstancesOrder(true);
|
||||
averageMeans.buildClusterer(instances);
|
||||
averageCentroids = averageMeans.getClusterCentroids();
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
assert fullCentroids != null;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
assert averageCentroids != null;
|
||||
|
||||
//creating real cluster
|
||||
SimpleKMeans kMeans = new SimpleKMeans();
|
||||
try {
|
||||
kMeans.setNumClusters(5);
|
||||
kMeans.setPreserveInstancesOrder(true);
|
||||
kMeans.buildClusterer(instances);
|
||||
//creating real cluster
|
||||
SimpleKMeans fullMeans = new SimpleKMeans();
|
||||
try {
|
||||
fullMeans.setNumClusters(5);
|
||||
fullMeans.setPreserveInstancesOrder(true);
|
||||
fullMeans.buildClusterer(instances);
|
||||
|
||||
int count = 0;
|
||||
count = putIntoMap(fullCentroids, count);
|
||||
int count = 0;
|
||||
count = putIntoMap(averageCentroids, count);
|
||||
|
||||
Instances centroids = kMeans.getClusterCentroids();
|
||||
putIntoMap(centroids, count);
|
||||
Instances centroids = fullMeans.getClusterCentroids();
|
||||
putIntoMap(centroids, count);
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -84,10 +85,10 @@ public class Cluster implements Analysis<Map<Integer, Map<String, String>>> {
|
|||
* puts data into map.
|
||||
*
|
||||
* @param centroids cluster analysis result
|
||||
* @param count current insert count
|
||||
* @param count current insert count
|
||||
* @return count increment
|
||||
*/
|
||||
private int putIntoMap(Instances centroids, int count) {
|
||||
private int putIntoMap(@NotNull Instances centroids, int count) {
|
||||
for (int i = 0; i < centroids.numInstances(); i++) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
for (int j = 0; j < centroids.numAttributes(); j++) {
|
||||
|
|
|
@ -5,6 +5,8 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* object to better handle day, hour combinations.
|
||||
*
|
||||
* @author Johannes Theiner
|
||||
* @version 0.1
|
||||
* @since 0.1
|
||||
|
|
|
@ -31,17 +31,19 @@ public class ShoppingTimes implements Analysis<Map<DayHour, Integer>> {
|
|||
*/
|
||||
@Override
|
||||
public Map<DayHour, Integer> getResult() {
|
||||
if (result == null) {
|
||||
result = new HashMap<>();
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for(Instance instance : instances) {
|
||||
DayHour dayHour = new DayHour(instance.stringValue(Attribute.SHOPPING_DAY), instance.stringValue(Attribute.SHOPPING_HOUR));
|
||||
int tmp = 1;
|
||||
if(result.containsKey(dayHour))
|
||||
tmp = result.get(dayHour) + 1;
|
||||
result = new HashMap<>();
|
||||
|
||||
result.put(dayHour, tmp);
|
||||
}
|
||||
for (Instance instance : instances) {
|
||||
DayHour dayHour = new DayHour(instance.stringValue(Attribute.SHOPPING_DAY), instance.stringValue(Attribute.SHOPPING_HOUR));
|
||||
int tmp = 1;
|
||||
if (result.containsKey(dayHour))
|
||||
tmp = result.get(dayHour) + 1;
|
||||
|
||||
result.put(dayHour, tmp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package de.hsel.spm.baudas.analysis;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import weka.core.Instance;
|
||||
import weka.core.Instances;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* get sum for every article and sort them ascending.
|
||||
*
|
||||
* @author Karsten Eden
|
||||
* @version 0.1
|
||||
* @since 0.1
|
||||
|
@ -22,29 +24,34 @@ public class TopFlopArticle implements Analysis<Map<String, Integer>> {
|
|||
private Instances instances;
|
||||
private Map<String, Integer> results;
|
||||
|
||||
public TopFlopArticle(File file){
|
||||
results = new HashMap<>();
|
||||
public TopFlopArticle(File file) {
|
||||
|
||||
instances = load(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* get sum for every article and sort them asending
|
||||
* get result of analysis.
|
||||
*
|
||||
* @return Map of Name of Products and Sum of Values
|
||||
*/
|
||||
public Map<String, Integer> getResult() {
|
||||
if (results != null) {
|
||||
return results;
|
||||
}
|
||||
results = new HashMap<>();
|
||||
String name;
|
||||
Double sum = 0.0;
|
||||
for(int i=11; i<=25; i++) {
|
||||
double sum = 0.0;
|
||||
for (int i = 11; i <= 25; i++) {
|
||||
for (Instance instance : instances) {
|
||||
sum += instance.value(i);
|
||||
}
|
||||
name = instances.attribute(i).name();
|
||||
results.put(name, sum.intValue());
|
||||
results.put(name, (int) sum);
|
||||
sum = 0.0;
|
||||
}
|
||||
//Sort Map in ascending order
|
||||
Stream<Map.Entry<String, Integer>> sorted = results.entrySet().stream().sorted(Map.Entry.comparingByValue());
|
||||
results = sorted.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (e1, e2) -> e2, LinkedHashMap::new));
|
||||
results = sorted.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new));
|
||||
return results;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Week Overview Analysis.
|
||||
* Week WeekOverviewDiagram Analysis.
|
||||
*
|
||||
* @author Julian Hinxlage
|
||||
* @version 0.1
|
||||
|
@ -21,19 +21,26 @@ public class WeekOverview implements Analysis<Map<String, Map.Entry<Double, Inte
|
|||
private Map<String, Map.Entry<Double, Integer>> result;
|
||||
|
||||
public WeekOverview(File file) {
|
||||
result = new HashMap<>();
|
||||
|
||||
instances = load(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* get results for analysis.
|
||||
*
|
||||
* @return day, amount, count
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Map.Entry<Double, Integer>> getResult() {
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
result = new HashMap<>();
|
||||
int dayIndex = Attribute.SHOPPING_DAY;
|
||||
int amountIndex = Attribute.PURCHASE_AMOUNT;
|
||||
|
||||
//TODO: replace values when #SPM-17 is merged
|
||||
int dayIndex = 5;
|
||||
int amountIndex = 10;
|
||||
|
||||
int startArticles = 11;
|
||||
int endArticles = 26;
|
||||
int startArticles = Attribute.POWER_TOOLS;
|
||||
int endArticles = Attribute.GARDENING_TOOLS + 1;
|
||||
|
||||
for (int i = 0; i < instances.numInstances(); i++) {
|
||||
Instance instance = instances.get(i);
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
package de.hsel.spm.baudas.web;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import de.hsel.spm.baudas.analysis.WeekOverview;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Johannes Theiner
|
||||
* @version 0.1
|
||||
* @since 0.1
|
||||
**/
|
||||
@WebServlet("/week_overview")
|
||||
public class Overview extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
req.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
resp.setContentType("application/json");
|
||||
PrintWriter out = resp.getWriter();
|
||||
|
||||
Gson gson = new Gson();
|
||||
|
||||
WeekOverview overview = new WeekOverview(Data.get(Data.getFiles().peek().getUuid()));
|
||||
|
||||
List<String> labels = new ArrayList<>();
|
||||
|
||||
List<String> data1 = new ArrayList<>();
|
||||
List<String> data2 = new ArrayList<>();
|
||||
|
||||
for(Map.Entry<String, Map.Entry<Double, Integer>> entry : overview.getResult().entrySet()) {
|
||||
labels.add(entry.getKey());
|
||||
data1.add(entry.getValue().getKey().toString());
|
||||
data2.add(entry.getValue().getValue().toString());
|
||||
}
|
||||
|
||||
List<String> definedOrder = // define your custom order
|
||||
Arrays.asList("Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag");
|
||||
|
||||
Comparator<String> comparator = Comparator.comparingInt(definedOrder::indexOf);
|
||||
labels.sort(comparator);
|
||||
|
||||
List<List<String>> data = new ArrayList<>();
|
||||
data.add(data1);
|
||||
data.add(data2);
|
||||
|
||||
Result result = new Result(labels, data);
|
||||
|
||||
out.print(gson.toJson(result));
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package de.hsel.spm.baudas.web;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Johannes Theiner
|
||||
* @version 0.1
|
||||
* @since 0.1
|
||||
**/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class Result {
|
||||
|
||||
private List<String> labels;
|
||||
private List<List<String>> data;
|
||||
}
|
|
@ -56,6 +56,6 @@ public class Upload extends HttpServlet {
|
|||
|
||||
Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
resp.sendRedirect("index.jsp");
|
||||
resp.sendRedirect("");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package de.hsel.spm.baudas.web;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import de.hsel.spm.baudas.analysis.WeekOverview;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* changes data from week overview into readable format for chart.js
|
||||
*
|
||||
* @author Johannes Theiner
|
||||
* @version 0.1
|
||||
* @since 0.1
|
||||
**/
|
||||
@WebServlet("/week_overview")
|
||||
public class WeekOverviewDiagram extends HttpServlet {
|
||||
|
||||
/**
|
||||
* do get.
|
||||
*
|
||||
* @param req request
|
||||
* @param resp response
|
||||
* @throws IOException writer could not be retrieved
|
||||
*/
|
||||
@Override
|
||||
protected void doGet(@NotNull HttpServletRequest req, @NotNull HttpServletResponse resp) throws IOException {
|
||||
req.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
resp.setContentType("application/json");
|
||||
PrintWriter out = resp.getWriter();
|
||||
|
||||
List<String> definedOrder = Arrays.asList("Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag");
|
||||
Map<String, List<String>> result = new HashMap<>();
|
||||
|
||||
Gson gson = new Gson();
|
||||
|
||||
SavedFile file = Data.getFiles().peek();
|
||||
if (file == null) {
|
||||
result.put("labels", definedOrder);
|
||||
result.put("count", new ArrayList<>());
|
||||
result.put("revenue", new ArrayList<>());
|
||||
out.print(gson.toJson(result));
|
||||
return;
|
||||
}
|
||||
assert file.getUuid() != null;
|
||||
WeekOverview overview = new WeekOverview(Data.get(file.getUuid()));
|
||||
|
||||
List<String> labels = new ArrayList<>();
|
||||
|
||||
List<String> count = new ArrayList<>();
|
||||
List<String> revenue = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, Map.Entry<Double, Integer>> entry : overview.getResult().entrySet()) {
|
||||
labels.add(entry.getKey());
|
||||
count.add(entry.getValue().getKey().toString());
|
||||
revenue.add(entry.getValue().getValue().toString());
|
||||
}
|
||||
|
||||
|
||||
Comparator<String> comparator = Comparator.comparingInt(definedOrder::indexOf);
|
||||
labels.sort(comparator);
|
||||
|
||||
for (String label : labels) {
|
||||
Map.Entry<Double, Integer> entry = overview.getResult().get(label);
|
||||
count.add(entry.getKey().toString());
|
||||
revenue.add(entry.getValue().toString());
|
||||
}
|
||||
|
||||
|
||||
result.put("labels", labels);
|
||||
result.put("count", count);
|
||||
result.put("revenue", revenue);
|
||||
|
||||
out.print(gson.toJson(result));
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<% response.setCharacterEncoding(StandardCharsets.UTF_8.name()); %>
|
||||
<% request.setCharacterEncoding(StandardCharsets.UTF_8.name()); %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<title>BauDas</title>
|
||||
<!--Import Google Icon Font-->
|
||||
|
@ -10,6 +10,7 @@
|
|||
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" media="screen,projection" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" integrity="sha256-aa0xaJgmK/X74WM224KMQeNQC2xYKwlAt08oZqjeF0E=" crossorigin="anonymous" />
|
||||
<meta charset="UTF-8">
|
||||
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=utf-8">
|
||||
|
||||
<!--Let browser know website is optimized for mobile-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
@ -31,7 +32,7 @@
|
|||
<!--Navbar Items-->
|
||||
<div class="nav-wrapper col 2 right">
|
||||
<ul class="right hide-on-med-and-down">
|
||||
<li><a data-target="slide-out" class="sidenav-trigger show-on-large"><i class="material-icons left">menu</i>Menü</a></li><!--Sidenav-->
|
||||
<li><a data-target="slide-out" class="sidenav-trigger show-on-large"><i class="material-icons left">menu</i>Menü</a></li><!--Sidenav-->
|
||||
<li><a href="login.html"><i class="material-icons left">person_outline</i>Logout</a></li><!--Logout-->
|
||||
</ul>
|
||||
<ul class="right">
|
||||
|
|
|
@ -8,13 +8,13 @@ $.ajax({
|
|||
labels: results.labels,
|
||||
datasets: [{
|
||||
label: "Warenanzahl",
|
||||
data: results.data[0],
|
||||
data: results.count,
|
||||
fill: true,
|
||||
backgroundColor: 'rgba(113, 114, 231, 0.7)',
|
||||
lineTension: 0
|
||||
}, {
|
||||
label: "Einnahmen in €",
|
||||
data: results.data[1],
|
||||
data: results.revenue,
|
||||
fill: true,
|
||||
backgroundColor: 'rgba(104, 216, 154, 0.8)',
|
||||
lineTension: 0
|
||||
|
|
|
@ -3,7 +3,7 @@ $.ajax({
|
|||
dataType: 'json'
|
||||
}).done(function (results) {
|
||||
new Chart(document.getElementById("top_articles_chart"), {
|
||||
type: 'phorizontalBarie',
|
||||
type: 'horizontalBar',
|
||||
data: {
|
||||
labels: results.labels,
|
||||
datasets: [{
|
||||
|
|
|
@ -13,7 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertTimeout;
|
|||
|
||||
|
||||
/**
|
||||
* Week Overview Analysis Test.
|
||||
* Week WeekOverviewDiagram Analysis Test.
|
||||
*
|
||||
* @author Johannes Theiner
|
||||
* @version 0.1
|
||||
|
|
Loading…
Reference in New Issue